This is my third article on using the Nanoc3 static site generator. The other topics in this mini-series include

  • Integrating the Compass CSS framework
  • Using Haml templates

This article shows how to create display GitHub Gist’s in Nanoc3. Gists are code snippets hosted on GitHub. I’ve started accumulating a few of them, and I thought it would be cool to list them on my web site.

Nanoc3 includes the concept of DataSources. As the name suggests this is where Nanoc3 sources all of the “items” to display in the site. By default the main data source is the filesystem. All the pages and posts are loaded from the content folder.

Before creating a DataSource I need to load my Gists from GitHub. This can be very easily done using HTTParty. I have placed all of this code within the lib folder of my site as gist_datasouce.rb. You can see the complete code for this on GitHub.

require "httparty"

class Gist
  include HTTParty
  base_uri 'http://gist.github.com/'

  def list(username)
    self.class.get('/api/v1/json/gists/' + username)['gists']
  end

  def contents(id, filename)
    self.class.get('/raw/' + id + '/' + filename)
  end
end

The above code creates a new class called Gist which has two methods:

  • list which returns all the Gists associated with a username
  • contents which returns the content of a specified Gist

Now on to the DataSource…

Firstly extend the Nanoc3::DataSource class and create an identity. Then override the items method. The items method will be invoked by Nanoc3 to obtain a list of new items from this data source.

In the following code I download a list of Gists from GitHub, and for each of them I create a new Gist.

class GistDataSource < Nanoc3::DataSource
  identifier :gist

  def items
    items = []  
    api = Gist.new
    api.list(self.config[:username]).each do |gist|
      attributes = {
        :url => 'http://gist.github.com/' + gist['repo'],
        :title => 'Gist #' + gist['repo'] + ': ' + gist['description'],
        :author => gist['owner'],
        :created_at => gist['created_at'],
        :kind => 'gist'
      }
      items << Nanoc3::Item.new(gist['description'], attributes, '/gist/' + gist['repo'])
    end
    items
  end
end

You may have noticed the config variable. This contains options loaded from the site’s config.yaml file. In this case it is the GitHub username.

The config.yaml file is also used to enable the data source:

data_sources: 
  -
    type: filesystem_unified
    items_root: /
    layouts_root: /
  - 
    type: gist
    config:
      username: 'owengriffin'

With the above code the Gists should be loaded into the site’s collection of items. You’ll need to replace the username with your own.

Now how to display them. Firstly I added the following helper which will return all of Gist items in the site:

def gists
  @items.select { |item| item[:kind] == 'gist' }
end

Then within my site layouts I added the following Haml to my templates:

%h2 Gists
  %ul.gists
    - gists.each do |gist|
      %li.gist
        %a(href="#{gist.path}")= gist[:title]

Last but not least I wanted to create a page for each of my Gists. This required creating a new rule and layout.

All Gist items created by my data source will be placed within the /gists/ path on my site.

compile '/gist/*' do
  filter :kramdown
  layout 'kind_gist'
end

Notice that above I’m using a kind_gist layout. This layout displays the title of the Gist and embeds the Gist into the page using the GitHub’s Javascript code.

#content.tag
  %h2.title
    = item[:title]
  .content
    %script(src="https://gist.github.com/#{item.identifier.match(/\/([0-9]+)/)[1]}.js")

The regular expression just extracts the Gist identifier from the pathname.