Meet Jekyll the Static Site Generator - Part 2
2013-03-19Part II
In part 1 I discussed why I chose Jekyll to build this site and presented a high level overview of how Jekyll works. In this post, I'll dive into the depths of Jekyll and show off some of its features.
Liquid Templates
The template engine used by Jekyll is called Liquid. Liquid makes it easy to create a layout and pull in page elements dynamically.
Jekyll will compile content into a page using a layout like this:
// _layouts/default.html
<!DOCTYPE html>
<html lang="en">
<head>
{% include head.inc %}
</head>
<body>
<header>
{% include header.inc %}
</header>
<div id="main">
{{ content }}
</div>
<aside>
{% include sidebar.inc %}
</aside>
</body>
{% include js.inc %}
</html>
Including partials
Jekyll will automatically find includes in the _includes directory.
{% include links.inc %}
Loops and conditionals
Any page that begins with a YAML Front matter block...
---
// predefined default variables
layout: default
category: funny
published: true
tags: cats
// custom variables
context: cats
title: Funny Cats
---
can declare variables which can be accessed in Liquid. This allows the conditional placement of content. For instance, you can place a sidebar on a page based on a context variable...
--snip--
<aside>
{% case page.context %}
{% when 'about' %}
{% include sidebars/about-sidebar.inc %}
{% when 'contact' %}
{% include sidebars/contact-sidebar.inc %}
{% when 'home' %}
{% include sidebars/home-sidebar.inc %}
{% when 'blog' %}
{% include sidebars/blog-sidebar.inc %}
{% else %}
{% endcase %}
</aside>
It's also simple to create a recent posts block with a loop...
<h3>Recent Posts</h3>
<ul>
{% for post in site.posts limit: 6 %}
<li><a href="{{ post.url }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
Site-wide variables can be declared in _config.yml. This is a convenient place to put primary navigation…
// _config.yml
---
nav:
- text: about
url: /about/index.html
- text: resume
url: /resume/index.html
- text: contact
url: /contact/index.html
- text: blog
url: /blog/index.html
Which can be included in the layout
<nav>
{% for link in site.nav %}
{% assign active = nil %}
{% if page.url == link.url or page.layout == link.layout %}
{% assign active = 'class="active"' %}
{% endif %}
<li><a {{ active }} href="/{{ link.text }}/">{{ link.text }}</a>{{ indicator }}</li>
{% endfor %}
</nav>
Plug-ins
Out of the box, Jekyll is well equipped to create a blog with a custom layout, and it has built in support for markdown. But augment Jekyll with plugins and you can start cooking with gas.
Jekyll Asset pipeline
This is an essential plug-in for Jekyll that will compile sass, and also aggregate and compress javascript and css.
~ gem install Jekyll-asset-pipeline
You have to install a compressor. I like the yui-compressor because it will minify both javascript and css.
~ gem install yui-compressor
Once these Ruby gems are installed, enabling the asset pipeline plug-in is as simple as putting a config file inside the _plugins directory. Here's the one I use for this site…
require 'Jekyll_asset_pipeline'
module JekyllAssetPipeline
class SassConverter < JekyllAssetPipeline::Converter
require 'sass'
def self.filetype
'.sass'
end
def convert
return Sass::Engine.new(@content,
:load_paths => ['.','../_assets','_assets/sass','../_assets/sass'],
:syntax => :sass
).render
end
end
class CssCompressor < JekyllAssetPipeline::Compressor
require 'yui/compressor'
def self.filetype
'.css'
end
def compress
return YUI::CssCompressor.new.compress(@content)
end
end
class JavaScriptCompressor < JekyllAssetPipeline::Compressor
require 'yui/compressor'
def self.filetype
'.js'
end
def compress
return YUI::JavaScriptCompressor.new(:munge => true).compress(@content)
end
end
end
The asset pipeline plug-in hooks into Liquid and looks for assets to include
inside the _assets
folder.
Adding javascript looks like this:
{% javascript_asset_tag global %}
- /_assets/js/jquery.js
- /_assets/js/highlight.js
- /_assets/js/init.js
{% endjavascript_asset_tag %}
And css:
{% css_asset_tag global %}
- /_assets/css/normalize.css
- /_assets/screen.sass
{% endcss_asset_tag %}
Including any file ending in .sass will cause asset pipeline to compile the sass into css on site build.
I also like to use a plug-in for sitemap generation.
Just include it in the _plugins
directory and a sitemap will be automatically
generated on site build.
Helpers
Thor is an alternative to Rake. I like to use it as a helper for creating posts and deploying my site. Thor has some nifty features.
~ gem install thor
A Thor task for creating posts:
class Site < Thor
include Thor::Actions
desc "post", "create a new post"
def post
title = ask("Title:")
@title = title
@description = ask("Description:")
@category = ask("Category:")
@date = Time.now.strftime('%Y-%m-%d %k:%M:%S')
filename = "#{Time.now.strftime('%Y-%m-%d')}-#{title.gsub(/\s/, '-').downcase}.md"
template "_thor/templates/post", "_posts/#{filename}"
if ENV['EDITOR']
system("$EDITOR _posts/#{filename}")
else
system("vim _posts/#{filename}")
end
end
end
// Thor template for posts
// lives in _thor/templates
---
layout: post
published: false
date: <%= @date %>
title: <%= @title %>
description: <%= @description %>
category: <%= @category %>
image: <%= @image %>
---
From the command line, run thor site:post and it will prompt for info about
the post - title, description, category and an image - and then create a file
in _posts
and open that file in your editor.
Thor could also be used to run Jekyll, and then rsync
the contents of _site to
a server for easy deployment.
You can also use Jenkins for deployment. For this site, I have the Jekyll stack and Thor installed on my host server. I then use Jenkins to run the thor deploy task which copies the contents of _site into the public html folder on my host. Updating my site is as simple as writing some content, saving that content into version control, and then running the Jenkins build.
Taking this one step further, you could have Jenkins watch a remote repository for changes, and automatically run a build and deploy whenever it sees a change in the code base. That way, the site would be updated every time you pushed changes to your repository.
So go start using Jekyll! Trust me, it's fun...