これまでrestructured textでコンテンツを記述していたサイトを
リプレースしようということで、nanocを使ってみた。
Rubyで書かれていて、それなりにメンテされていて、ドキュメントもある、という観点でnanocを選択。
同様のプロダクトについては以下にいろいろあるのでnanoc以外を調べたい人には参考になるかも知れない。
ただし、あんまり活発ではないのも結構含まれている。
http://nanoc.stoneship.org/docs/1-introduction/
さて、静的なHTMLを生成するのに以下のようなことができればとりあえず満足。
- 適当な記法でコンテンツを記述したい(nanocだとMarkdown)
- 英語/日本語のコンテンツを用意したい
- 言語ごとにディレクトリを切らずに同一階層に置きたい
- パンくずリストは必須
nanocでMarkdownを有効にするには生成されるRulesを以下のように編集すれば良い
compile '*' do if item.binary? # don't filter binary items else filter :kramdown filter :erb layout 'default' end end
英語/日本語のコンテンツを同階層に置きたい、というのはちょっとやっかい。
というのも、そもそもnanocはディレクトリに複数のHTMLが生成されるのを基本的には良しとしないポリシーらしいから。
そのあたりは nanoc create_itemを実行して雛形を生成してみるとよくわかる。
各ディレクトリにはindex.htmlだけが許容される。
以前はconfig.yamlにno_dirsというオプションが指定できたようなのだが、3.xではバッサリ削除されている。
ゆえにnanocとしては例えば/about.htmlと/about/index.htmlはitem.identifierだと同じ扱いになってしまう。
それでは今回は困るので、以下のようにしてコンパイル元のファイルを:content_filenameから取得して
/about.htmlになるのか、/about/index.htmlが生成されるのかを判定してあげるコードを追加することにした。以下は厳密には正しくないけどおおむね目的は達成できる。
ちなみにこれもRulesに記述する。
route '*' do if item.binary? # Write item with identifier /foo/ to /foo.ext p item item.identifier.chop + '.' + item[:extension] else # Write item with identifier /foo/ to /foo/index.html if item.identifier == "/" then ret = "/index.html" elsif item.attributes[:content_filename] =~ /^content(\/.*index.ja)\.md$/ then ret = $1 + ".html" elsif item.attributes[:content_filename] =~ /^content\/(.+index)\.md$/ then ret = item.identifier + "index.html" else ret = item.identifier.chop + ".html" end ret end end
ちなみにnanocのサイトには多言語サイトの例があるけど、そっちは
en/とかディレクトリを切る方法なので今回は採用しなかった。
http://nanoc.stoneship.org/docs/6-guides/#creating-multilingual-sites
config.yamlに allow_periods_in_identifiers: trueを追記しておかないと、foo.ja.mdなんかはnanoc compileで処理できないので注意。
あとはパンくずリストの実現。とりあえず以下のようなのをlayouts/default.htmlに入れておけば
上位階層からそれっぽいのが生成される。
これを入れるときはlib/default.rbにてinclude Nanoc::Helpers::Breadcrumbsを忘れずに。
<% breadcrumbs_trail.each do |crumb| %> <% if crumb != breadcrumbs_trail[0] %> > <% end %> <%= link_to(crumb[:title], crumb.reps.find { |r| r.name == :default }) %> <% end %>