Jekyll Capitalize Categories
I just wasted two hours solving a problem caused by throwing away good information.
Jekyll has a site.categories collection that keeps a list of all categories on
a site. As it should. For some crazy reason, though, that list throws away case
formatting. For example, a category called “My Category” would be stored as “my
category” in site.categories.
I iterate over site.categories to build my navigation menu, so I wanted that
case-sensitivity back. I found a hack that works. Keep reading to see my solution.
Note: There is almost certainly a clean fix by adding plugins, but I am using GitHub Pages for my site, and do not control the Jekyll configuration.
The Problem
<ul>
{% for category in site.categories %}
<li>
<a href="/{{ category | first }}.html">{{ category | first | capitalize }}</a>
</li>
{% endfor %}
</ul>This would create a series of links for category pages. Where the first piece of
information stored in a category is its name. So in the case of site.categories
containing the following: ['cat1', 'cat2'] Jekyll would produce:
<ul>
<li>
<a href="/cat1.html">Cat1</a>
</li>
<li>
<a href="/cat2.html">Cat2</a>
</li>
</ul>But let’s use a real-world example and see where this falls apart. Assume we have
the categories “Reading List” and “My Thoughts”. Here, site.categories contains:
['reading list', 'my thoughts']. Note the stripped case.
Our code above would produce:
<ul>
<li>
<a href="/reading list.html">Reading list</a>
</li>
<li>
<a href="/my thoughts.html">My thoughts</a>
</li>
</ul>So note here: the capitalize filter only capitalizes the first character of the
filtered string (not all words.) I could find no combination of filters that gave
me the title-case, camel-case or otherwise solution that I wanted.
Note also: the space in the URL is debatably okay.
The Hacky Solution
So I’ll cut to the chase. I said I found a solution. On the individual post
object inside the site.categories.CATEGORY collection, there is a variable
exposed called category if you use a single category per post.
So basically, if your YAML FrontMatter looks like:
---
title: Jekyll Capitalize Categories
layout: post
category: Jekyll Issues
---Then the post or page element viewing this post will have a post.category
element that has “Jekyll Issues” with correct capitalization.
In my case, I only use the single category: FrontMatter, not the plural. So
all my posts have a post.category.
Ergo:
<ul>
{% for category in site.categories %}
<li>
<a href="/{{ category | first }}.html">{{ category[1][0].category }}</a>
</li>
{% endfor %}
</ul>Produces:
<ul>
<li>
<a href="/jekyll issues.html">Jekyll Issues</a>
</li>
</ul>Note the two different capitalizations. In the category object here, category[0]
is the mangled name (eg- ‘jekyll issues’), category[1] is the list of posts in
that category. Therefore category[1][0] is the first post in a category.
And since each post in my system has a post.category defined by the YAML
FrontMatter: category[1][0].category retrieves the non-mangled category name
from the first post in that category (eg- ‘Jekyll Issues’).
TL;DR
To display the Jekyll category name preserving case (eg- Title Case or whatever):
{% for category in site.categories %}
{{ category[1][0].category }}
{% endfor %}Note: This only works when you use category: in the YAML FrontMatter. If you
use categories: to apply several categories to a post, you’re on your own.
Good luck.