# Pages composées

> Le Markdown des pages composées : le délimiteur de page à quatre deux-points qui nomme un modèle de page, les blocs et l’attribut slot qui envoient le contenu dans les blocs du modèle, les figures dont les étiquettes se posent sur les ancres d’une image, et les avertissements qui confrontent le contenu au modèle

- Version HTML: https://postext.dev/fr/docs/composed-pages
- Dernière mise à jour: 2026-10-16
- Temps de lecture: 9 min
- Autres langues: [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), [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), [ja](https://postext.dev/ja/docs/composed-pages.md), [ar](https://postext.dev/ar/docs/composed-pages.md)

## En bref

Certaines pages ne sont pas une simple colonne de texte courant mais un assemblage de blocs, comme une page de manuel scolaire avec un bandeau de titre, un texte et trois encadrés de couleur accompagnés de photos. Postext les appelle des pages composées. La forme de la page est un modèle rangé dans la configuration, et le Markdown se contente de dire quel morceau de texte va dans quel bloc. Cette page montre comment écrire ce Markdown : le délimiteur de page, les blocs, les noms de slot et les images avec des étiquettes, comme les noms sur une carte. Elle liste aussi les avertissements que donne Postext quand le texte et le modèle ne concordent pas.

**Le modèle porte la forme de la page ; le Markdown porte son contenu et dit dans quel bloc va chaque morceau.**

Une page composée est une page mise en page d’après un modèle : des blocs nommés (un bandeau de titre, un texte, un encadré avec sa photo), des groupes qui se déplacent ensemble et un décor, le tout défini dans la configuration sous `pageTemplates`. Le Markdown de la page est une section délimitée qui nomme son modèle et verse le contenu dans les blocs en les appelant par leur nom. Aucune position ni aucune taille ne s’écrit dans le Markdown, et aucun texte de contenu ne s’écrit dans la configuration : une traduction, c’est le même modèle avec d’autres mots.

Cette page traite du Markdown et de la façon dont la page en est composée. Le modèle lui-même (ses blocs, ses tailles, ses styles et son décor) est décrit dans [Configuration › Pages composées](https://postext.dev/fr/docs/configuration-composed-pages.md). Un document sans pages composées se met en page exactement comme avant.

## Le délimiteur de page

```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…
::::
```

Une page composée s’ouvre par une ligne de **quatre deux-points** suivie de `page` et de ses attributs, et se ferme par une ligne qui ne contient que le **même nombre de deux-points**. À l’intérieur, les conteneurs à trois deux-points (`:::frame`, `:::callout`, `:::figure`, `:::columns`, `:::paper`) s’ouvrent et se ferment comme d’habitude : un `:::` seul ferme donc le plus intérieur d’entre eux, jamais la page. Une page écrite avec cinq deux-points (`:::::page`) se ferme avec cinq ; une ligne de quatre deux-points y devient alors du texte ordinaire.

| Attribut | Effet |
| --- | --- |
| `template="…"` | Obligatoire. L’id d’une entrée de `pageTemplates`. |
| `spread` | La page est une double page, sur deux pages en regard ; le modèle doit lui aussi être un modèle de double page. |
| `id="…"`, `#id` | Une ancre : un `:ref` qui la vise imprime le numéro de la page où tombe la page composée. |
| tout autre attribut | Une valeur que le modèle lit sous la forme `{attr.name}`, par exemple une image de fond choisie page par page : `fondo="banda-retos"` avec `resourceId: "{attr.fondo}"` dans le décor. |

Une page composée commence toujours une nouvelle page (ou une nouvelle double page), et le texte qui suit son délimiteur de fermeture commence sur la suivante.

Le `:::page{split=…}` à trois deux-points est une page de bande dessinée (voir [Bande dessinée](https://postext.dev/fr/docs/comics.md)) et garde ce sens. Un `:::page` à trois deux-points qui porte `template=` reste lu comme une page de bande dessinée, et l’avertissement `pageFenceLength` rappelle qu’une page composée demande quatre deux-points.

Quand un délimiteur manque, l’analyseur se rattrape sans perdre de texte :

- une page laissée ouverte court jusqu’à la fin du chapitre et est signalée comme conteneur non fermé, sur sa ligne d’ouverture ;
- une ligne `::::page` rencontrée alors qu’une page est ouverte ferme d’abord, à cet endroit, la page ouverte (signalée de la même façon) ;
- le délimiteur de fermeture ferme tout bloc ou encadré resté ouvert dans la page, et signale chacun d’eux ;
- un délimiteur de fermeture qui a un autre nombre de deux-points n’est pas celui de la page : il reste dans le texte, où vous le voyez.

## Blocs et slots

```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**…
:::
```

Un **slot** est le nom que réclame un morceau de contenu ; il correspond au nom d’un bloc du modèle. `:::frame{slot="…"}` envoie tout ce qu’il contient dans ce bloc. Son corps accepte tout le Markdown : paragraphes, listes, titres, pastilles, insertions `::resource`, renvois `:ref`, notes de bas de page, `:::columns` et encadrés imbriqués. `label` et `title` donnent leurs mots à l’onglet ou au titre du bloc, comme pour un `:::callout` ; l’apparence du bloc vient du style d’encadré que le modèle lui attribue.

Un élément isolé peut nommer lui-même son slot :

| Élément | Écriture |
| --- | --- |
| Un titre | `## Retos {slot="retos-titulo"}` |
| Une insertion de ressource | `::resource{id="dinero-pago" slot="dinero-fotos"}` (les deux attributs, dans n’importe quel ordre) |
| Un listing de code | `````js {slot="codigo"}`` |
| Un encadré ou tout autre conteneur | `:::callout{type="nota" slot="aside"}` : l’encadré entier va dans le slot |
| Une figure | `:::figure{resource="mapa" slot="mapa"}` (voir plus bas) |

Le contenu se répartit ainsi :

- Plusieurs morceaux qui portent le même slot sont réunis dans l’ordre du Markdown.
- Le contenu sans slot va dans le **bloc de flux** du modèle (le bloc marqué `flow`).
- Un titre sans slot va d’abord au bloc qui prend son niveau (`takes: "h1"`), si le modèle en a un : le titre d’un thème de manuel s’écrit donc simplement `# Titre` en haut de la page.
- Le contenu qui nomme un slot absent du modèle va dans le bloc de flux et est signalé (`slotUnknown`).

Hors d’une page composée, un `slot` est lu et ne change rien.

## Figures avec étiquettes

```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="…"}` place une ressource, avec sa légende et son numéro, comme le fait `::resource`, et énumère les étiquettes à poser sur l’image : une ligne `::label[TEXT]{…}` par étiquette, les lignes vides entre elles étant permises.

- `at` nomme une ancre de la ressource (un point défini une seule fois sur l’image et commun à toutes les langues), ou donne un point en pourcentages de l’image, `at="x% y%"`, pour une étiquette sans ancre.
- `style` nomme un style d’étiquette et remplace celui de l’ancre.
- Le texte entre crochets est du Markdown en ligne : gras, italique, pastilles.

Une figure fonctionne aussi bien dans le texte courant que dans un bloc. Les étiquettes sont lues et conservées avec leur source ; leur dessin sur l’image viendra dans une version ultérieure, et d’ici là une figure est composée comme sa ressource. Dans une figure, une ligne qui n’est ni une étiquette ni une ligne vide termine une figure dont le `:::` de fermeture manque, et elle est signalée comme conteneur non fermé.

## Exemple

La page d’un manuel scolaire, avec un bandeau de titre, un texte suivi de sa liste et trois encadrés de couleur, chacun avec sa photo à côté :

```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"}
::::
```

Le titre va au bloc qui prend `h1` ; l’intertitre, le paragraphe et la liste vont au bloc de flux ; chaque encadré et chaque photo vont au bloc de leur slot. L’édition catalane reprend les mêmes lignes avec d’autres mots : le modèle, les slots et les photos ne changent pas.

## Comment la page est composée

Une page composée occupe une page à elle (rôle `composed` pour le filtre `pages` des éléments de maquette). Le modèle est choisi selon le côté où tombe la page, ce qui applique son `variants.recto` ou son `variants.verso`. Chaque bloc est ensuite placé puis rempli, l’un après l’autre, avec la typographie du reste du livre : styles de paragraphe et de titre, listes, pastilles, appels de note et style d’encadré du bloc.

### Placer les blocs

Un bloc se met dans sa cellule de grille, ou là où le met son `placement` (un ancrage, un bord et un décalage, comme pour un élément de maquette), ou, sans l’un ni l’autre, dans le coin supérieur gauche de la zone du modèle, sur toute la largeur de la zone. Un bloc ancré à un autre (`"to": "#dinero"`) est placé après lui et se déplace avec lui : `below` le suspend sous l’autre bloc, `right-of` le met à côté, et un coin comme `top-right` l’attache à ce coin de la boîte de l’autre bloc.

Sa hauteur est fixe (une longueur ou un pourcentage), `fill` (jusqu’au bord de la zone) ou `auto`, la valeur par défaut : la hauteur du contenu qu’il reçoit, entre `minHeight` et `maxHeight`, sans jamais dépasser le pied de la zone. Dans un bloc plus haut que son contenu, `verticalAlign` dit où se place ce contenu (`top`, `middle`, `bottom`, ou `justify` pour répartir l’espace entre ses éléments). Le style d’encadré du bloc dessine le fond, la bordure, les coins arrondis, la bande et l’icône à la taille entière du bloc ; le `label` du délimiteur `:::frame` s’imprime dans l’onglet du style.

### Le bloc de flux et les titres

Le contenu qui ne nomme aucun slot va dans le bloc marqué `flow` ; le premier titre d’un niveau va au bloc qui le prend avec `takes`. Les blocs d’une page se lisent dans l’ordre où leur contenu apparaît pour la première fois dans le Markdown, chacun en entier : un lecteur d’écran, le PDF balisé et les sorties recomposables lisent un encadré après le texte qui ouvre la page, et non au milieu.

### Chaîner des blocs

`next` envoie ce qu’un bloc ne peut pas contenir vers un autre bloc de la même page, et celui-ci vers un autre encore, comme des blocs de texte chaînés en PAO :

```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" } } }
```

Le texte est coupé entre deux lignes et continue dans le bloc suivant, recomposé à la largeur de ce bloc, sans rien perdre ni répéter. `overflow.continueIn: "#frame"` a le même effet. La suite sur la page suivante est prévue (`"next-page"`).

### Les blocs qui repoussent le texte

Un bloc avec `exclude: "push"` tient le texte des autres blocs hors de son rectangle : une ligne d’un autre bloc qui le rencontre est composée plus courte du côté que couvre le rectangle, comme le texte habille une image dans le texte courant. Une photo ancrée au coin d’un encadré et marquée `push` fait courir le texte de l’encadré à côté d’elle. Un encadré qui doit garder une colonne fixe libre pour ses images peut plutôt utiliser `padding`.

### Décor, titres courants et calques

Le décor du modèle (`decoration` : images, filets, boîtes et textes courts) est posé une fois que les blocs ont leur boîte définitive : un élément peut donc s’ancrer à un bloc (`"to": "#gasto"`) et le suivre. Ses textes lisent les attributs de la page elle-même : `fondo="banda-retos"` sur le délimiteur de page donne `{attr.fondo}`, par exemple pour choisir page par page une image de fond avec `"resourceId": "{attr.fondo}"`. Les titres courants les lisent aussi. Le `header` ou le `footer` d’un modèle remplace celui de la section, `false` le masque, et sans l’un ni l’autre ce sont les titres courants de la section qui s’impriment.

Les blocs se peignent dans l’ordre de leur `layer` : le décor au calque 0, les blocs au calque 1 par défaut, un calque plus élevé par-dessus un calque plus bas, un calque négatif sous le décor. `rotate` fait tourner un bloc et son contenu ensemble, de n’importe quel angle, autour du centre du bloc, dans le canvas, le PDF, la visionneuse HTML et l’EPUB à mise en page fixe.

### Le contenu qui ne tient pas

Un bloc dont le contenu est plus haut que lui, sans bloc suivant où continuer, garde tout ce contenu dans le document mais n’en montre que ce qui tient : le reste est coupé au pied du bloc dans la sortie paginée, et l’avertissement [`frameOverflow`](https://postext.dev/fr/docs/composed-pages.md#frameoverflow) dit de combien. Le contenu qu’aucun bloc ne prend (pas de bloc de flux, ou un bloc absent de ce côté) est composé dans le texte courant, sur la page qui suit la page composée.

## Avertissements

Les vérifications lisent le Markdown et la configuration avant toute mise en page. Elles apparaissent donc pendant la frappe dans le panneau Vérifications, ainsi que dans `postext check` et dans les `contentWarnings` du document, chacune avec la plage source de ce qu’elle concerne (voir [Configuration › Avertissements dans le document](https://postext.dev/fr/docs/configuration-programmatic-usage.md#avertissements-dans-le-document)).

| Type | Cause | Correction |
| --- | --- | --- |
| `templateUnknown` | Le délimiteur de page nomme un modèle qu’aucune entrée de `pageTemplates` ne définit, ou n’en nomme aucun. Ses slots ne sont pas vérifiés. | Corriger l’id, ou ajouter le modèle à la configuration. |
| `slotUnknown` | Un `slot="…"` ne nomme aucun bloc du modèle de la page (les blocs hérités par `extends` et ceux d’une page de `variants` comptent). Le contenu va dans le bloc de flux. | Corriger le nom du slot, ou ajouter au modèle un bloc de ce nom. |
| `slotEmpty` | Un bloc du modèle ne reçoit rien sur cette page : aucun slot ne le nomme, il ne prend aucun titre et, s’il s’agit du bloc de flux, aucun contenu ne reste sans slot. Un bloc qui ne reçoit que la suite d’un autre bloc (`next`) n’est pas signalé. `postext check` le liste comme une note. | Écrire du contenu pour ce bloc avec son slot, ou marquer le bloc `optional: true` dans le modèle. |
| `pageFenceLength` | Un `:::page` à trois deux-points porte `template=`. Il est lu comme une page de bande dessinée, comme avant. | Ouvrir la page avec quatre deux-points, `::::page{template="…"}`, et la fermer avec `::::`. |
| `unclosedContainer` | Une page composée, un bloc ou une figure n’est jamais fermé (voir plus haut comment l’analyseur se rattrape). Le panneau Vérifications désigne la page composée par `::::page`. | Ajouter le délimiteur de fermeture : autant de deux-points que sur la ligne d’ouverture de la page, ou `:::` pour un bloc ou une figure. |

### frameOverflow

Cet avertissement vient de la mise en page, pas des vérifications de la source décrites plus haut : il apparaît une fois la page composée, dans le panneau Vérifications, dans `postext check` et dans les `contentWarnings` du document.

**Cause.** Le contenu versé dans un bloc (par son slot, ou celui que reçoit le bloc de flux) est plus haut que le bloc, et le bloc n’a plus de `next` où continuer. Le plus souvent, il y a plus de texte que le bloc n’en contient : une traduction plus longue que l’original, ou un bloc tenu par un `height` ou un `maxHeight` fixe. Ce qui ne tient pas est coupé au pied du bloc dans la sortie paginée ; il reste dans le document, dans la table de correspondance avec la source et dans l’EPUB recomposable. L’avertissement donne le modèle, le bloc, la page, la hauteur coupée (`overflowMm`) et `configPath`, le pointeur JSON du bloc dans la configuration (`/pageTemplates/0/frames/2`).

**Correction.** Donnez plus de place au bloc (augmentez ou retirez son `height` ou son `maxHeight`), chaînez-le à un autre bloc avec `next`, raccourcissez le texte ou composez la page avec un autre modèle. Pour l’instant, la mise en page ne réduit pas le texte pour le faire tenir.

## Depuis le code

`composedPages(blocks)` lit les éléments analysés d’un chapitre (`parseMarkdownWithIssues(markdown).blocks`) et renvoie un nœud par délimiteur de page, dans l’ordre, avec son `template`, `spread`, `attrs` et la plage source de chaque valeur (`attrSources`), son `fenceIndex` (le rang du délimiteur dans le chapitre, le même dans toutes les langues), `slots` (les indices des éléments de chaque slot, dans l’ordre du Markdown), `unassigned` (les éléments sans slot) et la plage source de la page entière. Un élément porte le slot qu’il nomme dans `ContentBlock.slot`, avec la plage source de la valeur ; une figure est un `resourceBlock` dont `figure` contient les attributs et les étiquettes, chaque étiquette avec son texte, ses segments en ligne et une correspondance avec sa source dans le Markdown. `checkComposedSlots(pages, config)` renvoie les trois avertissements de slot pour ces pages.

Après la mise en page, le `VDTPage.composed` d’une page composée consigne son modèle, la variante appliquée, les attributs du délimiteur de page et, pour chaque bloc, son id (`cp0:dinero` : le rang du délimiteur de page et le nom du bloc, le même dans toutes les langues), sa boîte, son calque, sa rotation, la hauteur du contenu qui n’a pas tenu (`overflowPx`), le bloc dont il est la suite ou dans lequel il continue, son chemin dans la configuration (`/pageTemplates/0/frames/2`) et les ids de ses éléments. Ces éléments sont des encadrés ordinaires dans `page.floats` et `doc.blocks`, avec leurs plages source, si bien qu’un clic dans un bloc non tourné de l’aperçu du Sandbox mène à son Markdown. `composedPaintOrder(page)` donne l’ordre dans lequel un moteur de rendu peint les blocs et le décor, et `frameMatrix(frame)` la rotation d’un bloc.
