Skip to content

Instantly share code, notes, and snippets.

@stympy
Created May 23, 2011 13:05
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save stympy/986652 to your computer and use it in GitHub Desktop.
Save stympy/986652 to your computer and use it in GitHub Desktop.
Archive generator plugin for jekyll
# Jekyll archive page generator with pagination.
#
# Based on the category generator from
# http://recursive-design.com/projects/jekyll-plugins/,
# which is copyright (c) 2010 Dave Perrett,
# http://recursive-design.com/ and is licensed under the MIT
# license (http://www.opensource.org/licenses/mit-license.php), and
# on the pagination code from Jekyll itself.
#
# This code is copyright (c) 2011 Benjamin Curtis, and is licensed
# under the MIT license.
#
# A generator that creates archive pages for jekyll sites.
#
# To use it, simply drop this script into the _plugins directory of your Jekyll site. You should
# also create a file called 'archive_index.html' in the _layouts directory of your jekyll site
# with the following contents (note: you should remove the leading '# ' characters):
#
# ================================== COPY BELOW THIS LINE ==================================
# ---
# layout: default
# ---
#
# {% for post in paginator.posts %}
# {% include post.html %}
# {% endfor %}
#
# <p class="navigation">
# {% if paginator.next_page %}
# <span class="alignleft"><a href="/archives/{{ page.year}}/{{ page.month }}/page/{{ paginator.next_page }}/">« Previous Entries</a></span>
# {% endif %}
#
# {% if paginator.previous_page %}
# {% if paginator.previous_page > 1 %}
# <span class="alignright"><a href="/archives/{{ page.year}}/{{ page.month }}/page/{{ paginator.previous_page }}/">Next Entries »</a></span>
# {% else %}
# <span class="alignright"><a href="/archives/{{ page.year}}/{{ page.month }}/">Next Entries »</a></span>
# {% endif %}
# {% endif %}
# </p>
# ================================== COPY ABOVE THIS LINE ==================================
#
# You can alter the _layout_ setting if you wish to use an alternate layout, and obviously you
# can change the HTML above as you see fit.
#
# When you compile your jekyll site, this plugin will loop through the list of archives in your
# site, and use the layout above to generate a page for each one with a list of links to the
# individual posts.
#
# Included filters :
# - archive_links: Outputs the list of archives as <link> tags for use in the <head>
# - archive_selects: Outputs the list of archives as <option> tags for use in a navigation drop-down box
#
# Available _config.yml settings :
# - archive_dir: The subfolder to build archive pages in (default is 'archives').
# - archive_title_prefix: The string used before the archive name in the page title (default is
# 'Archive: ').
module Jekyll
# The ArchiveIndex class creates a single archive page for the specified archive.
class ArchiveIndex < Page
# Initializes a new ArchiveIndex.
#
# +base+ is the String path to the <source>.
# +archive_dir+ is the String path between <source> and the archive folder.
def initialize(site, base, archive_dir, year, month)
@site = site
@base = base
@dir = archive_dir
@name = 'index.html'
self.process(@name)
# Read the YAML data from the layout page.
self.read_yaml(File.join(base, '_layouts'), 'archive_index.html')
# Set the year and month for this page
self.data['year'] = year
self.data['month'] = month
# Set the title for this page.
title_prefix = site.config['archive_title_prefix'] || 'Archive: '
self.data['title'] = "#{title_prefix}#{year} &raquo; #{Jekyll::Filters::Months[month.to_i]}"
# Set the meta-description for this page.
meta_description_prefix = site.config['archive_meta_description_prefix'] || 'Archive: '
self.data['description'] = "#{meta_description_prefix}#{year} #{month}"
end
end
# The Site class is a built-in Jekyll class with access to global site config information.
class Site
# Creates an instance of ArchiveIndex for each archive page, renders it, and
# writes the output to a file.
#
# +archive_dir+ is the String path to the archive folder.
# +archive+ is the archive currently being processed.
def write_archive_index(archive_dir, posts, year, month)
index = ArchiveIndex.new(self, self.source, archive_dir, year, month)
pages = Pager.calculate_pages(posts, self.config['paginate'].to_i)
(1..pages).each do |num_page|
pager = Pager.new(self.config, num_page, posts, pages)
if num_page > 1
newpage = ArchiveIndex.new(self, self.source, archive_dir, year, month)
newpage.pager = pager
newpage.dir = File.join(archive_dir, "page/#{num_page}")
self.pages << newpage
else
index.pager = pager
end
end
index.render(self.layouts, site_payload)
index.write(self.dest)
# Record the fact that this page has been added, otherwise Site::cleanup will remove it.
self.pages << index
end
# Loops through the list of archive pages and processes each one.
def write_archive_indexes
if self.layouts.key? 'archive_index'
dir = self.config['archive_dir'] || 'archives'
posts_by_year_month = self.posts.inject({}) do |h, post|
((h[post.year] ||= {})[post.month] ||= []) << post
h
end.each do |year, months|
months.each do |month, posts|
self.write_archive_index(File.join(dir, year, month), posts.reverse, year, month)
end
end
# Throw an exception if the layout couldn't be found.
else
throw "No 'archive_index' layout found."
end
end
alias_method :original_site_payload, :site_payload
def site_payload
pl = original_site_payload
pl['site']['archives'] =
self.posts.inject(Hash.new(0)) do |h, post|
h["#{post.year}/#{post.month}"] += 1
h
end
pl
end
end
# Jekyll hook - the generate method is called by jekyll, and generates all of the archive pages.
class GenerateArchives < Generator
safe true
priority :low
def generate(site)
site.write_archive_indexes
end
end
class Post
def year
@year ||= date.strftime("%Y")
end
def month
@month ||= date.strftime("%m")
end
end
# Adds some extra filters used during the archive creation process.
module Filters
Months = %w(None January February March April May June July August September October November December)
# Outputs a list of archives for archive links in the head
#
# +archives+ is the list of archives to format.
#
# Returns string
def archive_links(archives)
archives.keys.sort.reverse.collect do |path|
year, month = path.split('/').map(&:to_i)
%Q{<link rel="archives" title="#{Months[month]} #{year}" href="/archives/#{path}/" />}
end
end
# Outputs a list of archives for archive select options in the sidebar
#
# +archives+ is the list of archives to format.
#
# Returns string
def archive_selects(archives)
archives.sort.reverse.collect do |path, count|
year, month = path.split('/').map(&:to_i)
%Q{<option value="/archives/#{path}/"> #{Months[month]} #{year} &nbsp;(#{count})</option>}
end
end
end
end
@cheshire137
Copy link

I get the following error when I try to start my Jekyll server:

% jekyll serve --trace
Configuration file: /myjekyllsite/_config.yml
            Source: /myjekyllsite
       Destination: /myjekyllsite/_site
      Generating... /Users/me/.rvm/gems/ruby-2.0.0-p353/gems/jekyll-1.4.3/lib/jekyll/generators/pagination.rb:182:in `initialize': undefined method `config' for #<Hash:0x007fca5a8717a8> (NoMethodError)
  from /myjekyllsite/_plugins/generate_archives.rb:103:in `new'
  from /myjekyllsite/_plugins/generate_archives.rb:103:in `block in write_archive_index'
  from /myjekyllsite/_plugins/generate_archives.rb:102:in `each'
  from /myjekyllsite/_plugins/generate_archives.rb:102:in `write_archive_index'
  from /myjekyllsite/_plugins/generate_archives.rb:130:in `block (2 levels) in write_archive_indexes'
  from /myjekyllsite/_plugins/generate_archives.rb:129:in `each'
  from /myjekyllsite/_plugins/generate_archives.rb:129:in `block in write_archive_indexes'
  from /myjekyllsite/_plugins/generate_archives.rb:128:in `each'
  from /myjekyllsite/_plugins/generate_archives.rb:128:in `write_archive_indexes'
  from /myjekyllsite/_plugins/generate_archives.rb:161:in `generate'

@digin8
Copy link

digin8 commented Feb 8, 2014

Hi, thanks for this, but I get this error with jekyll build and jekyll serve:

/Users/admin/.rvm/gems/ruby-2.1.0/gems/jekyll-1.4.3/lib/jekyll/generators/pagination.rb:96:in `ceil': Infinity (FloatDomainError)

What does this mean?

@phocks
Copy link

phocks commented Aug 11, 2014

I am getting this error. Script is perhaps not compatible with the latest version?

jekyll 2.2.0 | Error: uninitialized constant Jekyll::Site::Pager

@efung
Copy link

efung commented Aug 24, 2014

The pagination stuff was moved to its own gem in Jekyll 2.1.0. So the class is now Jekyll::Paginate::Pager.

@scotthso-zz
Copy link

So how do we fix @phocks error?

@niksmac
Copy link

niksmac commented Jan 7, 2016

@scotthso, replace Pager with Jekyll::Paginate::Pager

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment