Writing your first Metalsmith plugin

I'm really a fan of Metalsmith, which I've written about before. It's super easy to get up and running, and the syntax is simple too. Also nice, is the fact that it doesn't choose between configuration or code. You can use either a JSON file or Node.

At a certain point in time, you're likely to need something that nobody has written a Metalsmith plugin for yet. This is probably more true now, when it's still quite early days for Metalsmith.

Turns out, it isn't hard to do.

Start with an empty index.js file and add the following structure:

module.exports = plugin;

function plugin(options){
    return function(files, metalsmith, done){
        setImmediate(done);
        Object.keys(files).forEach(function(file){
            var data = files[file];
        }
    }
}

This already contains some logic for looping over the files. Let's break it down.

module.exports = plugin;

This defines what inside this module is publicly available. If you're not familiar with javascript modules, Scott K. Allen wrote a great post on them.

The function we're exporting should return a new function. This is the logic of our Metalsmith plugin. This function receives three parameters: files, metalsmith and done. The most interesting for us is the files parameter. The metalsmith parameter contains metadata and done is a function to call when we're done (which we do implicitly via the setImmediate call.

Keep in mind that the files parameter is not an Array. It is an object where the keys are the filenames. So, if in your source folder you have two files, ´main.md´ and ´detail.md`, you would receive the following object:

{
    main: { /* ... */ },
    detail { /* ... */ }
}

The properties of each of these two objects depends on what is in our Markdown (if you're using the Metalsmith-Markdown plugin).

The line var data = files[file] resolves to var data = files['main'] and so will return the object with all its properties. Now you can start changing any of these properties as you see fit.

Put this in a subfolder of the node_modules folder in your project and you can start using it in your Metalsmith script (if you're using Node):

var my_plugin = require('./node_modules/whatever');

Metalsmith(__dirname)
    .source('./src')
    .destination('./build')
    .use(my_plugin())
    .build(function(err) {});

I've use this to make a Metalsmith plugin to create a simple gallery, using Skeleton CSS. There already exists a general gallery plugin, so I'll probably switch to that one, but I learnt something along the way, which is always nice.