詳しく知る
はじめに
本記事では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_article
とprev_article
がセットされ、ディレクトリのindex.html
がビルドされます。この動作はプログラマブルで、少し複雑です。
next_article
はPureBuilder::ACCS::DEFINITIONS[:next]
というProcを使って、prev_articles
はPureBuilder::ACCS::DEFINITIONS[:next]
というProcを使って設定されます。
blessmethod_accs_rel
が設定されている場合、デフォルトのアルゴリズムで設定されます。
デフォルトのアルゴリズムがどのように並び替えて前後を判定するかは、設定値によって異なります。
numbering
はファイル名の先頭部分を数値として並び替えます。
date
はdate
をもとに並び替えます。
timestamp
はtimestamp
をもとに並び替えます。
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/")
["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
によって記事本文とルーターを識別できるようにしています。
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のコードを、cmd
とfilter
は外部コマンドを実行するためのものです。
具体的な使い方はREADMEを参照してください。
Blessはドキュメントのメタデータを編集するための機能でしたが、Hooksはドキュメントそのものを編集したり、ドキュメント以外に作用したりするためのものです。
例えば、pbsimply-searchutils
プラグインはHooksを使って検索インデックスを生成します。