npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

connect-blog

v1.6.0

Published

Blog middleware you can add to your Connect/Express app, uses a directory of static files.

Downloads

24

Readme

connect-blog

Blog middleware you can add to your Connect/Express app, uses a directory of static files.

Synopsis

var connectBlog = require('connect-blog');

var blog = connectBlog({
    domain : 'example.com',
});

// later on
app.get('/', blog);
app.get('/:path', blog);

This example will serve this blog at the root level of the example.com domain. You must set both / and /:path so that we can determine in the middleware whether to show the index page or something else. The /:path parameter must also be called path, not anything else.

What is connect-blog

'connect-blog' is middleware for Express/Connect. It can read a directory full of static *.md and *.json files and then serve up a blog for you. Each post should consist of two files.

Imagine a post called my-first-post. Therefore, you require:

  • my-first-post.md
  • my-first-post.json

(Note: you can also use *.textile or *.html files for the content, or *.ini or *.yaml files for the meta data about the post.)

Once 'connect-blog' has read those files in, it will create a structure similar to the following:

{
    name    : 'my-first-post',
    content : ' ... the markdown from the *.md file ... ',
    html    : ' ... the HTML from the MarkDown conversion ... ',
    meta    : {
        // then entire data read from the *.json file
    }
}

By keeping to this structure, 'connect-blog' knows where to find everything. An example *.json file would be:

{
    "title" : "My First Post",
    "date"  : "2013-10-04T02:02:17.516Z",
    "tags"  : [ "css", "html5", "javascript", "app" ]
}

Please note that the published time of the post comes from the date field and it must be parseable by new Date(date). The year and month of that date is also used in the archive. The date is used in all templates (index, post, archive, tag) and the feeds (RSS, Atom). The tags are used for the tagging posts and in the tagcloud template. (Of course, you need to write the templates yourself so this could change.)

You can add in any other data you like this *.json file that you may need in the templates related to each post.

A default post is set up once either of these files are read. The default post looks like:

var now = new Date();
var nowMoment = moment(now);
{
    name : '...', // same as the filename, e.g. basename.json or basename.md
    meta : {
        title     : basename.split(/-/).map(function(str) { return str.substr(0, 1).toUpperCase() + str.substr(1); }).join(' '),
        date      : now,
        moment    : nowMoment,
        year      : nowMoment.format('YYYY'),
        month     : nowMoment.format('MM'),
        day       : nowMoment.format('DD'),
        monthname : nowMoment.format('MMMM'),
        category  : 'general',
        tags    : [],
    },
    content : '',
    html    : '',
}

This default post is set so that if you just have basename.md and no basename.json, then the blog will still render and not throw errors. Same if you have basename.json but not basename.md (but that wouldn't be much good either). Basically anything to stop it crashing, however you should check that your blog is being rendered as you want it prior to publishing.

Synopsis

To set up a blog from within Express, try this:

var blog = require('connect-blog');

var blog = connectBlog({
    title       : 'CSS Minifier Blog',
    description : 'The CSS Minifier Blog, for All Your Minifying Needs!',
    contentDir  : fs.joinPath('/', __dirname, 'blog'),
    domain      : 'cssminifier.com',
    basePath    : '/blog',
});

app.get( '/blog/',      blog );
app.get( '/blog/:path', blog );

This will serve the following pages:

/blog/                       - renders the 'blog-index' template
/blog/rss20.xml              - creates a RSS 2.0 XML file
/blog/atom.xml               - creates an Atom XML file
/blog/archive                - renders 'blog-archive' template
/blog/archive-<year>         - renders 'blog-archive' template
/blog/archive-<year>-<month> - renders 'blog-archive' template
/blog/tag                    - renders 'blog-tagcloud' template
/blog/tag-<tag-name>         - renders 'blog-tag' template
/blog/<post-name>            - renders 'blog-post' template

Each template gets access to the following variables:

  • title - the 'title' you passed in when setting the blog up
  • posts - a chronological array of all posts
  • pages - all the posts split up into pages (using opts.indexCount)
  • latest - a reversed list of the latest 10 posts (defined by opts.latestCount)
  • tagged - an object of each tag, each containing an array of posts
  • archive - an object of year numbers, each an object of month numbers, each an array of posts

e.g.

title  = opts.title;
posts  = [ ...posts... ];
latest = [ ...posts... ];
tagged = {
    tag1 : [ ...posts... ],
    tag2 : [ ...posts... ],
    tag3 : [ ...posts... ],
};
archive = {
    '2013' : {
        '01' : [ ...posts ... ],
        '02' : [ ...posts ... ],
        '03' : [ ...posts ... ],
    },
    '2012' : {
        '08' : [ ...posts ... ],
        '09' : [ ...posts ... ],
        '10' : [ ...posts ... ],
    },
};

Default Options

The default options have reasonable (not necessarily sensible) defaults for each of these keys, so the only onw you MUST provide is the domain.

var defaults = {
    title                : 'Blog',
    description          : '',
    contentDir           : 'blog',
    indexCount           : 10,
    latestCount          : 20,
    basePath             : '',
    indexTemplate        : 'blog-index',
    postTemplate         : 'blog-post',
    tagAllTemplate       : 'blog-tag-all',
    tagOneTemplate       : 'blog-tag-one',
    archiveAllTemplate   : 'blog-archive-all',
    archiveYearTemplate  : 'blog-archive-year',
    archiveMonthTemplate : 'blog-archive-month',
};

So, to go with defaults you can just call:

var blogMiddleware = connectBlog({ domain : 'example.com' });

Routes

When a route is rendered it is called as follows so that it is independent of whatever template language you have already set up.

res.render('blog-post');

The /rss20.xml and /atom.xml do not call a template since the XML is generated within the middleware. They only look at the opts originally passed in to create the middleware and the latest variable.

Blog Index

Page     : /
Template : 'blog-index'
Locals   : (none)

Archive Index

Page     : /archive
Template : 'blog-archive'
Locals   : title -> opts.title + ' Archive'
         : thisArchive -> archive

Year Archive

Page     : /archive-<year>
Template : 'blog-archive'
Locals   : title -> opts.title + ' Archive'
         : thisArchive -> archive[year]

Month Archive

Page     : /archive-<year>-<month>
Template : 'blog-archive'
Locals   : title -> opts.title + ' Archive'
         : thisArchive -> archive[year][month]

Tag Index

Page     : /tag
Template : 'blog-tagcloud'
Locals   : title -> opts.title + ' TagCloud'

Specific Tag

Page     : /tag-<name>
Template : 'blog-tag'
Locals   : title -> opts.title + ' : ' + tag
         : thesePosts -> tagged[tag]
         : thisTagName -> tag

Post

Page     : /<post-name>
Template : 'blog-post'
Locals   : title -> post.meta.title
         : thisPost -> post[postName]

Author

Written by Andrew Chilton - Twitter - GitHub.

License

(Ends)