# Configurazione: risorse e tabelle

> I tipi di risorsa e la loro numerazione, gli stili di tabelle e didascalie, i diagrammi a inchiostro unico e i video in stampa

- Versione HTML: https://postext.dev/it/docs/configuration-resources
- Ultimo aggiornamento: 2026-10-10
- Tempo di lettura: 5 min
- Altre lingue: [en](https://postext.dev/en/docs/configuration-resources.md), [es](https://postext.dev/es/docs/configuration-resources.md), [ca](https://postext.dev/ca/docs/configuration-resources.md), [de](https://postext.dev/de/docs/configuration-resources.md), [fr](https://postext.dev/fr/docs/configuration-resources.md), [pt](https://postext.dev/pt/docs/configuration-resources.md), [zh](https://postext.dev/zh/docs/configuration-resources.md), [ja](https://postext.dev/ja/docs/configuration-resources.md), [ar](https://postext.dev/ar/docs/configuration-resources.md)

## In breve

Questa pagina tratta le impostazioni di figure, tabelle, diagrammi e video. Postext li chiama risorse e numera ogni tipo per conto suo. Stabilisci l’aspetto delle tabelle: i filetti, i fondi, i caratteri e il modo in cui si dividono tra le pagine. Stabilisci come si scrive la didascalia di una figura o di una tabella. Puoi anche stampare i diagrammi con un solo colore d’inchiostro e scegliere come appare un video sulla carta.

## Tipi di risorsa

Un **tipo di risorsa** è una categoria definibile dall’utente (*Figura*, *Tabella*, *Diagramma*, *Listato*…) che determina come vengono numerate, accompagnate da didascalia e richiamate le risorse di quel tipo. L’elenco si trova in `config.resourceTypes`; la Sandbox lo modifica in **Grafica → Figure e tabelle → Numerazione e posizione**.

Quando `config.resourceTypes` non è impostato, Postext fornisce tre tipi predefiniti integrati: **Figura**, **Tabella** e **Video**, ciascuno numerato per conto suo con `{h1}.{n}` (che riparte a ogni titolo di livello 1) e contatori decimali. Un elenco senza un tipo `video` (un libro salvato prima che esistessero i video) numera comunque le risorse video di tipo `video`: per loro viene aggiunto il tipo Video integrato (`effectiveResourceTypes(config, resources)`), e `defaultVideoResourceType(locale)` lo restituisce da solo. I nomi sono nella lingua del documento: `config.locale`, altrimenti `bodyText.hyphenation.locale`, altrimenti l’inglese (vedi [Lingua del documento](https://postext.dev/it/docs/configuration-text.md#lingua-del-documento)).

I tipi predefiniti integrati tengono conto della lingua. La funzione esportata `defaultResourceTypes(locale = 'en')` localizza i nomi dei tipi, le etichette brevi e i prefissi delle didascalie nella lingua del documento: l’inglese dà *Figure*/*Fig.* e *Table*/*Tab.*; lo spagnolo dà *Figura*/*Fig.* e *Tabla*/*Tabla*; anche francese, tedesco, italiano, portoghese, catalano e olandese hanno i loro (la tabella in [Lingua del documento](https://postext.dev/it/docs/configuration-text.md#lingua-del-documento) li elenca). Le etichette regionali come `es-ES` si risolvono per lingua, e qualsiasi lingua senza traduzioni ripiega sull’inglese. Il comportamento della numerazione (`numberingTemplate: '{h1}.{n}'`, `resetOn: 'h1'`, contatori decimali) non dipende dalla lingua. Ogni chiamata restituisce oggetti nuovi, quindi puoi modificare liberamente il risultato:

```ts
import { defaultResourceTypes } from 'postext';

const types = defaultResourceTypes('es');
// => [{ id: 'figure', name: 'Figura', shortLabel: 'Fig.', captionPrefix: 'Figura',
//       numberingTemplate: '{h1}.{n}', resetOn: 'h1', counterFormat: 'decimal', … },
//     { id: 'table',  name: 'Tabla',  shortLabel: 'Tabla', captionPrefix: 'Tabla', … },
//     { id: 'video',  name: 'Vídeo',  shortLabel: 'Vídeo', captionPrefix: 'Vídeo', … }]
```

```ts
type ResourceCounterFormat =
  | 'decimal'
  | 'roman-lower'
  | 'roman-upper'
  | 'alpha-lower'
  | 'alpha-upper';

type ResourceCounterReset = 'never' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';

interface ResourcePlacement {
  position?: 'auto' | 'top' | 'bottom' | 'here'; // which free slot a float may take; 'here' = inline embed at the ::resource directive
  span?: 'column' | 'page' | 'side';             // one column, the full content width, or the float-only side column
  rotate?: 'ccw' | 'cw';                         // a quarter turn: a landscape table on a page of its own
  width?: number;                                // fraction (0 < width < 1) of the column or page width; default: the whole width
  align?: 'left' | 'center' | 'right';           // where a float narrower than its column sits; default 'left'
  captionSide?: boolean;                         // caption beside the figure, in the side column of a oneAndHalf layout (column floats and resources set in the text)
  columns?: number;                              // a 'column' float across this many adjacent columns (since 1.18)
  wrap?: 'none' | 'left' | 'right' | 'start' | 'end'; // text beside the resource, at that side of its column (since 1.24)
  wrapGap?: Dimension;                           // space between the wrapped resource and the text (since 1.24)
}

interface ResourceType {
  id: string;                          // stable id, referenced by Resource.typeId
  name: string;                        // singular display name, e.g. "Figure"
  namePlural?: string;                 // optional plural, e.g. "Figures"
  shortLabel: string;                  // compact label for inline refs, e.g. "Fig."
  numberingTemplate: string;           // "{h1}.{n}" or "{n}"
  resetOn: ResourceCounterReset;       // when the {n} counter resets
  counterFormat: ResourceCounterFormat;// how {n} is formatted
  captionPrefix: string;               // prepended to the caption, e.g. "Figure"
  defaultPlacement?: ResourcePlacement;// fallback placement for this type's resources
}
```

`ResourcePlacement` ha la stessa forma del `placement` che una risorsa imposta per conto proprio. `position` sceglie il tipo di spazio libero che un elemento flottante può occupare: `auto` (il valore predefinito) prende il primo dopo il primo rimando, `top` / `bottom` lo limitano a quel tipo di fascia, `here` incorpora la risorsa nel testo. `span` imposta l’estensione dell’elemento flottante: una colonna, l’intera larghezza del contenuto o la colonna laterale riservata agli elementi flottanti di un impaginato a colonna e mezza. `rotate` ruota la risorsa di un quarto di giro e ne fa un elemento flottante a tutta pagina su una pagina tutta sua. `width` restringe un elemento flottante a una frazione della sua colonna (o della pagina, per un elemento a tutta larghezza): per esempio una tabella piccola in una colonna larga. `align` dice dove si colloca un elemento flottante più stretto (a sinistra per impostazione predefinita, al centro o a destra) e dove si colloca nel suo spazio un’immagine più stretta di quello spazio: una bitmap più piccola della colonna, o un’immagine ridotta da `layout.fitFiguresToPage`. La didascalia e la nota mantengono la giustezza dello spazio. (Fino a postext 1.4 un’immagine del genere veniva sempre allineata a sinistra.) `captionSide` colloca la didascalia accanto alla figura nella colonna laterale riservata agli elementi flottanti di un impaginato a colonna e mezza (`layout.sideColumnRole: 'floats'`), allineata alla testa della figura (al piede, per un elemento flottante in basso); si applica agli elementi flottanti di colonna e, da postext 1.28, a una risorsa composta nel testo (`position: 'here'`, larga una colonna, senza testo che le scorra attorno), la cui didascalia e la cui nota stanno nella colonna laterale all’altezza della testa del corpo della risorsa dove quella colonna è libera accanto, e sotto il corpo dove non lo è (`layout.inlineCaptionSide`, attivo per impostazione predefinita; `false` riserva le didascalie laterali agli elementi flottanti di colonna); una pagina senza una colonna del genere tiene la didascalia sotto la figura. Quando né la risorsa né il suo tipo impostano un posizionamento, vale il predefinito integrato `auto` / `column`. `shrink` (`'never'`, `'page'`, `'slot'`) e `minScale` (0.7 se non impostato) riducono un’immagine flottante allo spazio disponibile invece di spostarla oltre, e `captionMeasure: 'body'` compone la didascalia e la nota di un’immagine più stretta del suo spazio alla larghezza dell’immagine (vedi [Formato del documento › Posizionamento](https://postext.dev/it/docs/document-format.md#collocazione)); `layout.floatShrink` dà il valore predefinito del documento per i primi due. `wrap` colloca un’incorporazione nel testo o un elemento flottante di una colonna su un lato della sua colonna con il testo che scorre accanto, a distanza `wrapGap`; `layout.wrap` contiene i valori predefiniti (vedi [Formato del documento › Testo attorno alle risorse](https://postext.dev/it/docs/document-format.md#testo-intorno-alle-immagini)). `citingPage` permette a un elemento flottante `top` o `auto` di aprire la pagina o la colonna in cui cade la riga che lo cita, invece di prendere il primo spazio libero successivo; `layout.floatsAtCitingPage` dà il valore predefinito del documento e `layout.maxTopFraction` la quota della colonna che può occupare (vedi [Formato del documento › Posizionamento](https://postext.dev/it/docs/document-format.md#collocazione)).

`columns` (da postext 1.18) estende un elemento flottante `span: 'column'` su quel numero di colonne adiacenti in una pagina che ne ha diverse: un’immagine su due delle cinque colonne di un quotidiano. La sua giustezza è data da quelle colonne e dagli intercolonni tra loro. Occupa la testa di una serie di colonne vuote che cominciano alla stessa altezza, oppure il piede della colonna che la cita e delle colonne vuote successive; tante colonne quante ne ha la pagina, o più, ne fanno un elemento flottante a tutta larghezza. Viene ignorato dagli span `'page'` e `'side'`, da una risorsa ruotata (`rotate`) e da un’incorporazione nel testo (`here`), e `captionSide` si applica solo a un elemento flottante largo una colonna.

| Proprietà | Tipo | Descrizione |
| --- | --- | --- |
| `id` | `string` | Identificatore stabile a cui fa riferimento il `typeId` di ogni risorsa. Si imposta una volta, quando il tipo viene creato; eliminare un tipo a cui alcune risorse fanno ancora riferimento genera un avviso di **tipo orfano**. |
| `name` | `string` | Nome visualizzato al singolare. Usato dal rimando in linea `style="full"` (ad esempio `Figure 1.7`). |
| `namePlural` | `string` (opzionale) | Nome visualizzato al plurale, per le etichette dell’interfaccia e gli elenchi di risorse. |
| `shortLabel` | `string` | Abbreviazione compatta usata dallo stile di rimando in linea predefinito (ad esempio `Fig. 1.7`). |
| `numberingTemplate` | `string` | Modello per il numero calcolato. Vedi **Token del modello** più avanti. Le forme comuni sono `{h1}.{n}` (per capitolo, ad esempio `2.3`) e `{n}` (un conteggio progressivo unico). |
| `resetOn` | `ResourceCounterReset` | `'never'` dà un unico conteggio progressivo per tutto il documento; da `'h1'` a `'h6'` azzerano il contatore `{n}` ogni volta che si incontra un titolo di quel livello (o di un livello superiore). Imposta il valore corrispondente al livello di titolo che compare nel modello: ad esempio `{h1}.{n}` con `resetOn: 'h1'`. |
| `counterFormat` | `ResourceCounterFormat` | Come viene scritto il contatore `{n}`: decimale (`1, 2, 3`), romano minuscolo/maiuscolo (`i, ii` / `I, II`) o alfabetico minuscolo/maiuscolo (`a, b` / `A, B`). Sono accettate anche le grafie delle pagine e degli elenchi (`'lower-roman'`, `'arabic'`…; vedi [Grafie dei formati di numerazione](https://postext.dev/it/docs/configuration-page-layout.md#grafie-dei-formati-di-numerazione)); un valore sconosciuto conta in decimale e viene segnalato. I token dei titoli (`{h1}`…) sono sempre scritti in decimale. |
| `captionPrefix` | `string` | Testo anteposto alla didascalia della figura o della tabella. Il numero calcolato segue il prefisso: una didascalia appare come `{captionPrefix} {number}. {caption text}`, ad esempio **Figura 1.7. La pianta originale.** Un tipo con `numberingTemplate` vuoto non ha numero, e la sua didascalia appare come `{captionPrefix}. {caption text}`. Gli spazi alla fine del prefisso vengono eliminati, e un prefisso che termina già con `.`, `:`, `!`, `?` o `…` (o con la loro forma a larghezza piena) non riceve un secondo punto: **Tav. Righe a 0°**. |
| `defaultPlacement` | `ResourcePlacement` (opzionale) | Posizionamento usato dalle risorse di questo tipo che non impostano un proprio `placement`: `position`, `span`, `rotate`, `width`, `align`, `captionSide` e `columns`, ciascuno risolto in modo indipendente. Quando né la risorsa né il tipo impostano un campo, vale il predefinito integrato: `auto` / `column`, dritta, a tutta larghezza, allineata a sinistra, didascalia sotto la figura. Vedi [Numerazione e rimandi](https://postext.dev/it/docs/configuration-resources.md#numerazione-e-rimandi) più avanti per la catena di risoluzione e [Formato del documento › Risorse](https://postext.dev/it/docs/document-format.md#risorse) per l’effetto di ogni valore, comprese le risorse ruotate. |
| `captionStyle` | `CaptionStyleConfig` (opzionale) | Sostituzione parziale dello [stile delle didascalie](https://postext.dev/it/docs/configuration-resources.md#stile-delle-didascalie) per le risorse di questo tipo. Solo le chiavi che imposti sostituiscono il `captionStyle` globale; tutto il resto viene ereditato (un `color` sostituito determina anche i colori dell’etichetta e della nota, a meno che questi non siano impostati esplicitamente). Uso tipico: tabelle con didascalia *sopra* su una barra colorata, mentre le figure tengono la didascalia sotto. I riferimenti alla tavolozza si risolvono come qualsiasi altro colore. |

### Token del modello

`numberingTemplate` viene elaborato dallo stesso motore della numerazione dei titoli (vedi [Titoli](https://postext.dev/it/docs/configuration-text.md#titoli)). Riconosce due tipi di token:

- `{n}`: il contatore del tipo, formattato secondo `counterFormat`. È il valore che aumenta a ogni risorsa e si azzera secondo `resetOn`.
- da `{h1}` a `{h6}`: i numeri dei titoli in vigore nel punto del primo rimando, in decimale a meno che il token non indichi uno stile. `{h1}` è il numero del titolo di livello 1 corrente, `{h2}` quello di livello 2, e così via.
- `{h1:A}`, `{h2:i}`, `{n:i}`: un token seguito da due punti e da uno stile viene scritto in quello stile, uno qualsiasi di quelli accettati da un modello di titolo: `1`, `01`, `A`, `a`, `I`, `i`, il nome di un formato di numerazione come `upper-roman`, un token di un carattere come `一` o `①`, o uno stile in lettere come `Words`. Su `{n}` lo stile prevale su `counterFormat` per quel token. Uno stile sconosciuto conta in decimale. Da postext 1.28.

Qualsiasi altro testo è letterale. Una barra rovesciata rende letterale un `{`, un `}` o un `\`. Quando un token di titolo non ha un valore disponibile (ad esempio `{h1}` prima di qualsiasi titolo di livello 1), sparisce insieme al separatore adiacente: così `{h1}.{n}` si riduce senza problemi al semplice contatore.

Un modello vuoto (`''`) non stampa alcun numero, anche se il tipo continua a contare le sue risorse: una didascalia appare come *Do. Lines at 0°* e un `:ref` stampa la sola etichetta (*Do*). Fino a postext 1.4 una didascalia del genere appariva come *Do .Lines at 0°* e il rimando terminava con uno spazio indivisibile.

| Modello | Con `h1 = 2`, contatore = 3 | Note |
| --- | --- | --- |
| `{n}` | `3` | Un conteggio progressivo unico. Da abbinare a `resetOn: 'never'`. |
| `{h1}.{n}` | `2.3` | Per capitolo. Da abbinare a `resetOn: 'h1'`. |
| `{h1}.{h2}.{n}` | `2.0.3` | Per sezione. Da abbinare a `resetOn: 'h2'`. |
| `{h1:A}.{n}` | `B.3` | Con lettere, per le appendici. Da abbinare a `resetOn: 'h1'`. |

**Appendici.** Un libro le cui appendici sono contrassegnate da lettere tramite uno stile di titolo (`numberingTemplate: 'Appendix {1:A}'`, con `startAt=1` sulla prima) dà alle loro figure e tabelle un tipo a sé, `{ ...table, id: 'table-a', numberingTemplate: '{h1:A}.{n}', resetOn: 'h1' }`. Un solo tipo serve tutte le appendici: stampa *Table A.1*, *A.2* e *B.1*, nella didascalia e nel `:ref`. Un semplice `{h1}` in quella posizione stampa il numero del titolo in decimale (*Table 1.1*).

### Numerazione e rimandi

Il numero prodotto da un tipo di risorsa è ciò che `:ref` stampa e ciò che il prefisso della didascalia precede. `:ref{id}` è la forma principale: il primo rimando in ordine di lettura **incorpora** la risorsa, che flotta nel primo spazio libero dopo quel rimando, cioè il piede della colonna che la richiama, la testa o il piede della colonna vuota successiva, o una fascia della pagina successiva (secondo il posizionamento risolto: `position: 'auto' | 'top' | 'bottom' | 'here'` e `span: 'column' | 'page' | 'side'`, più `rotate`, `width`, `align` e `captionSide`, risolti per ogni risorsa, poi con il `defaultPlacement` del tipo, poi con il predefinito integrato `auto` / `column`; `'top'` / `'bottom'` limitano la ricerca a quel tipo di spazio). L’incorporazione a blocco `::resource{id}` è facoltativa e serve solo per `placement.position: 'here'`, un’incorporazione nel testo, non flottante, in un punto preciso del flusso. La grammatica completa lato documento (entrambe le forme più le opzioni `style` e `text` di `:ref`) è documentata in [Formato del documento › Risorse](https://postext.dev/it/docs/document-format.md#risorse), compreso il modo in cui l’ordine dei primi rimandi determina il conteggio.

È lo stesso schema della numerazione dei titoli: come un livello di titolo porta un `numberingTemplate`, ne porta uno anche un tipo di risorsa; ma il contatore delle risorse (`{n}`) avanza a ogni primo rimando anziché a ogni titolo, e `resetOn` lo ricollega alla gerarchia dei titoli.

### Che cosa viene numerato

Una risorsa viene numerata quando il testo la richiama (con `:ref` o con un’incorporazione `::resource`), nell’ordine di quei primi rimandi, qualunque sia il suo posizionamento: flottante, nel testo (`here`), nella colonna laterale o ruotata. Una risorsa disegnata solo da un elemento grafico (un elemento `image` di un’apertura di capitolo, di una testatina o di una pagina di parte) o che nessuno richiama non riceve un numero e non fa avanzare il contatore del suo tipo. Così, in un saggio fotografico le cui tavole al vivo sono immagini delle aperture e la cui unica tavola più piccola è un elemento flottante citato, quell’elemento è la tavola **I**, per quante tavole abbiano mostrato prima le aperture; numera le tavole delle aperture nel loro progetto grafico (con un attributo come `{attr.plate}`) e lascia il contatore alle tavole citate dal testo.

In un libro impaginato capitolo per capitolo (la Sandbox, `buildBundle` o `buildDocument` con i contatori passati da `continuationAfter()`), conta il primo rimando dell’intero libro: una risorsa mantiene il numero ricevuto nel capitolo che la richiama per primo, e solo quel capitolo la colloca. Il `:ref` di un capitolo successivo stampa quel numero e non colloca nulla, e lì un’incorporazione `::resource` di una risorsa flottante è solo un altro rimando (un’incorporazione nel testo `here` viene comunque composta dove è scritta). Un rimando del genere è un link alla figura quando la figura si trova nello stesso output: un PDF dell’intero libro lo collega alla pagina del capitolo precedente. Un capitolo generato da solo, in HTML o PDF, lo compone come testo semplice nel colore dei link, perché la sua figura non è in quel documento. Un host che riunisce l’HTML dei capitoli in una sola pagina passa a `renderToHtml` le risorse ancorate dai capitoli, come `refTargets`, e un rimando del genere torna a essere un link alla figura del capitolo precedente:

```ts
import { anchoredResourceIds, buildBundle, renderToHtml } from 'postext';

const docs = buildBundle(bundle);
const refTargets = new Set(docs.flatMap((d) => [...anchoredResourceIds(d)]));
const html = docs.map((d) => renderToHtml(d, { refTargets })).join('');
```

**Cambiato in postext 1.5:** fino alla 1.4 ogni capitolo che richiamava una figura la faceva flottare di nuovo, e l’HTML di ogni `:ref` era un link, che la sua figura fosse nella pagina oppure no.

`{h1}` è il conteggio progressivo dei titoli di livello 1: ogni H1 lo fa avanzare, a meno che il suo stile di titolo non imposti `numbered: false`; un `numberingTemplate` vuoto nasconde il numero del titolo, ma non ferma il conteggio. Un articolo il cui unico H1 è il titolo numera quindi le sue figure `1.1`, `1.2`… con i tipi integrati `{h1}.{n}`. Due modi per stampare Figura 1, 2…:

- un tipo numerato `{n}` con `resetOn: 'never'` (con `resetOn: 'h1'` il conteggio ripartirebbe a ogni H1);
- uno [stile di titolo](https://postext.dev/it/docs/configuration-styles.md#stili-dei-titoli) con `numbered: false` sul titolo, e su ogni altro H1 che non deve contare: un titolo del genere non fa avanzare `{h1}` ma lo lascia com’era (vuoto prima del primo H1 contato, dove `{h1}.{n}` si riduce al semplice contatore) e non fa mai scattare `resetOn: 'h1'`, così il conteggio prosegue oltre. Dopo `# Introduction` e la sua Figura 1.1, la prima figura sotto un `# Appendix` non numerato è la 1.2, non la 2.1.

```ts
// Figure 1, 2, 3… in a single-article document
resourceTypes: defaultResourceTypes('en').map((t) => ({ ...t, numberingTemplate: '{n}', resetOn: 'never' })),
```

## Stile delle tabelle

La proprietà `tableStyle` controlla la tipografia e la decorazione delle risorse di tipo tabella: di tutte le tabelle, a meno che una non scelga uno [stile di tabella con nome](https://postext.dev/it/docs/configuration-resources.md#stili-di-tabella-con-nome). Le celle del corpo e quelle d’intestazione hanno stili indipendenti. Famiglia, corpo e colori del carattere ereditano quelli risolti del testo corrente quando non sono impostati, così un documento senza `tableStyle` compone le tabelle con la tipografia del testo corrente.

```ts
const config: PostextConfig = {
  tableStyle: {
    headerBold: true,
    headerBackground: { hex: '#f0f0f0', model: 'hex' },
    borders: true,
    borderWidth: { value: 0.75, unit: 'pt' },
  },
};
```

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `bodyFontFamily` | `string` | font del testo corrente | Famiglia di caratteri delle celle del corpo. |
| `bodyFontSize` | `Dimension` | corpo del testo corrente | Corpo del carattere delle celle del corpo. |
| `bodyColor` | `ColorValue` | colore del testo corrente | Colore del testo delle celle del corpo. |
| `headerFontFamily` | `string` | font del testo corrente | Famiglia di caratteri delle celle d’intestazione. |
| `headerFontSize` | `Dimension` | corpo del testo corrente | Corpo del carattere delle celle d’intestazione. |
| `headerColor` | `ColorValue` | colore del testo corrente | Colore del testo delle celle d’intestazione. |
| `headerBold` | `boolean` | `true` | Compone le celle d’intestazione in grassetto. |
| `headerItalic` | `boolean` | `false` | Compone le celle d’intestazione in corsivo. |
| `headerLetterSpacing` | `Dimension` | `0pt` | Tracking dopo ogni carattere di una cella d’intestazione, spazi compresi, come il `letter-spacing` del CSS. I valori positivi distanziano le lettere (un’intestazione in maiuscolo di solito vuole da `0.05em` a `0.1em`), quelli negativi le stringono. Un `em` è il corpo dell’intestazione. Le righe d’intestazione vengono misurate con questo valore, quindi vanno a capo, si centrano e si allineano tenendo conto del tracking, e canvas, HTML e PDF lo disegnano allo stesso modo. Si applica a ogni cella d’intestazione: le righe d’intestazione e qualsiasi cella marcata `isHeader`. |
| `headerTextTransform` | `'none' \| 'uppercase'` | `'none'` | Compone le celle d’intestazione in maiuscolo. Il testo mantiene la sua lunghezza, così la Sandbox continua a far corrispondere ogni lettera al sorgente: una lettera la cui maiuscola è più lunga (`ß`) resta com’è. I rimandi alle risorse mantengono la loro etichetta. |
| `headerBackgroundEnabled` | `boolean` | `true` | Disegna un fondo dietro la riga d’intestazione. |
| `headerBackground` | `ColorValue` | `#f0f0f0` | Colore di fondo della riga d’intestazione. |
| `bodyBackgroundEnabled` | `boolean` | `false` | Disegna un fondo dietro le righe del corpo. |
| `bodyBackground` | `ColorValue` | `#ffffff` | Colore di fondo delle righe del corpo (disegnato solo se attivo). |
| `bodyAlternateBackgroundEnabled` | `boolean` | `false` | Righe alternate: riempie una riga del corpo su due con `bodyAlternateBackground`. Vedi [righe alternate](https://postext.dev/it/docs/configuration-resources.md#righe-alternate). |
| `bodyAlternateBackground` | `ColorValue` | `#f2f2f2` | Fondo delle righe alternate del corpo (disegnato solo se attivo). |
| `borders` | `boolean` | `true` | Traccia i bordi delle celle. |
| `borderColor` | `ColorValue` | colore del testo corrente | Colore del tratto dei bordi. |
| `borderWidth` | `Dimension` | `0.75pt` | Spessore del tratto dei bordi (≈1px a 96 DPI; scala con i DPI della pagina). Non usato da `'booktabs'`, che ha spessori propri. |
| `cellPadding` | `Dimension` | `0.375em` | Spaziatura interna di ogni cella. |
| `rules` | `'grid' \| 'horizontal' \| 'outer' \| 'none' \| 'booktabs'` | `'grid'` | Quali filetti tracciare quando `borders` è attivo: la griglia completa delle celle, solo i filetti orizzontali (bordo superiore e inferiore di ogni riga, nessun verticale), solo la cornice esterna, nessuno, oppure i tre filetti di una tabella da rivista scientifica (vedi [filetti booktabs](https://postext.dev/it/docs/configuration-resources.md#filetti-booktabs)). |
| `borderRadius` | `Dimension` | `0` | Raggio degli angoli della cornice esterna della tabella. La cornice viene tracciata arrotondata (con i filetti `grid` o `outer`), i fondi delle celle e il fondo dell’intestazione vengono ritagliati su di essa (anche con `rules: 'none'` o con i bordi disattivati) e i filetti orizzontali vengono accorciati sul suo contorno esterno; i filetti interni restano dritti. Una tabella divisa tra più pagine arrotonda gli angoli superiori della prima parte e quelli inferiori dell’ultima. Limitato a metà della larghezza e dell’altezza della tabella. I filetti `'booktabs'` restano dritti (i fondi vengono comunque ritagliati). |
| `heavyRuleWidth` | `Dimension` | `0.08em` | Booktabs: i filetti sopra la tabella e sotto la sua ultima riga. Un `em` è il corpo delle celle del corpo. |
| `lightRuleWidth` | `Dimension` | `0.05em` | Booktabs: il filetto sotto le righe d’intestazione e i filetti di gruppo. |
| `spanRuleWidth` | `Dimension` | `0.03em` | Booktabs: i filetti sotto le celle d’intestazione che coprono più colonne. |
| `spanRules` | `'trimmed' \| 'full' \| 'none'` | `'trimmed'` | Booktabs: i filetti sotto le celle d’intestazione che coprono più colonne, sopra l’ultima riga d’intestazione: accorciati alle due estremità di `spanRuleTrim`, estesi a tutta la cella, oppure assenti. |
| `spanRuleTrim` | `Dimension` | `0.5em` | Booktabs: di quanto viene accorciato a ciascuna estremità un filetto di raggruppamento accorciato. |
| `groupRules` | `boolean` | `false` | Booktabs: un filetto sottile sopra ogni riga del corpo che apre un gruppo. |
| `continuedFootRule` | `'bottom' \| 'light' \| 'none'` | `'light'` | Booktabs: che cosa chiude una parte di una tabella divisa che prosegue a pagina seguente. |
| `overflow` | `'split' \| 'clip' \| 'hide'` | `'split'` | Che cosa succede a una tabella più alta della pagina: prosegue nelle pagine successive, tiene solo le righe che entrano, oppure viene omessa. Con `splitInline`, vale anche per una tabella composta nel testo che non entra nel resto della sua colonna. Vedi più avanti. |
| `splitInline` | `boolean` | `true` | Applica `overflow` anche alle tabelle collocate `here`: una tabella nel testo che non entra nello spazio rimasto nella sua colonna viene tagliata tra due righe e prosegue in testa alla colonna successiva. `false` sposta una tabella del genere intera alla colonna successiva, come fino a postext 1.24; le configurazioni salvate da versioni precedenti i cui capitoli incorporano una risorsa vengono lette con `false`. Vedi [Tabelle più alte della pagina](https://postext.dev/it/docs/configuration-resources.md#tabelle-più-alte-della-pagina). Da postext 1.25. |
| `continuedSuffix` | `string` | `'(cont.)'` | Aggiunto, in corsivo, alla didascalia di ogni parte successiva di una tabella divisa, dopo uno spazio; un suffisso che comincia con un carattere cinese o a larghezza piena (`'（续）'`) viene composto attaccato alla didascalia. |
| `continuesMarkerEnabled` | `boolean` | `true` | Compone un indicatore sotto ogni parte che prosegue nella pagina successiva. |
| `continuesMarker` | `string` | `'Continued'` / `'Continúa'` | Testo di quell’indicatore, allineato a destra sotto la parte con il carattere delle note (vedi [stile delle didascalie](https://postext.dev/it/docs/configuration-resources.md#stile-delle-didascalie)). Il valore predefinito segue la lingua del documento (vedi [Lingua del documento](https://postext.dev/it/docs/configuration-text.md#lingua-del-documento) per le otto lingue). |

Gli spessori dei bordi restano frazionari: un filetto di `0.5pt` viene tracciato come filetto sottilissimo nel PDF e sullo schermo invece di essere arrotondato a un pixel intero (il minimo è 0,25 px).

### Righe alternate

Le tabelle di dati lunghe si seguono meglio in orizzontale quando una riga su due è colorata. `bodyAlternateBackgroundEnabled` attiva le strisce e `bodyAlternateBackground` ne imposta il colore:

```ts
const config: PostextConfig = {
  tableStyle: {
    bodyBackgroundEnabled: true,
    bodyBackground: { hex: '#ffffff', model: 'hex' },
    bodyAlternateBackgroundEnabled: true,
    bodyAlternateBackground: { hex: '#eef3fa', model: 'hex' },
  },
};
```

Le righe si contano dalla prima riga dopo le righe d’intestazione (`TableModel.headerRowCount`, o le righe iniziali fatte di celle d’intestazione): quella riga mantiene `bodyBackground` (o nessun fondo finché `bodyBackgroundEnabled` è disattivato), la successiva prende il fondo alternato, e così via. Il conteggio segue il modello della tabella, non la pagina, così una tabella divisa tra più pagine mantiene la striscia di ogni riga su ogni pagina, e una cella unita su più righe prende la striscia della sua prima riga. Le celle d’intestazione mantengono il fondo dell’intestazione, il `background` proprio di una cella prevale su entrambi, e un colore collegato alla tavolozza segue la tavolozza. Uno [stile di tabella con nome](https://postext.dev/it/docs/configuration-resources.md#stili-di-tabella-con-nome) imposta i due campi come qualsiasi altro, così uno stile può essere a strisce mentre le altre tabelle del documento no; nella Sandbox sono l’interruttore *Righe alternate* e il suo colore, sotto **Celle del corpo**.

Nel VDT le celle delle righe alternate portano `alternate: true`, e l’impaginazione della tabella porta `bodyAlternateBackground`. `tableCellFill(table, cell)` restituisce il fondo con cui viene disegnata una cella (il suo, quello dell’intestazione, quello alternato o quello del corpo), ed è ciò che disegnano tutti i backend canvas, HTML e PDF. I fondi vicini si incontrano senza giunture: un browser con un rapporto di pixel frazionario o un visualizzatore PDF applica l’antialiasing a ogni fondo separatamente e lascerebbe trasparire la pagina in un filo sottilissimo tra due celle, per questo i backend HTML e PDF disegnano `tableCellFillRects(table)` (il fondo di ogni cella con una striscia su ogni lato che condivide con una cella disegnata dopo, che quella cella poi copre) e il canvas allinea i suoi fondi ai pixel del dispositivo.

### Filetti booktabs

Le tabelle delle riviste scientifiche e dei manuali si compongono di solito con tre filetti e nessuna linea verticale: un filetto spesso sopra la tabella, uno sottile sotto l’intestazione e uno spesso sotto l’ultima riga, con filetti corti sotto le intestazioni che raggruppano più colonne (il pacchetto LaTeX `booktabs`: `\toprule`, `\midrule`, `\cmidrule`, `\bottomrule`). `rules: 'booktabs'` traccia questo schema:

```ts
const config: PostextConfig = {
  tableStyle: {
    rules: 'booktabs',
    borderColor: { hex: '#000000', model: 'hex' },
    headerBackgroundEnabled: false,
  },
};
```

- Il filetto sopra la tabella e quello sotto la sua ultima riga sono spessi `heavyRuleWidth` (`0.08em`), il filetto sotto le righe d’intestazione `lightRuleWidth` (`0.05em`). Una tabella senza righe d’intestazione non ha il filetto d’intestazione.
- Una cella d’intestazione che copre più colonne sopra l’ultima riga d’intestazione riceve sotto di sé un filetto spesso `spanRuleWidth` (`0.03em`). Con `spanRules: 'trimmed'` (il valore predefinito) il filetto viene accorciato di `spanRuleTrim` (`0.5em`) alle due estremità, così i filetti sotto due intestazioni vicine non si toccano; `'full'` lo estende a tutta la cella e `'none'` lo omette.
- `groupRules: true` aggiunge un filetto sottile sopra ogni riga del corpo che apre un gruppo (una cella unica su tutta la tabella, o una riga di celle d’intestazione), a meno che la riga non apra la tabella o una pagina, dove c’è già il filetto d’intestazione.
- Gli spessori si risolvono rispetto al corpo delle celle del corpo (`bodyFontSize`), così un corpo d’intestazione più grande non ingrossa il filetto d’intestazione. Uno spessore di `0` elimina quel filetto.
- I filetti prendono `borderColor` (un colore collegato alla tavolozza segue la tavolozza e `:::part palette`), e `borders: false` li disattiva. `borderWidth` non si applica, e nemmeno `borderRadius`: i filetti restano dritti, mentre i fondi delle celle vengono comunque ritagliati sulla cornice arrotondata. I fondi dell’intestazione, le righe alternate e il `background` proprio di una cella funzionano come con gli altri schemi, sotto i filetti.
- Una tabella divisa tra più pagine ripete le righe d’intestazione su ogni parte, così ogni parte si apre con il filetto spesso e il filetto d’intestazione. Il filetto spesso sotto l’ultima riga chiude solo l’ultima parte; una parte che prosegue a pagina seguente termina con `continuedFootRule`: un filetto sottile (`'light'`, il valore predefinito), il filetto spesso (`'bottom'`) o niente (`'none'`).

L’impaginazione calcola i filetti una volta sola. La tabella del VDT li porta come `strokes` (`{ x1, y1, x2, y2, widthPx }`, relativi all’angolo superiore sinistro del corpo della tabella), e il canvas, il visualizzatore HTML, il PDF e l’EPUB a layout fisso tracciano esattamente quelli; in un PDF con tag sono artefatti di impaginazione. L’EPUB a layout fluido li scrive come bordi CSS sulla tabella e sulla sua intestazione, con i filetti accorciati disegnati come linee di sfondo. Nella Sandbox, **Booktabs** nel menu *Filetti* mostra questi campi e nasconde *Spessore del bordo* e *Raggio degli angoli*.

### Stili di tabella con nome

Raramente un documento compone tutte le tabelle allo stesso modo: una lista di controllo in una griglia blu notte con la cornice arrotondata, una riga di opzioni racchiusa solo dalla cornice esterna, una tabella di dati con semplici filetti orizzontali. `tableStyles` dichiara varianti con nome, e una risorsa tabella ne sceglie una con `table.styleId`. Ogni campo che uno stile non imposta viene letto prima da `tableStyle` e poi dal testo corrente, così uno stile dichiara solo ciò che distingue le sue tabelle. Una tabella senza `styleId`, o con un id che nessuno stile dichiara, mantiene `tableStyle`: un documento senza `tableStyles` viene composto esattamente come prima.

```ts
const config: PostextConfig = {
  tableStyle: {
    borderColor: { hex: '#163a76', model: 'hex' },
    borderWidth: { value: 1.3, unit: 'pt' },
    borderRadius: { value: 10, unit: 'pt' },
  },
  tableStyles: [
    {
      id: 'option',
      name: 'Option row',
      rules: 'outer',
      borderColor: { hex: '#7a9cc6', model: 'hex' },
      borderWidth: { value: 1, unit: 'pt' },
      borderRadius: { value: 8, unit: 'pt' },
      headerBackgroundEnabled: false,
    },
  ],
};

// In the resources: this table is set in the "option" style.
const resource: Resource = {
  id: 'choices', typeId: 'table', kind: 'table', createdAt: 0, updatedAt: 0,
  table: { model: { rows: [/* … */] }, styleId: 'option' },
};
```

Ogni voce accetta tutti i campi di `tableStyle` più `id` (ciò a cui fa riferimento `table.styleId`) e un `name` facoltativo per l’editor (per impostazione predefinita è l’id). Tutto ciò che uno stile può impostare si applica tabella per tabella: tipografia, fondi, bordi, filetti, raggio degli angoli, spaziatura interna e il comportamento in caso di sbordamento con le sue stringhe di continuazione. `resolveTableStylesConfig(styles, tableStyle, resolvedBodyText, locale?)` restituisce l’elenco risolto, `pickTableStyle(resolved, styleId)` lo stile con cui viene composta una tabella, e `stripTableStylesDefaults` elimina i campi non impostati (mantiene un campo uguale al suo predefinito integrato, che continua a sostituire un valore diverso di `tableStyle`). In un EPUB a layout fluido uno stile con nome è una classe sulla tabella (`pt-table-<id>`), a cui dà stile il foglio di stile del libro.

### Tabelle più alte della pagina

Una tabella flottante che non entra nella pagina nuova che le viene offerta non viene schiacciata né lasciata sbordare: con `overflow: 'split'` (il valore predefinito) il motore la taglia tra due righe all’ultimo bordo che entra nella pagina e la prosegue nelle pagine successive, quante ne servono. Ogni parte successiva ripete le righe d’intestazione della tabella (`TableModel.headerRowCount`, o le righe iniziali fatte di celle d’intestazione quando non è impostato) e riporta la didascalia con `continuedSuffix` dopo la descrizione: «Tabella 6-4. Titolo *(cont.)*». Ogni parte che prosegue riceve sotto di sé `continuesMarker`, allineato a destra, con il carattere delle note; la nota della tabella viene tenuta per l’ultima parte. Un taglio non attraversa mai una cella unita (un rowspan passa intero alla parte successiva), e una riga che fa da intestazione alle righe sottostanti (una cella unica su tutta la tabella) viene portata alla parte successiva invece di restare isolata al piede di una pagina. Una tabella booktabs chiude ogni parte che prosegue con `continuedFootRule` (vedi [filetti booktabs](https://postext.dev/it/docs/configuration-resources.md#filetti-booktabs)).

**Dove finisce la prima parte.** Una tabella a cui viene offerta la testa di una colonna vuota dopo il suo rimando prende le righe che entrano lì e prosegue nello spazio successivo. Riempie la colonna fino al piede quando ha la colonna tutta per sé: una parte che lascerebbe sotto di sé meno di tre righe di testo prende anche quelle, piuttosto che lasciare un moncone di testo. Quando la colonna contiene già un’altra fascia di elementi flottanti (per esempio una figura a tutta larghezza in testa alla pagina), la parte si ferma invece almeno tre righe di testo prima del piede, lo spazio per il testo che ogni elemento flottante lascia quando condivide una colonna con un altro, così la colonna termina con un po’ di testo sotto la tabella invece che con soli elementi flottanti. Perché una tabella lunga arrivi fino al piede della sua colonna, citala dove la pagina in cui comincia non porta altri elementi flottanti (dopo la pagina di una figura a tutta larghezza, per esempio), oppure adatta le sue righe alla colonna.

`'clip'` tiene le righe iniziali che entrano nella pagina e scarta il resto in silenzio (la nota chiude comunque la parte); `'hide'` omette del tutto la tabella. Entrambi si applicano solo quando la tabella è più alta di una pagina: una tabella che entra viene collocata intera in qualsiasi modalità.

**Tabelle composte nel testo.** Una tabella collocata `here` (incorporata con `::resource`) segue le stesse regole da postext 1.25 (`splitInline`, attivo per impostazione predefinita). Quando non entra nello spazio rimasto nella sua colonna, viene tagliata tra due righe: la prima parte mantiene sopra di sé lo spazio degli elementi flottanti e almeno le righe d’intestazione e due righe del corpo (se sono meno, l’intera tabella comincia nella colonna successiva, come prima), ogni parte successiva apre la colonna seguente senza spazio sopra, impaginata alla larghezza di quella colonna (un impaginato a colonna e mezza compone una parte nella colonna stretta alla sua larghezza), e il testo dopo la riga `::resource` segue l’ultima parte. La ripetizione dell’intestazione, la didascalia con il suffisso, l’indicatore, la nota sull’ultima parte, la coda di tre righe e i tagli che rispettano le celle unite e le intestazioni di gruppo sono quelli di una tabella flottante. Una tabella con meno di cinque righe del corpo non viene mai tagliata. `'clip'` tiene le righe iniziali di una tabella nel testo più alta di una colonna, composte in testa a una colonna; `'hide'` omette una tabella del genere; una più bassa passa intera alla colonna successiva in entrambe le modalità. Una pagina aperta da una tabella nel testo tiene libero dagli elementi flottanti solo lo spazio della prima parte, così una figura a tutta larghezza in attesa apre quella pagina e la tabella prosegue sotto. Le tabelle nel testo su una pagina verticale, e le tabelle dentro un riquadro, non vengono tagliate. `splitInline: false` sposta una tabella nel testo intera alla colonna successiva, come fino a postext 1.24.

Le stringhe di continuazione hanno valori predefiniti per lingua del documento (`locale`, altrimenti la lingua di sillabazione): inglese `(cont.)` / `Continued`, spagnolo `(cont.)` / `Continúa`, e analogamente in francese, tedesco, italiano, portoghese, catalano e olandese (elencate in [Lingua del documento](https://postext.dev/it/docs/configuration-text.md#lingua-del-documento)).

Il contenuto delle celle è Markdown in linea, e un a capo dentro una cella (un carattere di nuova riga, o `\\` come nelle didascalie e nelle note) comincia un nuovo paragrafo. Un paragrafo che si apre con un punto elenco o un trattino (`•`, `-`, `*`, `–`) o con un numero (`1.`, `1)`) seguito da uno spazio viene composto come voce di elenco: il segno viene disegnato come è scritto, il testo rientra rispetto al segno di `unorderedLists.gap` del documento, le righe a capo si allineano al testo, e due spazi iniziali annidano un livello. Così una cella scritta come `• Ofrece elección\n• Acomoda a personas diestras y zurdas` diventa un elenco di due voci. Una riga fatta solo di spazi normali non aggiunge nulla; una riga che contiene uno spazio indivisibile (U+00A0) è una riga della cella, come in CommonMark, quindi `1\n` seguito da uno spazio indivisibile rende la riga alta due righe di testo. Uno spazio indivisibile alla fine del testo di una cella mantiene la sua larghezza: `760` e uno spazio indivisibile, allineati a destra sopra `(231)`, terminano uno spazio prima del bordo, il che avvicina lo 0 all’1. Le cifre si allineano esattamente solo dove lo spazio è largo quanto la parentesi, e nella maggior parte dei caratteri è più stretto. (Fino a postext 1.4 venivano eliminati entrambi.)

Le larghezze delle colonne appartengono al modello della tabella, non allo stile: `TableModel.columnWidths` è un array facoltativo di pesi relativi, uno per colonna, normalizzati al momento dell’impaginazione; `[2, 1, 1]` dà alla prima colonna metà della larghezza. Un array mancante, di lunghezza sbagliata o con un peso non positivo ripiega su una divisione in parti uguali. L’editor di tabelle mantiene l’array allineato quando si aggiungono o si rimuovono colonne.

### Costruire i modelli di tabella

Un `TableModel` è una griglia ordinata per righe, e ogni cella viene impaginata in base alla sua posizione: `rows[r][c]` sta nella colonna `c`. Una cella unita mantiene quindi nella griglia le celle che copre, ciascuna marcata `hiddenBy` con la sua cella principale, a differenza di una tabella HTML, che le omette. Le funzioni di supporto per il modello esportate da `postext` mantengono questa forma; sono funzioni pure che restituiscono un nuovo modello: `mergeCells(model, { start, end })` e `unmergeCell(model, at)`, `addRow`, `addColumn`, `removeRow`, `removeColumn`, `setCellContent`, `setCellImage`, `setCellBackground` e `setAlignment`. Le quattro funzioni per righe e colonne mantengono intere le unioni: una riga o una colonna aggiunta dentro un blocco unito lo allarga, una aggiunta prima lo sposta, una rimossa da esso lo restringe (un blocco che perde la sua prima riga o colonna mantiene il contenuto nella sua nuova cella in alto a sinistra) e ogni `hiddenBy` continua a puntare alla sua cella principale.

`parseTSV(text, options?)` costruisce un modello da un testo separato da tabulazioni, come un intervallo incollato da un foglio di calcolo: le righe si separano agli a capo, le celle alle tabulazioni, e le righe corte vengono completate perché la griglia sia rettangolare. `headerRows` trasforma le righe iniziali in righe d’intestazione: le loro celle ricevono `isHeader` e il modello `headerRowCount`, così una tabella divisa tra più pagine le ripete.

```ts
import { parseTSV, mergeCells } from 'postext';

let model = parseTSV('Part\tQty\tNote\nBolt\t4\tM6\nNut\t8\t', { headerRows: 1 });
// model.headerRowCount === 1; model.rows[0][0] is { content: 'Part', isHeader: true }
model = mergeCells(model, { start: { row: 2, col: 1 }, end: { row: 2, col: 2 } });
// rows[2][1] gets colSpan: 2; rows[2][2] stays in the grid with hiddenBy: { row: 2, col: 1 }
```

`tableGridIssues(model)` controlla la griglia. Restituisce un elenco vuoto per un modello corretto, e altrimenti ogni punto in cui la griglia si rompe, in ordine di riga: `spanOverlap`, una cella visibile sotto il `colSpan` / `rowSpan` di un’altra cella (`coveredBy` indica quella cella), che è ciò che produce una cella coperta omessa alla maniera dell’HTML, perché ogni cella successiva slitta sull’unione; e `missingCells`, una riga che termina prima dell’ultima colonna senza un’unione che copra il resto, il che lascia un buco.

```ts
import { tableGridIssues } from 'postext';

tableGridIssues({
  rows: [
    [{ content: 'A', colSpan: 2 }, { content: 'C' }],
    [{ content: '1' }, { content: '2' }, { content: '3' }],
  ],
});
// => [{ kind: 'spanOverlap', row: 0, col: 1, coveredBy: { row: 0, col: 0 } },
//     { kind: 'missingCells', row: 0, col: 2 }]
```

Una tabella usata dal documento la cui griglia presenta problemi del genere viene segnalata in `doc.contentWarnings` come `raggedTableGrid` (vedi [Avvisi nel documento](https://postext.dev/it/docs/configuration-programmatic-usage.md#avvisi-nel-documento)).

## Stile delle didascalie

La proprietà `captionStyle` controlla le didascalie delle risorse (la riga `Figure 1 — …` sotto, o sopra, immagini, SVG e tabelle). L’etichetta numerata e la descrizione condividono lo stesso carattere e lo stesso corpo (un vincolo del motore), ma l’etichetta può avere peso, corsivo e colore propri. Famiglia, corpo e colore del carattere ereditano quelli del testo corrente quando non sono impostati. La didascalia può stare **sopra** la risorsa (la convenzione abituale per le tabelle) ed essere composta su una **barra** colorata larga quanto il blocco; una **nota** facoltativa più piccola (riga della fonte, crediti: `Resource.note`) ha il suo stile nel sotto-oggetto `note`. Un tipo di risorsa può sostituire uno qualsiasi di questi campi per le proprie risorse tramite `ResourceType.captionStyle` (vedi [Tipi di risorsa](https://postext.dev/it/docs/configuration-resources.md#tipi-di-risorsa)).

```ts
const config: PostextConfig = {
  captionStyle: {
    align: 'center',
    labelBold: true,
    labelColor: { hex: '#295AA3', model: 'hex' },
    descriptionItalic: true,
    position: 'above',
    backgroundEnabled: true,
    padding: { value: 0.35, unit: 'em' },
    note: { italic: true, align: 'left' },
  },
};
```

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `fontFamily` | `string` | font del testo corrente | Famiglia di caratteri della didascalia (etichetta e descrizione). |
| `fontSize` | `Dimension` | corpo del testo corrente | Corpo del carattere della didascalia (etichetta e descrizione). |
| `color` | `ColorValue` | colore del testo corrente | Colore del testo della descrizione. |
| `align` | `'left' \| 'center' \| 'right' \| 'justify' \| 'start' \| 'end'` | `'left'` | Allineamento orizzontale delle righe della didascalia. `'justify'` allarga ogni riga tranne l’ultima a tutta la larghezza. Su una barra di didascalia le righe si allineano dentro la sua spaziatura interna; una didascalia laterale si allinea entro la propria larghezza. |
| `gap` | `Dimension` | `0.75em` | Spazio verticale tra la risorsa e la sua didascalia. |
| `labelBold` | `boolean` | `true` | Compone l’etichetta numerata (ad esempio `Figure 1`) in grassetto. |
| `labelItalic` | `boolean` | `false` | Compone l’etichetta numerata in corsivo. |
| `labelColor` | `ColorValue` | `color` della didascalia | Colore dell’etichetta numerata. |
| `descriptionItalic` | `boolean` | `false` | Compone il testo della descrizione in corsivo. |
| `position` | `'above' \| 'below'` | `'below'` | Dove si trova la didascalia. Con `'above'` la didascalia (e la sua barra) viene prima e il corpo della risorsa scende dell’altezza della didascalia più `gap`; la nota va allora sotto il corpo. |
| `backgroundEnabled` | `boolean` | `false` | Disegna una barra dietro la didascalia. La barra è larga quanto il blocco e racchiude le righe della didascalia più `padding` su ogni lato. |
| `background` | `ColorValue` | colore principale della tavolozza | Colore di riempimento della barra (disegnata solo se attiva). |
| `padding` | `Dimension` | `0.35em` | Spaziatura interna tra il bordo della barra e il testo della didascalia. Ignorata quando la barra è disattivata. |
| `note` | `object` | — | Stile della nota della risorsa: vedi la sotto-tabella più avanti. |
| `labelNumberGap` | `string` | spazio indivisibile; `''` in un documento giapponese | Che cosa sta tra l’etichetta e il numero, nella didascalia e in un `:ref` in linea: *Figura 1.7*, *Fig. 1.7*. Cinese e giapponese li compongono attaccati: `''` dà 图1-1, ed è il valore predefinito in un documento giapponese (図1-1). |
| `labelSeparator` | `string` | `'. '`; `'　'` in un documento giapponese | Che cosa segue il numero, prima della descrizione: *Figura 1.7. Una didascalia*. Le didascalie cinesi prendono uno spazio ideografico, `'　'` (图1-1　标题), e così quelle giapponesi, per impostazione predefinita (図1-1　東京の地図, JLReq §4.3). Un’etichetta senza numero segue la propria regola: un punto, a meno che il prefisso non termini già con uno. |

Il sotto-oggetto `note` dà stile a `Resource.note`, un breve testo (fonte, crediti, un’osservazione) composto sotto la risorsa in un corpo più piccolo. Accetta la stessa formattazione in linea e gli stessi segni `:ref` della didascalia ed eredita il carattere della didascalia. Viene collocato sotto la didascalia quando la didascalia è sotto, e sotto il corpo della risorsa quando la didascalia è sopra; la sua altezza conta nel blocco, così una risorsa con una nota flotta come un’unità sola.

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `note.fontSize` | `Dimension` | 0,85 × corpo della didascalia | Corpo del carattere della nota. |
| `note.color` | `ColorValue` | `color` della didascalia | Colore del testo della nota. |
| `note.italic` | `boolean` | `false` | Compone la nota in corsivo. |
| `note.gap` | `Dimension` | `0.35em` | Spazio tra la nota e ciò che la precede (didascalia o corpo). |
| `note.align` | `'left' \| 'center' \| 'right' \| 'justify' \| 'start' \| 'end'` | `'left'` | Allineamento orizzontale delle righe della nota, come `align` per la didascalia. |

Le sostituzioni per tipo si fondono con `mergeCaptionStyle(resolvedCaptionStyle, override, palette?)`, esportata per gli host che hanno bisogno della stessa risoluzione fuori dalla pipeline.

## Stile dei diagrammi

La proprietà `diagramStyle` controlla come vengono colorati i diagrammi SVG incorporati (risorse `kind: 'svg'`) e in quali font è composto il loro testo. La **modalità a inchiostro unico** è un passaggio di ricolorazione che trasforma ogni colore di un diagramma in una tinta di un solo inchiostro, così le figure vengono riprodotte fedelmente quando il documento è stampato con un unico colore spot. I **font incorporati** inseriscono in ogni SVG i caratteri che il suo testo nomina, così le sue etichette sono composte nei font del documento sul canvas, in HTML e in EPUB (vedi [Font nel testo SVG](https://postext.dev/it/docs/configuration-resources.md#font-nel-testo-svg)).

```ts
const config: PostextConfig = {
  diagramStyle: {
    singleInk: true,
    inkColor: { hex: '#295AA3', model: 'hex' },
  },
};
```

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `singleInk` | `boolean` | `false` | Ricolora ogni diagramma SVG incorporato in tinte di un solo inchiostro. |
| `inkColor` | `ColorValue` | Colore principale (`#295AA3`) | L’inchiostro. Il valore predefinito è il colore principale della palette del documento (collegato alla palette tramite `paletteId: 'main-color'`), quindi cambiando il campione di colore della palette si ritingono i diagrammi insieme ai titoli e ai tratti in grassetto. |
| `inlineFonts` | `boolean` | `true` | Incorpora in ogni SVG i caratteri che il suo testo nomina (`font-family`) come data URI `@font-face` prima che venga mostrato come immagine: sul canvas, in HTML, in EPUB e nel ripiego raster del PDF. Non viene mai scritto nel file salvato. Una risorsa vi rinuncia con `svg.inlineFonts: false` (da postext 1.25). |

### Come funziona l’inchiostro unico

Quando `singleInk` è attivo, ogni colore nel markup SVG viene riscritto come una tinta di `inkColor` la cui intensità è **1 − luminanza relativa** (coefficienti Rec. 709 applicati ai canali con codifica gamma: un’approssimazione percettiva più che sufficiente per la mappatura delle tinte). La mappatura conserva il valore percepito: il bianco diventa il bianco della carta, il nero diventa l’inchiostro pieno, e i riempimenti chiari restano chiari qualunque sia la loro tonalità originale. Uno sfondo giallo pallido diventa una tinta pallida dell’inchiostro; un tratto scuro si avvicina all’inchiostro pieno.

La ricolorazione viene eseguita dalla funzione esportata `applySingleInkToSvg(svgText, inkHex)`, che lavora senza DOM sul markup SVG come testo:

- I valori esadecimali `#rgb` / `#rgba` / `#rrggbb` / `#rrggbbaa`, le funzioni `rgb()` / `rgba()` e le funzioni `hsl()` / `hsla()` vengono riscritti ovunque compaiano: attributi di presentazione, `style` in linea, gradienti, `<defs>`. Le funzioni possono usare canali interi, decimali o in percentuale e la sintassi con virgole o con spazi, quindi vengono ricolorati anche `rgb(11.37%, 20%, 50.59%)` (come lo scrive Cairo) e `rgb(51 102 153 / 50%)`. Una funzione tinta viene riscritta come `rgb(…)` o `rgba(…)`.
- Le parole chiave `white` e `black` vengono sostituite solo dove compaiono come valori di colorazione (`fill`, `stroke`, `stop-color`, `flood-color`, `color`, come attributi o proprietà di stile in linea), mai dentro il contenuto testuale o le etichette.
- `none`, `transparent` e `currentColor` restano invariati, come pure gli altri colori con nome (`red`, `steelblue`…) e il nero predefinito di una forma o di un testo che non imposta alcun riempimento. Assegna a questi elementi un colore esplicito perché vengano ricolorati.
- I canali alfa vengono conservati (i nibble di `#rgba` / `#rrggbbaa` e le componenti alfa di `rgba(…)` passano invariati; un’alfa in percentuale viene scritta come numero).
- Quando `inkHex` non si può interpretare, l’input viene restituito invariato.
- Il risultato porta `data-postext-single-ink="#…"` (l’inchiostro) sul suo `<svg>` radice, e un markup che lo porta già viene restituito così com’è, qualunque inchiostro indichi. La mappatura non è idempotente (un secondo passaggio schiarisce ogni colore, e il nero esce a circa due terzi dell’inchiostro), quindi un’immagine viene ricolorata una sola volta, da chiunque arrivi prima tra il tuo codice e i backend. (Il marcatore è nuovo in postext 1.5; il markup ricolorato dalla 1.4 non lo ha.)

```ts
import { applySingleInkToSvg } from 'postext';

const recoloured = applySingleInkToSvg(svgText, '#295AA3');
applySingleInkToSvg(recoloured, '#295AA3') === recoloured; // true: never twice
```

L’inchiostro unico si applica in tutti e tre i backend: il backend PDF ricolora i byte SVG che `resourceBytes` gli passa prima di disegnarli come vettori, e i backend canvas e HTML tingono le immagini SVG che dipingono quando lo chiedi (vedi [Inchiostro unico sul canvas e in HTML](https://postext.dev/it/docs/configuration-resources.md#inchiostro-unico-sul-canvas-e-in-html)), così il PDF esportato corrisponde all’anteprima a schermo.

Resolver e stripper seguono le altre sezioni, accanto ai tipi `DiagramStyleConfig` / `ResolvedDiagramStyleConfig`:

```ts
import {
  DEFAULT_DIAGRAM_STYLE_CONFIG,
  resolveDiagramStyleConfig,
  stripDiagramStyleDefaults,
  applySingleInkToSvg,
} from 'postext';
import type { DiagramStyleConfig, ResolvedDiagramStyleConfig } from 'postext';

const resolved = resolveDiagramStyleConfig(config.diagramStyle);
// => { singleInk: false, inkColor: { hex: '#295AA3', model: 'hex', paletteId: 'main-color' } }

const minimal  = stripDiagramStyleDefaults(config.diagramStyle);
// => undefined when everything matches the defaults
```

### Inchiostro unico sul canvas e in HTML

I backend canvas e HTML ricevono le immagini già decodificate (`registerResourceImage`) o come URL (`resourceImageUrl`), non come markup SVG. Su richiesta applicano la stessa mappatura a ciò che disegnano:

- **Canvas** (`renderPage`, `renderPageToCanvas`, `renderToCanvas`). Ogni immagine SVG a cui si applica la tinta (una figura, l’immagine di una cella di tabella, un’immagine di progetto grafico, l’icona o il marcatore di un riquadro) viene rasterizzata alla dimensione con cui è collocata e i suoi pixel vengono tinti con l’inchiostro, sia che sia stata registrata come `<img>` sia come `ImageBitmap`. La bitmap tinta finisce in cache come qualsiasi raster vettoriale. Un’immagine bitmap non viene mai tinta.
- **HTML** (`renderToHtml`, `renderToHtmlIndexed`). Ogni `<img>` SVG riceve `filter: url(#pt-ink-…)`, che punta a un `feColorMatrix` contenuto nella sua pagina: un `<svg>` di dimensione zero che contiene il `<filter>`, collocato per primo nella pagina, e parte del `decorationHtml` della pagina nell’output indicizzato. Ogni pagina lo porta mentre l’inchiostro unico è attivo, che contenga o no un’immagine, così un host che aggiorna i blocchi uno per uno non introduce mai un’immagine a cui manca il filtro.

**Mai tinta due volte.** Fino a postext 1.4 i backend canvas e HTML dipingevano le immagini così come le ricevevano, quindi gli host ricoloravano da sé il markup con `applySingleInkToSvg` prima di passarlo. Gli adattatori dei pacchetti e la Sandbox lo fanno ancora, perché il passaggio sul markup dà esattamente i colori del PDF (vedi l’ultimo paragrafo qui sotto). Un’immagine viene quindi tinta una volta sola, secondo tre regole valide in tutti e tre i backend:

- **Il markup marcato non viene toccato.** Il backend PDF ricolora `resourceBytes` con `applySingleInkToSvg`, quindi i byte SVG già ricolorati vengono disegnati così come sono. Sul canvas e in HTML, nemmeno un’immagine caricata da un data URI SVG il cui markup porta il marcatore viene mai tinta.
- **Disattivato salvo richiesta, in postext 1.x.** Il canvas tinge un’immagine SVG registrata senza un proprio flag solo quando il rendering passa `singleInk: true` (`RenderPageOptions`), e una registrata con `registerResourceImage(id, img, { singleInk: true })` in qualsiasi rendering. Il backend HTML tinge quando `renderToHtml` riceve `singleInk: true`, o quando il suo resolver `resourceImageUrl` porta `singleInk: true`. Un host scritto per la 1.4, che ricolora il markup e registra l’immagine decodificata senza flag, mantiene il suo output. La prossima versione major tingerà per impostazione predefinita.
- **`singleInk: false` non viene mai tinto.** Dietro un URL blob o di rete il markup non si può rileggere, quindi un’immagine che hai ricolorato da te e decodifichi in quel modo va registrata con `singleInk: false`, come fanno `registerBundleImages` e la Sandbox. `bundleImageUrl(bundle)` restituisce un resolver che porta `singleInk: false`, e `bundleResourceBytes` passa al PDF i byte originali del pacchetto, che il backend PDF ricolora una volta.

Entrambi i backend conoscono il tipo di ogni immagine dal VDT: una figura e un’immagine di cella portano il tipo della loro risorsa, e un blocco immagine di progetto grafico porta `imageKind` (`'svg'` o `'bitmap'`), preso dalla sua risorsa durante l’impaginazione. Per un VDT costruito prima che esistesse `imageKind`, il canvas tratta come SVG un’immagine di progetto grafico registrata come sorgente vettoriale, e il backend HTML una il cui URL è un data URI SVG o termina in `.svg`.

O ricolori da te il markup o lasci che i backend tingano l’immagine grezza, non entrambe le cose:

```ts
import { applySingleInkToSvg, registerResourceImage, renderPage, renderToHtml } from 'postext';

// Raw SVG: tinted while diagramStyle.singleInk is on…
registerResourceImage('diagram.svg', rawImg, { singleInk: true });
// …or register it plainly and ask on each render.
registerResourceImage('diagram.svg', rawImg);
const canvas = renderPage(doc.pages[0], doc, { singleInk: true });

// Recoloured before decoding (as postext 1.4 hosts do): painted as given.
const inked = applySingleInkToSvg(svgText, ink);
registerResourceImage('diagram.svg', await decode(inked), { singleInk: false });

// The HTML backend with URLs to the raw markup.
const html = renderToHtml(doc, { resourceImageUrl: urlFor, singleInk: true });
```

`renderToHtml` prende il valore predefinito di `singleInk` dal flag del resolver, quindi `bundleImageUrl(bundle)` non ha bisogno di opzioni.

Per ogni colore che il passaggio sul markup riscrive (valori esadecimali, `rgb()` e `hsl()`, `white` e `black`; vedi [Come funziona l’inchiostro unico](https://postext.dev/it/docs/configuration-resources.md#come-funziona-linchiostro-unico)), la mappatura sui pixel dà lo stesso risultato, bordi antialiasing e gradienti compresi. I due differiscono dove il passaggio sul markup lascia stare un colore: i colori con nome diversi da `white` e `black`, `currentColor`, forme e testi senza riempimento (disegnati nel nero predefinito) e le bitmap incorporate nell’SVG vengono tinti a schermo ma mantengono il loro colore nel PDF. Assegna a ogni elemento di un diagramma un colore esplicito esadecimale, `rgb()` o `hsl()` per ottenere un output identico. Quando il canvas non può rileggere i pixel (un `<img>` di un’altra origine, caricato senza CORS), l’immagine viene dipinta senza tinta.

### Font nel testo SVG

Un’immagine SVG viene mostrata tramite un’immagine: un `<img>` sul canvas, in HTML e in EPUB. Un documento immagine non vede i web font della pagina, quindi `<text font-family="IBM Plex Sans">` ripiegherebbe su un carattere di sistema. Da postext 1.25 il motore incorpora nel markup i caratteri che il testo nomina prima che l’immagine venga decodificata o fornita come URL: una regola `@font-face` per ogni file di font, con i suoi byte come data URI, in uno `<style>` subito dopo il tag `<svg>` radice. Il PDF non ha bisogno di nulla di tutto questo: compone il testo SVG come testo vero nei suoi font incorporati (vedi [Byte delle risorse e master di stampa](https://postext.dev/it/docs/configuration-programmatic-usage.md#byte-delle-risorse-e-master-di-stampa)).

Ciò che il testo richiede viene letto da `font-family`, `font-weight`, `font-style` e `font`, come attributi, negli attributi `style` ed ereditato dai gruppi che lo contengono; conta anche una regola `<style>` che nomina una famiglia. Le famiglie generiche (`serif`, `sans-serif`…) e il testo in `<title>` o `<desc>` vengono esclusi, e una famiglia che l’SVG dichiara da sé con `@font-face` non viene toccata. Un tratto di testo scorre il suo elenco `font-family` fino alla prima famiglia che ha un carattere disponibile. Prima viene la ricolorazione per l’inchiostro unico, poi i font.

I caratteri provengono da un **provider** con il contratto del `PdfFontProvider` di postext-pdf, così un solo provider serve entrambi: viene chiamato con la famiglia, il peso e lo stile, e i caratteri che l’SVG compone in quel carattere, e risponde con uno o più file. A una famiglia servita come porzioni per unicode-range (Fontsource, Google Fonts) risponde con le porzioni di cui quei caratteri hanno bisogno, così un SVG con etichette latine porta solo il file `latin`. Il provider predefinito legge il registro dei font del motore: `loadBundleFonts` vi registra i caratteri di un pacchetto, e un host registra i propri con `registerFontBytes(family, weight, style, bytes, { unicodeRange })`, o `registerFontUrl(…)` per un file scaricato la prima volta che un SVG ne ha bisogno. Una famiglia che nessuno ha registrato viene cercata nelle regole `@font-face` dei fogli di stile leggibili della pagina. Un `FontFace` aggiunto a `document.fonts` da byte non conserva i byte, quindi il motore non può rileggerlo: registra anche quei caratteri.

```ts
import { registerFontBytes, registerSvgImage, renderPage } from 'postext';

registerFontBytes('IBM Plex Sans', 700, 'normal', plexBoldWoff2);
await registerSvgImage('chart.svg', svgText);   // recoloured, fonts inlined, decoded, registered
const canvas = renderPage(doc.pages[0], doc);
```

Dove avviene:

- **Canvas.** `registerSvgImage(fileId, svgText, options)` ricolora (`inkHex`), incorpora i font (`fonts`, un provider; `inlineFonts: false` salta il passaggio), decodifica e registra l’immagine come sorgente vettoriale, e restituisce che cosa è stato di ogni carattere. `registerBundleImages(bundle)` fa lo stesso per gli SVG di un pacchetto, cominciando dai caratteri del pacchetto stesso. `prepareSvgMarkup(svgText, options)` restituisce il markup preparato per un host che decodifica per conto proprio.
- **HTML.** `bundleImageUrl(bundle)` serve il markup SVG con i caratteri del pacchetto incorporati. `renderToHtml(doc, { inlineSvgFonts: true })` incorpora i font nei data URI `data:` SVG che `resourceImageUrl` restituisce, a partire dai caratteri che il registro tiene in memoria (oppure `inlineSvgFonts: { fonts, maxBytes, withhold }`). Un object URL non si può leggere in modo sincrono, quindi un host che serve URL blob incorpora i font prima di crearli.
- **EPUB.** `postext-epub` incorpora i font dai `fonts` del libro, poi da `svgFonts.provider`, prima di scrivere un SVG (vedi [Libri EPUB](https://postext.dev/it/docs/configuration-programmatic-usage.md#libri-epub-postext-epub)).
- **PDF.** Il testo SVG viene composto come testo vero nei font incorporati. Uno `<style>` che contiene solo regole `@font-face` (caratteri incorporati dall’autore) non fa più ripiegare la figura su un raster. Quando una figura ripiega comunque (un filtro, un gradiente), il suo raster viene creato con i caratteri incorporati dal `fontProvider` del PDF.

Sono esportate anche le funzioni di livello più basso: `svgFontRequests(svgText)` elenca per ogni tratto le famiglie, il peso, lo stile e i caratteri; `inlineSvgFonts(svgText, provider, options)` e `inlineSvgFontsSync(svgText, syncProvider, options)` restituiscono il markup; `inlineSvgFontsDetailed` aggiunge un resoconto di ogni carattere (`inlined`, `declared`, `unavailable`, `withheld`, `tooLarge`).

| Opzione | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `maxBytes` | `number` | 2 MiB | Massimo di byte di font incorporati in un SVG (prima del base64, che aggiunge un terzo). I caratteri che insieme lo superano non vengono incorporati affatto, e viene segnalato `svgFontsTooLarge`. |
| `formats` | `('woff2' \| 'woff' \| 'ttf' \| 'otf')[]` | tutti e quattro | I formati di file da incorporare; i file di altri formati vengono saltati. |
| `withhold` | `(family) => boolean` | nessuno | Famiglie da escludere da un file che esce dall’app (non ridistribuibili). Il loro riferimento resta e il lettore ripiega; `onWithheld(family)` viene informato di ciascuna. |
| `onWarning` | `(warning) => void` | nessuno | Viene informato di una famiglia senza caratteri (`svgFontUnavailable`) e del limite di dimensione (`svgFontsTooLarge`). |

**Rinunciare.** `diagramStyle.inlineFonts: false` lascia ogni SVG come è salvato; `svg.inlineFonts: false` su una risorsa la lascia identica byte per byte, per un SVG che porta i propri caratteri o che non deve cambiare. Un pacchetto scrive la rinuncia della risorsa come `"inlineFonts": false` nel suo `preset.json`.

**Licenze.** Incorporare i font mette file di font dentro immagini che possono uscire dall’app (un’esportazione HTML, un EPUB). Avviene quando un’immagine viene mostrata o esportata, mai nei byte salvati della risorsa, e `withhold` esclude le famiglie che una licenza non ti permette di cedere: chi scrive l’EPUB trattiene i caratteri marcati `redistributable: false`, e la Sandbox le famiglie personalizzate marcate allo stesso modo.

## Stile dei video

La proprietà `videoStyle` stabilisce come vengono stampate le [risorse video](https://postext.dev/it/docs/document-format.md#video) (il simbolo di riproduzione e il codice QR sopra la locandina, e se la locandina rimanda al video) e che cosa offrono i loro player nel visualizzatore HTML e in EPUB.

```ts
const config: PostextConfig = {
  videoStyle: {
    playMark: { shape: 'rounded', position: 'top-left', size: { value: 10, unit: 'mm' } },
    qr: { position: 'bottom-right', size: { value: 20, unit: 'mm' }, errorCorrection: 'Q' },
    player: { download: false, privacy: true },
  },
};
```

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `playMark` | `VideoPlayMarkConfig` | vedi sotto | Il simbolo stampato sulla locandina per indicare che si può riprodurre. |
| `qr` | `VideoQrConfig` | vedi sotto | Il codice QR stampato sulla locandina: apre la pagina YouTube o Vimeo del video, o l’indirizzo di produzione di un file. |
| `linkPoster` | `boolean` | `true` | Fa della locandina un link al video: un’annotazione di link sopra di essa nel PDF, e un `<a>` che la racchiude in HTML e in EPUB ovunque la locandina venga mostrata. |
| `html` | `'player'` · `'poster'` | `'player'` | Che cosa l’output HTML compone per un video: il suo player, o la locandina stampata con le sue sovrapposizioni. |
| `player` | `VideoPlayerOptions` | vedi sotto | Le opzioni del player di ogni video; il `video.player` proprio di un video vi si sovrappone. |

### Simbolo di riproduzione

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `enabled` | `boolean` | `true` | Stampa il simbolo. |
| `shape` | `'circle'` · `'rounded'` · `'triangle'` | `'circle'` | Un disco con un triangolo, un rettangolo arrotondato con un triangolo (largo 1,45 volte la sua altezza), o il solo triangolo, contornato con il colore di sfondo. |
| `position` | `VideoOverlayPosition` | `'center'` | `'center'`, un angolo (`'top-left'`, `'top-right'`, `'bottom-left'`, `'bottom-right'`) o il centro di un lato (`'top'`, `'bottom'`, `'left'`, `'right'`). Le posizioni sono fisiche: l’angolo in alto a destra è l’angolo in alto a destra anche in un libro da destra a sinistra. |
| `size` | `Dimension` | `12mm` | Altezza del simbolo; mai più del 40% del lato più corto della locandina. |
| `inset` | `Dimension` | `4mm` | Distanza dai bordi della locandina in un angolo o su un lato. |
| `color` | `ColorValue` | bianco | Il triangolo. |
| `background` | `ColorValue` | Colore principale | Il disco o il rettangolo dietro di esso; il contorno del triangolo quando è da solo. Collegato alla palette per impostazione predefinita. |
| `backgroundOpacity` | `number` | `0.9` | Opacità dello sfondo, 0–1. |

### Codice QR

| Proprietà | Tipo | Predefinito | Descrizione |
| --- | --- | --- | --- |
| `enabled` | `boolean` | `true` | Stampa il codice. Un file senza indirizzo di produzione non ne riceve alcuno. |
| `position` | `VideoOverlayPosition` | `'bottom-right'` | Come per il simbolo di riproduzione. Assegna ai due posizioni diverse. |
| `size` | `Dimension` | `18mm` | Lato del codice con la sua zona di rispetto; mai più del 45% del lato più corto della locandina. Le fotocamere dei telefoni leggono moduli da un terzo di millimetro in su: un indirizzo di 30 caratteri produce un codice di 29 moduli, quindi 18 mm con una zona di rispetto di 2 danno moduli di 0,55 mm. |
| `inset` | `Dimension` | `3mm` | Distanza dai bordi della locandina. |
| `errorCorrection` | `'L'` · `'M'` · `'Q'` · `'H'` | `'M'` | Quanta parte del codice può essere danneggiata o coperta restando leggibile: circa il 7%, 15%, 25% o 30%. Viene alzata automaticamente finché il codice mantiene lo stesso numero di moduli. |
| `quietZone` | `number` | `2` | Moduli chiari attorno al codice, sulla sua piastrina (0–8). La piastrina si stacca dalla locandina, quindi i quattro moduli che lo standard richiede sulla carta libera non servono. |
| `color` | `ColorValue` | nero | I moduli scuri. Tienili scuri su una piastrina chiara: la maggior parte dei lettori non legge i codici invertiti. |
| `background` | `ColorValue` | bianco | La piastrina. |
| `radius` | `Dimension` | `1mm` | Raggio degli angoli della piastrina. |

Il codice viene codificato dal motore stesso (`encodeQr(text, level)`: modalità byte, UTF-8, versioni da 1 a 40, la maschera con la penalità più bassa) e disegnato come vettori: il canvas riempie un unico tracciato di sequenze di moduli, il PDF un solo `drawSvgPath`, e l’HTML un solo `<path>` con `shape-rendering="crispEdges"`, così resta nitido a qualunque dimensione di stampa.

### Opzioni del player

`VideoPlayerOptions`, in `videoStyle.player` e nel `video.player` di ogni video. Il player HTML5 di un file le rispetta tutte; i player di YouTube e Vimeo rispettano ciò che i loro parametri di incorporamento consentono.

| Proprietà | Predefinito | Rispettata da | Descrizione |
| --- | --- | --- | --- |
| `controls` | `true` | YouTube, Vimeo, file | Mostra i controlli del player. |
| `download` | `true` | file | Offre il pulsante di download del browser (`controlslist="nodownload"` quando è disattivato). Nasconde il pulsante; non protegge il file. YouTube e Vimeo non offrono mai il download. |
| `fullscreen` | `true` | YouTube, Vimeo, file | Offre lo schermo intero (`fs=0`, l’`allowfullscreen` dell’iframe, `nofullscreen`). |
| `playbackRate` | `true` | Vimeo, file | Offre il menu della velocità (`speed=0`, `noplaybackrate`). |
| `pictureInPicture` | `true` | Vimeo, file | Offre il picture-in-picture (`pip=0`, `disablepictureinpicture`). |
| `remotePlayback` | `true` | file | Offre la trasmissione a un altro schermo (`disableremoteplayback`). |
| `autoplay` | `false` | YouTube, Vimeo, file | Avvia la riproduzione da sola, sempre senza audio, come richiedono i browser. |
| `muted` | `false` | YouTube, Vimeo, file | Comincia con l’audio disattivato. |
| `loop` | `false` | YouTube, Vimeo, file | Alla fine riprende dall’inizio. |
| `exclusive` | `true` | Folio, visualizzatore HTML, EPUB (dove gli script vengono eseguiti); file | Avviare questo video mette in pausa gli altri visibili, così ne suona uno alla volta. `false` lo lascia suonare insieme agli altri: le brevi clip mute in loop di una pagina, più d’una in contemporanea. Da postext 1.18. |
| `preload` | `'metadata'` | file | Quanto carica il browser prima della riproduzione: `'none'`, `'metadata'` o `'auto'`. |
| `privacy` | `true` | YouTube, Vimeo | Incorporamenti con privacy avanzata: YouTube da `youtube-nocookie.com`, Vimeo con `dnt=1`. |

Un EPUB conserva solo gli attributi che il suo schema conosce: un file si riproduce con `controls`, `autoplay`, `muted`, `loop`, `playsinline` e `preload`, più il marcatore `data-pt-alongside`, e il resto lo decide il sistema di lettura.

Un video non esclusivo porta `data-pt-alongside` nell’output HTML. `coordinateVideoPlayback(root)` fa rispettare la regola ai player sotto `root` (l’elemento che contiene l’output di `renderToHtml`): avviare un video esclusivo mette in pausa tutti gli altri in riproduzione, e avviarne uno che suona insieme agli altri mette in pausa solo quelli esclusivi. Restituisce una funzione che smette di ascoltare. `playsAlongside(el)` e `videosToPause(started, videos, alongside)` offrono la stessa regola a un host con player propri. In [Folio](https://postext.dev/it/docs/document-format.md#video-sulle-pagine-di-folio) un video che parte da solo e suona insieme agli altri (`autoplay` con `exclusive: false`) si avvia, senza audio, ogni volta che la sua pagina entra in vista e si ferma quando la pagina viene girata, più d’uno in contemporanea, e `loop` lo fa ripartire dall’inizio. Una pagina o un capitolo EPUB con video da coordinare (due o più, di cui uno esclusivo) collega la stessa regola come piccolo script, `scripts/videos.js` (l’esportazione `VIDEO_PLAYBACK_SCRIPT`), e il pacchetto dichiara quel documento `scripted`. Un sistema di lettura che esegue gli script fa rispettare la regola ai video di quel documento, ma non a quelli della pagina a fronte, che è un altro documento; uno che non esegue script riproduce ogni video secondo le sue regole, come fanno sempre i player di YouTube e Vimeo.

Resolver e stripper seguono le altre sezioni, accanto ai tipi `VideoStyleConfig` / `ResolvedVideoStyleConfig`:

```ts
import {
  DEFAULT_VIDEO_STYLE_CONFIG,
  DEFAULT_VIDEO_PLAYER_OPTIONS,
  resolveVideoStyleConfig,
  resolveVideoPlayerOptions,
  stripVideoStyleDefaults,
} from 'postext';

const resolved = resolveVideoStyleConfig(config.videoStyle);
const player = resolveVideoPlayerOptions(resource.video?.player, resolved.player);
const minimal = stripVideoStyleDefaults(config.videoStyle); // undefined when all defaults
```
