bentomas.com

Custom Liquid tags with Jekyll

This site is powered by the static site generator Jekyll, which in turn uses Liquid for its templating engine. One of the first thigs I did when setting bentomas.com up was write my own custom Liquid tag (I wrote a regroup tag which can be seen in action (twice!) on the /archives page). As per the recommendation I forked the official copy of Jekyll and made my changes. However, this quickly became a pain.

I wanted to be able to use the default, straight out of the box, official Jekyll without compiling and installing my own gem while still using custom Liquid tags.

It seemed to me that there should be an official way to extend Jekyll without the need to modify the code, and as it turned out someone else agreed with me. GitHub user n8agrin has actually written a fix, but it has yet to be merged into the official Jekyll source. The fix is actually really simple. It just includes some files in a specific directory.

I’m not a very patient person, so while I am waiting for this to be officially accepted, I came up with a temporary solution. All the Jekyll action happens through the jekyll command which for me is located at /usr/local/bin/jekyll. Here’s what that looks like:

#!/usr/local/bin/ruby
#
# This file was generated by RubyGems.
#
# The application 'mojombo-jekyll' is installed as part of a gem, and
# this file is here to facilitate running it.

require 'rubygems'

version = ">= 0"

if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end

gem 'mojombo-jekyll', version
load Gem.bin_path('mojombo-jekyll', 'jekyll', version)

Not too much going on. The solution I came up with was to require my Liquid extension files (as per the fix linked to above) some where in that script. After a couple tries here is what I came up with:

#! /usr/bin/env ruby

require 'rubygems'

version = ">= 0"

if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
  version = $1
  ARGV.shift
end

require 'jekyll'

# Dynamically add other tags on a per site basis
if File.directory?('_liquid_extensions')
  Dir.chdir('_liquid_extensions') do
    Dir['*.rb'].each do |file|
      require file
    end
  end
end

gem 'mojombo-jekyll', version
load Gem.bin_path('mojombo-jekyll', 'jekyll', version)

Now instead of using the jekyll command, I use this custom command (which I saved as _custom_jekyll.rb). Easy as pie! I haven’t made any changes to the Jekyll code, so I can continue to use Rubygems to stay up to date. And any extensions I want to make to the Liquid templating language I stick in _liquid_extensions/.