Tag clouds in Jekyll - no plugins required
Jekyll has built-in support for tagging of pages and posts, but doesn’t provide any functionality to create tag clouds. Because this is so common, there is a nice plugin for it: jekyll-tagging.
When upgrading to Jekyll 3.3.1 I found that the plugin stopped working. So I decided to cook my own simple solution to get it to work. In this post I’ll shortly explain how I solved it.
Preparations
For the proposed solutions to work, you will have to set a tag_dir variable in your _config.yml:
# Tags
tag_dir: tag
Tag Cloud for a Post
This is the simple one, you can see an example at the bottom of this post. In the post template (_layouts/post.html), you can add:
{% if page.tags != empty %}
<footer>
<p>Read more:</p>
<ul class="tag-list">
{% for tag in page.tags %}
<li><a href="{{ site.tag_dir | prepend: '/' }}/{{ tag | uri_escape }}">{{ tag }}</a></li>
{% endfor %}
</ul>
</footer>
{% endif %}
This simple loop lists the post tags and creates a link to the tag page (see below).
Tag Cloud for your entire Site
This creates a sorted collection of all tags used throughout your site and renders it in a list:
{% assign all_tags = '' | split: ',' %}
{% for post in site.posts %}
{% for tags in post.tags %}
{% for tag in tags %}
{% assign all_tags = all_tags | push: tag %}
{% endfor %}
{% endfor %}
{% endfor %}
{% assign all_tags = all_tags | sort %}
{% assign all_tags = all_tags | uniq %}
<ul class="tag-list">
{% for tag in all_tags %}
<li><a href="{{ site.tag_dir | prepend: '/' }}/{{ tag | uri_escape }}">{{ tag }}</a></li>
{% endfor %}
</ul>
Generating a Tag Page for each tag
When users click a tag, they should see a list of pages that also use that tag (Tag Index). The snippet below creates those pages for you (based on the Category page generator example).
Make a new file _plugins/jekyll-tag-pages.rb:
module Jekyll
class TagPage < Page
def initialize(site, base, dir, tag)
@site = site
@base = base
@dir = dir
@name = 'index.html'
self.process(@name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
tag_title_prefix = site.config['tag_title_prefix'] || 'Tag: '
self.data['title'] = "#{tag_title_prefix}#{tag}"
end
end
class TagPageGenerator < Generator
safe true
def generate(site)
if site.layouts.key? 'tag_index'
dir = site.config['tag_dir'] || 'tag'
site.tags.each_key do |tag|
site.pages << TagPage.new(site, site.source, File.join(dir, tag), tag)
end
end
end
end
end
We also need to provide the Tag Index with a view. The code above expects the view to be in _layouts/tag_index.html. To render the list, use this snippet:
<ul class="archive-list">
{% for post in site.tags[page.tag] %}
<li>
<a href='{{post.url}}'>{{post.title}}</a>
<time datetime='{{post.date | date: "%Y-%m-%d"}}'>{{post.date | date: "%Y-%m-%d" }}</time>
</li>
{% endfor %}
</ul>
That’s a wrap!
That should give you enough information to roll your own custom tag clouds. Feel free to get in touch if you have any questions or suggestions!