詳しく知る

はじめに

本記事ではPureBuilder Simplyをより深く使うために必要な知識を俯瞰的に紹介します。

個々の詳しい仕様についてはREADMEを参照してください。

プロジェクトとドキュメントルート

PureBuilder SimplyではMarkdownやReSTなどのドキュメントを置く「ドキュメントソースルート」と、PureBuilder Simplyによってビルドされたファイルを配置する「ドキュメントビルドルート」のふたつのディレクトリを扱います。

v3.2.1まではpbsimplyコマンドはドキュメントソースルートにおいて実行することになっていました。 v3.2.2でこの点が変更され、ドキュメントソースルート以下のどこにいても実行できるようになりました。 ただし、これはドキュメントソースルート上で実行されたとみなされるだけなので、ドキュメントソースルートにおいて実行することが依然として推奨されます。

ドキュメントソースルートはシンプルに、.pbsimply.yamlファイルが置かれているディレクトリです。対して、ドキュメントビルドルートは.pbsimply.yamlで設定されたディレクトリです。

.pbsimply.yamlのデフォルト設定ではビルドディレクトリとして../Buildを指定しているため、ドキュメントソースルートとドキュメントビルドルートは同じディレクトリに存在する状態がデフォルトです。 これを便宜上、PureBuilder Simplyのプロジェクトディレクトリと呼んでいます。しかし、プロジェクトディレクトリを設置しなければならないという制約はありません。

pbsimplyコマンド

pbsimplyコマンドはRubyの実行ファイルで、RubyGemsでインストールされた場合はGems実行ファイルになります。場合によっては、RubyGemsのbinディレクトリをパスに含める設定が必要です。

pbsimplyコマンドには-f, -I, -A, -o FILE, -m FILEのコマンドラインオプションがありますが、ほとんどの場合使うのは-fだけです。

pbsimplyはファイルの編集を検出し、文書、またはメタデータに変更があった場合のみビルド処理を行います。こうしなければ、1つの記事を更新するたびに同一ディレクトリ内のすべての記事をビルドする必要があり、時間がかかってしまいます。

-fオプションをつけた場合、更新がないと判定された場合でもビルドします。

-fオプションが必要となるのは、テンプレートを更新した場合です。 pbsimplyはテンプレートの更新を検出しないため、テンプレートを更新した後は-fオプションをつけてすべての記事をビルドし直す必要があります。

サブディレクトリとACCS

pbsimplyに与える引数は、ファイル、またはディレクトリです。 ファイルを与えた場合はそのファイルだけをビルドし、ディレクトリを与えた場合はそのディレクトリに含まれるすべてのファイルをビルドします。 ディレクトリを指定した場合も、再帰的なビルドは行わず、単一層のディレクトリがひとまとまりの記事群として扱われます。

ドキュメントソースルート以下のディレクトリ構成は、静的ファイルとしてサーブする場合はそのままパス構成になりますが、ビルドと管理の利便性を考えると適切にディレクトリ分けするのが好ましいと言えます。

PureBuilder Simplyにおいてディレクトリ単位で扱うのが好ましい最大の理由がACCSです。

ACCSは「一連の記事」を扱うためのPureBuilder Simplyの機能です。 .accs.yamlが置かれたディレクトリをビルドすると自動的に有効になります。

ACCSが有効になると、自動的にfrontmatterにnext_articleprev_articleがセットされ、ディレクトリのindex.htmlがビルドされます。この動作はプログラマブルで、少し複雑です。

next_articlePureBuilder::ACCS::DEFINITIONS[:next]というProcを使って、prev_articlesPureBuilder::ACCS::DEFINITIONS[:next]というProcを使って設定されます。

blessmethod_accs_relが設定されている場合、デフォルトのアルゴリズムで設定されます。 デフォルトのアルゴリズムがどのように並び替えて前後を判定するかは、設定値によって異なります。 numberingはファイル名の先頭部分を数値として並び替えます。 datedateをもとに並び替えます。 timestamptimestampをもとに並び替えます。 lexicalはファイル名を辞書順で並び替えます。

ACCSのindex.htmlをビルドするのに使われるのが、ACCSディレクトリ、またはドキュメントソースルートに置かれた.accsindex.erbというeRubyファイルを用いて行われます。 どちらも存在しない場合、デフォルトのeRubyテンプレートが用いられます。

デフォルトのACCSテンプレートはcategoryで分類し、dateによって並び替えます。 categoryはACCSのデフォルト機能で利用されますが、PureBuilder Simply組み込みの(上書き不可能な)機能では利用されません。

また、デフォルトのACCSテンプレートでは設定ファイルのaccs_orderによって、昇順・降順を切り替えることができます。

ドメイン固定絶対パス

PureBuilder Simplyで構成されるファイルは、一般的なCMSほどファイル配置・パスに制限がなく、ユーザーが自由に構成することができます。 このため、PureBuilder Simplyがパスを勝手に補完することをしません。

PureBuilder Simplyのソースを編集するとき、ドキュメントソースルートは仮想的な/になります。 そして、ソースドキュメントのリンクにおける/は、ドメインのルートになります。 https://www.example.com/がドキュメントビルドルートと等しいのであれば、ドキュメントソースルートを/とみなして、/から始まるリンクを書くことですべての箇所で整合性が取れます。

例えばドキュメントソースルートを起点としてimg/logo.pngがあるとします。 この画像を貼るには

![ロゴ](/img/logo.png)

と書くことでリンクできます。

また、この形式で書いた場合、Visual Studio Code (=VSCode)(あるいはCode OSS)ではファイルパスに対して補完が効き、マークダウンプレビューでも表示されるため便利です。

もしウェブサーバー上の公開パスがルートにないサブパスである場合、例えばhttps://www.example.com/fooのような場合は方法がふたつあります。 そのうち、より簡単で便利なのは、ドキュメントソースルートに公開パスと同じサブディレクトリを用意することです。

pbsimply-initを使って構成されたファイルをhttps://www.example.com/fooに合わせるには、次のようなファイル配置になります。

.accsindex.erb
.pbsimply.yaml
foo/articles/.accs.yaml
foo/articles/20231028-untitled.md
foo/css/style.css
foo/index.md
menu.yaml
template.erb

このように配置されたファイルをビルドすると、ドキュメントビルドルートにはfooだけが作られ、すべてのビルドファイルはfoo以下に作られます。 画像などのファイルもfoo以下に配置するようにしましょう。

これでfooディレクトリの中身を公開ソースのルートにアップロードすれば、整合性が保てます。

/から始まるパスで書いた場合の問題点は、ビルドしたHTMLファイルをローカルファイルとして開いて確認することができないことです。 PureBuilder Simplyではこのような確認のためにpbsimply-testserverコマンドを用意しています。 このコマンドをドキュメントソースルートで実行することでローカルのwebサーバーが起動し、ビルドしたファイルがサーブされます。

Bless

基礎概念と用法

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"
  end

lang$lang$の形で言語を設定できるように、lang_jalang_en$if(lang_ja)$の形で条件分離に使えるようにセットしています。 lang_specificによって記事本文とルーターを識別できるようにしています。

Hooks

HooksはPureBuilder Simplyの処理中に呼ばれる追加のRuby関数です。 Hooksを使えば、PureBuilder Simplyの処理に追加の挙動を加えることができます。

Hooksを設定するには、ドキュメントソースルートの.pbsimply-hooks.rbによって、PBSimply::Hooks.load_hooksを定義します。 Blessと違い、Rubyでのみ書くことができます。

load_hooksには引数としてHooksオブジェクトが渡されます。 Hooksオブジェクトはpre, post, process, deleteのアクセサメソッドを持ち、いずれもタイミングオブジェクトが返ります。

タイミングオブジェクトは、add, <<, cmd, filterという4つのメソッドを持っています。add<<はRubyのコードを、cmdfilterは外部コマンドを実行するためのものです。

具体的な使い方はREADMEを参照してください。

Blessはドキュメントのメタデータを編集するための機能でしたが、Hooksはドキュメントそのものを編集したり、ドキュメント以外に作用したりするためのものです。 例えば、pbsimply-searchutilsプラグインはHooksを使って検索インデックスを生成します。

最終更新日: 2024-03-31