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/")
["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"]
frontmatterelsif frontmatter["source_path"].include?("en/")
["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/')
frontmatterelse
["lang"] = "en"
frontmatterend
lang
は$lang$
の形で言語を設定できるように、lang_ja
やlang_en
は$if(lang_ja)$
の形で条件分離に使えるようにセットしています。
lang_specific
によって記事本文とルーターを識別できるようにしています。
祝福する
Rubyで祝福する
.pbsimply-bless.rb
というRubyスクリプトファイルを使うことでFrontmatterに手を加えることができます。
これを使用したい場合、同ファイルでPureBuilder::BLESS
Procオブジェクトを定義してください。
このオブジェクトは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) {
= nil
content = nil
filetype = File.read(frontmatter["source_path"])
content = File.extname(frontmatter["_filename"])
filetype
= frontmatter["page_url"].sub(/^\.?\/?/, "/")
url ["topicpath"] = []
frontmatter= url.split("/")
url 1 .. url.length).each do |i|
(= url[0, i].join("/")
path if v = TOPICPATH[path]
["topicpath"].push({"title" => v[0], "url" => v[1]})
frontmatterelse
["topicpath"].push({"title" => frontmatter["title"]})
frontmatterbreak
end
end
if frontmatter["category"] && url.include?("articles")
["category_spec"] = [ARTICLE_CATS[url[-2]], frontmatter["category"]].join("::")
frontmatterend
if content
if((filetype == ".md" && content =~ %r:\!\[.*\]\(/img/thumb/:) || (filetype == ".rst" || filetype == ".rest") && content =~ %r!\.\. image:: .*?/img/thumb!)
["lightbox"] = true
frontmatterend
end
}
= nil
article_order = {}
rev_article_order_index
PureBuilder::ACCS::BLESS = -> (frontmatter, pb) {
["ACCS"] = true
frontmatterunless 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 }
article_orderend
}
PureBuilder::ACCS::DEFINITIONS[:next] = ->(frontmatter, pb) {
= rev_article_order_index[frontmatter["_filename"]] or next nil
index 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) {
= rev_article_order_index[frontmatter["_filename"]] or next nil
index 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
が用意されています。