Blessing機能
基礎概念と用法
PureBuilder Simplyはドキュメントのメタデータ、つまりFrontmatterを強く活用します。 Pandocテンプレートからも、eRubyテンプレートからもこのFrontmatterを参照することができ、テンプレートが条件分岐やイテレータのような構造を利用できることで、Frontmatterによって出力内容を根本的に変えることができます。 これにより、ひとつのテンプレートにより、異なる形式の出力を得ることもできます。
PureBuilder Simply自体が、自動的に様々なFrontmatterをセットします。 こうして自動的にセットされる要素が、事前にビルドされるものでありながら、動的な要素をドキュメントに組み込むことができます。
「Bless」はこのFrontmatterにパラメータを動的にセットする処理の拡張です。 Frontmatterを動的に拡張することこそがPureBuilder Simplyの強力さの源であり、それを拡張できる「Bless」は極めて強力な機能です。
Blessを使う方法は、Rubyのライブラリとして実装する方法と、コマンドとして実装する方法があります。
Rubyライブラリとして実装するには、ドキュメントソースルートに.pbsimply-bless.rbというRubyスクリプトファイルを置きます。
このファイルはライブラリとしてロードされ、PureBuilder::BLESSというProcオブジェクトがセットされることを期待します。
Bless時にはPureBuilder::BLESS.call(frontmatter, self)の形式で呼び出され、Frontmatterと、PBSimplyクラスの子孫クラスのインスタンス(PureBuilder
Simplyの本体オブジェクト)にアクセスできます。
そして、この処理の中でfrontmatterを更新することができます。
コマンドとして実装するには、Bless用のコマンドを用意し、設定ファイルのbless_cmdにコマンドをセットします。
bless_cmdはRubyのKernel.systemに渡される値です。コマンドと引数からなる配列とすることも、単にコマンドライン文字列にすることも可能です。
Blessコマンドからは$PBSIMPLY_WORKING_DIR/pbsimply-frontmatter.jsonというパスでFrontmatterにアクセスできます。
Blessを行うには、このファイルを書き換えます。 PureBuilder
SimplyはBlessコマンドを実行後、Frontmatter
JSONファイルを再度読み直してFrontmatterを更新します。
ACCS更新時はbless_accscmdに設定されたコマンドが呼ばれます。
用例
このウェブサイトは日本語と英語に対応しており、各ページで言語切り替えができます。
言語ごとのページは単純に/en/と/ja/という違いによって切り替えられますが、記事本文以外にも言語によって作りが異なっています。
これを実現するために、.pbsimply-bless.rbで次のようにしています。
if frontmatter["source_path"].include?("ja/")
frontmatter["lang"] = "ja"
frontmatter["lang_specific"] = true
frontmatter["lang_ja"] = true
frontmatter["pagelink_en"] = frontmatter["page_url"].sub('/ja/', '/en/')
frontmatter["pagelink_ja"] = frontmatter["page_url"]
elsif frontmatter["source_path"].include?("en/")
frontmatter["lang"] = "en"
frontmatter["lang_specific"] = true
frontmatter["lang_en"] = true
frontmatter["pagelink_en"] = frontmatter["page_url"]
frontmatter["pagelink_ja"] = frontmatter["page_url"].sub('/en/', '/ja/')
else
frontmatter["lang"] = "en"
endlangは$lang$の形で言語を設定できるように、lang_jaやlang_enは$if(lang_ja)$の形で条件分離に使えるようにセットしています。
lang_specificによって記事本文とルーターを識別できるようにしています。
祝福する
Rubyで祝福する
.pbsimply-bless.rbというRubyスクリプトファイルを使うことでFrontmatterに手を加えることができます。
これを使用したい場合、同ファイルでPureBuilder::BLESSProcオブジェクトを定義してください。
このオブジェクトはPureBuilder::BLESS.call(frontmatter, self)のように呼び出されます。
呼び出されるタイミングはシステムによってセットされる値が全てセットされた後です。
この関数は値を返す必要はなく、引数として渡されたFrontmatter Hashオブジェクトを直接変更する形で利用します。
もしも処理中のディレクトリがACCSドキュメントディレクトリである場合、PureBuilder::BLESSのあとでさらにPureBuilder::ACCS::BLESSも(定義されていれば)呼び出されます。
さらにあなたはPureBuilder::ACCS::DEFINITIONS
Hashに対してProc値を追加することができます。
これらはACCSで特定の値を動的にセットするために使われます。
| Key | 動作 |
|---|---|
:next |
戻り値をfrontmatter["next_article"]にセットする |
:prev |
戻り値をfrontmatter["prev_article"]にセットする |
Rubyでの祝福の例
次に示すのはChienomiのblessing scriptです。
#!/bin/env ruby
load "./.lib/categories.rb"
TOPICPATH = {
"" => ["TOP", "/"],
"/articles" => ["Articles", "/#Category"],
"/override" => ["Override", "/"],
"/archives" => ["Old Archives", "/articlelist-wp.html"]
}
ARTICLE_CATS.each do |k,v|
TOPICPATH[["/articles", k].join("/")] = [v, ["", "articles", k, ""].join("/")]
end
PureBuilder::BLESS = ->(frontmatter, pb) {
content = nil
filetype = nil
content = File.read(frontmatter["source_path"])
filetype = File.extname(frontmatter["_filename"])
url = frontmatter["page_url"].sub(/^\.?\/?/, "/")
frontmatter["topicpath"] = []
url = url.split("/")
(1 .. url.length).each do |i|
path = url[0, i].join("/")
if v = TOPICPATH[path]
frontmatter["topicpath"].push({"title" => v[0], "url" => v[1]})
else
frontmatter["topicpath"].push({"title" => frontmatter["title"]})
break
end
end
if frontmatter["category"] && url.include?("articles")
frontmatter["category_spec"] = [ARTICLE_CATS[url[-2]], frontmatter["category"]].join("::")
end
if content
if((filetype == ".md" && content =~ %r:\!\[.*\]\(/img/thumb/:) || (filetype == ".rst" || filetype == ".rest") && content =~ %r!\.\. image:: .*?/img/thumb!)
frontmatter["lightbox"] = true
end
end
}
article_order = nil
rev_article_order_index = {}
PureBuilder::ACCS::BLESS = -> (frontmatter, pb) {
frontmatter["ACCS"] = true
unless article_order
article_order = pb.indexes.to_a.sort_by {|i| i[1]["date"]}
article_order.each_with_index {|x,i| rev_article_order_index[x[0]] = i }
end
}
PureBuilder::ACCS::DEFINITIONS[:next] = ->(frontmatter, pb) {
index = rev_article_order_index[frontmatter["_filename"]] or next nil
if article_order[index + 1]
{"url" => article_order[index + 1][1]["page_url"],
"title" => article_order[index + 1][1]["title"]}
end
}
PureBuilder::ACCS::DEFINITIONS[:prev] = ->(frontmatter, pb) {
index = rev_article_order_index[frontmatter["_filename"]] or next nil
if index > 0
{"url" => article_order[index - 1][1]["page_url"],
"title" => article_order[index - 1][1]["title"]}
end
}他の言語、あるいはコマンドで祝福する
設定ファイルのbless_styleの値としてcmdをセットすると、Ruby
Procの代わりに外部コマンドによって祝福を行います。
bless_cmdは通常の祝福用、bless_accscmdはACCSの祝福用のコマンドを設定します。
いずれの場合も環境変数$PBSIMPLY_WORKING_DIRのディレクトリにあるpbsimply-frontmatter.jsonファイルからドキュメントメタデータを読み取ることができ、同ファイルを書き換えることで変更を反映することができます。
自動的な祝福
いくつかの設定は自動的に予め用意されたメソッドで祝福されます。
これらは設定ファイルにおいて値を設定しておくことで、Blessingフェーズで自動的に処理されます。
ACCSの前後関係
blessmethod_accs_relはnext_articleとprev_articleを設定します。
これらはurlとtitleからなる連想配列です。
numbering (ファイル名先頭の数値),
lexical (ファイル名辞書順), date,
timestampが用意されています。