# Páginas compostas

> O Markdown das páginas compostas: a cerca de página de quatro dois-pontos que nomeia um modelo de página, os blocos e o atributo slot que levam o conteúdo aos blocos do modelo, as figuras com rótulos nas âncoras de uma imagem e os avisos que conferem o conteúdo com o modelo

- Versão HTML: https://postext.dev/pt/docs/composed-pages
- Última atualização: 2026-10-16
- Tempo de leitura: 9 min
- Outros idiomas: [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), [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)

## Em poucas palavras

Algumas páginas não são uma coluna de texto corrido, e sim um conjunto de caixas, como a página de um livro didático com uma faixa para o título, um texto e três caixas coloridas com fotos. O Postext chama essas páginas de páginas compostas. A forma da página é um modelo que fica na configuração, e o Markdown só diz qual trecho de texto vai em cada caixa. Esta página mostra como escrever esse Markdown: a cerca da página, os blocos, os nomes de slot e as imagens com rótulos, como os nomes de um mapa. Ela também lista os avisos que o Postext dá quando o texto e o modelo não batem.

**O modelo guarda a forma da página; o Markdown guarda o conteúdo e diz para qual bloco vai cada trecho.**

Uma página composta é diagramada a partir de um modelo: blocos com nome (uma faixa de título, um texto, uma caixa com a sua foto), grupos que se movem juntos e uma decoração, tudo definido na configuração, em `pageTemplates`. O Markdown da página é um contêiner cercado que nomeia o seu modelo e distribui o conteúdo pelos blocos, pelo nome de cada um. Nenhuma posição ou tamanho é escrito no Markdown, e nenhum texto do conteúdo é escrito na configuração, então uma tradução é o mesmo modelo com outras palavras.

Esta página trata do Markdown e de como a página é composta a partir dele. O modelo em si (os seus blocos, tamanhos, estilos e decoração) está descrito em [Configuração › Páginas compostas](https://postext.dev/pt/docs/configuration-composed-pages.md). Um documento sem páginas compostas é diagramado exatamente como antes.

## A cerca 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…
::::
```

Uma página composta abre com uma linha de **quatro dois-pontos** seguida de `page` e dos seus atributos, e fecha com uma linha que só tem o **mesmo número de dois-pontos**. Dentro dela, os contêineres de três dois-pontos (`:::frame`, `:::callout`, `:::figure`, `:::columns`, `:::paper`) abrem e fecham como sempre, então um `:::` sozinho fecha o mais interno deles e nunca a página. Uma página escrita com cinco dois-pontos (`:::::page`) fecha com cinco, e uma linha de quatro dois-pontos dentro dela passa a ser texto comum.

| Atributo | Efeito |
| --- | --- |
| `template="…"` | Obrigatório. O id de uma entrada de `pageTemplates`. |
| `spread` | A página é uma página dupla, que ocupa duas páginas frente a frente; o modelo também precisa ser de página dupla. |
| `id="…"`, `#id` | Uma âncora: um `:ref` que aponta para ela imprime a página em que a página composta cai. |
| qualquer outro | Um valor que o modelo lê como `{attr.name}`, por exemplo uma imagem de fundo escolhida página a página: `fondo="banda-retos"` com `resourceId: "{attr.fondo}"` na decoração. |

Uma página composta sempre começa uma página nova (ou uma página dupla), e o texto depois da sua cerca de fechamento começa na seguinte.

O `:::page{split=…}` de três dois-pontos é uma página de quadrinhos (veja [Quadrinhos](https://postext.dev/pt/docs/comics.md)) e mantém esse sentido. Um `:::page` de três dois-pontos que traz `template=` continua sendo lido como página de quadrinhos, e o aviso `pageFenceLength` diz que uma página composta precisa de quatro dois-pontos.

Quando falta uma cerca, o analisador se recupera sem perder texto:

- uma página que fica aberta vai até o fim do capítulo e é assinalada como contêiner não fechado na sua linha de abertura;
- uma linha `::::page` encontrada com uma página aberta fecha antes, ali mesmo, a página aberta (e é assinalada do mesmo jeito);
- a cerca de fechamento fecha qualquer bloco ou boxe que ainda esteja aberto dentro da página, e assinala cada um;
- uma cerca de fechamento com outro número de dois-pontos não é a da página: ela fica no texto, à vista.

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

Um **slot** é o nome que um trecho de conteúdo pede, e corresponde ao nome de um bloco do modelo. `:::frame{slot="…"}` manda para esse bloco tudo o que está dentro dele. O seu corpo é Markdown completo: parágrafos, listas, títulos, chips, inserções `::resource`, referências `:ref`, notas de rodapé, `:::columns` e boxes aninhados. `label` e `title` dão as palavras da aba ou do título do bloco, como num `:::callout`; a aparência do bloco vem do estilo de boxe que o modelo atribui a ele.

Um elemento avulso também pode nomear o seu próprio slot:

| Elemento | Como se escreve |
| --- | --- |
| Um título | `## Retos {slot="retos-titulo"}` |
| Uma inserção de recurso | `::resource{id="dinero-pago" slot="dinero-fotos"}` (os dois atributos, em qualquer ordem) |
| Uma listagem de código | `````js {slot="codigo"}`` |
| Um boxe ou qualquer outro contêiner | `:::callout{type="nota" slot="aside"}`: o boxe inteiro vai para o slot |
| Uma figura | `:::figure{resource="mapa" slot="mapa"}` (veja abaixo) |

Como o conteúdo é distribuído:

- Vários trechos com o mesmo slot são juntados na ordem do Markdown.
- O conteúdo sem slot vai para o **bloco de fluxo** do modelo (o que está marcado com `flow`).
- Um título sem slot vai primeiro para o bloco que recebe o seu nível (`takes: "h1"`), se o modelo tiver um, então o título de um tema de livro didático é só um `# Título` no alto da página.
- O conteúdo que nomeia um slot que o modelo não tem vai para o bloco de fluxo e é assinalado (`slotUnknown`).

Um `slot` fora de uma página composta é lido e não muda nada.

## Figuras com rótulos

```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="…"}` coloca um recurso, com a sua legenda e o seu número, como faz `::resource`, e lista os rótulos que vão sobre a imagem: uma linha `::label[TEXTO]{…}` por rótulo, com linhas em branco permitidas entre elas.

- `at` nomeia uma âncora do recurso (um ponto definido uma única vez sobre a imagem e compartilhado por todos os idiomas), ou dá um ponto em porcentagens da imagem, `at="x% y%"`, para um rótulo sem âncora.
- `style` nomeia um estilo de rótulo e passa por cima do estilo da âncora.
- O texto entre colchetes é Markdown em linha: negrito, itálico, chips.

Uma figura funciona tanto no texto corrido quanto dentro de um bloco. Os rótulos são lidos e guardados junto com a sua posição no Markdown; desenhá-los sobre a imagem fica para uma versão futura, e até lá a figura é composta como o seu recurso. Uma linha dentro de uma figura que não é um rótulo nem está em branco encerra uma figura que ficou sem o `:::` de fechamento, e é assinalada como contêiner não fechado.

## Exemplo

A página de um livro didático, com uma faixa de título, um texto com a sua lista e três caixas coloridas, cada uma com a sua foto ao lado:

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

O título vai para o bloco que recebe `h1`; o subtítulo, o parágrafo e a lista, para o bloco de fluxo; cada caixa e cada foto, para o bloco do seu slot. A edição em catalão são as mesmas linhas com outras palavras: o modelo, os slots e as fotos não mudam.

## Como a página é composta

Uma página composta ocupa uma página só sua (papel `composed` para o filtro `pages` dos elementos de design). O modelo é escolhido conforme o lado em que a página cai, então vale o seu `variants.recto` ou o seu `variants.verso`. Depois cada bloco é posicionado e preenchido, um após o outro, com a tipografia do resto do livro: estilos de parágrafo e de título, listas, chips, chamadas de nota e o estilo de boxe do bloco.

### Posicionar os blocos

Um bloco fica na sua célula da grade, ou onde o seu `placement` o coloca (uma âncora, uma borda e um deslocamento, como num elemento de design), ou, sem nenhum dos dois, no canto superior esquerdo da área do modelo, com a largura da área inteira. Um bloco ancorado a outro (`"to": "#dinero"`) é posicionado depois dele e se move com ele: `below` o pendura embaixo do outro bloco, `right-of` o põe ao lado, e um canto como `top-right` o prende a esse canto da caixa do outro bloco.

A sua altura é fixa (um comprimento ou uma porcentagem), `fill` (até a borda da área) ou `auto`, o padrão: a altura do conteúdo que ele recebe, entre `minHeight` e `maxHeight`, e nunca além do pé da área. Num bloco mais alto que o seu conteúdo, `verticalAlign` diz onde esse conteúdo fica (`top`, `middle`, `bottom`, ou `justify` para distribuir o espaço entre os seus elementos). O estilo de boxe do bloco desenha o fundo, a borda, os cantos arredondados, a faixa e o ícone no tamanho inteiro do bloco; o `label` da cerca `:::frame` sai impresso na aba do estilo.

### O bloco de fluxo e os títulos

O conteúdo que não nomeia nenhum slot vai para o bloco marcado com `flow`; o primeiro título de um nível vai para o bloco que o recebe com `takes`. Os blocos de uma página são lidos na ordem em que o seu conteúdo aparece pela primeira vez no Markdown, cada um inteiro: um leitor de tela, o PDF etiquetado e as saídas de layout fluido leem um boxe depois do texto que abre a página, e não no meio dele.

### Encadear blocos

`next` manda o que um bloco não consegue conter para outro bloco da mesma página, e esse para outro, como as caixas de texto encadeadas dos programas de diagramação:

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

O texto é cortado entre duas linhas e continua no bloco seguinte, quebrado de novo na largura desse bloco, sem perder nem repetir nada. `overflow.continueIn: "#frame"` quer dizer o mesmo. Continuar na página seguinte está previsto (`"next-page"`).

### Blocos que afastam o texto

Um bloco com `exclude: "push"` mantém o texto dos outros blocos fora do seu retângulo: a linha de outro bloco que esbarra nele é composta mais curta do lado que o retângulo cobre, do mesmo jeito que o texto contorna uma imagem no texto corrido. Uma foto ancorada no canto de uma caixa e marcada com `push` faz o texto da caixa correr ao lado dela. Uma caixa que precisa deixar livre uma coluna fixa para as suas imagens pode usar `padding` no lugar disso.

### Decoração, cabeços e camadas

A `decoration` do modelo (imagens, fios, caixas e textos curtos) é posicionada quando os blocos já têm a sua caixa definitiva, então um elemento pode se ancorar a um bloco (`"to": "#gasto"`) e acompanhá-lo. Os seus textos leem os atributos da própria página: `fondo="banda-retos"` na cerca de página dá `{attr.fondo}`, por exemplo para escolher página a página uma imagem de fundo com `"resourceId": "{attr.fondo}"`. Os cabeços e rodapés também leem esses atributos. O `header` ou o `footer` de um modelo substitui o da seção, `false` o esconde e, quando o modelo não define nenhum dos dois, saem os da seção.

Os blocos são pintados na ordem da sua `layer`: a decoração na camada 0, os blocos na 1 por padrão, uma camada mais alta por cima de uma mais baixa e uma camada negativa por baixo da decoração. `rotate` gira um bloco junto com o seu conteúdo, em qualquer ângulo e em torno do centro do bloco, no canvas, no PDF, no visualizador HTML e no EPUB de layout fixo.

### Conteúdo que não cabe

Um bloco cujo conteúdo é mais alto que ele, sem um bloco seguinte onde continuar, guarda todo esse conteúdo no documento, mas só mostra o que cabe: o resto é cortado no pé do bloco na saída paginada, e o aviso [`frameOverflow`](https://postext.dev/pt/docs/composed-pages.md#frameoverflow) diz quanto. O conteúdo que nenhum bloco recebe (não há bloco de fluxo, ou falta um bloco nesse lado) é composto no texto corrido, na página que vem depois da página composta.

## Avisos

As verificações leem o Markdown e a configuração antes de qualquer diagramação, então aparecem no painel Verificações enquanto você digita, no `postext check` e nos `contentWarnings` do documento, cada uma com o intervalo de origem daquilo que aponta (veja [Configuração › Avisos no documento](https://postext.dev/pt/docs/configuration-programmatic-usage.md#avisos-no-documento)).

| Tipo | Causa | Correção |
| --- | --- | --- |
| `templateUnknown` | A cerca da página nomeia um modelo que não está em `pageTemplates`, ou não nomeia nenhum. Os slots da página não são verificados. | Corrija o id ou acrescente o modelo à configuração. |
| `slotUnknown` | Um `slot="…"` não nomeia nenhum bloco do modelo da página (contam os blocos herdados por `extends` e os de uma página de `variants`). O conteúdo vai para o bloco de fluxo. | Corrija o nome do slot ou acrescente ao modelo um bloco com esse nome. |
| `slotEmpty` | Um bloco do modelo não recebe nada nesta página: nenhum slot o nomeia, ele não recebe nenhum título e, se for o bloco de fluxo, não sobra conteúdo sem slot. Um bloco que só recebe o que outro bloco continua nele (`next`) não é assinalado. O `postext check` o lista como nota. | Escreva conteúdo para esse bloco com o slot dele, ou marque-o como `optional: true` no modelo. |
| `pageFenceLength` | Um `:::page` de três dois-pontos traz `template=`. Ele é lido como página de quadrinhos, como antes. | Abra a página com quatro dois-pontos, `::::page{template="…"}`, e feche com `::::`. |
| `unclosedContainer` | Uma página composta, um bloco ou uma figura fica sem fechamento (veja as regras de recuperação acima). O painel Verificações chama a página composta de `::::page`. | Acrescente a cerca de fechamento: tantos dois-pontos quanto a linha de abertura da página, ou `:::` para um bloco ou uma figura. |

### frameOverflow

Este aviso vem da diagramação, não das verificações do código-fonte descritas acima: ele aparece quando a página já está composta, no painel Verificações, no `postext check` e nos `contentWarnings` do documento.

**Causa.** O conteúdo que entra em um bloco (pelo slot dele, ou o que vai para o bloco de fluxo) é mais alto que o bloco, e o bloco não tem mais nenhum `next` onde continuar. Quase sempre há mais texto do que o bloco comporta: uma tradução mais longa que o original, ou um bloco preso a um `height` ou `maxHeight` fixo. O que não cabe é cortado no pé do bloco na saída paginada; continua no documento, no mapa de origem e no EPUB de layout fluido. O aviso informa o modelo, o bloco, a página, a altura cortada (`overflowMm`) e `configPath`, o ponteiro JSON do bloco na configuração (`/pageTemplates/0/frames/2`).

**Correção.** Dê mais espaço ao bloco (aumente ou remova o `height` ou o `maxHeight` dele), encadeie-o a outro bloco com `next`, encurte o texto ou componha a página com outro modelo. Por enquanto a diagramação não reduz o texto para que ele caiba.

## No código

`composedPages(blocks)` lê os blocos analisados de um capítulo (`parseMarkdownWithIssues(markdown).blocks`) e devolve um nó por cerca de página, em ordem: o seu `template`, `spread`, `attrs` com o intervalo de origem de cada valor (`attrSources`), o seu `fenceIndex` (o ordinal da cerca no capítulo, o mesmo em todos os idiomas), `slots` (os índices dos blocos de cada slot, na ordem do Markdown), `unassigned` (os blocos sem slot) e o intervalo de origem da página inteira. Um bloco traz o slot que nomeia em `ContentBlock.slot`, com o intervalo de origem do valor; uma figura é um `resourceBlock` cujo `figure` guarda os seus atributos e rótulos, cada rótulo com o seu texto, os seus trechos em linha e um mapa de origem que leva de volta ao Markdown. `checkComposedSlots(pages, config)` devolve os três avisos de slot dessas páginas.

Depois da diagramação, o `VDTPage.composed` de uma página composta registra o seu modelo, a variante aplicada, os atributos da cerca de página e, para cada bloco, o seu id (`cp0:dinero`: o ordinal da cerca de página e o nome do bloco, o mesmo em todos os idiomas), a sua caixa, a camada, o giro, a altura do conteúdo que não coube (`overflowPx`), o bloco de onde ele vem ou para onde continua, o seu caminho na configuração (`/pageTemplates/0/frames/2`) e os ids dos seus elementos. Esses elementos são boxes comuns em `page.floats` e `doc.blocks`, com os seus intervalos de origem, então um clique num bloco sem giro da prévia do Sandbox leva ao seu Markdown. `composedPaintOrder(page)` dá a ordem em que um renderizador pinta os blocos e a decoração, e `frameMatrix(frame)`, o giro de um bloco.
