静的Webサイト生成に便利なrote
Rubygemsのroteが静的Webサイトの生成に便利です。まだまだ機能は少ないのですが、Railsのレイアウト機能を取ってきた感じなのでRailsやってる人は何となく使い方を把握するのは早いと思います。
`rote create PROJECT_NAME`を実行すると、gem/rote-xxx/lib/rote/project以下がコピーされます。
ディレクトリツリーはこんな感じ。
- / - README - Rakefile : taskを記述するだけでなく生成するファイルの設定ファイルもかねている - doc/ : 生成元のデータを入力したファイルを置くディレクトリ - layouts/ : テンプレート内にテンプレートを埋め込むためのもの - pages/ : メインとなるディレクトリ。アクセスできる各ページはここに置く - res/ : データ変換を行わない画像ファイルやCSSを置くためのディレクトリ - html/ : 生成後のファイルが置かれるディレクトリ。初期は存在しない。
各ディレクトリ名は設定をいじることで変えることもできる。
初期の設定では
- ROOT/pages/index.thtml
- ROOT/pages/index.rb
- ROOT/layout/normal.thtml
があって、ROOT/pages/index.rbの中で
layout "normal"
とすることでROOT/layout/normal.thtmlの中にROOT/pages/index.thtmlが埋め込まれたHTMLが生成されます。
初期の設定では
thtml, textile => Textile (RedCloth) + ERB mhtml, markdown => Markdown (BlueCloth) + ERB rdhtml, rdoc => RDoc + ERB html => ERBのみ
となってます。
とりあえず自分はこれにはてな記法を追加してみました。Rubygemsよりhparserをインストールします。
# libディレクトリを作成しRoteを拡張する # ROOT/lib/rote/filters/hparser.rb require 'rubygems' require 'hparser' require 'rote/filters/base' module Rote module Filters class HParser < TextFilter def initialize *hparser_opts super() @hparser_opts = hparser_opts end def handler text, page hparser = ::HParser::Parser.new hparser.parse(text).map {|e| e.to_html }.join "\n" end end end end
RedClothのスクリプトをまんまパクっただけです。使い方間違ってたらコメントください。
Rakefileに以下の設定を追加します。
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib")) require 'rote/filters/hparser' ws = Rote::DocTask.new(:doc) do |site| # 元々ある行 # この中に書く site.ext_mapping(/hatena/, 'html') do |page| page.extend Format::HTML page.page_filter Filters::HParser.new end end # ここまで
これで*.hatenaファイルの中にはてな記法 + ERBを書いておくと良きに計らって変換してくれます。ただ普通のはてな記法よりも用途的に生でHTMLを書いたりidやclassをいろいろ指定するのでhparserそのままでは少しつらい感じもします。
開発の際はROOT/html以下をルートディレクトリにしてWEBrickを立ち上げてます。これと同時並行してdoc_monitorというファイルの生成の同期をしてくれるタスクがあるのですがこれを使うと保存した内容がすぐWebブラウザから見れるので便利です。ただ、doc_monitorにも難点があって、ちょっとでもテンプレートファイルなどに文法ミスがあるとすぐrakeが死んでしまうためタスクの再起動が煩わしいという問題があります。
ということでここは次のように書き換えてしまいました。
# lib/rote/rotetasks.rb desc "Monitor and automatically rebuild the documentation" task "#{name}_monitor" do loop do begin # 追加 # ... sleep monitor_interval rescue ::SignalException => e # ここから exit rescue ::Exception => e $stderr.puts e.message sleep monitor_interval * 2 next end end end
Exceptionをすべて流してしまうのはあまりよくないんだろうなぁと思いつつこうやってしまいました。
sleep間隔をのばしているのは同じエラーメッセージが頻繁に更新されるのが個人的に嫌だったからです。ただしmonitor_intervalの設定に関わらず2倍にしているので長く設定していればいるほど間隔が空いてしまいます。logとかかけとけばよいのかなと思いつつ詳しいところがわからないので適当に流しておきました。この変更は作者さんにパッチとして送ってみようかと思います。
ところでこのdoc_monitorにはdoc_refreshというタスクがフックとして用意されていて、
このタスクに任意のスクリプトを書いておくとファイルが更新されたときにそのファイルに対してスクリプトを実行させることができます。UsersguideのページではMacのAppleスクリプトを利用してSafariを自動リロードする方法が書かれています。これに関してはruby-osa版とMozRepl使ったやつを後で書きます。
標準状態で使える機能はまだ少ないのですが、RailsのようにERBの中で使える標準のHelperスクリプトが増えればかなり便利に使えるのではないかと思います。また、HTMLだけでなく他の出力形式にも対応すると面白いかなぁとおもいます。
とりあえず個人的にはこんなの欲しいなぁと思っていてちょうどしっくり来たのでもうちょっと使い込んでみようかと思います。