概要
以下のようなYAMLファイル(publication.yaml
)を食わせて、
-
title: How to write web sites with slim
author: R. Robota, T. Tanaka
journal: Ruby Journal
year: 2010
volume: 10
page: 1-7
arxiv: 1234.56789
-
title: Using YAML file with slim
author: R. Robota
journal: Journal of Slim
year: 2018
volume: 8
page: 1275
-
title: This is a sample file for Slim and YAML
author: S. Yaml, T. XML and R. Robota
journal: J. Yaml. Phys.
year: 2017
volume: 3
page: 12-18
arxiv: 1908.01234
以下のようなHTMLを吐くSlimテンプレートのサンプルです。
ソースは以下においておきます。
何をしたいか
論文リストとかそうですが、とりあえずなんかリストがあり、それを静的なHTMLにしたい、ということはよくあります。とりあえず論文リストはJSONかYAMLで用意されてるとしましょう。これをHTMLにしたい。さほど更新頻度も高くないので、CMSとかデータベースを導入するほどでもない、でもHTMLを直書きするのは嫌だ、という気持ち、わかっていただけますよね?
で、どうしましょう。
そういう用途では、とりあえずPHPでゴリゴリ書いちゃう、という方法が考えられます。PHPはそれが本職の言語なので、わりとまっとうな気がします。
もしくはJSON+JavaScriptというのもありな気がしますね。JSのテンプレートエンジンは豊富にあるので、好きなのを使ってなんとかする、というのが最近では良い気がします。
ですが、個人的に母国語がRubyということもあって、Rubyスクリプトの埋め込みができる軽量テンプレートエンジン、Slimを使うことにします。
Slimとは
Slimは軽量テンプレート言語です。おそらくRuby on Railsと一緒に使われることが多いと思いますが、ローカルでHTMLを吐くのにも使えます。日本語の公式ドキュメントがわかりやすいので、使うのは簡単だと思います。
Rubyとgemが入っていればSlimのインストールは簡単です。
$ sudo gem install slim
このあと、
$ slimrb -v
とかやってバージョン情報が出てきたらインストールされています。
例えば、
doctype html
html
head
title My first Slim
body
h1 This is test
h2 Hello Slim
こんなファイルを作って、
$ slimrb test.slim
とslimに食わせると、
<!DOCTYPE html><html><head><title>My first Slim</title></head><body><h1>This is test</h1><h2>Hello Slim</h2></body></html>
と、HTMLにしてくれます。-p
オプションをつけると人間が読みやすい形にしてくれます。
$ slimrb -p test.slim
<!DOCTYPE html>
<html>
<head>
<title>My first Slim</title>
</head>
<body>
<h1>
This is test
</h1>
<h2>
Hello Slim
</h2>
</body>
</html>
さて、Slimの特徴は、Rubyスクリプトをそのまま埋め込めることです。ハイフン-
のあとにRubyスクリプトが書けます。また、=
を使って、HTML要素にRubyの実行結果を代入できます。たとえば変数a
を定義して、h1
に突っ込むにはこうします。
doctype html
html
head
title My first Slim
body
- a = "Hello"
h1 = a
<!DOCTYPE html>
<html>
<head>
<title>My first Slim</title>
</head>
<body>
<h1>
Hello
</h1>
</body>
</html>
上記のようにa
に代入された値を、h1
要素に突っ込むことができました。
また、配列などに対してeach
を使い、その要素を列挙できます。
doctype html
html
head
title My first Slim
body
ol
- ["Dog", "Cat", "Cow"].each do |animal|
li = animal
これをslimrbに食わせるとこんなHTMLになります。
<!DOCTYPE html>
<html>
<head>
<title>My first Slim</title>
</head>
<body>
<ol>
<li>
Dog
</li>
<li>
Cat
</li>
<li>
Cow
</li>
</ol>
</body>
</html>
リストとeachのからみは直感的なので、特に苦労することはないと思います。
YAMLから論文リストを作る
まずはナイーブに作る
ではいよいよYAMLで書かれた論文リストからHTMLにしましょう。とりあえず
- タイトル
- 著者
- ジャーナル情報
- (もしあれば)arXivへのリンク
を出力することにします。
RubyはYAMLを読み込めば、それがそのままハッシュとして使えるので、先程のeachの例を参考にすれば簡単に書けます。
doctype html
html
- require 'yaml'
head
title Publication List
body
h1 Publication List
ol
- YAML.load_file("publication.yaml").each do |d|
li :dl
dt = d["title"]
dd == "#{d["journal"]}, <strong>#{d["volume"]}</strong>, #{d["page"]} (#{d["year"]})"
dd = d["author"]
- if d.has_key? "arxiv"
dd == "<a href=\"https://arxiv.org/abs/#{d["arxiv"]}\">arXiv:#{d["arxiv"]}</a>"
事前にrequire 'yaml'
しておき、YAML.load_file("publication.yaml")
でYAMLファイルをロードして、each
でそれぞれのアイテムを表示します。if
文も使えるので、特に難しいことはありませんが、テンプレートとしてはかなり読みづらいので、少し修正しましょう。
ハッシュアクセスをプロパティっぽくする
いちいちd["title"]
とか書くより、d.title
と書きたいものです。Hashie
を使えばできるっぽいのですが、なぜかローカルで動かなかったので、Hash
クラスにメソッドを追加してしまいましょう。
class Hash
def method_missing(method, *args)
key = method.to_s
if self.has_key? key
self[key]
else
false
end
end
def
存在しないメソッドを読んだら、そのメソッド名のキーがあればその値を、そうでなければfalse
を返す関数を作ってやります。これにより、slimファイルはこんな感じになります。yaml
をrequireした後に自分で作ったmyhash.rb
をrequireしています。
doctype html
html
- require 'yaml'
- require './myhash.rb'
head
title Publication List
body
h1 Publication List
ol
- YAML.load_file("publication.yaml").each do |d|
li :dl
dt = d.title
dd == "#{d.journal}, <strong>#{d.volume}</strong>, #{d.page} (#{d.year})"
dd = d.author
- if d.arxiv
dd == "<a href=\"https://arxiv.org/abs/#{d.arxiv}\">arXiv:#{d.arxiv}</a>"
生のハッシュっぽさが消えて、少し読みやすくなりました。
そうそう、Slimでは普通にHTMLタグを使うとエスケープされてしまいます。それを防ぐためには=
ではなく==
を使います。
もう少しすっきりさせる
少し読みやすくなったものの、まだ"#{d.journal}, <strong>#{d.volume}</strong>, #{d.page} (#{d.year})"
みたいなのがあって嫌です。これもmyhash.rb
に逃がしてしまいましょう。
class Hash
def journal_ref
"#{journal}, <strong>#{volume}</strong>, #{page} (#{year})"
end
def arxiv_ref
"<a href=\"https://arxiv.org/abs/#{arxiv}\">arXiv:#{arxiv}</a>"
end
def
これで、slimファイルはこんな感じになります。
doctype html
html
- require 'yaml'
- require './myhash.rb'
head
title Publication List
body
h1 Publication List
ol
- YAML.load_file("publication.yaml").each do |d|
li :dl
dt = d.title
dd == d.journal_ref
dd = d.author
- if d.arxiv
dd == d.arxiv_ref
だいぶすっきりしましたね。
まとめ
軽量テンプレート言語Slimを使って、ローカルでYAMLファイルから論文リストを作ってみました。知っている人には簡単なのでしょうが、そのものずばりのサンプルがなくてちょっと苦労したのでここに公開しておきます。
ずいぶん昔、文献リストをXMLで管理していたことがありました。その時に「RubyとYAMLでやれば楽じゃない?」と言われたのですが、当時はPerlを使っていてRubyを使えなかったのと、将来XSLTを使う予定があったので、その時はXMLを選びました。でもXSLTは(僕には)難易度が高く、そのうち第一言語がRubyになったので、結局Ruby+YAMLでなんかすることが多くなりました(YAMLで履歴書とか)。
Slimは簡単で、かつRubyが埋め込めるので、HTMLを手書きに近い管理をしていて、かつRubyistな人(つまり私のような人)にはお勧めです。