# テンプレートページ

> テンプレートページのMarkdown。ページテンプレートを指定するコロン4つのページフェンス、テンプレートの枠へ内容を送る枠とslot属性、絵のアンカーにラベルを置く図、そして内容をテンプレートと照らし合わせる警告

- HTML版: https://postext.dev/ja/docs/composed-pages
- 最終更新: 2026-10-16
- 読了時間: 9分
- 他の言語: [en](https://postext.dev/en/docs/composed-pages.md), [es](https://postext.dev/es/docs/composed-pages.md), [ca](https://postext.dev/ca/docs/composed-pages.md), [de](https://postext.dev/de/docs/composed-pages.md), [fr](https://postext.dev/fr/docs/composed-pages.md), [it](https://postext.dev/it/docs/composed-pages.md), [pt](https://postext.dev/pt/docs/composed-pages.md), [zh](https://postext.dev/zh/docs/composed-pages.md), [ar](https://postext.dev/ar/docs/composed-pages.md)

## かんたんな説明

ページの中には、1段の本文ではなく、いくつもの枠を組み合わせてできているものがあります。たとえば教科書のページで、題名の帯と本文があり、写真の付いた色付きの囲みが3つ並んでいるようなものです。Postextはこうしたページをテンプレートページと呼びます。ページの形は設定の中のテンプレートが決め、Markdownにはどの文章をどの枠に入れるかだけを書きます。このページでは、ページフェンス、枠、スロットの名前、地図の地名のようにラベルを付けた絵という、そのMarkdownの書き方を説明し、文章とテンプレートが合わないときにPostextが出す警告も挙げます。

**ページの形はテンプレートが持ち、Markdownは中身を持って、それぞれをどの枠に入れるかを示します。**

テンプレートページは、テンプレートから組むページです。テンプレートには名前の付いた枠（題名の帯、本文、写真の付いた囲み）、まとめて動くグループ、飾りがあり、すべて設定の`pageTemplates`に定義します。ページのMarkdownはフェンスで囲んだブロックで、使うテンプレートを名指しし、内容を名前で各枠に流し込みます。Markdownに位置や大きさを書くことはなく、設定に本文の文章を書くこともありません。ですから翻訳は、同じテンプレートに別の言葉を入れたものになります。

このページでは、Markdownと、そこからページがどう組まれるかを扱います。テンプレートそのもの（枠、大きさ、スタイル、飾り）は[設定 › テンプレートページ](https://postext.dev/ja/docs/configuration-composed-pages.md)で説明しています。テンプレートページのない文書は、これまでとまったく同じに組まれます。

## ページフェンス

```md
::::page{template="tema-cajas" fondo="banda-retos"}
# La actividad económica y el dinero

Las personas utilizan :chip[recursos]{style="clave"} que se obtienen de la naturaleza…
::::
```

テンプレートページは、**コロン4つ**に`page`と属性を続けた行で始まり、**同じ数のコロン**だけの行で閉じます。中では、コロン3つのコンテナー（`:::frame`、`:::callout`、`:::figure`、`:::columns`、`:::paper`）がいつもどおり開いて閉じるので、単独の`:::`はそのうちいちばん内側のものを閉じ、ページを閉じることはありません。コロン5つで書いたページ（`:::::page`）は5つで閉じ、その中ではコロン4つの行はただのテキストです。

| 属性 | 働き |
| --- | --- |
| `template="…"` | 必須。`pageTemplates`の項目のIDです。 |
| `spread` | ページを向かい合う2ページの見開きにします。テンプレートも見開き用でなければなりません。 |
| `id="…"`、`#id` | アンカーです。これを指す`:ref`は、テンプレートページが入ったページの番号を印字します。 |
| その他の属性 | テンプレートが`{attr.name}`として読む値です。たとえばページごとに選ぶ背景の絵なら、ページに`fondo="banda-retos"`、飾りに`resourceId: "{attr.fondo}"`と書きます。 |

テンプレートページはいつも新しいページ（または見開き）から始まり、閉じるフェンスの後のテキストは次のページから始まります。

コロン3つの`:::page{split=…}`はコミックのページで（[漫画](https://postext.dev/ja/docs/comics.md)を参照）、その意味は変わりません。`template=`を持つコロン3つの`:::page`もコミックのページとして読まれ、警告`pageFenceLength`がテンプレートページにはコロンが4つ要ることを知らせます。

フェンスが欠けていても、パーサーはテキストを失わずに立て直します。

- 開いたままのページは章の終わりまで続き、開始行で閉じていないコンテナーとして報告されます。
- ページが開いている間に`::::page`の行が現れると、まずそこで開いているページを閉じます（同じように報告されます）。
- 閉じるフェンスは、ページの中でまだ開いている枠やボックスをすべて閉じ、その一つ一つを報告します。
- コロンの数が違う閉じるフェンスは、そのページのものではありません。テキストに残るので、目で確かめられます。

## 枠とスロット

```md
:::frame{slot="dinero" label="El dinero"}
Es el instrumento utilizado como medio de pago…

Hasta hace pocos años, lo más normal era pagar con dinero en **efectivo**…
:::
```

**スロット**は、内容が求める行き先の名前で、テンプレートの枠の名前と対応します。`:::frame{slot="…"}`は、中のものをすべてその枠に送ります。中身には、段落、リスト、見出し、チップ、`::resource`の埋め込み、`:ref`の参照、脚注、`:::columns`、入れ子の囲みなど、どんなMarkdownでも書けます。`label`と`title`は、`:::callout`と同じく、枠のタブや見出しの文字を与えます。枠の見た目は、テンプレートがその枠に割り当てた囲みスタイルで決まります。

1つのブロックが自分でスロットを名乗ることもできます。

| ブロック | 書き方 |
| --- | --- |
| 見出し | `## Retos {slot="retos-titulo"}` |
| リソースの埋め込み | `::resource{id="dinero-pago" slot="dinero-fotos"}`（2つの属性はどの順でもかまいません） |
| コードブロック | `````js {slot="codigo"}`` |
| ボックスやその他のコンテナー | `:::callout{type="nota" slot="aside"}`：ボックス全体がスロットに入ります |
| 図 | `:::figure{resource="mapa" slot="mapa"}`（下記を参照） |

内容は次のように振り分けられます。

- 同じスロットを持つ複数の内容は、Markdownの順につながります。
- スロットのない内容は、テンプレートの**流し込み枠**（`flow`の付いた枠）に入ります。
- スロットのない見出しは、テンプレートにその見出しのレベルを受け取る枠（`takes: "h1"`）があれば、まずそこに入ります。ですから教科書の単元の題名は、ページの頭に`# 題名`と書くだけで済みます。
- テンプレートにないスロットを名乗る内容は、流し込み枠に入り、報告されます（`slotUnknown`）。

テンプレートページの外にある`slot`は読まれますが、何も変えません。

## ラベル付きの図

```md
:::figure{resource="mapa-europa" slot="mapa"}
::label[OCÉANO ATLÁNTICO]{at="atlantico" style="mar"}
::label[**Madrid**]{at="madrid"}
::label[Mar Negro]{at="62% 48%"}
:::
```

`:::figure{resource="…"}`は、`::resource`と同じく1つのリソースをキャプションと番号付きで置き、絵の上に置くラベルを並べます。ラベル1つにつき`::label[テキスト]{…}`を1行書き、間に空行をはさんでもかまいません。

- `at`は、リソースのアンカー（絵の上に一度だけ定義し、すべての言語で共有する点）を指定します。アンカーのないラベルには、絵に対するパーセントで点を`at="x% y%"`と指定します。
- `style`はラベルスタイルを指定し、アンカーのスタイルより優先します。
- 角かっこの中のテキストはインラインのMarkdownで、ボールド、イタリック、チップが使えます。

図は、枠の中だけでなく本文の流れの中でも使えます。ラベルは読み取られ、ソースの位置とともに保持されます。絵の上にラベルを描く処理は今後のリリースで入り、それまで図はリソースのとおりに組まれます。図の中にラベルでも空行でもない行が現れると、閉じる`:::`のない図はそこで終わり、閉じていないコンテナーとして報告されます。

## 作例

教科書の1ページです。題名の帯、リスト付きの本文、そしてそれぞれ横に写真を添えた色付きの囲みが3つあります。

```md
::::page{template="tema-cajas" fondo="banda-retos"}
# La actividad económica y el dinero

## La actividad económica

Las personas utilizan :chip[recursos]{style="clave"} que se obtienen de la naturaleza…

- Las :chip[empresas.]{style="clave"} Ofrecen bienes y servicios a cambio de un beneficio.
- Las :chip[personas y familias.]{style="clave"} Adquieren lo que ofrecen las empresas…

:::frame{slot="dinero" label="El dinero"}
Es el instrumento utilizado como medio de pago, ya que su valor es conocido…
:::

::resource{id="dinero-pago" slot="dinero-fotos"}

:::frame{slot="gasto" label="El gasto"}
- **Fijo:** es el que se produce todos los meses…
- **Variable:** puede cambiar según las necesidades…
:::

::resource{id="gasto-compras" slot="gasto-fotos"}

:::frame{slot="ahorro" label="Préstamos y ahorro"}
Si necesitas o quieres comprar algo muy caro…
:::

::resource{id="ahorro-balanza" slot="ahorro-fotos"}
::::
```

題名は`h1`を受け取る枠に、小見出し、段落、リストは流し込み枠に、囲みと写真はそれぞれのスロットの枠に入ります。カタルーニャ語版は、同じ行に別の言葉を入れたものです。テンプレートもスロットも写真も変わりません。

## ページの組み方

テンプレートページは1ページを丸ごと使います（デザイン要素の`pages`フィルターでは役割`composed`のページです）。テンプレートはページが左右どちらに来るかで選ばれ、`variants.recto`か`variants.verso`が当てはまります。そのうえで枠を1つずつ配置して中身を流し込みます。組版の設定は本の他の部分と同じで、段落スタイルと見出しスタイル、リスト、チップ、脚注の合印、そして枠の囲みスタイルが使われます。

### 枠の配置

枠はグリッドのセルに置かれるか、`placement`の指定する位置（デザイン要素と同じく、アンカー、辺、オフセット）に置かれます。どちらもなければ、テンプレートの領域の左上の角に、領域と同じ幅で置かれます。ほかの枠に固定した枠（`"to": "#dinero"`）は、その枠の後に配置され、その枠と一緒に動きます。`below`ならその枠の下に、`right-of`なら横に付き、`top-right`のような角を指定すると、その枠のボックスの同じ角に留められます。

枠の高さは、固定値（長さかパーセント）、`fill`（領域の端まで）、既定の`auto`のいずれかです。`auto`では受け取った中身の高さになり、`minHeight`と`maxHeight`の間に収まって、領域の下端を越えることはありません。枠が中身より高いときは、`verticalAlign`が中身の位置を決めます（`top`、`middle`、`bottom`、またはブロックの間に余白を配る`justify`）。枠の囲みスタイルは、背景、枠線、角丸、帯、アイコンを枠いっぱいの大きさで描き、`:::frame`フェンスの`label`はスタイルのタブに入ります。

### 流し込み枠と見出し

スロットを名乗らない内容は`flow`の付いた枠に入り、各レベルの最初の見出しは、`takes`でそのレベルを受け取る枠に入ります。ページ上の枠は、中身がMarkdownに最初に現れた順に、1つずつまとめて読まれます。スクリーンリーダー、タグ付きPDF、リフロー型の出力は、ページの冒頭の本文の後に囲みを読み、本文の途中に割り込ませることはありません。

### 枠をつなぐ

`next`は、枠に収まりきらない分を同じページの別の枠に送り、その枠からさらに次の枠へ送ります。組版ソフトでテキストフレームを連結するのと同じです。

```json
{ "name": "columna-1", "flow": true, "next": "columna-2", "height": { "value": 120, "unit": "mm" } },
{ "name": "columna-2", "placement": { "anchor": { "to": "#columna-1", "edge": "right-of" } } }
```

テキストは行と行の間で切れて次の枠に続き、その枠の幅で改めて行分けされます。失われる部分も、重複する部分もありません。`overflow.continueIn: "#frame"`も同じ意味です。次のページに続ける指定（`"next-page"`）は予定されています。

### テキストを押しのける枠

`exclude: "push"`を付けた枠は、ほかの枠のテキストを自分の矩形に入れません。ほかの枠の行がこの矩形にかかると、矩形が覆う側で行が短く組まれます。本文の流れでテキストが画像を回り込むのと同じです。囲みの角に固定して`push`を付けた写真があれば、囲みのテキストはその写真の横を流れます。写真のための列を決まった幅で空けておきたい囲みには、代わりに`padding`を使えます。

### 飾り、柱、レイヤー

テンプレートの飾り（`decoration`。画像、罫線、ボックス、短いテキスト）は、枠のボックスが確定してから置かれるので、要素を枠に固定して（`"to": "#gasto"`）その枠についていかせることができます。飾りのテキストはそのページの属性を読みます。ページフェンスに`fondo="banda-retos"`と書けば`{attr.fondo}`になり、たとえば`"resourceId": "{attr.fondo}"`で背景の画像をページごとに選べます。柱とノンブルもこの属性を読みます。テンプレートの`header`や`footer`はそのセクションのものに代わり、`false`なら表示されず、どちらも指定しなければセクションの柱とノンブルが入ります。

枠は`layer`の順に描かれます。飾りがレイヤー0、枠は既定でレイヤー1にあり、番号の大きいレイヤーが小さいレイヤーの上に、負のレイヤーは飾りの下に描かれます。`rotate`は枠を中身ごと、枠の中心を軸に任意の角度で回転させます。キャンバス、PDF、HTMLビューアー、固定レイアウトのEPUBのどれでも同じです。

### 収まらない内容

中身が枠より高く、続きを流す次の枠もない場合、中身はすべて文書に残りますが、表示されるのは収まる分だけです。残りはページ単位の出力では枠の下端で切れ、警告[`frameOverflow`](https://postext.dev/ja/docs/composed-pages.md#frameoverflow)がその量を示します。どの枠も受け取らない内容（流し込み枠がない、またはこのページの側のテンプレートに枠がない）は、テンプレートページの次のページの本文の流れに組まれます。

## 警告

検査は割り付けの前にMarkdownと設定を読むので、入力するそばから検査パネルに表示され、`postext check`と文書の`contentWarnings`にも現れます。どの警告にも、対象となる箇所のソース範囲が付きます（[設定 › 文書の中の警告](https://postext.dev/ja/docs/configuration-programmatic-usage.md#文書の中の警告)を参照）。

| 種類 | 原因 | 対処 |
| --- | --- | --- |
| `templateUnknown` | ページフェンスが`pageTemplates`のどの項目にもないテンプレートを指定しているか、テンプレートを指定していない。スロットは検査されません。 | IDを直すか、テンプレートを設定に加えます。 |
| `slotUnknown` | `slot="…"`の名前が、ページのテンプレートのどの枠にも当たらない（`extends`で受け継いだ枠と`variants`のページの枠も数えます）。その内容は流し込み枠に入ります。 | スロット名を直すか、その名前の枠をテンプレートに加えます。 |
| `slotEmpty` | テンプレートの枠が、このページで何も受け取らない。どのスロットもその枠を指さず、見出しも受け取らず、流し込み枠の場合はスロットのない内容も残っていない。ほかの枠からの続き（`next`）を受け取るだけの枠は報告されません。`postext check`では注記として挙がります。 | スロットを付けてその枠の内容を書くか、テンプレートでその枠を`optional: true`にします。 |
| `pageFenceLength` | コロン3つの`:::page`が`template=`を持っている。これまでどおりコミックのページとして読まれます。 | ページをコロン4つの`::::page{template="…"}`で開き、`::::`で閉じます。 |
| `unclosedContainer` | テンプレートページ、枠、図のどれかが閉じられていない（上の立て直しの規則を参照）。検査パネルではテンプレートページを`::::page`と呼びます。 | 閉じるフェンスを加えます。テンプレートページには開始行と同じ数のコロン、枠や図には`:::`です。 |

### frameOverflow

この警告は上の検査のようにソースを読んで出るものではなく、割り付けから出ます。ページが組み上がってから、検査パネル、`postext check`、文書の`contentWarnings`に現れます。

**原因**：枠に流し込んだ内容（スロットで指定したもの、または流し込み枠に入るもの）が枠より高く、続きを流す`next`の枠も残っていません。たいていは枠に収まる以上のテキストがある場合で、原文より長くなった翻訳や、`height`や`maxHeight`で高さを固定した枠がよくある例です。収まらない部分はページ単位の出力では枠の下端で切れますが、文書、ソースとの対応表、リフロー型のEPUBには残ります。警告にはテンプレート、枠、ページ、切れた高さ（`overflowMm`）、そして設定の中の枠を指すJSONポインタ`configPath`（`/pageTemplates/0/frames/2`）が付きます。

**対処**：枠を広げる（`height`や`maxHeight`を大きくするか外す）、`next`で別の枠につなぐ、テキストを短くする、別のテンプレートでそのページを組む、のいずれかです。今のところ、割り付けがテキストを縮めて収めることはしません。

## コードから使う

`composedPages(blocks)`は、章を解析したブロック（`parseMarkdownWithIssues(markdown).blocks`）を読み、ページフェンスごとに1つのノードを順に返します。ノードには、`template`、`spread`、各値のソース範囲（`attrSources`）を伴う`attrs`、`fenceIndex`（章の中でのフェンスの通し番号で、どの言語でも同じ）、`slots`（スロットごとのブロックの添字。Markdownの順）、`unassigned`（スロットのないブロック）、そしてページ全体のソース範囲が入ります。ブロックは、自分が名乗るスロットを、値のソース範囲とともに`ContentBlock.slot`に持ちます。図は`resourceBlock`で、その`figure`が属性とラベルを持ち、各ラベルにはテキスト、インラインのスパン、Markdownへ戻るソースマップがあります。`checkComposedSlots(pages, config)`は、それらのページについてスロットの警告3種を返します。

割り付けの後、テンプレートページの`VDTPage.composed`には、テンプレート、適用されたバリアント、ページフェンスの属性が記録されます。枠ごとには、id（`cp0:dinero`。ページフェンスの通し番号と枠の名前で、どの言語でも同じ）、ボックス、レイヤー、回転、収まらなかった中身の高さ（`overflowPx`）、続きの元や先の枠、設定の中のパス（`/pageTemplates/0/frames/2`）、ブロックのidが入ります。これらのブロックは`page.floats`と`doc.blocks`にある通常の囲みのブロックで、ソース範囲も持っているので、Sandboxのプレビューで回転していない枠をクリックすると、そのMarkdownに移動します。`composedPaintOrder(page)`はレンダラーが枠と飾りを描く順序を、`frameMatrix(frame)`は枠の回転を返します。
