haml による Web サイトの構築

訳あって CMS などを使わない Web サイトの構築をすることになった。とはいえ、今さら html の直書きなんてやってられないということで、haml で記述する簡易システムを作った。

とりあえず、haml を使えるようにということで Gemfile を書く。

source 'http://rubygems.org'

gem 'haml'

haml の gem は bundler によって vendor/bundle にインストールする(gem install bundler でインストールされていることが前提)。

bundle install --path vendor/bundle

オリジナルの haml と自動生成される html はそれぞれ contents/haml, contents/html に書かれるものとし、事前にこれらのディレクトリを作っておく。

mkdir -p contents/h{a,t}ml

ほとんどのページはタイトル以外はヘッダ情報などは変わらないので、用意する haml は 1 行目にタイトルを記述し、2行目以降に内容を記載する。contents/haml/index.haml の例はこんな感じ。haml なので閉じタグか必要ないこと、Ruby のプログラムが内部に書けること、テーブルクラスのデフォルト値などを予め変数で設定しておけることなどができ、html を直接書くよりも便利にサイト管理ができる。

小林研究室 (東京都立産業技術高等専門学校 ものづくり工学科 電気電子工学コース)
.jumbotron
  %h1 小林研究室
  %p
    これはテストページです
%table{ class: default_table_class }
  %thead
    %tr
      %th x
      %th x*x
  %tbody
    - (1..10).each do |i|
      %tr
        %td= i
        %td= i*i

この部分 haml を入力として、正式な haml ファイルを生成する makeHaml.rb という ruby スクリプトを書く。ヘッダには Bootswatch の CSSjQuery と Bootstrap の Javascript のための CDN が記載されている。body の頭に今後さまざまな定数を用意する予定である(今は default_table_class だけ定義している)。また、haml なので読み込んだ部分 haml のインデント調整だけはわすれないようにする。

#! /usr/bin/env ruby
if ARGV.length == 1
  open(ARGV.first) do |f|
    title = f.gets
    print <<"EOL"
!!!
%html
  %head
    %meta{charset: 'UTF-8'}
    %link{href: "https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/flatly/bootstrap.min.css", rel: "stylesheet", integrity: "sha384-XYCjB+hFAjSbgf9yKUgbysEjaVLOXhCgATTEBpCqT1R3jvG5LGRAK5ZIyRbH5vpX", crossorigin: "anonymous"}
    %script{src: "https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"}
    %script{src: "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js", integrity: "sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS", crossorigin:"anonymous"}
    %title #{ title }
  %body
    .container-fluid
      - default_table_class = "table table-bordered table-striped table-hover"
EOL
    for line in f
      print "      #{line}"
    end
  end
end

これらの部品ができてしまえば、該当する haml から html を自動生成するだけである。存在する haml ファイルの中から更新されたものだけを html に変換するように Rakefile を記載する。Makefile と違って動的に依存関係を作成できるので、こんな簡単に書けてしまう。

srcs = Dir::glob('contents/**/*.haml')
dst_hash = srcs.map { |f| [ f, f.gsub(/haml/, 'html') ] }.to_h

dst_hash.each do |k, v|
  desc v
  file v => k do |t|
    exec = "./makeHaml.rb #{k} | bundle exec haml -s #{ v }"
    sh exec
  end
end

task default: dst_hash.values

あとは、このディレクトリで以下のコマンドを実行するだけである。haml ディレクトリを操作し、前回から更新されたものだけが html に変換される。

rake

ローカルで変更を確認したら、git で親リポジトリに push する。親リポジトリでは .git/hooks/post-update を構成しておき、該当のサーバに html ファイル群を rsync で同期する。

以上が今日 2 時間程度で作ったシステム。このシステムのおかげでコンテンツを作るのは楽になったが、中身を考えるのは時間がかかりそうだ。