公開ルールと検証
公開ルールとアセットをどう扱うか
公開するかどうかは何で決まるか
content.filters.publishStrategy は2つの値を取ります。
| 値 | 公開される条件 | 意味 |
|---|---|---|
explicit(既定) |
frontmatter の publish が true |
公開を明示したノートだけ |
selective |
private と draft のどちらも true でない |
非公開を明示したノート以外すべて |
公開判定は isPublished / isPublishable に集約されており、ノートのレンダリング、診断、prebuild でのアセット収集はすべて同じルールを使います。サイト側で公開判定を独自に実装しないでください。「プレビューでは見えるのに本番には出ない」という食い違いは、そこから生まれます。
Diagram source
flowchart LR
Vault["プライベート Vault"]
Publish{"publish: true?"}
Vault --> Publish
Publish -->|"はい"| Public["公開"]
Publish -->|"いいえ"| NotPublic["非公開"]
プライベート Vault では、既定の explicit が最も理解しやすいモデルです。
exclude はどう書くか
exclude は contentRoot からの相対パス(/ 区切りに正規化)に対して glob パターンを照合します。パターンがパス全体にアンカーされる点に注意してください。
| パターン | 一致する | 一致しない |
|---|---|---|
.obsidian/** |
.obsidian/app.json |
notes/.obsidian/app.json |
**/.obsidian/** |
上記の両方 | — |
Templates/** |
Templates/daily.md |
notes/Templates/daily.md |
**/Templates/** |
上記の両方 | — |
private/** |
private/secret.md |
notes/private/secret.md |
* は1つのセグメント内にとどまり、** はセグメントをまたぎます。同名のフォルダがサブフォルダにも現れる可能性があるなら、**/ を付けると安全です。スキャフォールドの既定値が **/templates/** と **/private/** になっているのはそのためです。
exclude は読み込み前に絞り込むため、除外されたノートはリンク解決やグラフに現れません。非公開にしたいノートは、publish: true を付けないことに加えて、可能ならフォルダごと除外してください。
コンテンツ画像と添付ファイルは公開のされ方が違う
Vault 内のファイルは3種類に分かれ、それぞれ公開する主体が異なります。
| 種類 | 対象 | 公開 URL | 公開する主体 |
|---|---|---|---|
| コンテンツ画像 | 画像(png、jpg、svg など) |
/<Vault からの相対論理パス> |
ビルド(生成物として出力) |
| 添付ファイル / メディア | Markdown でも画像でもないファイル | /assets/attachments/<Vault からの相対論理パス> |
サイト側の prebuild 手順 |
| 静的アセット | サイトアプリケーションが管理するファイル | / 以下の任意の場所 |
Vite の public/ ディレクトリ |
コンテンツ画像については、サイト側で何もする必要がありません。obsidianMarkdown() が公開ページから参照されている画像を、論理パスを保ったままビルド出力に書き出します。開発サーバーも同じ論理パスでコンテンツから直接配信します。どこからも参照されていない画像や、非公開ページだけから参照されている画像は書き出されません。
Diagram source
flowchart LR
Image["コンテンツ画像<br/>assets/logo.png"]
Attach["![[attachments/report.pdf]]"]
Image -->|"ビルドが書き出す"| Public["公開アセット"]
Attach -->|"URL のみ"| Copy["prebuild でコピー"]
Copy --> Public
添付ファイルとメディアは別です。次のような埋め込みは、
![[attachments/report.pdf]]
URL を生成しますが、ファイル自体は公開ディレクトリにコピーされません。サイト側に、公開するファイルだけをコピーする prebuild 手順を追加してください。参照実装は website/scripts/build_images.ts です(prebuild スクリプトから tsx scripts/build_images.ts として呼び出し、public/assets/attachments/ へコピーします)。
この実装の流れは次のとおりです。
contentRootを走査して、画像(IMAGE_EXTENSIONS)と添付ファイル(isAttachmentPath)を列挙します。ContentManagerでコンテンツをビルドし、公開ノートから参照されているアセットだけを集めます。参照元はリンクと、レンダリング後の HTML にあるsrc/hrefです。- 参照されたアセットだけを
public/assets/attachments/<Vault からの相対パス>にコピーします(画像はpublic/<相対パス>にコピーし、初回ビルド前でも開発サーバーが配信できるようにします)。サイズと mtime が変わっていなければコピーを省略します。 - 公開ディレクトリにだけ存在し、コンテンツにない孤立した添付ファイルを削除します。
Diagram source
flowchart TD
Vault["Vault のアセット"]
PublicNotes["公開ノート"]
Referenced["参照されたアセット"]
Copy["コピー"]
Public["公開アセット"]
Vault --> Referenced
PublicNotes --> Referenced
Referenced --> Copy
Copy --> Public
要するに、「Vault にあるからコピーする」のではなく、「公開ノートが参照しているからコピーする」というルールです。Vault 全体をコピーする近道は取らないでください。非公開ノート、非公開ページだけから参照される画像、未参照の添付ファイル、.obsidian のメタデータが漏れる恐れがあります。コンテンツ画像はビルドがすでに絞り込んで出力します。添付ファイルとメディアの公開はサイトアプリケーションの責任なので、公開ノートが参照するファイルだけをコピーします。公開ノートが非公開ノートへリンクして境界を越えていないか確認するには、@riebeckite/plugin-diagnostics の riebeckite-diagnostics を実行してください。該当する参照を publish-boundary 警告として報告します。runDiagnostics() を使えば、同じ結果をプログラムから取得できます。詳しくは 診断 を参照してください。
生成される URL
コンテンツ画像は Vault からの論理パスをそのまま保ちます。
Vault:
assets/logo.png
公開 URL:
/assets/logo.png
添付ファイルとメディアには専用のプレフィックスを付けるため、同名のファイルと画像が衝突しません。
/assets/attachments/<Vault からの相対論理パス>
たとえば、次のようになります。
Vault:
attachments/report.pdf
公開 URL:
/assets/attachments/attachments/report.pdf
attachment()は解決済みの Vault ルートから埋め込みファイルのサイズを読み、ルート外のパスは拒否します。media()は同じ論理パスに対応する音声・動画を描画します。
public/ 下の実際の配置と公開 URL を一致させておくと、ビルド後の 404 を減らせます。
リポジトリの公開範囲と公開境界は別物
リポジトリをプライベートにすることと、Riebeckite が何を公開するかは別の話です。
リポジトリの公開範囲
→ Git リポジトリを誰が読めるか
Riebeckite の公開
→ サイトに何が出るか
プライベート Vault でも、非公開情報を公開出力にコピーするビルドをすれば、それは公開されたことになります。次の3つを揃えてください。
exclude
+
publishStrategy
+
公開ノートだけを対象にしたアセットコピー
特に、Vault 全体を public/ にコピーしないでください。prebuild のコピーが参照済みアセットだけを選ぶ仕組みは前述のとおりです。
ビルド前にルートと公開境界を検証する
ルートと公開境界は、ビルド前に CLI で確認できます。作業ディレクトリに依存しないことは、入れ子のディレクトリから実行すると確かめられます。
cd site/app
npm exec riebeckite check
npm exec riebeckite doctor
npm exec riebeckite inspect config
npm exec -- riebeckite inspect content --list
npm exec riebeckite inspect graph
npm exec riebeckite build
結果は次の順に確認します。
checkは設定とプラグインの取り決めを検証します。doctorは読み取れない、または不正なファイルシステムのコンテンツソースを報告します。inspect configでは、Directoryが解決済みの絶対パス、PublishingがpublishStrategy、Excludeがパターン数です。まずここで、Vault がどこを指しているかを確定させます。- WikiLink や埋め込みを調べる前に、
inspect content --listで期待する論理パスが読み込まれているか確認します。 inspect graphで、除外したノートがノードとして現れていないか確認します。buildは統合とルートのレンダリングを検証します。
Diagram source
flowchart LR
Check["check"]
Doctor["doctor"]
Config["inspect config"]
Content["inspect content"]
Graph["inspect graph"]
Build["build"]
Check --> Doctor
Doctor --> Config
Config --> Content
Content --> Graph
Graph --> Build
作業ディレクトリに依存しないことを確かめる
ルート解決の問題を調べるときは、サイトのルートだけでなく、入れ子のディレクトリからも CLI を実行します。
cd site/app
npm exec riebeckite inspect config
npm exec -- riebeckite inspect content --list
どちらも同じアプリケーションと Vault を解決するはずです。関係のないディレクトリから実行すると、設定ファイル自体が見つからないことがあります。