# Pàgines compostes

> El Markdown de les pàgines compostes: la tanca de pàgina de quatre dos punts que anomena una plantilla de pàgina, els marcs i l’atribut slot que porten el contingut als marcs de la plantilla, les figures amb rètols a les àncores d’una imatge i els avisos que comproven el contingut amb la plantilla

- Versió HTML: https://postext.dev/ca/docs/composed-pages
- Última actualització: 2026-10-16
- Temps de lectura: 9 min
- Altres idiomes: [en](https://postext.dev/en/docs/composed-pages.md), [es](https://postext.dev/es/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), [ja](https://postext.dev/ja/docs/composed-pages.md), [ar](https://postext.dev/ar/docs/composed-pages.md)

## En poques paraules

Algunes pàgines no són una columna de text corregut, sinó un conjunt de caixes, com la pàgina d'un llibre de text escolar amb una banda per al títol, un text i tres caixes de colors amb fotos. Postext les anomena pàgines compostes. La forma de la pàgina és una plantilla de la configuració, i el Markdown només diu quin tros de text va a cada caixa. Aquesta pàgina explica com s'escriu aquest Markdown: la tanca de la pàgina, els marcs, els noms de slot i les imatges amb rètols, com els noms d'un mapa. També recull els avisos que dona Postext quan el text i la plantilla no lliguen.

**La plantilla guarda la forma de la pàgina; el Markdown en guarda el contingut i diu a quin marc va cada tros.**

Una pàgina composta es maqueta a partir d'una plantilla: marcs amb nom (una banda de títol, un text, una caixa amb la seva foto), grups que es mouen junts i una decoració, tot definit a la configuració, a `pageTemplates`. El Markdown de la pàgina és un bloc amb tanca que anomena la seva plantilla i aboca el contingut als marcs pel seu nom. Al Markdown mai no s'hi escriu cap posició ni cap mida, i a la configuració mai no s'hi escriu text del contingut, de manera que una traducció és la mateixa plantilla amb altres paraules.

Aquesta pàgina tracta del Markdown i de com se'n compon la pàgina. La plantilla mateixa (els marcs, les mides, els estils i la decoració) es descriu a [Configuració › Pàgines compostes](https://postext.dev/ca/docs/configuration-composed-pages.md). Un document sense pàgines compostes es maqueta exactament igual que abans.

## La tanca de pàgina

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

Una pàgina composta s'obre amb una línia de **quatre dos punts** seguida de `page` i els seus atributs, i es tanca amb una línia que només porta el **mateix nombre de dos punts**. A dins, els contenidors de tres dos punts (`:::frame`, `:::callout`, `:::figure`, `:::columns`, `:::paper`) s'obren i es tanquen com sempre, així que un `:::` solt tanca el més interior i mai la pàgina. Una pàgina escrita amb cinc dos punts (`:::::page`) es tanca amb cinc, i una línia de quatre dos punts a dins passa a ser text normal.

| Atribut | Efecte |
| --- | --- |
| `template="…"` | Obligatori. L'id d'una entrada de `pageTemplates`. |
| `spread` | La pàgina és una doble pàgina que ocupa dues pàgines encarades; la plantilla també ha de ser de doble pàgina. |
| `id="…"`, `#id` | Una àncora: un `:ref` que hi apunta imprimeix la pàgina on cau la pàgina composta. |
| qualsevol altre | Un valor que la plantilla llegeix com a `{attr.name}`, per exemple una imatge de fons triada pàgina a pàgina: `fondo="banda-retos"` amb `resourceId: "{attr.fondo}"` a la decoració. |

Una pàgina composta sempre comença una pàgina nova (o una doble pàgina), i el text que segueix la seva tanca de tancament comença a la següent.

El `:::page{split=…}` de tres dos punts és una pàgina de còmic (vegeu [Còmics](https://postext.dev/ca/docs/comics.md)) i manté aquest sentit. Un `:::page` de tres dos punts que porta `template=` es continua llegint com a pàgina de còmic, i l'avís `pageFenceLength` indica que una pàgina composta necessita quatre dos punts.

Quan falta una tanca, l'analitzador es refà sense perdre text:

- una pàgina que es queda oberta arriba fins al final del capítol i s'assenyala com a contenidor sense tancar a la seva línia d'obertura;
- una línia `::::page` que apareix amb una pàgina oberta tanca abans allà la pàgina oberta (i s'assenyala de la mateixa manera);
- la tanca de tancament tanca qualsevol marc o caixa que encara estigui obert dins de la pàgina, i els assenyala un per un;
- una tanca de tancament amb un altre nombre de dos punts no és la de la pàgina: es queda al text, a la vista.

## Marcs i 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** és el nom que demana un tros de contingut, i coincideix amb el nom d'un marc de la plantilla. `:::frame{slot="…"}` envia a aquest marc tot el que conté. El seu cos és Markdown complet: paràgrafs, llistes, encapçalaments, xips, insercions `::resource`, referències `:ref`, notes a peu de pàgina, `:::columns` i caixes niades. `label` i `title` posen les paraules de la pestanya o del títol del marc, com en un `:::callout`; l'aspecte del marc surt de l'estil de requadre que li assigna la plantilla.

Un bloc solt també pot anomenar el seu propi slot:

| Bloc | Com s'escriu |
| --- | --- |
| Un encapçalament | `## Retos {slot="retos-titulo"}` |
| Una inserció de recurs | `::resource{id="dinero-pago" slot="dinero-fotos"}` (els dos atributs, en qualsevol ordre) |
| Un llistat de codi | `````js {slot="codigo"}`` |
| Una caixa o qualsevol altre contenidor | `:::callout{type="nota" slot="aside"}`: la caixa sencera va al slot |
| Una figura | `:::figure{resource="mapa" slot="mapa"}` (vegeu més avall) |

Com es reparteix el contingut:

- Diversos trossos amb el mateix slot s'ajunten en l'ordre del Markdown.
- El contingut sense slot va al **marc de flux** de la plantilla (el que porta `flow`).
- Un encapçalament sense slot va primer al marc que pren el seu nivell (`takes: "h1"`), si la plantilla en té cap, així que el títol d'un tema d'un llibre de text és un simple `# Títol` al capdamunt de la pàgina.
- El contingut que anomena un slot que la plantilla no té va al marc de flux i s'assenyala (`slotUnknown`).

Un `slot` fora d'una pàgina composta es llegeix i no canvia res.

## Figures amb rètols

```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="…"}` col·loca un recurs, amb el seu peu i el seu número, com fa `::resource`, i enumera els rètols que van sobre la imatge: una línia `::label[TEXT]{…}` per rètol, amb línies en blanc permeses entre elles.

- `at` anomena una àncora del recurs (un punt que es defineix una sola vegada sobre la imatge i que comparteixen totes les llengües), o dona un punt en percentatges de la imatge, `at="x% y%"`, per a un rètol sense àncora.
- `style` anomena un estil de rètol i s'imposa al de l'àncora.
- El text entre claudàtors és Markdown en línia: negreta, cursiva, xips.

Una figura funciona tant al text corregut com dins d'un marc. Els rètols es llegeixen i es guarden juntament amb la seva posició al Markdown; dibuixar-los sobre la imatge arribarà en una versió posterior, i fins aleshores la figura es compon igual que el seu recurs. Una línia dins d'una figura que no és un rètol ni és en blanc acaba una figura a la qual falta el `:::` de tancament, i s'assenyala com a contenidor sense tancar.

## Exemple

La pàgina d'un llibre de text escolar, amb una banda de títol, un text amb la seva llista i tres caixes de colors, cadascuna amb la seva foto al costat:

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

El títol va al marc que pren `h1`; el subtítol, el paràgraf i la llista, al marc de flux; cada caixa i cada foto, al marc del seu slot. L'edició en català són les mateixes línies amb altres paraules: la plantilla, els slots i les fotos no canvien.

## Com es compon la pàgina

Una pàgina composta ocupa una pàgina pròpia (amb el paper `composed` per al filtre `pages` dels elements de disseny). La plantilla es tria segons el costat on cau la pàgina, així que s'hi aplica el seu `variants.recto` o el seu `variants.verso`. Després es col·loca i s'omple cada marc, l'un rere l'altre, amb la tipografia de la resta del llibre: els estils de paràgraf i d'encapçalament, les llistes, els xips, les crides de nota i l'estil de requadre del marc.

### Col·locar els marcs

Un marc se situa a la seva cel·la de la retícula, o allà on el posa el seu `placement` (un ancoratge, una vora i un desplaçament, com un element de disseny), o, si no té cap dels dos, a l'angle superior esquerre de l'àrea de la plantilla i amb tota l'amplada de l'àrea. Un marc ancorat a un altre (`"to": "#dinero"`) es col·loca després d'aquest i s'hi mou: `below` el penja a sota de l'altre marc, `right-of` el posa al costat i un angle com `top-right` el subjecta en aquest angle de la caixa de l'altre marc.

La seva alçada és fixa (una longitud o un percentatge), `fill` (fins a la vora de l'àrea) o `auto`, el valor per defecte: l'alçada del contingut que rep, entre `minHeight` i `maxHeight`, sense passar mai del peu de l'àrea. En un marc més alt que el seu contingut, `verticalAlign` diu on queda aquest contingut (`top`, `middle`, `bottom`, o `justify` per repartir l'espai entre els seus blocs). L'estil de requadre del marc dibuixa el fons, la vora, els angles arrodonits, la franja i la icona a la mida completa del marc; el `label` de la tanca `:::frame` s'imprimeix a la pestanya de l'estil.

### El marc de flux i els encapçalaments

El contingut que no anomena cap slot va al marc marcat amb `flow`; el primer encapçalament d'un nivell va al marc que el pren amb `takes`. Els marcs d'una pàgina es llegeixen en l'ordre en què el seu contingut apareix per primer cop al Markdown, cadascun sencer: un lector de pantalla, el PDF etiquetat i les sortides de maquetació fluida llegeixen una caixa després del text que obre la pàgina, no pas al mig.

### Encadenar marcs

`next` envia el que un marc no pot contenir a un altre marc de la mateixa pàgina, i aquest a un altre, com els marcs de text enllaçats de la maquetació de sempre:

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

El text es talla entre dues línies i continua al marc següent, partit de nou a l'amplada d'aquell marc, sense perdre ni repetir res. `overflow.continueIn: "#frame"` vol dir el mateix. Continuar a la pàgina següent està previst (`"next-page"`).

### Marcs que aparten el text

Un marc amb `exclude: "push"` deixa fora del seu rectangle el text dels altres marcs: la línia d'un altre marc que hi topa es compon més curta pel costat que tapa el rectangle, igual que el text envolta una imatge al text corregut. Una foto ancorada a l'angle d'una caixa i marcada amb `push` fa que el text de la caixa corri al seu costat. Una caixa que hagi de deixar lliure una columna fixa per a les seves imatges pot fer servir `padding` en lloc d'això.

### Decoració, capçaleres i capes

La `decoration` de la plantilla (imatges, filets, caixes i textos breus) es col·loca quan els marcs ja tenen la caixa definitiva, de manera que un element es pot ancorar a un marc (`"to": "#gasto"`) i seguir-lo. Els seus textos llegeixen els atributs de la mateixa pàgina: `fondo="banda-retos"` a la tanca de pàgina dona `{attr.fondo}`, per exemple per triar pàgina a pàgina una imatge de fons amb `"resourceId": "{attr.fondo}"`. Les capçaleres i els peus de pàgina també els llegeixen. El `header` o el `footer` d'una plantilla substitueix el de la secció, `false` l'amaga i, si la plantilla no en fixa cap, s'imprimeixen els de la secció.

Els marcs es pinten en l'ordre de la seva `layer`: la decoració a la capa 0, els marcs a la 1 per defecte, una capa més alta damunt d'una de més baixa i una capa negativa a sota de la decoració. `rotate` gira un marc juntament amb el seu contingut, en qualsevol angle i al voltant del centre del marc, al llenç, al PDF, al visor HTML i a l'EPUB de maquetació fixa.

### Contingut que no hi cap

Un marc el contingut del qual és més alt que ell, sense cap marc següent on continuar, conserva tot aquest contingut al document però només mostra el que hi cap: la resta es talla al peu del marc a la sortida paginada, i l'avís [`frameOverflow`](https://postext.dev/ca/docs/composed-pages.md#frameoverflow) diu quant. El contingut que no recull cap marc (no hi ha marc de flux, o en aquest costat falta un marc) es compon al text corregut, a la pàgina que segueix la pàgina composta.

## Avisos

Les comprovacions llegeixen el Markdown i la configuració abans de maquetar res, així que apareixen al tauler Revisió mentre escrius, a `postext check` i als `contentWarnings` del document, cadascuna amb l'interval d'origen del que assenyala (vegeu [Configuració › Avisos del document](https://postext.dev/ca/docs/configuration-programmatic-usage.md#avisos-del-document)).

| Tipus | Causa | Solució |
| --- | --- | --- |
| `templateUnknown` | La tanca de la pàgina anomena una plantilla que no és a `pageTemplates`, o no n'anomena cap. Els seus slots no es comproven. | Corregeix l'id o afegeix la plantilla a la configuració. |
| `slotUnknown` | Un `slot="…"` no anomena cap marc de la plantilla de la pàgina (compten els marcs heretats amb `extends` i els d'una pàgina de `variants`). El contingut va al marc de flux. | Corregeix el nom del slot o afegeix a la plantilla un marc amb aquest nom. |
| `slotEmpty` | Un marc de la plantilla no rep res en aquesta pàgina: cap slot no l'anomena, no pren cap encapçalament i, si és el marc de flux, no queda contingut sense slot. No s'assenyala un marc que només rep el que un altre marc hi continua (`next`). `postext check` el llista com a nota. | Escriu contingut per a aquest marc amb el seu slot, o marca'l com a `optional: true` a la plantilla. |
| `pageFenceLength` | Un `:::page` de tres dos punts porta `template=`. Es llegeix com a pàgina de còmic, igual que abans. | Obre la pàgina amb quatre dos punts, `::::page{template="…"}`, i tanca-la amb `::::`. |
| `unclosedContainer` | Una pàgina composta, un marc o una figura no es tanca mai (vegeu les regles de recuperació de més amunt). El tauler Revisió anomena la pàgina composta `::::page`. | Afegeix la tanca de tancament: tants dos punts com la línia d'obertura de la pàgina, o `:::` per a un marc o una figura. |

### frameOverflow

Aquest avís el dona la maquetació, no les comprovacions del codi font d'aquí dalt: apareix quan la pàgina ja està composta, al tauler Revisió, a `postext check` i als `contentWarnings` del document.

**Causa.** El contingut que entra en un marc (pel seu slot, o el que rep el marc de flux) és més alt que el marc, i el marc no té cap `next` on continuar. Gairebé sempre hi ha més text del que hi cap: una traducció més llarga que l'original, o un marc subjecte a un `height` o un `maxHeight` fixos. El que no hi cap es talla al peu del marc a la sortida paginada; continua al document, al mapa d'origen i a l'EPUB de maquetació fluida. L'avís indica la plantilla, el marc, la pàgina, l'alçada tallada (`overflowMm`) i `configPath`, el punter JSON del marc a la configuració (`/pageTemplates/0/frames/2`).

**Solució.** Dona més espai al marc (puja o treu el seu `height` o el seu `maxHeight`), encadena'l a un altre marc amb `next`, escurça el text o compon la pàgina amb una altra plantilla. De moment la maquetació no redueix el text perquè hi càpiga.

## Des del codi

`composedPages(blocks)` llegeix els blocs analitzats d'un capítol (`parseMarkdownWithIssues(markdown).blocks`) i retorna un node per cada tanca de pàgina, en ordre: el seu `template`, `spread`, `attrs` amb l'interval d'origen de cada valor (`attrSources`), el seu `fenceIndex` (l'ordinal de la tanca dins del capítol, el mateix en totes les llengües), `slots` (els índexs dels blocs de cada slot, en l'ordre del Markdown), `unassigned` (els blocs sense slot) i l'interval d'origen de la pàgina sencera. Un bloc porta el slot que anomena a `ContentBlock.slot`, amb l'interval d'origen del valor; una figura és un `resourceBlock` el `figure` del qual guarda els seus atributs i els seus rètols, cada rètol amb el seu text, els seus trams en línia i un mapa d'origen que remet al Markdown. `checkComposedSlots(pages, config)` retorna els tres avisos de slot d'aquestes pàgines.

Després de la maquetació, el `VDTPage.composed` d'una pàgina composta registra la seva plantilla, la variant aplicada, els atributs de la tanca de pàgina i, per a cada marc, el seu id (`cp0:dinero`: l'ordinal de la tanca de pàgina i el nom del marc, el mateix en totes les llengües), la seva caixa, la capa, el gir, l'alçada del contingut que no hi ha cabut (`overflowPx`), el marc del qual continua o en el qual continua, el seu camí a la configuració (`/pageTemplates/0/frames/2`) i els ids dels seus blocs. Aquests blocs són blocs de requadre corrents a `page.floats` i `doc.blocks`, amb els seus intervals d'origen, així que un clic en un marc sense girar de la previsualització del Sandbox porta al seu Markdown. `composedPaintOrder(page)` dona l'ordre en què un renderitzador pinta els marcs i la decoració, i `frameMatrix(frame)`, el gir d'un marc.
