I'm fairly new to Handlebars, the templating system that the blogging system Ghost uses, but my initial impressions are that it's a pretty sweet tool to use. However, it's somewhat limited when you're developing a Ghost blog, due to the fact that Ghost only implements certain definitions. Odds are that some of you have been wishing you could implement your own definitions somehow. Obviously you could just edit the Ghost source, but that isn't update-safe, and you would have to remember to change it every time you updated.

According to the official Ghost documentation, both the index.js file and the core/ directory are modified on update inside your Ghost installation - which means that adding handlers anywhere inside these files is a bad idea (I recently saw something claiming that index.js was the best option). What we really need is something which is untouched by updates (for now, at least), and something which is loaded towards the startup of the application. Turns out, config.js meets these requirements. Normally I would not recommend messing around inside configuration files, but I'm going to demonstrate a safe way to go about doing this.

At the time of writing, config.js is untouched by updates - however this may change in future. Make sure to verify on the official documentation before updating.

Registering A Helper

The first helper I had a use for was a cool little conditional helper I found on StackOverflow. Arguably, this goes against the entire point of Handlebars.js, as noted by people in the comments on that question - however I decided to try it out, having never played about with my own helpers before.

There are various routes you can go with this, depending on your preference, but I decided to simply create a file name helpers.js to store all my definitions and expose it as a module. It looked a little something like this;

var hbs = require('express-hbs');

module.exports = function(){  
    hbs.registerHelper('cond', function (v1, operator, v2, options) {
        switch (operator) {
            case '==':
                return (v1 == v2) ? options.fn(this) : options.inverse(this);
            case '===':
                return (v1 === v2) ? options.fn(this) : options.inverse(this);
            case '<':
                return (v1 < v2) ? options.fn(this) : options.inverse(this);
            case '<=':
                return (v1 <= v2) ? options.fn(this) : options.inverse(this);
               case '>':
                return (v1 > v2) ? options.fn(this) : options.inverse(this);
               case '>=':
                return (v1 >= v2) ? options.fn(this) : options.inverse(this);
            case '&&':
                return (v1 && v2) ? options.fn(this) : options.inverse(this);
            case '||':
                return (v1 || v2) ? options.fn(this) : options.inverse(this);
            default:
                return options.inverse(this);
        }
    });
};

Naturally you can stack up various different helpers in this exported function, but this is all I need for now. So how do I get it to be read by Ghost?

Initializing Your Helpers

This bit is pretty simple, you simple execute your new module inside the config.js of Ghost. This can be achieved by adding a single line to the top of the file;

// Include any helper functions
require('./helpers')();  

which leaves me with the top of the config looking something along the lines of:

// # Ghost Configuration
// Setup your Ghost install for various environments
// Documentation can be found at http://support.ghost.org/config/

// Include any helper functions
require('./helpers')();

var path = require('path'),  
    config;

Result

So what does this leave us with? Well, simply try use your new helper from inside your code. I simply tried a new condition via my helper.

{{#cond 5 '==' 5}}
    <script>alert("Success!")</script>
{{/cond}}

If 5 == 5 (it does) just alert a success message - and sure enough, when I load my page again I see the message.

Downsides?

The biggest downside to this is that you now have to maintain code in two separate directories. This may not be an issue, as long as you remember to refresh your handlers file - e.g. if you start using a new handler locally, you need to remember to put it on the server.

This isn't too much of a big deal; in reality you could maintain your handlers file inside your theme, and simply create a symlink to the file inside the Ghost root directory (disclaimer: haven't tried this). This would allow you to update your server code by just refreshing a single directory.

Why Can't I Do This Already?

Ghost is a fairly new project, with a whole list of new features in the pipeline. I'm sure that there is a request in somewhere for a nicer way of doing this. Perhaps it will be possible via the Apps feature, with users having an App to define their handlers (I'm not overly familiar with this feature). Or perhaps it will be something else - either way the above method should get you started for now.