Nanoc のカスタマイズ - 年月毎の記事のアーカイブを用意する

Written by @dr_taka_n at 2010/07/25 16:12:45 [, ]

Nanoc で年月毎の記事のアーカイブを表示できるようにする。

年月毎のページ(Item)を取得し表示する

まずは、年月毎のページ(Item)を取得するためのヘルパーを用意する。

lib/helper.rb に以下のヘルパーを追加する。

lib/helper.rb:

def articles_by_year_month
  result = {}
  current_year = current_month = hash_of_year = items_of_the_month = nil

  sorted_articles.each do |article|
    d = Date.parse(article[:created_at])

    if current_year != d.year
      current_month = nil
      current_year = d.year
      hash_of_year = result[current_year] = {}
    end

    if current_month != d.month
      current_month = d.month
      items_of_the_month = hash_of_year[current_month] = []
    end

    items_of_the_month << article
  end
  result
end

def mm_str_month(month)
  sprintf("%02d", month)
end

articles_by_year_month により、{ 年 => { 月 => [Item の配列] } } というデータ構造の Hash が取得できるようになる。 より具体的には、{ 2010 => { 5 => [item1, item2], 6 => [item3, item4] } } となる。

上記で取得されるデータから、全ての記事の中から年月毎の記事の一覧を表示する部分を追加していく。

部分テンプレートとして、layouts/_articles_by_year_month.html ファイルを作成し、以下のコードを記述する。

layouts/_articles_by_year_month.html

<% articles_by_y_m = articles_by_year_month %>

<ul>
<% articles_by_y_m.keys.sort_by{|e| -e}.each do |year| %>
  <% articles_by_y_m[year].keys.sort_by{|e| -e}.each do |month| %>
    <li>
      <%= link_to("#{year}/#{mm_str_month(month)}", "/archives/#{year}/#{mm_str_month(month)}/") %>
      (<%= articles_by_y_m[year][month].size %>)
    </li>
  <% end %>
<% end %>
</ul>

上記の部分テンプレートを表示するために、layouts/default.html に記載されているサイドバー部分に表示部分を追加しておく。

<div id="sidebar-wrapper">
  <h2>Archives</h2>
    <%= render('_articles_by_year_month') %>
  ...

これで、記事の年月とその件数、年月毎の記事一覧を表示するためのリンク先(e.g. /archives/2010/06/)までは表示できるようになった。このサイトでいうと、以下の部分。

Nanoc Archives By Year Month

次に、記事一覧を表示するためのページを用意する。

年月毎の記事一覧を表示するためのページ(Item)を動的に生成する

同じタグを持つページの一覧を表示する際に実施した方法(Nanoc のカスタマイズ - タグを管理する)で年月毎の記事一覧も用意することにする。

RulespreprocessItem を動的に生成することにする。

ロジック自体は、helper に切り出しておく。

lib/helper.rb:

def create_year_month_archive_pages
  articles_by_year_month.each do |year, month_hash|
    month_hash.each do |month, articles|
      month_str = sprintf("%02d", month)
      items << ::Nanoc3::Item.new(
        "<%= render('_archive_by_year_month', :year => #{year}, :month => #{month}) %>",
        { :title => "Archives: #{year}/#{month_str}", :is_hidden => true },
        "/archives/#{year}/#{month_str}/",
        :binary => false
      )
    end
  end
end

上記の Item インスタンス生成の際に使用している部分テンプレート _archive_by_year_month は、以下の内容となる。

layouts/_articles_by_year_month.html:

<h2>Archive: <%= year %>/<%= mm_str_month(month) %></h2>

<ul>
<% articles_by_year_month[year][month].each do |article| %>
  <li>
    <%= link_to(article[:title], article.path) %><br />
    <span class="meta">
          <%= render('_summary_meta_info', :item => article) %>
    </span>
  </li>
<% end %>
</ul>

Rulespreprocess メソッドのブロックに以下の記載を追加し、年月毎のページの一覧を表示するための Item を動的に生成する。

preprocess do
  ...
  create_year_month_archive_pages
end

以上で完了となる! このサイトでいうと、以下の部分。

Nanoc Arhive Page

参考サイト

関連記事

  1. 静的な Web サイト生成ツール Nanoc 基本編 - まずは試してみる
  2. Nanoc のカスタマイズ - 最近の記事一覧の表示
  3. Nanoc のカスタマイズ - タグを管理する
  4. Nanoc のカスタマイズ - 年月毎の記事のアーカイブを用意する
blog comments powered by Disqus