Justkez

Trying to be a consistent blog 
« Back to blog

Generating a Tag Cloud in Jekyll

The term category and tag are used interchangeably throughout this posting; they are assumed to be the same thing.

Having recently adopted Jekyll to power this website, I have been doing a bit of hacking/extending to get some added features in. A few days ago it was integrating Twitter with Jekyll, and now it's generating a tag cloud.

Back in July, Alex Young blogged about his Jekyll migration, and thoughtfully included a link to some code he wrote to list all posts broken out by category/tag.

I wanted to take this a bit further, and generate a per-category page which listed all the postings for that category, but also to generate a tag cloud.

Generating tag pages

After making a few changes to Alex's code, I ended up with a tag stub in a Rakefile which loops through all the categories used on the site and generates a static HTML page with a list of all the postings in that category.

Remember that this code snippet requires you to define your per-post categories in the YAML header of each post, e.g.

    categories:
  - jekyll
  - blog
  - ruby
  

(You need to mkdir tags in your Jekyll directory before executing the code below)

Now, the Rakefile segment:

    desc 'Generate tags page'
task :tags do
  puts "Generating tags..."
  require 'rubygems'
  require 'jekyll'
  include Jekyll::Filters
  
  options = Jekyll.configuration({})
  site = Jekyll::Site.new(options)
  site.read_posts('')
  site.categories.sort.each do |category, posts|
    html = ''
    html << <<-HTML
---
layout: default
title: Postings tagged "#{category}"
---
    <h1 id="#{category}">Postings tagged "#{category}"</h1>

    html << '<ul class="posts">'
    posts.each do |post|
      post_data = post.to_liquid
      html << <<-HTML
        <li>#{post_data['title']}</li>
      HTML
    end
    html << '</ul>'
    
    File.open("tags/#{category}.html", 'w+') do |file|
      file.puts html
    end
  end
  puts 'Done.'
end
  

There is also a gist here

Now you can run rake tags and it will generate a number of HTML files in the tags/ subdirectory; regenerating through Jekyll will then copy these files over to your site. Navigating to /tags/jekyll.html should list all your Jekyll related posts.

Generating your tag cloud

The below snippet does something similar, but just loops through each category and counts the number of tagged postings. It then does some very rudimentary font-size scaling to make the more popular tags bigger.

    puts 'Generating tag cloud...'
require 'rubygems'
require 'jekyll'
include Jekyll::Filters

options = Jekyll.configuration({})
site = Jekyll::Site.new(options)
site.read_posts('')

html =<<-HTML
---
layout: default
title: Tag cloud
---

<h1>Tag cloud</h1>

    HTML

    site.categories.sort.each do |category, posts|
      html << <<-HTML
      HTML
      
      s = posts.count
      font_size = 12 + (s*1.5);
      html << "twitter?) with any queries or improvements, or post a comment below.

Comments (9)

Feb 21, 2010
Mark Hansen said...
Hey, Thanks! This was a really helpful post :) I used it to make a category list on my site.

But, you haven't closed the first 'HTML' heredoc. I forked the [gist](http://gist.github.com/310771) and made the change.

Cheers! :)

Feb 21, 2010
Mark Hansen said...
Also, the second code section seems to be cut off halfway through?
Apr 12, 2010
Bill Powell said...
Hi! Thanks very much for sharing these code snippets! But as Mark mentioned, it looks like the "tag cloud" snippet is unfinished/broken. Could you post it? I'm new to Ruby, and would love to see this in full.

Also, the first snippet is missing a closing "HTML". But I figured out where to put it. :)

Apr 13, 2010
kez said...
Bill, Mark -

Rather lazily, I have pasted the correct rakefile segment here: http://gist.github.com/364416

The cloud_basic generates a small tag cloud suitable for embedding in a navigation sidebar. The cloud generates a page in "tags/index.html" with a full size cloud. The tags generates a "tag/{category}/index.html" page for each tag.

Let me know if you run into any troubles.

kez.

Apr 15, 2010
Bill Powell said...
Hmm, I replied via email, but in case posterous didn't catch it -- thanks for the quick fix, kez! The snippet looks good.
May 06, 2010
Millisami said...
When I run the rake task `rake tags`, I get the following error:
=======================================
[~/rails_apps/jekyll_apps/nepalonrails (design)⚡] ➔ rake tags -t
(in /home/millisami/rails_apps/jekyll_apps/nepalonrails)
** Invoke tags (first_time)
** Execute tags
Generating tags...
Configuration from ./_config.yml
rake aborted!
uninitialized class variable @@site_url in Object
/home/millisami/rails_apps/jekyll_apps/nepalonrails/Rakefile:92
/home/millisami/rails_apps/jekyll_apps/nepalonrails/Rakefile:81:in `each'
/home/millisami/rails_apps/jekyll_ap
=======================================

Jekyll version 0.5.7

May 06, 2010
kez said...
Whoops. Updated the gist: http://gist.github.com/364416

@@site_url is a variable you declare to put absolute URLs in the tag pages; for some reason or another (can't remember), this was not coming through from the Jekyll config hash.

May 06, 2010
kez said...
(Absolute URLs are theoretically better for SEO)
May 08, 2010
Millisami said...
Thanks, now it works.!! :)

Leave a comment...

 
Got an account with one of these? Login here, or just enter your comment below.
Posterous-login    twitter