Automated example code displays

I’ve been writing some code examples for some of the UI components I’m writing for Ojay, and I need to display the implementation code and stylesheet on the page. Pretty standard fare: here’s a UI example, and here’s the code you need to implement it. Easy.

Trouble is, I don’t want to duplicate the code (once in a script block, once displayed on the page), especially while editing. It’s only going to get out of sync at some point, and it’s tedious to maintain. So, I cooked up a way of getting my page to display its own source code as part of the example. First thing you’re going to need is a script block and a textarea to display its source:

<script type="text/javascript" id="the-script">
    // code goes here...
</script>

<textarea id="the-display"><textarea>

You throw your example code in the script block and it sets up the example UI you’re demonstrating. Then, all you need to do is extract its contents and put the code in the textarea for display. (It doesn’t have to be a textarea, although you can be sure it will preserve line breaks that other elements might throw out.) In another script block, put the following:

var code = $('#the-script').node.innerHTML.unindent();
$('#the-display').setAttributes({
    value: code,
    rows: code.split(/\n/).length + 1
});

Simple enough, now you can be sure the example code that people read will match what’s actually running on the page. Just one thing is missing: that unindent() function. I needed this because the script gets indented quite a lot by my templating system, which produces nice nested easy-to-read HTML. I need to strip off the common indentation from all the lines to just leave the raw code. To do this, we find the minimum indentation of all the lines and then remove it from each line of the string, like so:

String.prototype.unindent = function() {
    var lines = this.replace(/^(\s*\n)*/, '')
            .replace(/(\n\s*)*$/, '').split(/\n/);
    var indent = lines.reduce(function(memo, line) {
        if (/^\s*$/.test(line)) return memo;
        var spaces = line.match(/^ +/);
        if (!spaces) return memo;
        return Math.min(memo, spaces[0].length);
    }, Infinity);
    return lines.map({slice: indent}).join("\n");
};

Not rocket science, just a nice demo of some functional programming and one less bit of duplication in my codebase. It works with inline style elements as well, but so far I’ve not found any reliable way of doing it with HTML code while maintaining line breaks in the display (at least, not without manually parsing the HTML myself). If anyone knows how I might do this then do leave some advice in the comments.

If you’ve enjoyed this article, you might enjoy my recently published book JavaScript Testing Recipes. It’s full of simple techniques for writing modular, maintainable JavaScript apps in the browser and on the server.