Asciidoc + Metalsmith

I decided to give integrating metalsmith and asciidoc a go

up

2014-10-30

I love metalsmith. It’s so easy to integrate extensions when they’re just middleware for reading and writing files. Very flexible – mind bending at times, perhaps a small challenge to debug occassionally, but really cool.

And so, this is my first post using AsciiDoc to format the source text of my post, and AsciiDoctor.js do perform the actual conversion to HTML.

We’ll see how it goes! I may not proceed with it’s usage, but it does provide some clear advantages over markdown. The downside, though, I don’t think the tooling for asciidoc is quite as ubiquitous as markdown.

As for the actual integration with metalsmith, I just created a plugin based on the metalsmith-markdown plugin:

var basename = require('path').basename;
var dirname = require('path').dirname;
var extname = require('path').extname;
var asciidoctor = require('asciidoctor.js')();
var opal = asciidoctor.Opal;
var asciidoc_processor = asciidoctor.Asciidoctor(true); // without extensions, pass 'true' for extensions

function is_asciidoc(filename) {
    return /\.adoc/.test(extname(filename));
}

var asciidoc = function(config) {
    config = config || {};
    var keys = config.keys || [];

    return function(files, metalsmith, done) {
        setImmediate(done);
        Object.keys(files).forEach(function(file){
            if(!is_asciidoc(file)) return;
            var data = files[file];
            var dir = dirname(file);
            var html = basename(file, extname(file)) + '.html';
            if('.' != dir) html = dir + '/' + html;

            var options = opal.hash2(
                ['doctype', 'attributes'],
                {doctype:'article', attributes: ['showtitle']});
            var str = asciidoc_processor.$convert(data.contents.toString(), options);
            data.contents = new Buffer(str);
            keys.forEach(function(key){
                data[key] = asciidoc_processor.$convert(data[key], options);
            });

            delete files[file];
            files[html] = data;
        });
    };
};

The config options aren’t really used when you instantiate the plugin… but one step at a time. I still have to figure out how to effectively add the config options to the options passed into the asciidoc_processor, which I haven’t done yet, because I ran out of time to work on it for the moment, and it’s kinda low priority for me.

I’m still using yaml front-matter in my source documents, which is kinda not how asciidoc is intended to have metadata, but it works for my purposes and means I don’t have to change anything else right now!