A little while back I started writing a static website generator in Python. It was taking a while to fully take shape because there's quite a lot to making such a program that can handle blog-style sites well. A few weeks ago I started applying it to a new site I'm developing for my photography business and that helped kickstart the development process again.

A few days ago I came across Jekyll and decided to throw my version away after barely five minutes of reading!

Jekyll is the engine behind "dynamic" GitHub Pages. The Pages feature allows users to publish content by simply pushing it into a GitHub hosted git repository. That content can be static content, or it can be dynamic via Jekyll.

The way Jekyll handles blog-like features and the templating it makes available via Liquid make it almost exactly what I was aiming for with my project.

So what you're looking at is a static site, generated by Jekyll from a bunch of templates and content files. The conversion of posts from the Wordpress database to the flat files was not particularly smooth. I wrote my own exporter because the one that comes with Jekyll doesn't transfer categories and tags, but that does give me the opportunity to show off the syntax highlighting support Jekyll provides via Pygments...

$outputroot = realpath($_SERVER['argv'][1]).'/';

$db = mysql_connect('localhost', 'root', '') or die("Connect failed\n");
mysql_select_db('stutdotnet', $db) or die("Select failed\n");

$query1 = mysql_query('select * from wp_posts where post_type = "post" and post_status = "publish"');

$sql = 'SELECT t.taxonomy, term.name, term.slug FROM wp_term_relationships AS tr INNER JOIN wp_term_taxonomy AS t ON t.term_taxonomy_id = tr.term_taxonomy_id INNER JOIN wp_terms AS term ON term.term_id = t.term_id WHERE tr.object_id = %%ID%% ORDER BY tr.term_order';

while ($row = mysql_fetch_assoc($query1))
    $title = $row['post_title'];
    $slug = $row['post_name'];
    $date = $row['post_date'];
    $content = $row['post_content'];
    $output_filename = $outputroot.array_shift(explode(' ', $row['post_date'])).'-'.$slug.'.markdown';
    $cats = array();
    $tags = array();

    $query2 = mysql_query(str_replace('%%ID%%', $row['ID'], $sql));
    while ($row2 = mysql_fetch_assoc($query2))
        if ($row2['taxonomy'] == 'category')
            $cats[] = $row2['slug'];
        elseif ($row2['taxonomy'] == 'post_tag')
            $tags[] = $row2['slug'];

    $fp = fopen($output_filename, 'wt');

    fwrite($fp, "---\n");
    fwrite($fp, "layout: \"post\"\n");
    fwrite($fp, "title: \"".str_replace('"', '\\"', $title)."\"\n");
    if (count($cats) > 0)
        fwrite($fp, "categories: \n");
        foreach ($cats as $cat)
            fwrite($fp, "- ".$cat."\n");
    if (count($tags) > 0)
        fwrite($fp, "tags: \n");
        foreach ($tags as $tag)
            fwrite($fp, "- ".$tag."\n");
    fwrite($fp, "---\n");
    fwrite($fp, $content);


Related posts

Jekyll comes complete with support for generating lists of related posts (as you'll see at the end of this post). Unfortunately the default implementation is not particularly good. There is a latent semantic indexing option that you can enable, but that increases the time taken to generate this site from ~15 seconds to just under an hour, and the results weren't that much better than the default! The site has ~250 posts so it's not particularly small, but it's not exactly large either. I may look at different ways of doing this, but for now the posts it displays are good enough.


I haven't yet completed the deployment system, but it will work off a post-receive git hook as detailed in the Jekyll docs.


So far I'm loving Jekyll and plan to use it for a few other sites, I only wish I'd found it a long time ago, before I spent so long developing a poor imitation from imagination. Maybe one day I'll learn that most of the ideas I come up with have probably been done already!

blog comments powered by Disqus