読者です 読者をやめる 読者になる 読者になる

静的Webサイト生成に便利なrote

Rubygemsroteが静的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だけでなく他の出力形式にも対応すると面白いかなぁとおもいます。

とりあえず個人的にはこんなの欲しいなぁと思っていてちょうどしっくり来たのでもうちょっと使い込んでみようかと思います。