Switching from Blogger to Jekyll was an amazing experience. Everything was quite easy (although not as fast as I thought, it’s always the same). I found only one problem a bit difficult to solve:

I wanted to use the GitHub pages hosting, uploading the Jekyll site source, not the final site, so I could have it everywhere just cloning the repo.

At the same time, I wanted to have categories and tags pages (a page for each tag and category).

I found two solutions to the problem:

  • Using a plugin like this one, which creates the pages. The problem is that GitHub doesn’t accept custom plugins for security reasons.
  • Creating the templates for each tag and category, as explained in this post. The solutions works perfectly on GitHub pages, but a new template has to be created manually every time a category or tag is added to the blog!

So I decided creating a small plugin that pre-generates the templated needed by the second solution. You can create the posts locally, and the templated will be created by the plugin. Then, upload the new post and templates to GitHub and that’s it.

There are two problems:

  • When the Jekyll server is started, new tags or categories won’t be generated on the _site folder. You have to start it again. When adding new tags with the server running, works ok. This could be solved using hooks, I guess, but this feature is not released yet.
  • Files edited directly on GitHub won’t run the plugin, so the new tags or categories won’t appear until the site is generated locally. Without plugins running there, there is no solution for that.

Installation

Copy the following files to the _layouts dir:

blog_by_category.html

---
layout: default
---

<h1>Articles by category :</h1>
<div>
    {% if site.categories[page.category] %}
        {% for post in site.categories[page.category] %}
            <a href="{{ post.url }}/">{{ post.title }}</a>
        {% endfor %}
    {% else %}
        <p>There are no posts for this category.</p>
    {% endif %}
</div>

blog_by_tag.html

---
layout: default
---

<h1>Articles by tag :</h1>
<div>
   {% if site.tags[page.tag] %}
        {% for post in site.tags[page.tag] %}
            <a href={{ post.url }}/>{{ post.title }}</a>
        {% endfor %}
    {% else %}
        <p>There are no posts for this tag.</p>
    {% endif %}
</div>

And the plugin to the _plugins dir:

categories_tags_generator.rb

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module Jekyll
  class TagsGenerator < Generator

    def generate(site)
        tags_dir = Dir.pwd + '/tags'

        if !Dir.exists?(tags_dir)
            puts "Creating tags dir"
            Dir.mkdir(tags_dir)
        end
        regenerate_flag = false

        site.tags.each do |i|
            if !File.exists?(tags_dir + '/' + i[0])
                puts "Creating tag page for: " + i[0]
                tag_file = File.new(tags_dir + '/' + i[0], "w")
                tag_file.puts("---\nlayout: blog_by_tag\ntag: " + i[0] + "\npermalink: /tags/" + i[0] + "/\n---")
                tag_file.close

                regenerate_flag = true
            end
        end

        if regenerate_flag
            FileUtils.touch Dir.pwd+'/_config.yml'
        end



    end
  end
end

Now you will have the url /tags/[name_of_the_tag] and /categories/[name_of_teh_category] pages accessible. There are many ways to create the links to them. To put an example, I create a category list and a tag word cloud using this code in the blog page:

<h1>Categories</h1>
{% for category in site.categories %}

        <a href="{{base_url}}/categories/{{ category | first}}/">
            {{ category | first }}
        </a>
        {% unless forloop.last %}, {% endunless %}

{% endfor %}
<h1>Tags</h1>
<div class="tagcloud">
{% for tag in site.tags %}

    <li style="font-size: {{ tag | last | size | times: 100 | divided_by: site.tags.size| plus: 70 }}%">
        <a href="{{base_url}}/tags/{{ tag | first |downcase | slugize }}/">
            {{ tag | first }}
        </a>

    </li>
{% endfor %}

When in a page, you can use something like this to get all the tag links:

<div class="tags">Tags: {% for tag in post.tags %}
<a href="{{base_url}}/tags/{{ tag |downcase | slugize }}/">{{tag}}</a>
  {% unless forloop.last %}, {% endunless %}
{% endfor %}</div>

Next post will be about maps again!