divillysausages.com

Leaving Jekyll behind

A while ago, I posted on how I was moving away from Drupal towards Jekyll, thus changing from a dynamic site to a static one. Well, over Christmas, I upgraded my 8 year old laptop for a spanking new Dell XPS 13 (which is great btw) and in the process of reinstalling all my programs, getting my different dev environments set up, and generally keeping my computer as fluff-free as possible, I took a good look at what was actually necessary.

Jekyll uses both Ruby and Python. I had originally installed Ruby a long time ago to test some Ruby on Rails stuff, back when it was the hot stuff, so it influenced my decision to install Jekyll in the first place. For my new laptop, I didn't want to install both languages just to generate my site, and firing up my old laptop just to do a build seemed like a pain (once you go SSD, you never go back), so something new was in order.

Enter heckle

I do do Node.js development though, and in searching around for a Node.js Jekyll replacement, I came across heckle, by marijnh. It seemed pretty straight-forward and did everything I was looking for, with the exception that it uses Mold as a template language instead of Liquid. Hmmm...

Enter liquid-node

Hunting around some more, I came across liquid-node, by sirlantis. Liquid-node is a port of the Liquid template engine to Node.js, using Promises for all the asyncy stuff. Two points stood out on the features panel: "Based on original Ruby code" and "High test coverage". Seems like it would do the job just nicely.

JekyllJS

I started a project (TypeScript), based off of heckle, using liquid-node, and named it JekyllJS, the idea being that you could take your existing Jekyll site, run it through JekyllJS, and it'd produce the same content.

All in all, development went surpisingly smoothly. I found another Node.js module, js-yaml to handle reading the _config.yml and each post's frontMatter, and with heckle's code as a reference, I was able to get something up and running pretty quickly.

Until I hit an Unknown tag: "{% highlight %}" Exception anyway. I guess Liquid has been updated since the Node.js port happened.

Highlighting code

I have a lot of code samples across my site, and you can set up Jekyll to use Pygments or Rouge to handle this for you. I didn't find a Node.js equivalent, so I settled for highlight.js, which happily allows itself to be installed as a Node.js module to allow for server-side pre-rendering (as opposed to each client highlighting the code on each page load).

Liquid-node allows you to write your own custom tags, so I wrote one for the {% highlight %} tag that takes the chunk of text, and pipes it through highlight.js. The results are obviously different from what Pygments or Rouge generate, but I can live with the difference - as an added bonus, the CSS is smaller.

Other differences

I also had to hack a patch for the {% include %} tag, as the liquid-node version doesn't allow for tokens in order to use dynamic includes, which I use for adding comments and files to posts. The patch doesn't handle assigning variables, but there's an issue open for it, so maybe it'll happen in the future. It's included at the end of the post (as liquid-node is written in coffeescript and I don't know that). Just replace the include.js file in the node_modules/liquid-node/lib/liquid/tags/ folder after all the dependencies are installed.

When I added Markdown support using the marked node.js library I found that it was escaping all quotes for all reasons, including normal text ("don't", "can't", "I'm", etc). I don't particularly like this behaviour (it's still valid HTML though), so I added a fix around it. Just replace the marked.js file - included at the end of the post - in the node_modules/marked/lib/ folder if you want to do the same.

Another difference is the way that dates are parsed. Normally in your frontMatter, you'd specify a date like so:

date: 2016-01-23 19:50:00 +0100

and Jekyll would treat this date as-is, i.e. +1hr after GMT. JavaScript however, takes into account Romance Daylight Time, which handles the extra hour for daylights time. This means that if you're in the EU and you use CET during the winter, you'll use CEST during the summer, or during the last Sunday of March to the last Sunday of October, and +0100 will act as +0200.

var d1 = new Date( "2016-03-01 00:00:00 +0100" ) // Tue Mar 01 2016 00:00:00 GMT+0100 (Romance Standard Time)
var d2 = new Date( "2016-04-01 00:00:00 +0100" ) // Fri Apr 01 2016 01:00:00 GMT+0200 (Romance Daylight Time)

Depending on when you've published your post (i.e. the date), this behaviour can change the rendered day, or even month, which may or may not be a problem for you. I've not found a way around this behaviour, but if it's affecting you, you can try changing the date set in your frontMatter.

As for categories, I don't use them in my site, so I've no idea how they're supposed to render, so I didn't include them in JekyllJS.

The final thing I came across was when using {% if %} checks. I was checking to see if a variable was set in one of my templates using {% if someVar == null %}. For liquid-node, I had to change this to {% if someVar == undefined %} or simply {% if someVar %}.

The JekyllJS config

JekyllJS comes with a simple config file, config/default.json, meaning you can change a few things without having to re-compile the project. It looks like this:

{
	"log":{
		"level":"info"
	},
	"src":{
		"path":"C:/PATH/TO/WEBSITE/",
		"404":"/404/"
	},
	"meta":{
		"keywords":"default,keywords,here",
		"description":"default description"
	},
	"opengraph":{
		"fb:admins":"XXXXX",
		"og:type":"article",
		"og:image":"/img/open_graph.png"
	},
	"highlight":{
		"parentClassName":"highlight",
		"shouldWrap":true
	},
	"server":{
		"port":4000
	}
}

which translates as

Running JekyllJS

I compared the generated site using an SVN diff, and aside from the Date and difference in highlighted code, it matches out. If you try it and see something, let me know.

As for running it, you can generate your site using

node app.js | "./node_modules/.bin/bunyan" -o short

from a command line. The bit at the end is just running the output through Bunyan, which is the logging lib I use in the project.

If you want to test your site, JekyllJS will also serve it for you via

node app.js serve | "./node_modules/.bin/bunyan" -o short

which will start a local webserver under the port set in the config. It'll also handle 404 errors with the specified URL.

Get JekyllJS

You can find the code over on Bitbucket, and you can install the dependencies using npm install. Also on site is the liquid code that I use to generate my tags, archive, and feed.xml if it's something interesting to you.

Files

Comments

Submit a comment

* indicates required