Fork me on GitHub

Started: 16 Jan 2012

This all started when I decided to replace my crufty old wordpress site with a static site, and to have it hosted at GitHub. It made the most sense to use their really nifty program, jekyll, but it really is a blogging platform, and getting it to categorize things the way I want was not straightforward. It can do things like “projects” and such, but you need to write an extension for it, and I didn’t feel like going to all that trouble - which is silly, since I ended up writing what ended up being a huge project!

Next, I took a peek at hyde (original, new version), and I kind of wish I had looked at them more, because StrangeCase has a lot in common with it (them?). Besides, I really wanted a new project to toy with, and I had a vision of a site generator that required zero configuration, and had a minimum set of features, but with which a reasonably complex site could be generated.

The most important thing was for it to be very easy to do few things I wanted:

  • create an index page based on the contents of a (for instance) blogs/ folder.
  • create <img /> tags for all the images in a folder of images.
  • add properties to a file using YAML front matter (this one they both got right, I just imitated it!)
  • add meta data to a config file that is accessible in all the pages.
  • nothing should have to be configured, it should “just work”

I had mixed success. Back in version 1.0 or so, I had something that was just a few files, and could generate Here was the original config file, as of today, 16 Jan 2012:

yaml meta: analytics: 'UA-15076738-1' title: stuff by colinta header: colinta author: name: Colin T.A. Gray github: colinta twitter: colinta

All these configurations are just used in templates. Nothing related to StrangeCase.

But after a while, I needed features, and those features needed more code, and that code neede a refactor. Now I’m at version 4.1.5, and my config.yaml file looks like this:

yaml deploy_path: /var/www/colinta meta: analytics: 'UA-15076738-1' title: stuff by colinta header: colinta author: name: Colin T.A. Gray github: twitter: colinta extensions: - strange_case.extensions.markdown.MarkdownExtension filters: date: markdown: strange_case.extensions.markdown.markdown json: json.dumps sha: strange_case.extensions.hashlib.sha processors: - strange_case.extensions.image - strange_case.extensions.category - strange_case.extensions.paginated - strange_case.extensions.scss

The upside is that StrangeCase is very compartmentalized, and it will be easy, going forward, to add more file types, filters, and extensions.

I’ll illustrate how simple some of the other tasks can be by showing how StrangeCase treats folders of images and pages.

{%- for image in site.static.images -%}
  <img width="100" src="{{ image.url }}" />
{% endfor -%}

The site variable is the root node of a generated site. You can access properties on a node, and you can access its child nodes by name, or by iterating over them. I’m doing both here:

site.static.images refers to the site/static/images/ folder.

for image in site.static.images iterates over the items in the images folder. These are also node objects, and they have a few handy properties, obviously.

So that’s all it takes to iterate over a folder of assets. How about listing the projects/ folder?

{%- for project in site.projects -%}
  {{ project.title }}<br/>
{% endfor -%}

There’s not much more to go over that isn’t in the README, but here goes, since you’re still here and paying attention…

The only file that is special-cased is index.html. This file does not appear in the listing above (there is a file there, though:, if you don’t believe me). This is because index files are more of a textual representation of the folder itself, not so much an entry in the folder. I think this trade off of “special-case” vs “intuitive feature” is a good one.

The thing that, I think, makes StrangeCase of the greatest benefit is that you are always, essentially, working in a tree. And trees are easy. You can talk to your parent page, or prev or next, or your children if you are working with a folder.

This means that if you want to feature a blog on your home page, you just refer to it by name:

<h1>My favorite plugin is <a href="{{ site.projects.move_text.url }}">{{ site.projects.move_text.title }}</a>.</h1>

Here is what the YAML front matter looks like. Really it’s no different from jekyll or hyde, so no surprises here.

files: is a special key in folder config.yaml files. It contains the YAML front matter for files that would otherwise have no way to specify it, like images.

category: project

title: MoveText
header: Sublime Text 2 Plugin

  - Sublime Plugins

about: Select text and drag it around, or setup a text “tunnel” to move code from one location to another.
github: colinta/SublimeMoveText
{% extends 'layouts/project.j2' %}

You have no doubt noticed that there are a few special variables that can go in config.yaml that change things like variables names and deploy locations. But I promise I kept them to a minimum. Or tried to, at least.

  • name: the name you use to reference this page from other pages
  • target_name: the file name to use after the file is copied or rendered

And finally, the name: StrangeCase? As in “The StrangeCase of Dr. jekyll and Mr. hyde”. Which leaves the-of-and if someone wants to kill a weekend writing a static site generator. That’s how long StrangeCase took to write. That should give some indication of how simple it really is.