Paginated Archives in Nanoc 4.x

Created on 2020-09-01T05:02:12.799917

Return to the Index

This card can also be read via Gemini.

Uses the preprocess hook to find all site entries which are articles, sorts them by creation date, and creates archive pages which are paginated.

The archive pages are generated as though the user had written them in markdown by hand.

#!/usr/bin/env ruby

compile '/**/*.html' do
  layout '/default.*'

  if item.identifier =~ '**/index.*'
    write item.identifier.to_s
  else
    write item.identifier.without_ext + '/index.html'
  end
end

# This is an example rule that matches Markdown (.md) files, and filters them
# using the :kramdown filter. It is commented out by default, because kramdown
# is not bundled with Nanoc or Ruby.
#
compile '/**/*.md' do
  filter :erb # or erubis, if you need moar speed
  filter :kramdown
  layout '/default.*'

  if item.identifier =~ '**/index.*'
    write item.identifier.to_s
  else
    write item.identifier.without_ext + '/index.html'
  end
end

compile '/**/*' do
  write item.identifier.to_s
end

layout '/**/*', :erb

preprocess do
    # find all articles
    poasts = @items.find_all do |e| e[:kind] == 'article' end
    # sort oldest article first
    oldpoasts = poasts.sort_by do|p| p[:'created-at'] end
    # zip so we have an array of [post index, item]
    # then group by index modulo entries per page
    # we can then iterate over grouped indices to create the paginated archives
    per_page = 1
    pages = (0..oldpoasts.length-1).zip(oldpoasts).group_by do |e| e[0] % (per_page+1) end
    pages.each do |index, page|
        # since item.path is not known until routing is done, we have to
        # engage in brain melting UwU. we output some eruby that injects
        # the path of the item being listed, later, when the archive page
        # is being compiled
        text = page.collect do |index, item|
            <)
MARKDOWN
        # the newline is implied because MARKDOWN is on its own line
        end

        # now create navigation pointers, but use unshift so they are at the top
        if index > 0 then
            text.unshift "- [Previous](/metapoast/poast-#{index-1})\n"
        end
        if index < pages.length-1 then
            text.unshift "- [Next](/metapoast/poast-#{index+1})\n"
        end

        @items.create(text.join("\n"), {}, "/metapoast/poast-#{index}.md")
    end
end