Your Own Gravity Your Own Gravity     Categories     About     Feed    

Jekyll Categories

I recently implemented categories on this site, which are really acting as tags here. Jekyll supports both, and if you override the default URL scheme in config.yml (which puts a post “under” its category in the URL, e.g. /technology/my-interesting-post – I’m using permalink: /:title/ instead), the difference mostly evaporates. I figured I’d just stick with categories for now.

Anyway, here is how I implemented it. First, a slightly modified categories.rb plug-in from the Jekyll site goes in your _plugins folder:

module Jekyll

  class CategoryPage < Page
    def initialize(site, base, dir, category)
      @site = site
      @base = base
      @dir = dir
      @name = 'index.html'

      self.process(@name)
      self.read_yaml(File.join(base, '_layouts'), 'categories.html')
      self.data['category'] = category

      category_title_prefix = site.config['category_title_prefix'] || 'Category: '
      self.data['title'] = "#{category_title_prefix}#{category}"
    end
  end

  class CategoryPageGenerator < Generator
    safe true

    def generate(site)
      if site.layouts.key? 'categories'
        dir = site.config['category_dir'] || 'categories'
        site.categories.each_key do |category|
          site.pages << CategoryPage.new(site, site.source, 
			File.join(dir, category), category)
        end
      end
    end
  end

end

Next, create a categories.html layout for the categories pages in your _layouts folder:

---
layout: default
---

<article class="page">
  <h3>Category: {{ page.category }}</h3>
  <div>&nbsp;</div>   
  {% for post in site.categories[page.category] %}
    <p><a href="{{ post.url }}">{{ post.title }}</a></p>
  {% endfor %}
</article>

Then add support in the post.html layout to show categories somewhere in your post layout (I put it at the end of the post content):

<article class="post">
  <h1 class="post-title">{{ page.title }}</h1>
  <time datetime="{{ page.date | date_to_xmlschema }}" 
    class="post-date">{{ page.date | date_to_string }}</time>
  {{ content }}
    {% if page.categories != empty %}
        <p class="category">Categories &nbsp;&nbsp; 
        {% for category in page.categories %}
          <a href="/categories/{{ category }}">
            {{ category }}</a> &nbsp;&nbsp;
        {% endfor %}
    {% endif %}
    </p>
</article>

You should now be able to find posts by categories, e.g. /categories/Technology.

Categories    Meta    Technology