`transclude` は、`:::include{file="./path.md"}` ディレクティブで別の Markdown / MDX ファイルを埋め込む機能です。Obsidian の `![[path]]` ウィキリンク構文とは異なり、`<include>` コンポーネントをレンダリングする仕組みでもありません。mdast の visitor チェーンの先頭で対象ファイルを解析し、その AST を元の文書へ差し込んだあと、通常の Markdown パイプラインで処理します。

:::danger[transclude を有効にしてから include を記述]

`transclude` はデフォルトで無効です。無効なままだと、zfb は解析済みの段落、つまり `Text(":::include")` とそれに続く `MdxTextExpression` を変換せずに残します。式に保持された生の属性文字列 `file="./x.md"` は正しい JavaScript ではないため、コンパイル後の JSX モジュールが壊れ、SSR は 500 を返します。原因は機能が無効なことであり、レンダラー不足ではありません。そもそも `<include>` コンポーネントは設計上存在せず、必要もありません。

ライブディレクティブを書く前に、`zudoDoc({...})` で `transclude: true` を設定してください。パッケージが管理する `markdown.features` ブロックを直接設定してはいけません。

:::

## 設定

zudo-doc の設定で transclude を有効にします。

```ts title="zfb.config.ts"
import { defineConfig } from "zfb/config";
import { zudoDoc } from "@takazudo/zudo-doc/config";

export default defineConfig(
  zudoDoc({
    transclude: true,
  }),
);
```

zudo-doc が公開する設定は boolean で、デフォルトは `false` です。一方、zfb の `transclude` はオブジェクト型の Markdown 機能であり、`true` という省略記法を受け付けません。そのため `zudoDoc()` は、有効時に `markdown.features.transclude: {}` へ内部変換します。このショーケースでは設定を有効にしているため、次の例もサイトをビルドするたびに実行されます。

## include の動作例

次の一文は、ページとしてルーティングされない専用の Markdown ファイルから取り込まれています。検証用の目印がビルド後の HTML に現れるため、単にビルドが成功しただけでなく、AST が実際に差し込まれたことまで確認できます。

:::include{file="../../transclude-fixtures/transclude-live-demo-ja.md"}

## ディレクティブ構文

基本の include です。パスは、このディレクティブを記述したソースファイルを基準に解決されます。

```md
:::include{file="./snippets/intro.md"}
```

ファイルを通常のフェンスコードブロックとして取り込みます。`code=true` を指定してもタイトルバーは付きません。

```md
:::include{file="./examples/hello.rs" code=true lang="rust"}
```

1 始まりで両端を含む行範囲を指定します。`lines` の値は正確に `N-M` の形式でなければなりません。

```md
:::include{file="./src/lib.rs" code=true lang="rust" lines="10-30"}
```

ディレクティブにラベルを付けてはいけません。`:::include[Title]{file="./snippet.md"}` は transclude 構文に一致せず、上記と同じ不正な式による SSR エラーを引き起こします。

## ファイルシステムとエラー処理の制約

- 対象ファイルは実在する必要があり、パスはソースファイルからの相対パスで指定します。絶対パスとエイリアスは使えません。
- パスを正規化したあとも、対象はプロジェクトルート内に収まっていなければなりません。パストラバーサルでもシンボリックリンクでも、この境界を越えることはできません。
- transclude の処理に失敗すると、原因が不正なパス、`lines` の範囲、深すぎる再帰、循環参照のいずれであっても、必ずビルドエラーになります。`linkValidation` のような警告のみのモードはありません。
- include したファイルから別のファイルをさらに include できますが、再帰は深さ 5 までです。循環参照は、この上限に達する前でも必ず検出されます。
- Markdown にブロック要素として認識させるため、ディレクティブの前後には空行が必要です。

## ビルドコンテキストが必要

transclude の処理には、ソースファイルのパスとプロジェクトのファイルシステムが必要です。コンテキストを持たない `@takazudo/zfb-md-wasm/render` のパイプラインでは何も起こらず、この機能のテストには使えません。実際の `zfb build` または `zfb dev` を実行し、取り込んだ固有の内容がレンダリング結果に含まれることまで確認してください。