Jekyll
By Tom Preston-Werner, Nick Quaranto, and many awesome contributors!
Jekyll is a simple, blog aware, static site generator. It takes a template directory (representing the raw form of a website), runs it through Textile or Markdown and Liquid converters, and spits out a complete, static website suitable for serving with Apache or your favorite web server. This is also the engine behind GitHub Pages, which you can use to host your project’s page or blog right here from GitHub.
Getting Started
- Install the gem
- Read up about its Usage and Configuration
- Take a gander at some existing Sites
- Fork and Contribute your own modifications
- Have questions? Post them on the Mailing List
Diving In
- Migrate from your previous system
- Learn how the YAML Front Matter works
- Put information on your site with Template Data
- Customize the Permalinks your posts are generated with
- Use the built-in Liquid Extensions to make your life easier
Dependencies
- RedCloth: Textile support
- Liquid: Templating system
- Classifier: Generating related posts
- Maruku: Default markdown engine
- Directory Watcher: Auto-regeneration of sites
- Open4: Talking to pygments for syntax highlighting
===
Posts are handled in a special way by Jekyll. The date you specify in the
filename is used to construct the URL in the generated site. The example post,
for instance, ends up at
http://tom.preston-werner.com/2008/11/17/blogging-like-a-hacker.html
.
Jekyll also supports specifying the post time in the filename. The format is e.g.
‘2009-04-13_23-45-my-post.html’. Note that the time is prefixed by an underscore,
not a dash, so post slugs starting with numbers won’t be parsed incorrectly.
Times in the filename must be on a 24-hour clock. Times and dates are treated by
Jekyll as local time.
Categories for posts are derived from the directory structure the posts were
found within. A post that appears in the directory foo/bar/_posts is placed in
the categories ‘foo’ and ‘bar’. By selecting posts from particular categories
in your Liquid templates, you will be able to host multiple blogs within a
site.
Files that do not reside in directories prefixed with an underscore are
mirrored into a corresponding directory structure in the generated site. If a
file does not have a YAML preface, it is not run through the Liquid
interpreter. Binary files are copied over unmodified.
Jekyll is still a very young project. I’ve only developed the exact
functionality that I’ve needed. As time goes on I’d like to see the project
mature and support additional features. If you end up using Jekyll for your
own blog, drop me a line and let me know what you’d like to see in future
versions. Better yet, fork the project over at GitHub and hack in the features
yourself!
Example Proto-Site
My own personal site/blog is generated with Jekyll.
The proto-site repo
(http://github.com/mojombo/tpw) is converted
into the actual site
(http://tom.preston-werner.com/)
Install
The best way to install Jekyll is via RubyGems:
$ sudo gem install mojombo-jekyll -s http://gems.github.com/Jekyll requires the gems `directory_watcher`, `liquid`, `open4`,
and `maruku` (for markdown support). These are automatically
installed by the gem install command.
Maruku comes with optional support for LaTeX to PNG rendering via
blahtex (Version 0.6) which must be in
your $PATH along with `dvips`.
(NOTE: the version of maruku I am using is `remi-maruku` on GitHub as it
does not assume a fixed location for `dvips`.)
Run
This will generate the site and place it in /path/to/proto/site/_site. If
you’d like the generated site placed somewhere else:
And if you don’t want to be in the proto site root to run Jekyll:
$ jekyll /path/to/proto/site /path/to/place/generated/siteRun Options
Autobuild
There is an autobuild feature that will regenerate your site if any of the
files change. The autobuild feature can be used on any of the invocations:
Related Posts
By default, the “related posts” functionality will produce crappy results.
In order to get high quality results with a true LSI algorithm, you must
enable it (it may take some time to run if you have many posts):
Code Highlighting
For static code highlighting, you can install Pygments (see below) and then
use that to make your code blocks look pretty. To activate Pygments support
during the conversion:
Markdown Processor
By default, Jekyll uses Maruku (pure Ruby) for
Markdown support. If you’d like to use RDiscount (faster, but requires
compilation), you must install it (gem install rdiscount) and then you can
have it used instead:
Sass
To transform all .sass
files anywhere in your file tree to CSS (e.g. ‘/css/site.sass’ will
generate ‘/css/site.css’):
Haml
To transform .haml files to HTML
(e.g. ‘/about.haml’ will generate ‘/about.html’):
Note that pages and posts must have a YAML metadata block at the top to be
converted. Layouts don’t need to.
Haml content is intentionally not filtered, so you can use any Ruby code.
If you want to define methods you can call from your Haml files, create
a _helpers.rb file in the root of your blog and put the methods there,
inside a module named Helpers.
Jekyll provides some helpers out of the box:
h(string) HTML entity-escapes the input string. link_to(text, url) Creates a link to the URL with the linked text (or markup).Local Server
When previewing complex sites locally, simply opening the site in a web
browser (using file://) can cause problems with links that are relative to
the site root (e.g., “/stylesheets/style.css”). To get around this, Jekyll
can launch a simple WEBrick server (works well in conjunction with —auto).
Default port is 4000:
Permalink Style
By default, the permalink for each post begins with its date in ‘YYYY/MM/DD’
format.
If you do not wish to have the date appear in the URL of each post,
you can change the permalink style to ‘none’ so that only the ‘slug’ part of
the filename is used. For example, with the permalink style set to ‘none’ the
file ‘2009-01-01-happy-new-year.markdown’ will have a permalink like
‘http://yoursite.com/happy-new-year.html’. The date of the post will still be
read from the filename (and is required!) to be used elsewhere in Jekyll.
If you want WordPress-style pretty URLs that leave off the .html, you can
change the permalink style to ‘pretty’ and directories corresponding to the
date parts and post name will be made and an index.html will be placed in the
leaf directory resulting in URLs like 2008/11/17/blogging-like-a-hacker/.
Another way to leave off the .html is to configure Apache with ‘Options +MultiViews’.
Just link to pages without the extension (and without a trailing slash, like ‘/about’).
Then tell Jekyll not to add ‘.html’ when linking to blog posts, like so:
Note that this has no effect with ‘—permalink pretty’ since that makes an index.html
file in a directory.
Configuration File
All of the options listed above can be specified on a site-by-site basis in
a ‘_config.yml’ file at the root of the site’s source. As the filename
suggests, the configuration is given in YAML. As
well as all of the options discussed in the last section, there are a few
additional options:
The default configuration is shown below as in YAML format:
destination: ./_site auto: false lsi: false server_port: 4000 pygments: false markdown: maruku permalink: date maruku: use_tex: false use_divs: false png_dir: images/latex png_url: /images/latexParameters set in a configuration file override the default values. Parameters
set using command line options override both the default values and those set
in a configuration file.
Additionally, you can set defaults for the post data blocks. For example, you
can set the default layout for posts, so you don’t have to specify it in every
post:
Any values set in the actual post will override these defaults.
Data
Jekyll traverses your site looking for files to process. Any files with YAML
front matter (see below) are subject to processing. For each of these files,
Jekyll makes a variety of data available to the pages via Haml or the Liquid
Liquid templating system. The following is a reference of the available data.
Global
Site
Post
YAML Front Matter
Any files that contain a YAML front matter block will be processed by Jekyll
as special files. The front matter must be the first thing in the file and
takes the form of:
--- layout: post title: Blogging Like a Hacker ---
Between the triple-dashed lines, you can set predefined variables (see below
for a reference) or custom data of your own.
Predefined Global Variables
_layouts
directory.
A default layout for posts can be set in the configuration file.
See above.
Predefined Post Variables
Custom Variables
Any variables in the front matter that are not predefined are mixed into the
data that is sent to the Liquid templating engine during the conversion. For
instance, if you set a title
, you can use that in your layout to
set the page title:
<title>{{ page.title }}</title>
Filters, Tags, and Blocks
In addition to the built-in Liquid filters, tags, and blocks, Jekyll provides
some additional items that you can use in your site.
Date to XML Schema (Filter)
Convert a Time into XML Schema format.
{{ site.time | date_to_xmlschema }}becomes
2008-11-17T13:07:54-08:00XML Escape (Filter)
Escape some text for use in XML.
{{ post.content | xml_escape }}Number of Words (Filter)
Count the number of words in some text.
{{ post.content | number_of_words }}becomes
1337Array to Sentence String
Convert an array into a sentence.
{{ page.tags | array_to_sentence_string }}becomes
foo, bar, and bazTextilize
Convert a Textile-formatted string into HTML, formatted via RedCloth
{{ page.excerpt | textilize }}Include (Tag)
If you have small page fragments that you wish to include in multiple places
on your site, you can use the include
tag.
{% include sig.textile %}
Jekyll expects all include files to be placed in an _includes
directory at the root of your source dir. So this will embed the contents of
/path/to/proto/site/_includes/sig.textile
into the calling file.
Code Highlighting (Block)
Jekyll has built in support for syntax highlighting of over 100
languages via Pygments.
In order to take advantage of this you’ll need to have Pygments installed, and
the pygmentize binary must be in your path. When you run Jekyll, make sure you
run it with Pygments support:
To denote a code block that should be highlighted:
{% highlight ruby %} def foo puts 'foo' end {% endhighlight %}
The argument to highlight
is the language identifier. To find the
appropriate identifier to use for your favorite language, look for the “short
name” on the Lexers page.
There is a second argument to highlight
called
linenos
that is optional. Including the linenos
argument will force the highlighted code to include line numbers. For
instance, the following code block would include line numbers next to each
line:
{% highlight ruby linenos %} def foo puts 'foo' end {% endhighlight %}
In order for the highlighting to show up, you’ll need to include a
highlighting stylesheet. For an example stylesheet you can look at
syntax.css. These
are the same styles as used by GitHub and you are free to use them for your
own site. If you use linenos, you might want to include an additional CSS
class definition for lineno
in syntax.css to distinguish the line
numbers from the highlighted code.
Categories
Posts are placed into categories based on the directory structure they are
found within (see above for an example). The categories can be accessed from
within a Liquid template as follows:
{% for post in site.categories.foo %} <li><span>{{ post.date | date_to_string }}</span> - {{ post.title }}</li> {% endfor %}
This would list all the posts in the category ‘foo’ by date and title.
The posts within each category are sorted in reverse chronological order.
Tags
Tags are like categories or topics but not reflected in the URL.
Blog migrations
Movable Type
To migrate your MT blog into Jekyll, you’ll need read access to the database.
The lib/jekyll/converters/mt.rb module provides a simple convert to create
.markdown files in a _posts directory based on the entries contained therein.
You may need to adjust the SQL query used to retrieve MT entries. Left alone,
it will attempt to pull all entries across all blogs regardless of status.
Please check the results and verify the posts before publishing.
Typo 4+
To migrate your Typo blog into Jekyll, you’ll need read access to the MySQL
database. The lib/jekyll/converters/typo.rb module provides a simple convert
to create .html, .textile, or .markdown files in a _posts directory based on
the entries contained therein.
You may need to adjust the code used to filter Typo entries. Left alone,
it will attempt to pull all entries across all blogs that were published.
This code also has only been tested with Typo version 4+. Previous versions
of Typo may not convert correctly. Please check the results and verify the
posts before publishing.
TextPattern 4
To migrate your TextPattern blog into Jekyll, you’ll need read access to the MySQL
database. The lib/jekyll/converters/textpattern.rb module provides a simple convert to create .textile files in a _posts directory based on
the entries contained therein.
The hostname defaults to localhost, all other variables are needed
You may need to adjust the code used to filter entries. Left alone,
it will attempt to pull all entries that are live or sticky.
Contribute
If you’d like to hack on Jekyll, start by forking my repo on GitHub:
http://github.com/mojombo/jekyll
To get all of the dependencies, install the gem first. The best way to get
your changes merged back into core is as follows:
- Clone down your fork
- Create a topic branch to contain your change
- Hack away
- Add tests and make sure everything still passes by running `rake`
- If you are adding new functionality, document it in README.textile
- Do not change the version number, I will do that on my end
- If necessary, rebase your commits into logical chunks, without errors
- Push the branch up to GitHub
- Create an issue on mojombo/grit with a description and link to your branch
License
(The MIT License)
Copyright © 2008 Tom Preston-Werner
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.