Case Insensitive Category Posts Count in Jekyll

Last modified: 07 May 2017

Summary

Some of your posts have category names with different cases, example: HTML5, html5 and Html5. This will definitely happen when you have different users contributing to your Jekyll site.

The code here will pull all those posts and group them by the same category name regardless of it’s letter casing. An example output would look like this:

html5(10) animation(3) smoke effect(2) responsive(10) videos(5)

Installing

  1. Create a _plugins folder if one does not exist yet.
  2. Create a new file category_posts_count.rb
  3. Copy and paste the code below
  4. In your page/post, render them with {% render_categories_posts_count %}

category_posts_count.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
33
34
35
36
37
module Jekyll
  class RenderCategoriesPostsCountTag < Liquid::Tag
    def render(context)
      site_categories = context['site.categories']
      # prepare an array of hash to group the posts by categories
      # the keys are the lowercased category names, the values are the array of posts
      groups = {}
      for category in site_categories
        # group them by lowercasing the category names
        # this will effectively put all posts by same category name regardless of their category case
        category_name = category.first.downcase
        # create the array if it hasn't existed yet
        groups[category_name] = [] unless groups[category_name]

        # index 1 is where all the posts lives
        # (index 0 is the category name)
        groups[category_name] << category[1]
      end

      # using Boostrap 3.x classes to inline the lists
      html = '<div class="navbar-collapse collapse">'
      html += '<ul class="list-inline pull-right">'
      groups.each do |category_name, posts|
        posts.flatten!
        # slugify the path
        category_path = category_name.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
        html += '<li>'
        html += "<a href=\"/category/#{category_path}\">#{category_name} <span class=\"badge\">#{posts.count}</span></a>"
        html += '</li>'
      end
      # and return the HTML
      html + '</ul></div>'
    end
  end
end

Liquid::Template.register_tag('render_categories_posts_count', Jekyll::RenderCategoriesPostsCountTag)

A few technical notes

I use Bootstrap 3 so you can see the classes I use inlines the lists and floats it to the right.

To generate the category pages, I use the Jekyll Archive plugin.