Chienomi

PureBuilder Simply 3.5リリース

開発::util

PureBuilder Simply 3.5がリリースされた。

3.3から3.4におけては10ヶ月ほど経過しているのに対し、3.4から3.5は3ヶ月と短い。

3.4のときはかなり色々ごたごたして苦戦していた(主にドキュメント英訳関連)ので3.4について解説できていないので、今回は3.4と3.5の両方を解説していきたいと思う。

Version 3.4

3.4はドキュメントの移行が最大の焦点。 ドキュメントを整備する過程で気になった機能も追加された。

ドキュメントの移行

一番のトピックはこれ。 これまでREADMEに技術的な内容、公式サイトにはPR用という形になっていたが、全面的に公式サイトに集約する形になった。

このための整理が大変で、特にリポジトリのドキュメントは古い内容がそのまま残っていたりするため、現在の挙動の精査なども必要だった。

かなり大掛かりな作業になってしまったが、ドキュメント自体は読みやすくなったはずだ。

Pandocの対応ファイルの追加

新たに追加されたpandoc_input_extはソースファイルの拡張子とPandocの-fオプションの値の対応関係を記載する。 こんな感じ

---
pandoc_input_ext:
  mw: mediawiki
  muse: muse

従来は.md.rstのみが対象になっていたが、これによって対象となるソースファイルの拡張子を追加し、任意のフォーマットとして解釈することができる。 .txt.wikiが衝突しやすいためこの方式を採用した。

シンプルな機能だが、この機能があることでPandocのアップデートで対応形式が追加されるごとにPureBuilder Simplyでも自動的に対応可能なフォーマットが増えるという驚異のコスパである。

なお、そもそもdefault filesへのパススルーが可能であるため、PureBuilder Simplyでも勝手にPandocのfiltersが使えるようになっていたりする。

メタデータファイルのファイル名の拡張

従来、メタデータはファイル自体に書く(基本的にMarkdownやReSTのみ)か.meta.${filename}に書くという方式が取られていた。

Pandocでより多くのフォーマットをサポートするようにすると外部メタデータファイル方式が重要になるのだが、従来は拡張子が元のファイル名のものになるためエディタによっては扱いづらいという面があった。

そこで追加で.meta.${filename}.yaml.meta.${filename}.ymlをサポートするようにした。

ちなみに、DockerやKubernetesが使用していることから.yml派が多いようだが、.yamlのほうが公式寄りだ。 PureBuilder Simplyの設定ファイルは.yamlになっている。

CommonMarkerの拡張

設定項目に新たにcommonmarker_optionsが加わり、CommonMarkerに渡すオプションがコントロールできるようになった。これにより、GFMにも対応可能だ。

ちなみに、PureBuilder Simplyは4.0になるときにCommonMarkerをデフォルトにすることが検討されている。

Unicode normalization

設定ファイルにunicode_normalizeが追加され、設定すると最初のドキュメント抽出のときにUnicode normalizationが行われるようになった。

これは、最初にメタデータと本文を分離するという動作があり、ここで本文側に対して行われる。

正規化はソースドキュメントの責務と考えられることもあるが、執筆している環境によっては揺れが発生してしまい、正規化を自動化したいケースがある。 このためのものだ。

値として正規化方式(例: "nfkc")を与えることができる。

Skip update

skip_updateはシステムが使うfrontmatter値として追加されたもの。 この値が真である場合、無条件にmodifiedfalseになる。

-fオプションはこのmodifiedのチェックそのものを行わないので、-fオプションのほうが優先される。

skip_updateは主に、「既に公開している記事の更新作業中」に利用すると良い。 従来、ディレクトリ処理すると既に公開している記事の更新は自動的に反映されてしまい、更新途中だから除外してほしい、ということができなかった。 これを可能にするためのものだ。

Version 3.5

Version 3.5はPureBuilder Simplyを拡張したソフトウェアを想定した機能を2つ追加し、一部リファクタリングを行った。

Preflight

最大の目玉となるのが--preflightというCLIオプションの追加。

Preflight modeでは通常通りドキュメントの処理手順を行い、実際の生成前にリターンする。

つまり、frontmatterの読み取りやblessは行われるが、generateは呼ばれない。

hooksは#generateより前に起動されるものがないため、基本的には呼ばれないが、後述する通り削除は発生するためdeleteは呼ばれる可能性がある。

draftに戻されたケースとソースドキュメントが消失したケースの処理は行われるため、破壊的動作がないわけではない。 (この部分は将来的に見直されるかもしれない。)

これの重要なところは、事前にメタデータの組み上げが可能なことだ。

もし、blessは行わず、テンプレートで他のドキュメントの情報を参照することもないのであれば、この機能は特に意味がない。 重要なのは動的に生成される情報を使用したいときだ。

この場合、生成を2〜3回回す必要がある。 全体のメタデータを必要とするのであれば2回回さないといけないし、全体のメタデータが揃った状態で動的に情報を更新するのであれば3回回さないといけない。

しかも、差分更新すると変更のない部分はメタデータ生成処理自体がスキップされてしまうため、基本的に-fオプションを使う必要がある。 こうなると差分更新が使えないし、特にPandocを使っているとかなり重い。

そこで-pオプションである。

まず、ドキュメント生成をしないのでかなり軽い。

その上で、-pオプションは差分判定はするが、差分がない場合に処理から除外するのではなく、メタデータを維持するという挙動になる。 この差分判定に除外するキーを指定するためにcompr_ex_keysという設定(String[])が追加された。これはblessで動的に設定され、毎回異なる値になるようなキーを指定しておくことで差分判定に介入させないようにする。

また、-pオプションはメタデータ差分がある場合、_modifiedというキーを追加する。 これは差分生成に使用され、生成時に更新がある判定になる。 従来、メタデータを分離すると本文のほうに触らないと更新判定が発生しなかったが、この問題も解消される。

本文の生成がなくてもデータベースを更新して参照したい場合に便利。 そういうニーズはPureBuilder Simply自体にはないが、ウェブアプリに組み込みたいというような場合には必要だろう。

Only ACCS

もうひとつ追加されたのが--only-accsオプション。

これはその名の通り、ACCSインデックスの生成のみを行う。 --skip-accsと組み合わせることでインデックスの生成処理を分離することができる。

単純な機能だが、これもPureBuilder Simplyのフロントエンドを用意したい場合には便利。

Documentクラスの追加

少しややこしい話になるのだが、PBSimplyインスタンスというのはPureBuilder Simplyプロセッサを指している。 ではそのプロセッサがどのような属性を持っているかというと、処理対象である。 これは単一のファイル、またはディレクトリだ。

つまり、PBSimplyインスタンスは処理対象の引数が単位となっている。

が、ディレクトリを指定した場合はそのディレクトリ内のファイルが処理対象になるため、これは複数ある。この処理対象も状態を持つ必要があるため、「処理対象全体の変数」と「処理対象個別の変数」が混在している。 これはあまり良くない。

そこで、これをできるだけ分離するためにPBSimply::Documentクラスが新設された。 これは、従来配列だった個別ドキュメントの状態をクラス化したもので、一部ドキュメント固有の処理もこちらに移された。

名前だとドキュメントコンテンツを持っていそうに思うかもしれないが、PureBuilder Simplyではそれはファイルとして書き出すという約束になっているので持っていない。 Rubyだけで処理するのであれば本文文字列をもたせれば良いのだが、Ruby以外のツールにも渡せるようになっているのと、生成するのもRubyライブラリとは限らないことからだ。

ちなみに、この初期化のために渡す値は5つで、従来よりもちょっと多い。 ドキュメントの数だけ生成することを考えていまのところはそのまま渡しているけれど、これ以上増えるならキーワード渡しにせざるを得ない。

インデックス保持方法の変更

3.4.0のときに、差分更新をする際に差分がないと判定されるとfrontmatterがblessを経由せずに保存され、blessで入れている値を失うという問題があり、これが3.4.1で修正された。

が、一旦更新した上でとっておいたオリジナルから戻すという方法でやっており、だいぶ汚かった。 そこで、更新されたならインデックスも更新するという自然な方式になった。

ここにもPBSimply::Documentが絡んでいて、#frontmatter#orig_frontmatterで取り出せるようになり、全体のインデックスHashを持つ必要がなくなった。

-pオプションでは#effective_frontmatterによって適切なほうを返すようになっている。 こっちに統一しても良いのだが、効率の関係でそうしていない。

attr

attr symbol, boolの形式がdeprecatedだと言うので、attr_reader, attr_accessorに変更された。

どちらかというとattrのほうが望ましいのかと思っていたのだけど……