Chapitre 11 · Partie II · Le métier
Configuration : polices, couleurs et sortie
Unités, couleurs et palette, polices personnalisées, visionneuse HTML, PDF et production pour l’impression, visionneuse Folio et calques de débogage
En bref
Cette page présente les réglages communs à tout le livre et les réglages propres à chaque type de sortie. Elle explique comment écrire une mesure et une couleur, et comment nommer les couleurs d’une palette. Elle montre comment ajouter vos propres polices. Elle traite ensuite de la vue web, du fichier PDF, des fichiers que demande un imprimeur et du livre en 3D. La dernière section active les repères et les avertissements qui vous aident pendant le travail.
#Unités et couleurs
#Dimensions
Toutes les mesures physiques de Postext utilisent le type Dimension, une valeur associée à une unité :
interface Dimension {
value: number;
unit: DimensionUnit; // 'cm' | 'mm' | 'in' | 'pt' | 'px' | 'em' | 'rem'
}Unités absolues (cm, mm, in, pt, px) : elles sont converties en pixels selon la résolution (DPI) configurée. À 300 DPI, 1 cm vaut environ 118 px.
Unités relatives (em, rem) : elles suivent la taille de police courante. Un em est relatif à la taille de police de l’élément lui-même ; un rem est relatif à la taille de police du texte courant.
#Couleurs
Les couleurs sont stockées avec une représentation hexadécimale et un modèle colorimétrique cible :
interface ColorValue {
hex: string; // '#ff0000', 'transparent', etc.
model: ColorModel; // 'hex' | 'rgb' | 'cmyk' | 'hsl'
cmyk?: CmykPercent; // The exact process values of a colour authored in CMYK.
}Le champ model indique l’espace colorimétrique visé. Pour le rendu web, 'hex' ou 'rgb' sont les valeurs habituelles. Pour les flux d’impression, 'cmyk' indique que la couleur a été définie en CMJN, et cmyk conserve ses valeurs : un rendu d’impression en CMJN les applique telles quelles, hex servant de rendu à l’écran (voir Couleurs définies en CMJN).
Comme Postext vise une sortie de qualité éditoriale, la couleur par défaut du texte courant est livrée avec model: 'cmyk' (#000000). Les couleurs des titres, du gras, de l’italique et des listes renvoient par défaut à la Main Color de la palette (#295AA3, model: 'hex'). Le fond de page et les calques d’interface (grille de ligne de base, traits de coupe, indicateurs de débogage) utilisent par défaut model: 'hex'. Remplacez color.model sur n’importe quel champ si vous avez besoin d’une autre sémantique à l’export.
#Transparence
Une couleur peut être translucide. hex accepte un canal alpha, sous la forme #rgba ou #rrggbbaa. Il accepte aussi une couleur rgb() / rgba(), en syntaxe à virgules ou à espaces, avec l’alpha en nombre ou en pourcentage. transparent est entièrement transparent :
const config: PostextConfig = {
header: {
elements: [{
kind: 'box',
id: 'veil',
placement: {
anchor: { to: 'bleed', edge: 'top-left' },
size: { width: 'fill', height: { value: 40, unit: 'mm' } },
},
style: { backgroundColor: { hex: '#ffffffb3', model: 'hex' } }, // white at 70 %
}],
},
bodyText: { color: { hex: 'rgba(0, 0, 0, 0.85)', model: 'rgb' } },
};Les trois moteurs de rendu la peignent de la même façon. Le canvas et la visionneuse HTML prennent la valeur comme une couleur CSS. Le moteur PDF applique l’opacité de la couleur comme un alpha constant, un ExtGState avec ca pour les remplissages et CA pour les contours. Cela couvre le texte, les filets, les boîtes, les fonds et bordures de tableau, les pastilles, les pastilles de couleur et les formules. Une couleur translucide se compose par-dessus tout ce qui a été peint avant elle. Une boîte de l’en-tête ou du pied de page est peinte en dernier, elle voile donc le texte situé dessous ; une boîte dans un bandeau d’ouverture est peinte en premier, elle teinte donc la page sous le texte. Quand le PDF est forcé dans un autre espace colorimétrique (pdfGeneration.forceColorSpace avec colorSpace: 'cmyk' ou 'grayscale'), la couleur est convertie et son alpha conservé. Dans le Sandbox, le curseur d’opacité du sélecteur de couleur écrit ces valeurs sous la forme #rrggbbaa, et le sélecteur lit aussi les autres formes.
#Polices personnalisées
Postext résout chaque chaîne fontFamily à la fois dans le catalogue Google Fonts et dans la liste customFonts du document. En cas de nom identique, les polices personnalisées l’emportent : si vous déclarez customFonts: [{ name: 'Roboto', … }], Postext utilise le fichier que vous avez importé au lieu de la « Roboto » de Google Fonts.
Utilisez des polices personnalisées quand :
- le document a besoin d’un caractère de marque ou sous licence absent de Google Fonts ;
- l’environnement ne peut pas joindre les CDN de polices, jsDelivr (d’où le Sandbox tire les fichiers de Fontsource) ou Google Fonts (hors ligne, intranet, contraintes de confidentialité) ;
- vous devez garder le fichier de police privé et ne pas l’envoyer à un tiers.
#Schéma de configuration
type CustomFontFormat = 'woff2' | 'woff' | 'ttf' | 'otf';
type CustomFontStyle = 'normal' | 'italic';
interface CustomFontVariant {
weight: number; // CSS font-weight, 100..900
style: CustomFontStyle;
fileId: string; // opaque id of the binary in out-of-band storage
format: CustomFontFormat;
fileName?: string; // original upload filename (optional, shown in UI)
}
interface CustomFontFamily {
name: string; // used anywhere a Google Font family name fits
variants: CustomFontVariant[];
}
interface PostextConfig {
// ...
customFonts?: CustomFontFamily[];
}Le fichier binaire de chaque variante n’est pas intégré à la configuration. Celle-ci ne contient que des pointeurs fileId ; les octets sont stockés à part. Dans le Sandbox, cela veut dire IndexedDB (stockage clé-valeur, propre au navigateur, privé au document). Un intégrateur qui embarque Postext dans un autre hôte est libre de résoudre fileId comme il l’entend (point d’accès serveur, cache de service worker, n’importe quoi d’autre), pourvu que les octets atteignent le thread principal avant l’exécution de buildDocument.
#Gérer les polices personnalisées dans le Sandbox
Ouvrez le panneau Polices depuis la barre d’activité de gauche (entre Ressources et Design). Sa liste Caractères de ce livre montre chaque famille utilisée par la maquette, avec son rôle et sa provenance : Google Fonts, Fontsource (pour une famille absente de Google Fonts), votre fichier, ou nulle part (Introuvable). Sous Vos fichiers de police, pour chaque famille :
- Ajouter une famille : crée une famille vide ; renommez-la sur place.
- Importer des variantes : choisissez une graisse (100–900) et un style (normal / italique), puis sélectionnez un ou plusieurs fichiers
.woff2,.woff,.ttfou.otf. Chaque fichier devient une variante liée au couple (graisse, style) sélectionné ; le nom du fichier importé est mémorisé et affiché sur la ligne pour que vous puissiez distinguer les variantes. Vous pouvez ajuster à tout moment la graisse ou le style d’une variante depuis ses listes déroulantes. - Les variantes en double sont permises. Si deux fichiers occupent le même emplacement (graisse, style), les deux sont conservés et un avertissement Variante de police en double apparaît pour que vous corrigiez les réglages des fichiers en trop.
- Supprimer la variante ou Supprimer la famille : retire l’entrée de la configuration et les octets stockés dans IndexedDB.
Une fois une famille déclarée, chaque sélecteur de police la range sous Personnalisées, au-dessus de la liste Google Fonts. La choisir branche la famille sur chaque champ de famille de police auquel vous l’appliquez.
#Comportement au rendu
En coulisse :
- Quand
customFontschange, chaque famille déclarée est automatiquement enregistrée sous forme d’entréesFontFacedansdocument.fonts; la visionneuse HTML, la vue Canvas (qui mesure viadocument.fonts) et toute référence CSS directe utilisent ainsi le caractère personnalisé sans que l’utilisateur doive d’abord ouvrir le sélecteur de police. - Le worker de mise en page reçoit les mêmes ArrayBuffers par le chemin existant de transfert des polices, de sorte que la mesure (
buildFontString, pretext) fonctionne comme pour une famille du catalogue. - Modifier ou supprimer une variante vide le cache du worker pour cette famille et la réenregistre à la composition suivante, ce qui garde les aperçus synchronisés avec le jeu de variantes courant.
- Export PDF : les fichiers importés passent par le même pipeline
PdfFontProvider. Les fichiers.woff2sont décompressés ; les.ttfet.otfsont transmis tels quels. Le.woffest refusé avec une erreur explicite (pdf-lib ne sait pas intégrer du WOFF brut : réimportez en.woff2/.ttf/.otf). L’OpenType à contours CFF (.otfavec la signatureOTTO) est intégré sans sous-ensemble, car le découpage CFF de pdf-lib parcourt chaque glyphe au moment desave()et peut bloquer plusieurs minutes sur de vraies polices ; renoncer au sous-ensemble produit un PDF un peu plus lourd en échange de temps de rendu réguliers.
#Avertissements de police manquante
Le panneau Vérifications du Sandbox signale trois défaillances propres aux polices personnalisées dans son groupe Polices (toutes activées par le même interrupteur debug.warnings.missingFont qui commande déjà l’avertissement générique « non chargée ») :
- Famille de police inconnue : un
fontFamilydésigne un nom qui n’est ni une police Google Fonts connue ni une famille personnalisée déclarée. Il se déclenche aussi immédiatement quand vous supprimez une famille personnalisée encore référencée par un champfontFamily, sans attendre que le DOM s’en aperçoive. - Variante de police manquante : la famille existe, mais au moins un des emplacements standard de graisse et de style (400 / 700, normal / italique) n’a pas de fichier importé. L’avertissement énumère les combinaisons manquantes.
- Variante de police en double : deux fichiers importés ou plus partagent le même emplacement (graisse, style) dans une même famille. Un seul fichier sert réellement au rendu ; l’avertissement vous invite à réajuster les autres entrées.
Un clic sur l’un de ces avertissements ouvre le panneau Polices pour que vous importiez la variante manquante, ajoutiez de nouveau la famille ou départagiez les doublons.
Dès qu’une mise en page existe, le panneau liste aussi le Remplacement de police dans la mise en page (fontFallback) relevé par le moteur : un caractère sans lequel les pages ont été mesurées, soit absent, soit dessiné par le navigateur à partir d’une autre graisse ou d’une autre inclinaison. Une famille déjà signalée comme inconnue ou incomplète n’est pas listée deux fois. Avant la première mise en page, une vérification sur document.fonts en tient lieu.
#Palette de couleurs
La propriété colorPalette de PostextConfig vous permet de définir un jeu réutilisable de couleurs nommées et d’y faire référence depuis n’importe quelle ColorValue de la configuration. C’est l’équivalent dans Postext des propriétés personnalisées CSS ou du panneau Nuancier d’InDesign : modifiez une fois l’entrée de la palette, et chaque couleur qui y renvoie se met à jour dans tout le document.
interface ColorPaletteEntry {
id: string; // stable identifier — referenced by ColorValue.paletteId
name: string; // human label shown in sandbox UIs
value: ColorValue;
}#La palette par défaut
Postext est livré avec une palette par défaut d’une seule entrée appelée Main Color (id: 'main-color', hex #295AA3). Plusieurs valeurs par défaut (couleur des titres, couleur du gras et de l’italique du texte courant, couleur de :ref, couleurs des puces et des numéros de liste) renvoient à cette entrée via paletteId: 'main-color' ; modifier cette seule pastille de couleur reteinte donc toutes les parties du document qui l’utilisent.
Trois exports permettent d’examiner la palette par défaut, de la cloner ou de s’y comparer :
import {
DEFAULT_COLOR_PALETTE,
cloneDefaultColorPalette,
isDefaultColorPalette,
} from 'postext';
// Read-only snapshot of the shipped palette.
DEFAULT_COLOR_PALETTE;
// => [{ id: 'main-color', name: 'Main Color', value: { hex: '#295AA3', model: 'hex' } }]
// Independent copy — mutate this, not DEFAULT_COLOR_PALETTE.
const palette = cloneDefaultColorPalette();
// Detect whether a user has customised the palette at all.
isDefaultColorPalette(palette); // trueUne palette se place au premier niveau de la configuration :
const config: PostextConfig = {
colorPalette: [
{ id: 'ink', name: 'Ink', value: { hex: '#0a0a0a', model: 'cmyk' } },
{ id: 'accent', name: 'Accent', value: { hex: '#b8860b', model: 'hex' } },
],
bodyText: { color: { hex: '#000000', model: 'cmyk', paletteId: 'ink' } },
headings: { color: { hex: '#000000', model: 'hex', paletteId: 'accent' } },
};#Faire référence à une entrée de la palette
Toute ColorValue de la configuration peut porter un champ facultatif paletteId qui pointe vers une entrée de colorPalette : fond de page, couleurs du texte courant (y compris la couleur de :ref), couleurs des titres, filets de colonne, couleurs des listes, couleurs des tableaux, des légendes, des pastilles et des encadrés (boîte, bande, icône, marqueur, étiquette, titre, corps), couleurs des traits de coupe et de la grille de ligne de base, indicateurs de débogage, et chaque couleur d’une maquette : titres courants, ouvertures de titre et maquettes en colonne, maquettes et titres courants des styles de titre, pages de partie et lignes de partie de la table des matières (texte, filet, fond et bordure de boîte, contour, lettrine). Quand il est présent, le hex / model de l’entrée de palette l’emporte sur le hex / model de repli stocké à côté. Ce repli en ligne ne sert que si la palette est absente, vide ou ne contient pas cet identifiant : pratique pour livrer une configuration qui sera lue par un outil ignorant les palettes.
Modifié dans postext 1.5. Jusqu’à postext 1.4, la palette n’atteignait qu’une liste fixe de réglages : les couleurs des maquettes (titres courants, ouvertures, styles de titre, parties, lignes de la table des matières), bodyText.referenceColor, les couleurs des étiquettes d’encadré et les couleurs du gras et de l’italique dans le corps des encadrés gardaient le hex stocké à côté de leur paletteId. Un document dont la valeur stockée diffère de l’entrée de palette (tout document modifié dans le Sandbox après le changement de l’entrée, et chaque :ref quand la Main Color n’est pas #295AA3) imprime désormais la couleur de la palette, comme le lien l’indique. Pour garder une couleur telle qu’elle était, retirez son paletteId.
#Application des palettes
buildDocument applique la palette à deux endroits, pour que les couleurs référencées fonctionnent aussi bien pour les remplacements que vous avez écrits que pour les valeurs par défaut renseignées plus tard :
applyPaletteToConfig(config): résout chaqueColorValuede la configuration utilisateur brute qui porte unpaletteId. Utile pour examiner ce que le moteur verra réellement.applyPaletteToResolvedConfig(resolved, palette): s’exécute après la résolution des valeurs par défaut et réécrit les valeurs par défaut liées à la palette (couleur des titres, couleur du gras et de l’italique du texte courant, couleur de:ref, couleurs des listes, couleurs des maquettes par défaut) pour qu’elles correspondent à la palette active.
Les deux parcourent toute la configuration, si bien qu’aucune couleur liée à la palette n’est oubliée. La plupart des couleurs du flux de texte (texte courant, titres, listes, tableaux, légendes, pastilles, boîte, titre et corps de l’encadré) en sortent comme de simples valeurs. Toutes les autres (couleurs des maquettes, couleur de :ref, étiquettes d’encadré) prennent le hex / model de la palette et gardent leur paletteId. C’est ce lien que l’attribut palette d’une partie et le palette d’un style de titre remplacent sur leurs pages (voir Parties) ; il doit donc subsister. htmlViewer.overrides reste tel qu’il est écrit : la visionneuse HTML le fusionne en premier, et une palette qu’il contient s’applique alors à tout, maquettes comprises.
Vous aurez rarement besoin d’appeler ces fonctions vous-même, mais elles sont toutes deux exportées pour que vous puissiez les examiner ou les réutiliser :
import {
applyPaletteToConfig,
applyPaletteToResolvedConfig,
resolveColorValue,
} from 'postext';
const flat = applyPaletteToConfig(config);
// Every ColorValue with a paletteId in the raw config now carries the
// palette entry's hex/model (a design colour keeps its paletteId).
// `applyPaletteToResolvedConfig` is typically handled by buildDocument; use it
// directly if you build a ResolvedConfig yourself and want the palette applied.resolveColorValue(value, palette, fallback) est la variante pour une seule valeur, pratique quand vous composez des configurations par programme et devez résoudre une couleur à la fois.
#Modifier la palette
Une couleur dont le paletteId ne désigne aucune entrée imprime son hex / model stocké, qui peut être plus ancien que la couleur que lui donnait l’entrée. Avant de supprimer une entrée, réécrivez donc chaque ColorValue qui y est liée en couleur simple contenant la valeur actuelle de l’entrée. La section Palette du Sandbox (Maquette → Couleurs) le fait quand vous supprimez une entrée, où que se trouve la couleur (maquettes et étiquettes d’encadré comprises), et sa confirmation liste chaque réglage qui utilise l’entrée : par son nom, ou par son chemin dans la configuration (header.elements[2].color).
#Visionneuse HTML
La propriété htmlViewer règle la façon dont le moteur de rendu HTML dispose les pages à l’écran. Elle ne s’applique que lorsque vous rendez avec renderToHtml / renderToHtmlIndexed ; les chemins canvas et PDF l’ignorent complètement, car ils utilisent directement les valeurs configurées de page.width, page.height et page.dpi.
interface HtmlViewerConfig {
maxCharsPerLine?: number; // Target column width, in characters of the body font.
columnGap?: number; // Horizontal gap between columns in multi-column mode (px).
optimalLineBreaking?: boolean; // Use Knuth–Plass inside the HTML viewer instead of greedy.
overrides?: HtmlViewerOverrides; // Screen-only partial config merged over the document config.
}
type HtmlViewerOverrides = Omit<PostextConfig, 'htmlViewer'>;| Propriété | Type | Défaut | Description |
|---|---|---|---|
maxCharsPerLine | number | 70 | Longueur de ligne visée pour chaque colonne rendue, exprimée en caractères de la police du texte courant. La vue mesure une chaîne de prose représentative de cette longueur pour en déduire la largeur réelle en pixels ; le résultat s’adapte ainsi à toute combinaison de police proportionnelle et de corps. |
columnGap | number | 50 | Gouttière horizontale, en pixels CSS, entre les colonnes quand la visionneuse est en mode multicolonne. Ignorée en mode à une colonne. |
optimalLineBreaking | boolean | false | Active la coupure des lignes Knuth–Plass dans la visionneuse HTML. Désactivée par défaut, car la visionneuse relance la mise en page à chaque redimensionnement et à chaque changement de taille de police : l’algorithme glouton (premier ajustement) est assez rapide pour paraître instantané. Activez-la si vous voulez les mêmes coupures optimales que le moteur canvas. |
overrides | HtmlViewerOverrides | — | Une configuration partielle du document qui ne s’applique qu’à l’écran. La visionneuse HTML la fusionne par-dessus la configuration du document avant la mise en page (applyHtmlViewerOverrides) ; canvas et PDF l’ignorent. Les objets fusionnent récursivement ; un tableau levels (titres, listes, table des matières) fusionne entrée par entrée sur level ; tout autre tableau (les elements d’un emplacement de maquette, calloutStyles, colorPalette…) remplace en bloc le tableau de base. Usage typique : une ouverture de chapitre sans les bandeaux de l’imprimé, ou une page de partie dont le titre se replie contre le numéro au lieu d’une largeur fixe de format. Le Sandbox la modifie en JSON. |
const config: PostextConfig = {
headings: { levels: [{ level: 1, span: 'page', breakBefore: { enabled: true } }] },
htmlViewer: {
// On screen, chapters flow on without the page-span opener.
overrides: { headings: { levels: [{ level: 1, span: 'column', breakBefore: { enabled: false } }] } },
},
};Le résolveur et la fonction de nettoyage suivent le même schéma que les autres sections :
import {
DEFAULT_HTML_VIEWER_CONFIG,
resolveHtmlViewerConfig,
stripHtmlViewerDefaults,
} from 'postext';
const resolved = resolveHtmlViewerConfig(config.htmlViewer);
// => { maxCharsPerLine: 70, columnGap: 50, optimalLineBreaking: false }
const minimal = stripHtmlViewerDefaults(config.htmlViewer);
// => undefined when everything matches the defaultsVoir Intégrer la visionneuse HTML plus bas pour un exemple complet.
#Génération PDF (configuration)
La propriété pdfGeneration règle la façon dont le moteur PDF produit le document final. Ces réglages sont lus par le paquet postext-pdf au moment de l’export ; les visionneuses canvas et HTML les ignorent.
buildDocument les transporte dans le VDT, sous doc.config.pdfGeneration, et renderToPdf prend chaque réglage au premier endroit qui le fournit :
- ses propres options (
outlines,accessible,colorSpace) ; - le
pdfGenerationdu premier document qu’il rend (dans un livre, les réglages du premier chapitre s’appliquent à tout le fichier) ; - les valeurs par défaut : signets et balisage activés, couleur RVB.
Ainsi, renderToPdf(doc, { fontProvider }) suit la configuration, et une option passée à renderToPdf l’emporte pour ce seul réglage. forceColorSpace et colorSpace réunis tiennent lieu de l’option colorSpace : le colorSpace de la configuration s’applique tant que forceColorSpace est activé, et le PDF est en RVB quand il est désactivé. Les versions précédentes de postext-pdf ne lisaient que les options ; une configuration qui définit pdfGeneration modifie désormais le PDF d’un appelant qui ne passe aucune option.
type PdfColorSpace = 'rgb' | 'cmyk' | 'grayscale';
interface PdfGenerationConfig {
outlines?: boolean; // Emit PDF bookmarks from the heading tree.
forceColorSpace?: boolean; // Convert every colour to `colorSpace`.
colorSpace?: PdfColorSpace; // Target space used when `forceColorSpace` is true.
accessible?: boolean; // Tagged, PDF/UA-oriented output (structure tree, alt text, language).
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
outlines | boolean | true | Produit les signets PDF (outlines) à partir de la hiérarchie des titres, pour que le lecteur saute directement à n’importe quel titre depuis la barre latérale de sa visionneuse PDF. Désactivez-les pour les documents dont l’arborescence de titres n’a pas de sens (par exemple une affiche d’une seule page). |
forceColorSpace | boolean | false | Si vrai, chaque couleur du PDF rendu est convertie en colorSpace au moment de l’export. Laissez-le désactivé pour les PDF destinés d’abord à l’écran, dont les couleurs d’entrée sont déjà dans l’espace voulu ; activez-le pour garantir un seul espace colorimétrique quand les sources sont mêlées. |
colorSpace | 'rgb' | 'cmyk' | 'grayscale' | 'cmyk' | Espace colorimétrique cible utilisé quand forceColorSpace est activé. Utilisez 'cmyk' pour l’impression offset, 'rgb' pour les PDF destinés uniquement à l’écran et 'grayscale' pour les épreuves en noir et blanc. Sans effet quand forceColorSpace vaut false. Le CMJN est séparé avec le profil de sortie de print (FOGRA39 par défaut) et son traitement du noir, et les images RVB sont converties elles aussi ; une norme PDF/X définie là-bas écrit du CMJN quoi que dise ce réglage. |
accessible | boolean | true | Produit un PDF accessible et balisé, orienté PDF/UA-1 : un arbre de structure logique dans l’ordre de lecture (titres qui ne sautent jamais de niveau, paragraphes, listes, citations, encadrés, tableaux avec cellules d’en-tête, figures avec leur texte alternatif et leur légende, formules, renvois cliquables sous forme de liens, le contenu d’un :::toc comme un TOC avec un TOCI par ligne : le numéro de la ligne en Lbl, son titre et sa page dans une Reference qui contient le lien), le titre et la langue du document (le locale de premier niveau), l’identification PDF/UA dans les métadonnées XMP, et chaque marque décorative (fond de page, filets, grille de ligne de base, en-têtes et pieds de page courants, traits de coupe, en-têtes de tableau répétés, titre répété et marque de suite d’un encadré coupé) signalée comme artefact pour que les lecteurs d’écran l’ignorent. Une figure sans altText se rabat sur sa légende, puis sur son étiquette. Une figure ou un tableau flottant est lu juste après le texte qui le cite en premier, ou le texte qui précède sa ligne ::resource, et une boîte flottante après le texte qui précède sa clôture, même quand le flottant est placé sur une page ultérieure ; une liste ou une table des matières qui se poursuit au-delà d’un flottant reste un seul élément. Ne le désactivez que pour des fichiers maîtres d’impression où la structure supplémentaire n’est pas souhaitée. |
pdfGeneration: {
outlines: true,
accessible: true,
forceColorSpace: true,
colorSpace: 'cmyk',
}Le résolveur et la fonction de nettoyage correspondent à ceux des autres sections :
import {
DEFAULT_PDF_GENERATION_CONFIG,
resolvePdfGenerationConfig,
stripPdfGenerationDefaults,
} from 'postext';
const resolved = resolvePdfGenerationConfig(config.pdfGeneration);
// => { outlines: true, forceColorSpace: false, colorSpace: 'cmyk', accessible: true }
const minimal = stripPdfGenerationDefaults(config.pdfGeneration);
// => undefined when everything matches the defaultsVoir Générer des PDF plus bas pour la marche à suivre complète de l’export.
#Production pour l’impression (configuration)
La propriété print indique comment un livre part chez l’imprimeur : la norme PDF/X du fichier, le profil de sortie avec lequel son CMJN est séparé, la façon dont le noir s’imprime et les seuils du contrôle en amont (preflight). La mise en page l’ignore : la modifier ne déplace jamais une ligne. Trois éléments la lisent : postext-pdf quand il écrit le fichier, preflightDocument quand il contrôle un document mis en page, et l’aperçu d’impression des visionneuses canvas et Folio.
type PdfXStandard = 'none' | 'pdfx1a' | 'pdfx4';
interface PrintConfig {
standard?: PdfXStandard; // 'none': an ordinary PDF.
outputProfile?: string; // A catalogue id ('fogra39', 'fogra51'…) or 'custom'.
customProfile?: CustomOutputProfile; // An uploaded .icc file.
renderingIntent?: 'relative' | 'perceptual';
blackPointCompensation?: boolean;
convertImages?: boolean; // Separate RGB pictures (PDF/X-1a always does).
inkLimit?: number; // Total area coverage, percent.
black?: PrintBlackConfig;
preflight?: PrintPreflightConfig;
}
interface CustomOutputProfile {
name: string; // Its description, or the file name.
fileId: string; // The stored .icc file.
registryName?: string; // The condition's ICC registry name (FOGRA51…), else 'Custom'.
inkLimit?: number;
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
standard | 'none' | 'pdfx1a' | 'pdfx4' | 'none' | La variante PDF/X du fichier. 'pdfx1a' écrit du PDF/X-1a:2003 : CMJN et gris uniquement, sans transparence, accepté par tous les imprimeurs. 'pdfx4' écrit du PDF/X-4 : transparence et gestion des couleurs conservées, pour les flux actuels. L’une comme l’autre sépare chaque couleur avec le profil de sortie, quoi que dise pdfGeneration.colorSpace. |
outputProfile | string | 'fogra39' | La condition d’impression pour laquelle le CMJN est séparé : un identifiant du catalogue de profils, ou 'custom' pour customProfile. Un identifiant absent du catalogue, ou 'custom' sans fichier, revient à la valeur par défaut et produit un avertissement de configuration. |
customProfile | CustomOutputProfile | aucun | Un profil de sortie CMJN que vous fournissez, celui que vous donne votre imprimeur (le PSOcoated_v3.icc d’ECI, par exemple). Ses octets sont stockés à part, comme une police ; renderToPdf les reçoit par son option outputProfile. registryName est écrit comme identifiant de condition de l’output intent. |
renderingIntent | 'relative' | 'perceptual' | 'relative' | Le colorimétrique relatif garde exactes les couleurs que la presse sait imprimer et ramène les autres à la couleur imprimable la plus proche ; le perceptif compresse toute la gamme pour que les couleurs hors gamut gardent leurs rapports. |
blackPointCompensation | boolean | true | Avec le rendu relatif, fait correspondre le noir de l’écran au noir le plus profond qu’imprime la presse, pour que les tons les plus sombres gardent leur détail au lieu de se boucher. |
convertImages | boolean | true | Sépare les images RVB en CMJN avec le profil. Le PDF/X-1a le fait toujours. En PDF/X-4, false les garde en RVB, étiquetées sRGB par le /DefaultRGB des pages, pour que le RIP de l’imprimeur les convertisse. Les JPEG CMJN et en niveaux de gris sont toujours intégrés tels quels. |
inkLimit | number | celle du profil | Le total maximal de C+M+J+N, en pourcentage, accepté par le contrôle en amont. Par défaut, la limite selon laquelle le profil sépare (300 % pour la plupart des conditions offset, 230 % pour le papier journal IFRA26). |
black | PrintBlackConfig | voir Noir | Gris en noir seul, surimpression et noir enrichi. |
preflight | PrintPreflightConfig | voir Contrôle en amont | Ce que vérifie le contrôle en amont, et ses seuils. |
print: {
standard: 'pdfx4',
outputProfile: 'fogra51',
black: { richBlackColor: { c: 60, m: 40, y: 40, k: 100 } },
preflight: { minImageResolution: 300, safeZone: { value: 5, unit: 'mm' } },
}#Profils de sortie
postext livre ces profils de sortie CMJN dans son dossier icc/ (postext/icc/<id>.icc sur n’importe quel CDN npm, et /icc/<id>.icc sur postext.dev). Aucun n’est soumis à une restriction de droit d’auteur connue (CC0) : les profils FOGRA, GRACoL, SWOP et papier journal de colord, générés à partir des données de caractérisation de chaque condition, ainsi que FOGRA51 et FOGRA52, construits par postext avec ArgyllCMS à partir des données de la Fogra elle-même. Les profils d’ECI (ISO Coated v2, PSO Coated v3, PSO Uncoated v3) décrivent les mêmes conditions mais ne peuvent pas être redistribués ; importez-les comme profil personnalisé si votre imprimeur les demande.
| Id | Condition | Nom de registre | Limite d’encrage |
|---|---|---|---|
fogra39 | Offset, papier couché (condition ISO Coated v2) | FOGRA39 | 300 % |
fogra51 | Offset, couché premium (condition PSO Coated v3) | FOGRA51 | 300 % |
fogra52 | Offset, non couché sans bois (condition PSO Uncoated v3) | FOGRA52 | 300 % |
fogra47 | Offset, non couché blanc (PSO Uncoated ISO 12647) | FOGRA47 | 300 % |
fogra29 | Offset, non couché blanc | FOGRA29 | 300 % |
fogra30 | Offset, non couché jaunâtre | FOGRA30 | 340 % |
fogra27 | Offset, couché (ISO 12647-2:1996) | FOGRA27 | 300 % |
fogra28 | Rotative offset heatset, LWC brillant | FOGRA28 | 300 % |
fogra45 | Rotative offset heatset, LWC amélioré | FOGRA45 | 300 % |
fogra40 | Rotative offset heatset, papier SC | FOGRA40 | 340 % |
gracol2006 | GRACoL 2006, couché grade 1 | CGATS TR 006 | 300 % |
swop3 | SWOP 2006, couché grade 3 | CGATS TR 003 | 300 % |
swop5 | SWOP 2006, couché grade 5 | CGATS TR 005 | 300 % |
ifra26 | Papier journal coldset (ISO 12647-3) | IFRA26 | 230 % |
snap2007 | Papier journal SNAP 2007 | CGATS TR 002 | 320 % |
renderToPdf lit les octets du profil dans son option outputProfile ; sans eux, il télécharge le fichier du catalogue depuis profileBaseUrl (par défaut https://cdn.jsdelivr.net/npm/postext/icc/). Un rendu PDF/X dont le profil ne peut pas être chargé échoue ; un rendu CMJN ordinaire se rabat sur la formule classique avec un avertissement outputProfileUnavailable.
import { readFile } from 'node:fs/promises';
import { renderToPdf } from 'postext-pdf';
const pdf = await renderToPdf(doc, {
fontProvider,
print: { standard: 'pdfx1a', outputProfile: 'fogra39' },
outputProfile: await readFile('node_modules/postext/icc/fogra39.icc'),
});#PDF/X-1a et PDF/X-4
Les deux normes écrivent :
- l’output intent (
GTS_PDFX) qui nomme la condition d’impression et intègre le profil de destination ; - l’identification dans le dictionnaire Info (
GTS_PDFXVersion,/Trapped /False, le titre et les dates) et dans les métadonnées XMP (pdfxid:GTSPDFXVersion, les identifiants du document et de la version), fusionnée avec l’identification PDF/UA quand le fichier est balisé ; - une TrimBox et une BleedBox sur chaque page (la page entière quand il n’y a pas de traits de coupe) ;
- l’
/IDdu trailer ; - chaque couleur en DeviceCMYK (ou en gris) via le profil, et les traits de coupe en couleur de repérage ;
- aucune annotation de lien : un fichier destiné à la presse n’en porte aucune dans sa zone de fond perdu, donc les liens du PDF écran sont omis (les signets restent).
Le PDF/X-1a:2003 est du PDF 1.4 sans flux d’objets et sans transparence : une couleur translucide est appliquée telle qu’elle s’imprimerait sur le papier, l’alpha d’une image est aplati sur du blanc, et le négatif de page de débogage est omis (avec un avertissement pageNegativeIgnored). Le PDF/X-4 est du PDF 1.6 : la transparence reste, chaque page reçoit un groupe de transparence qui mélange en CMJN, et les images RVB conservées par convertImages: false sont étiquetées sRGB via /DefaultRGB.
Un fichier maître PDF pour l’impression (svg.pdfFileId) est intégré tel quel ; ses couleurs, ses polices et sa transparence sont donc les siennes ; le contrôle en amont signale ce qu’il apporte.
#Noir
interface PrintBlackConfig {
kOnlyNeutrals?: boolean; // Greys and black in black ink only.
overprint?: boolean; // 100 % K overprints.
richBlack?: boolean; // Large black areas in rich black.
richBlackColor?: CmykPercent; // { c, m, y, k } in percent.
richBlackMinSize?: Dimension; // The smaller side an area needs.
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
kOnlyNeutrals | boolean | true | Une couleur neutre (#000000, #808080…) s’imprime avec la seule encre noire, son K choisi pour que la luminosité corresponde, jamais en gris quadrichrome qui varie avec le repérage. Les images gardent la génération du noir propre au profil. |
overprint | boolean | true | Tout ce qui est peint en 100 % K seul (texte noir, filets, contours, petites formes noires) est en surimpression (op/OP avec OPM 1), pour qu’un décalage de plaque sur la presse n’ouvre jamais de liseré blanc autour. Tout le reste est en défonce ; les images et les dégradés ne sont jamais en surimpression. |
richBlack | boolean | true | Un aplat noir dont le petit côté atteint richBlackMinSize (un fond, un bandeau, une boîte) s’imprime en richBlackColor et en défonce, pour paraître profond au lieu de gris foncé. Le texte ne passe jamais en noir enrichi. |
richBlackColor | CmykPercent | | La formule du noir enrichi, en pourcentage. Gardez son total sous la limite d’encrage ; le contrôle en amont le vérifie. |
richBlackMinSize | Dimension | 6mm | Le petit côté qu’une zone noire doit atteindre pour s’imprimer en noir enrichi. |
#Couleurs définies en CMJN
Une couleur écrite en CMJN garde ses valeurs exactes : ColorValue.cmyk (en pourcentage) est appliqué tel quel dans un rendu d’impression, et hex est son rendu à l’écran. Une entrée de palette définie en CMJN couvre toutes les couleurs qui lui sont liées.
colorPalette: [
{ id: 'brand', name: 'Brand', value: { hex: '#00a0e3', model: 'cmyk', cmyk: { c: 100, m: 0, y: 0, k: 0 } } },
],#Contrôle en amont
interface PrintPreflightConfig {
enabled?: boolean;
minImageResolution?: number; // ppi at the printed size.
criticalImageResolution?: number;
minRuleWidth?: Dimension;
smallTextSize?: Dimension;
safeZone?: Dimension;
bleedSnap?: Dimension;
checkFonts?: boolean;
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
enabled | boolean | true | Exécute les contrôles. |
minImageResolution | number | 300 | Une image matricielle placée qui n’atteint pas ce nombre de pixels par pouce à sa taille imprimée, recadrage compris, reçoit un avertissement : figures, images de cellule de tableau, images de maquette, cases de bande dessinée. Une image sans résolution propre s’imprime à page.dpi à sa taille naturelle, si bien qu’une page mise en page à 150 dpi imprime chacune de ces images à 150 ppi ; une image qui a une résolution (bitmap.resolution, layout.bitmapResolution) s’imprime à cette résolution à sa taille naturelle. |
criticalImageResolution | number | 150 | En dessous, l’avertissement devient critique. Jamais au-dessus de minImageResolution. |
minRuleWidth | Dimension | 0.25pt | Filets, bordures, filets de colonne, filets de tableau et bordures de case de bande dessinée plus fins que cette valeur. |
smallTextSize | Dimension | 9pt | Texte de taille inférieure composé avec plus d’une encre (une couleur quadri, un noir enrichi) : il devient flou quand les plaques se décalent. Le texte noir, en K seul, n’est jamais compté. |
safeZone | Dimension | 5mm | Texte plus proche de la coupe que cette distance, là où le massicot risque de le couper. |
bleedSnap | Dimension | 3mm | Une boîte ou une image qui s’arrête aussi près de la coupe sans atteindre le fond perdu : prolongez-la dans le fond perdu ou rentrez-la. |
checkFonts | boolean | true | Signale les polices qu’un PDF placé n’intègre pas (le Sandbox examine chaque fichier maître d’impression avec inspectPrintMaster). Postext intègre toutes les polices qu’il compose. |
preflightDocument(doc, options) exécute les contrôles sur un document mis en page et renvoie une liste de problèmes, chacun avec un kind, une severity ('critical', 'warning' ou 'info'), l’index de page pageIndex absolu dans le livre, le rect fautif (en px de page) et, quand l’élément en a une, sa plage source. Les types sont lowImageResolution, declaredPixelsMismatch, rgbImage, thinRule, smallProcessText, inkLimit, safeZone et nearTrim. Sans transform, un neutre compte pour une encre et toute autre couleur pour trois, et l’encrage n’est pas vérifié ; avec une transformation, les décomptes et l’encrage sont exacts. La résolution d’une image est calculée à partir des pixels que déclare sa ressource, ou de ceux du fichier lui-même quand imageSize(fileId) les fournit (bitmapInfo sur les octets, ou l’image décodée) : une déclaration qui s’écarte de plus d’un pixel du fichier est signalée une fois comme declaredPixelsMismatch, un avertissement quand elle annonce plus de pixels que le fichier n’en a. placedImageResolutions(doc, { resources, imageSize }) liste chaque image matricielle placée avec sa résolution effective en ppi, que le contrôle en amont soit activé ou non.
import { bitmapInfo, outputTransform, parseIccProfile, preflightDocument, resolvePrintConfig } from 'postext';
import { inspectPrintMaster } from 'postext-pdf';
const print = resolvePrintConfig(config.print);
const transform = outputTransform(parseIccProfile(fogra51Bytes), { intent: print.renderingIntent });
const issues = preflightDocument(doc, {
print,
transform,
resources, // pixel sizes of the bitmaps
imageSize: (fileId) => bitmapInfo(bytesOf(fileId)), // the files' real pixels
imageColor: (fileId) => colourOf(fileId), // 'rgb' | 'cmyk' | 'gray', from the file
});
if (issues.some((i) => i.severity === 'critical')) process.exit(1);
const master = await inspectPrintMaster(masterBytes);
// => { nonEmbeddedFonts: ['Helvetica'], rgb: true, transparency: false }#Aperçu d’impression
Une page canvas peut être peinte telle qu’elle s’imprimera. createPrintPreview(transform, print, { paper, dpi, grayscale }) construit l’épreuve écran d’une configuration : chaque pixel est séparé via le profil (neutres en K seul, comme dans le PDF) et réaffiché à l’écran, sur le blanc propre du papier quand paper vaut true ; les zones noires assez grandes pour le noir enrichi apparaissent en noir enrichi. Avec grayscale, l’épreuve est une impression en niveaux de gris : un PDF forcé en niveaux de gris imprime la luminance de chaque couleur avec la seule encre noire, sans noir enrichi. Passez-la à renderPageToCanvas sous printPreview. Pour une vue de travail plutôt qu’une épreuve, guides ajoute les lignes de coupe, de fond perdu et de zone de sécurité, et marksFor entoure des zones d’une page (les rect du contrôle en amont) ; le Sandbox omet les deux, son aperçu ne montre donc que l’impression. postext-folio accepte le même objet sous printPreview ; avec paper: true, donnez entre-temps au livre une teinte de papier neutre (folio.paper.shade), sinon le papier est teinté deux fois.
import { createPrintPreview, renderPageToCanvas } from 'postext';
const preview = createPrintPreview(transform, print, { paper: true, dpi: doc.config.page.dpi });
renderPageToCanvas(page, doc, canvas, {
printPreview: { ...preview, guides: { safeZonePx: 59 }, marksFor: () => issues.map((i) => i.rect!).filter(Boolean) },
});#Moteur colorimétrique
La gestion des couleurs qu’utilise postext est exportée pour vos propres outils. Elle lit les profils ICC v2 et v4 (matrice/TRC et les tables de correspondance mft1, mft2, mAB, mBA) en TypeScript pur, sans WebAssembly.
parseIccProfile(bytes)lit un profil ;deviceChannels(profile)donne son nombre de canaux.outputTransform(profile, { intent, blackPointCompensation, preserveNeutrals })renvoiefromRgb(r, g, b)(sRGB 0..1 → CMJN 0..1),toLab(cmyk, paper?)etproof(cmyk, paper?)(CMJN → sRGB écran).cmykToLab,labToCmyk,srgbToLab,labToSrgb,deltaEettotalAreaCoveragesont les conversions unitaires ;buildRgbLut/sampleRgbLutcréent et lisent des tables de correspondance denses pour le travail au pixel.OUTPUT_PROFILES,outputProfileInfo(id)etloadOutputProfile(id, baseUrl?)donnent le catalogue ;srgbProfileBytes()écrit le profil sRGB avec lequel le PDF/X-4 étiquette le RVB ;authoredCmykColors(config)liste les couleurs qu’une configuration a définies en CMJN.
Le résolveur et la fonction de nettoyage correspondent à ceux des autres sections : resolvePrintConfig, stripPrintDefaults et profileInkLimit(config) (la limite du profil que nomme une configuration, avant tout remplacement par inkLimit), avec DEFAULT_PRINT_CONFIG, DEFAULT_PRINT_BLACK_CONFIG, DEFAULT_PRINT_PREFLIGHT_CONFIG et DEFAULT_RICH_BLACK.
#Contrôle du contraste (configuration)
La propriété contrast règle le contrôle qui indique si le texte d’un livre peut être lu : chaque couleur de texte face au fond sur lequel elle est composée. La mise en page l’ignore : la modifier ne déplace jamais une ligne. contrastDocument la lit quand il contrôle un document mis en page, le Sandbox liste les résultats dans Vérifications et affiche le rapport de contraste à côté de chaque champ de couleur, et postext check les imprime.
interface ContrastConfig {
enabled?: boolean;
level?: 'AA' | 'AAA';
mode?: 'auto' | 'screen' | 'print' | 'both';
reversedText?: {
enabled?: boolean;
minSize?: Dimension;
minFineSize?: Dimension;
lightWeight?: number;
};
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
enabled | boolean | true | Exécute le contrôle. |
level | 'AA' | 'AAA' | 'AA' | Le niveau WCAG 2 auquel les rapports sont tenus. Voir Seuils. |
mode | string | 'auto' | Le rendu examiné : 'screen', 'print', 'both', ou 'auto', qui examine toujours l’écran et aussi l’impression pour un livre préparé pour l’impression (une norme PDF/X dans print.standard, un PDF CMJN dans pdfGeneration, ou des traits de coupe dans page.cutLines). |
reversedText.enabled | boolean | true | Signale le texte en défonce dans le contrôle d’impression. |
reversedText.minSize | Dimension | 8pt | Le texte en défonce plus petit que cette taille est signalé. |
reversedText.minFineSize | Dimension | 12pt | Même chose pour l’italique et les graisses maigres, dont les traits sont plus fins. |
reversedText.lightWeight | number | 300 | Une graisse égale ou inférieure à celle-ci compte comme maigre. |
Un level ou un mode écrit autrement se lit comme la valeur par défaut et est signalé comme valeur de réglage inconnue (voir Avertissements de configuration).
#Seuils
Le rapport qu’un texte doit atteindre dépend de sa taille et de sa graisse, comme dans les WCAG 2.
| Niveau | Texte | Grand texte |
|---|---|---|
AA | 4,5:1 | 3:1 |
AAA | 7:1 | 4,5:1 |
Le grand texte mesure 18 pt ou plus, ou 14 pt ou plus avec une graisse de 700 ou davantage. Les tailles sont les tailles imprimées, en points. Un exposant ou un indice est jugé à la taille du texte auquel il appartient.
#Écran et impression
Postext compose les mêmes pages pour un écran et pour une presse, et une couleur ne se lit pas de la même façon sur les deux.
- Écran est le rapport de contraste WCAG 2 des couleurs sRGB,
(L1 + 0.05) / (L2 + 0.05)sur leurs luminances relatives : ce que montrent le canvas, la visionneuse HTML, un EPUB et un PDF RVB. - Impression est la même formule appliquée à la luminance de chaque couleur sur le papier. La couleur est séparée avec le profil de sortie du travail (une couleur définie en CMJN garde ses valeurs), la séparation est relue via le profil, et sa luminance est prise par rapport au papier nu, qui est le blanc d’une page imprimée comme le blanc de l’affichage est celui d’un écran. L’encre n’est jamais un noir parfait : un noir plein sur blanc atteint environ 14:1 sur papier couché (FOGRA39, FOGRA51), 8:1 sur papier non couché (FOGRA47, FOGRA52) et 5:1 sur papier journal (IFRA26, SNAP), là où un écran donne 21:1. Un gris qui passe à l’écran peut échouer sur le papier :
#767676sur blanc donne 4,54:1 à l’écran et environ 3,3:1 sur papier couché.
Le rapport d’impression exige la transformation du profil de sortie (options.transform, construite avec outputTransform). Sans elle, seul le texte en défonce est contrôlé pour l’impression.
#Texte en défonce
Un texte clair réservé dans un fond encré se bouche à l’impression quand il est petit ou que ses traits sont fins : l’encre du fond s’étale dans les lettres, et un fond composé de plusieurs encres dépend aussi du bon repérage des plaques. Le rapport de contraste ne le montre pas, puisque du blanc sur bleu foncé dépasse 10:1. Le contrôle d’impression signale ce texte à part (reversedText) quand il est plus petit que minSize, ou plus petit que minFineSize s’il est en italique ou d’une graisse égale ou inférieure à lightWeight. Chaque résultat indique de combien des quatre encres le fond est composé.
#Ce qui est examiné
Le contrôle lit les lignes de chaque bloc avec leurs couleurs en ligne (gras, italique, renvois, pastilles), les marqueurs de liste, les lettrines, les légendes, les notes et les cellules de tableau, ainsi que le texte des emplacements de maquette : titres courants, ouvertures, maquettes de titre, titres de boîte. Le fond est le remplissage le plus haut sous le texte : une boîte de maquette, un encadré, une barre de légende, une cellule de tableau, une pastille, ou à défaut la couleur de la page (page.backgroundColor, ou le papier que la palette d’une partie donne à ses pages). Une couleur translucide est mélangée avec ce qui se trouve dessous. Le texte posé sur une image est ignoré, puisque son fond n’est pas d’une seule couleur, de même que le lettrage de bande dessinée, les lectures ruby et les formules.
#Lancer le contrôle
contrastDocument(doc, options) renvoie les résultats d’un document mis en page, du rapport le plus faible au plus élevé. Chacun comporte l’index de page pageIndex absolu dans le livre, le rect sur la feuille (en px de page) et la plage source de sa première occurrence, les deux couleurs telles que peintes (color, background), la plus petite taille sizePt à laquelle il est composé avec son weight et son italic, un role ('body', 'heading', 'caption', 'table', 'runningHead', 'design', 'chip' ou 'marker'), le text du premier segment et le nombre count de segments composés ainsi. Une paire est signalée une fois par seuil, quel que soit le nombre de lignes qui l’utilisent.
lowContrastajoutelevel,large,required, le rapport dans chaque rendu contrôlé (screen,print) etfailing, les rendus sousrequired.reversedTextajoutereasons('small','italic','light'),minimumPtetinks.
Les options sont contrast (les réglages résolus, quand ce ne sont pas ceux du document), media (les rendus, quoi que dise mode) et transform.
import { contrastDocument, outputTransform, parseIccProfile } from 'postext';
const transform = outputTransform(parseIccProfile(fogra51Bytes));
for (const issue of contrastDocument(doc, { transform })) {
if (issue.kind === 'lowContrast') {
console.log(`${issue.color} on ${issue.background}: ${issue.screen}:1, ${issue.level} asks for ${issue.required}:1`);
}
}contrastPairs(doc, options) renvoie chaque paire texte et fond que compose le document, conforme ou non, avec son rapport screen, son rapport print quand la transformation est fournie, le rapport required et les couleurs telles que la configuration les écrit (textColor, groundColor) : ce qu’un outil de conception affiche à côté d’un champ de couleur. Il s’exécute quoi que dise enabled.
Les mesures sont exportées pour vos propres outils :
contrastRatio(a, b)etrelativeLuminance(color)donnent le rapport WCAG 2 et la luminance de couleurs sRGB.isLargeText(sizePt, weight)etcontrastThreshold(level, large)donnent le seuil d’une taille et d’une graisse.blendColors(top, under)donne une couleur translucide posée sur une autre, sous la forme#rrggbb.printContrastRatio(a, b, context),printLuminance(color, context)etprintSeparation(color, context)donnent les mêmes valeurs sur le papier. Le contexte contient latransformet, sousauthored, le résultat deauthoredCmykColors(config).contrastMedia(doc.config, contrast)donne les rendus auxquelsmodese résout pour un document.
Le résolveur et la fonction de nettoyage correspondent à ceux des autres sections : resolveContrastConfig et stripContrastDefaults, avec DEFAULT_CONTRAST_CONFIG, DEFAULT_CONTRAST_REVERSED_TEXT_CONFIG, CONTRAST_LEVELS et CONTRAST_MODES.
#Visionneuse Folio (configuration)
La propriété folio règle la façon dont la visionneuse Folio (postext-folio) présente le livre imprimé en 3D : l’angle de vue, le papier, la reliure, la surface sur laquelle repose le livre et la lumière. La mise en page l’ignore, tout comme les sorties canvas, HTML et PDF. buildDocument transporte les réglages résolus dans le VDT sous doc.config.folio quand la configuration en définit, si bien qu’un document qui n’en a pas garde son empreinte de mise en page.
interface FolioConfig {
tilt?: number; // Degrees from straight above, 0–70.
yaw?: number; // Degrees round the book, −180–180.
paper?: {
type?: 'uncoated' | 'bookWove' | 'coatedMatte' | 'coatedSilk' | 'coatedGloss'
| 'bible' | 'newsprint' | 'cardStock' | 'board';
grammage?: number; // g/m²
bulk?: number; // cm³/g; caliper µm = grammage × bulk
finish?: 'auto' | 'uncoated' | 'matte' | 'silk' | 'gloss';
texture?: 'auto' | 'smooth' | 'vellum' | 'wove' | 'laid' | 'linen' | 'felt';
textureStrength?: number; // 0–2
shade?: ColorValue;
showThrough?: boolean;
};
binding?: {
type?: 'hardcover' | 'paperback' | 'sewn' | 'layflat' | 'saddleStitch' | 'folded';
cover?: 'case' | 'pages';
coverMaterial?: 'auto' | 'cloth' | 'paper' | 'leather';
coverColor?: ColorValue;
spineImage?: string; // resource id
};
surface?: {
type?: 'oak' | 'walnut' | 'linen' | 'felt' | 'leather' | 'marble' | 'plain' | 'none';
color?: ColorValue;
};
lighting?: {
environment?: 'studio' | 'daylight' | 'lamp' | 'overcast' | 'night';
intensity?: number; // 0.25–2
shadows?: boolean;
};
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
tilt | number | 22 | Angle de la vue par rapport à la verticale, en degrés, limité à 0–70. À 0, le livre ouvert est vu à plat d’en haut ; un angle plus grand rapproche le pied des pages et montre l’épaisseur du bloc de pages. |
yaw | number | 0 | De combien la vue tourne autour du livre, en degrés, ramené dans −180–180. À 0, le livre est vu depuis le pied de ses pages ; un angle positif amène l’œil vers sa droite, un angle négatif vers sa gauche. Avec tilt, c’est la vue sur laquelle s’ouvre la visionneuse et celle vers laquelle resetView() revient en douceur. |
paper.type | FolioPaperType | 'uncoated' ; 'newsprint' sur un format de journal | La sorte de papier. Elle fournit les valeurs par défaut des cinq champs ci-dessous (voir le tableau des papiers). cardStock est du carton de couverture ; board est du carton rigide, comme dans un livre cartonné pour enfants, et ses feuillets tournent sans se courber. |
paper.grammage | number | celui du papier | Grammage en grammes par mètre carré, 20–2500. Un papier plus lourd est plus épais, plus raide et plus opaque : un feuillet se courbe selon un arc plus large et laisse moins voir le verso. |
paper.bulk | number | celle du papier | Main (épaisseur par unité de grammage), en cm³/g, 0,5–3. L’épaisseur d’une feuille en micromètres vaut grammage × main, et l’épaisseur du bloc de pages en découle avec le nombre de pages. |
paper.finish | FolioPaperFinish | 'auto' | Non couché (fibres, sans reflet), ou couché et calandré en mat, satiné (un reflet doux) ou brillant. Dans Folio, une page brillante reflète le feuillet qui tourne au-dessus d’elle. 'auto' reprend celui du papier. |
paper.texture | FolioPaperTexture | 'auto' | Le relief de la surface : smooth (calandré), vellum (un grain fin), wove (la texture régulière de la plupart des papiers d’édition, formée sur une toile métallique tissée), laid (fines lignes de vergeure croisées par des pontuseaux plus espacés, laissées par un rouleau égoutteur), linen (une trame toilée gaufrée), felt (marques de feutre irrégulières). 'auto' reprend celle du papier. |
paper.textureStrength | number | 1 | Intensité avec laquelle la texture apparaît dans la lumière, 0–2. |
paper.shade | ColorValue | celle du papier | La couleur du papier avant impression (blanc, naturel, crème). Les pages sont imprimées dessus. |
paper.showThrough | boolean | true | Le verso d’une page transparaît légèrement à travers un papier mince. Après le papier bible, c’est le papier journal qui le laisse le plus voir : son encre pénètre dans la feuille. |
binding.type | FolioBindingType | 'hardcover' ; 'folded' sur un format de journal | hardcover : reliure cartonnée (emboîtée), plats légèrement plus grands que les pages. paperback : dos collé (fraisé et collé), s’ouvre moins à plat. sewn : une couverture souple avec cahiers cousus. layflat : s’ouvre à plat, sans creux au petit fond. saddleStitch : feuilles pliées et agrafées dans le pli, comme un magazine ou une brochure ; pas de dos plat. folded (depuis postext 1.18) : un journal, feuilles pliées une fois et glissées les unes dans les autres sans rien pour les tenir ; pas d’agrafes, pas de dos ni de plat de couverture, et la première page est la une. Une suite :::paper avec un shade imprime une section, par exemple les pages économie, sur papier journal saumon. |
binding.cover | FolioCoverSource | 'case' | Les couvertures. 'case' dessine un emboîtage autour des pages. 'pages' prend la première page du livre comme premier plat et sa dernière page, quand c’est un verso, comme second plat : le livre reste fermé jusqu’à ce qu’on tourne la couverture, les plats tournent raides (en piqûre à cheval, la couverture est une feuille un peu plus lourde que les pages et tourne comme elles), et aucun emboîtage n’est dessiné. |
binding.coverMaterial | FolioCoverMaterial | 'auto' | 'auto' donne de la toile sur une reliure cartonnée et du carton ('paper') sur les autres reliures. |
binding.coverColor | ColorValue | bleu foncé (#2c3e57) | La couleur du matériau de couverture. |
binding.spineImage | string | aucune | L’identifiant d’une ressource bitmap ou SVG imprimée sur le dos : le dos tel qu’on le voit livre debout, tête en haut et premier plat à droite. Elle est ajustée pour couvrir le dos, centrée. Ignorée en piqûre à cheval et en reliure pliée. |
surface.type | FolioSurfaceType | 'oak' | Ce sur quoi repose le livre. 'none' laisse le fond de l’hôte. |
surface.color | ColorValue | aucune | Teinte la surface ; sur 'plain', c’est la couleur de la surface. |
lighting.environment | FolioEnvironment | 'studio' | L’environnement reflété par les papiers couchés et brillants, associé à la lumière principale qui projette les ombres. |
lighting.intensity | number | 1 | Exposition, 0,25–2. |
lighting.shadows | boolean | true | Ombres projetées par la lumière principale. |
Les papiers et les valeurs qu’ils fournissent (FOLIO_PAPER_STOCKS), typiques des fiches techniques des papetiers :
| Papier | Grammage | Main | Épaisseur | Fini | Texture | Teinte |
|---|---|---|---|---|---|---|
uncoated (offset sans bois) | 90 g/m² | 1,25 | 113 µm | non couché | vélin | #fcfbf8 |
bookWove (crème, bouffant) | 80 g/m² | 1,6 | 128 µm | non couché | vélin | #f6efdc |
coatedMatte | 115 g/m² | 1,0 | 115 µm | mat | lisse | #fdfdfc |
coatedSilk | 115 g/m² | 0,9 | 104 µm | satiné | lisse | #ffffff |
coatedGloss | 115 g/m² | 0,8 | 92 µm | brillant | lisse | #ffffff |
bible | 40 g/m² | 1,1 | 44 µm | non couché | grain fin | #f9f6ee |
newsprint | 48 g/m² | 1,5 | 72 µm | non couché | vélin | #ebe7dc |
cardStock | 250 g/m² | 1,2 | 300 µm | non couché | grain fin | #fbfaf6 |
board | 1250 g/m² | 1,6 | 2000 µm | satiné | lisse | #ffffff |
Un roman sur papier d’édition crème, relié en dos collé, sur un bureau en noyer sous une lampe de lecture :
folio: {
paper: { type: 'bookWove' },
binding: { type: 'paperback', coverColor: { hex: '#8a2b1f', model: 'hex' } },
surface: { type: 'walnut' },
lighting: { environment: 'lamp' },
}Une page au format de journal (page.sizePreset 'broadsheet', 'berliner', 'tabloid' ou 'compact') est présentée comme un journal quand la configuration ne nomme ni papier ni reliure : papier newsprint et reliure folded (depuis postext 1.18). Un papier ou une reliure que nomme la configuration est conservé, si bien que paper: { type: 'uncoated' } imprime un tabloïd sur papier offset. Les champs de papier définis sans sorte de papier (un grammage, un shade) s’appliquent au papier journal. Le résolveur et la fonction de nettoyage prennent le format en second argument, et folioForTrim(folio, sizePreset) écrit les deux valeurs par défaut dans la configuration :
resolveFolioConfig({ tilt: 30 }, 'tabloid');
// => { tilt: 30, paper: { type: 'newsprint', grammage: 48, bulk: 1.5, … }, binding: { type: 'folded', coverMaterial: 'paper', … }, … }
stripFolioDefaults({ paper: { type: 'newsprint' }, binding: { type: 'folded' } }, 'tabloid');
// => undefinedLes couleurs suivent les liens de palette comme n’importe quelle autre couleur de la configuration (paletteId). Le résolveur et la fonction de nettoyage correspondent à ceux des autres sections ; la fonction de nettoyage retire les valeurs de papier égales à celles du papier choisi :
import { FOLIO_PAPER_STOCKS, DEFAULT_FOLIO_CONFIG, resolveFolioConfig, stripFolioDefaults } from 'postext';
resolveFolioConfig({ paper: { type: 'bible' } }).paper;
// => { type: 'bible', grammage: 40, bulk: 1.1, finish: 'uncoated', texture: 'vellum', textureStrength: 1, shade: { hex: '#f9f6ee', … }, showThrough: true }
stripFolioDefaults({ paper: { type: 'bible', grammage: 40 } });
// => { paper: { type: 'bible' } }Dans le Sandbox, ces réglages forment le groupe Folio du panneau Maquette (Maquette → Folio → Visionneuse Folio (3D)), et l’onglet Folio les montre au fil de vos modifications, sans relancer la mise en page du livre. Voir Un livre en 3D pour la visionneuse elle-même, et Format du document › :::paper pour une suite de pages sur un autre papier.
#Débogage
La propriété debug regroupe deux sortes d’aides à la rédaction : des calques visuels qui gardent le texte source et la mise en page rendue synchronisés, et un ensemble d’avertissements qui font apparaître les problèmes typographiques ou structurels dans le panneau Vérifications du Sandbox. Ni les uns ni les autres n’affectent la sortie exportée.
| Propriété | Type | Description |
|---|---|---|
cursorSync | SyncIndicatorConfig | Curseur reproduit dans la mise en page rendue ; voir Calques visuels. |
selectionSync | SyncIndicatorConfig | Sélection du source surlignée sur la page ; voir Calques visuels. |
looseLineHighlight | LooseLineHighlightConfig | Calque sur les lignes justifiées lâches ; voir Calques visuels. |
pageNegative | | Négatif à fort contraste de la page ; voir Calques visuels. |
warnings | WarningsToggleConfig | Un booléen par type d’avertissement de rédaction affiché dans l’éditeur ; voir Avertissements. |
#Calques visuels
| Propriété | Type | Défaut | Description |
|---|---|---|---|
cursorSync.enabled | boolean | true | Affiche dans la mise en page rendue un curseur qui reproduit la position du curseur dans le source. |
cursorSync.color | ColorValue | #2563eb | Couleur de ce curseur. |
selectionSync.enabled | boolean | true | Surligne la plage rendue qui correspond à la sélection dans le source. |
selectionSync.color | ColorValue | #fde04780 | Couleur du surlignage : un jaune translucide par défaut. |
looseLineHighlight.enabled | boolean | false | Peint un calque sur les lignes justifiées dont l’espacement des mots dépasse threshold fois la largeur normale de l’espace. |
looseLineHighlight.color | ColorValue | #ff000040 | Couleur de ce calque. |
looseLineHighlight.threshold | number | 3 | Multiple de la largeur normale de l’espace au-delà duquel une ligne justifiée compte comme lâche. L’avertissement looseLines utilise le même seuil. Une ligne justifiée dont les espaces s’étireraient au-delà de 3× est composée en drapeau ; avec la valeur par défaut, le calque et l’avertissement ne trouvent donc presque rien dans le texte courant. Abaissez-le (1,5 ou 2) pour voir les lignes lâches mais encore justifiées. |
pageNegative.enabled | boolean | false | Affiche un calque négatif à fort contraste sur la page : utile pour examiner d’un coup d’œil la forme générale d’une double page (densité du texte, équilibre des colonnes, blancs) sans être distrait par le détail des glyphes. |
Chaque SyncIndicatorConfig vaut { enabled: boolean; color?: ColorValue }. LooseLineHighlightConfig vaut { enabled: boolean; color?: ColorValue; threshold?: number }. pageNegative est un simple interrupteur { enabled: boolean }.
debug: {
cursorSync: { enabled: true, color: { hex: '#ff0066', model: 'hex' } },
selectionSync: { enabled: false, color: { hex: '#fde04780', model: 'hex' } },
looseLineHighlight: { enabled: true, color: { hex: '#ff000040', model: 'hex' }, threshold: 3 },
pageNegative: { enabled: true },
}Ces calques sont dessinés par le Sandbox par-dessus son aperçu Canvas. Ils ne font pas partie de la page : renderPage, la sortie HTML et le PDF ne les peignent jamais.
#Lignes lâches dans votre propre canvas
Le moteur exporte le surlignage des lignes lâches sous forme de deux fonctions, pour une page que vous peignez vous-même :
import { buildDocument, renderPageToCanvas, drawLooseLines, findLooseLines } from 'postext';
const doc = buildDocument(content, config);
const canvas = document.querySelector('canvas')!;
renderPageToCanvas(doc.pages[0], doc, canvas, { scale: 0.5 });
drawLooseLines(canvas.getContext('2d')!, doc.pages[0], doc, { threshold: 2.5 });
// The same lines as data: a report, an SVG overlay, a count per page.
for (const { ratio, line, block } of findLooseLines(doc, { threshold: 2.5 })) {
console.log(`page ${block.pageIndex + 1}: ${ratio.toFixed(2)}× — ${line.text}`);
}findLooseLines(doc, { threshold?, pageIndex? })renvoie, dans l’ordre de lecture, chaque ligne justifiée dont l’espacement des mots dépassethreshold:{ block, line, ratio, x, y, width, height }.ratiovautlineWordSpacing(line): l’espacement tel queminWordSpacingetmaxWordSpacingle bornent (justifiedSpaceLimitRatioquand la ligne contient des espaces d’un autre caractère, sinonjustifiedSpaceRatio), si bien qu’une ligne composée à la limite et contenant une espace en gras n’est pas signalée avec un seuil égal àmaxWordSpacing. Le rectangle, en pixels de page, est la bande que couvre le surlignage : toute la largeur du bloc à hauteur de la ligne. Ce sont les lignes que le Sandbox surligne et signale commelooseLinedans son panneau Vérifications.drawLooseLines(ctx, page, doc, { threshold?, color? })remplit ces bandes pour une page et renvoie les lignes peintes. Elle dessine en pixels de page sous la transformation courante du contexte ; appelez-la donc juste aprèsrenderPageourenderPageToCanvassur le même canvas : les deux laissent le contexte mis à l’échelle de la page.coloraccepte n’importe quel style de remplissage canvas.- Valeurs par défaut. Les deux fonctions utilisent le seuil (3) et la couleur (
#ff000040) par défaut, et non ledebug.looseLineHighlightdu document : ce réglage appartient au Sandbox. Pour suivre une configuration, passezresolveDebugConfig(config.debug).looseLineHighlight.thresholdet.color.hex.
#Avertissements
debug.warnings détermine quels problèmes de rédaction apparaissent dans le panneau Vérifications du Sandbox (réglé dans Maquette → Avancé → Avertissements). Chaque clé est un interrupteur booléen indépendant ; mettez-en une à false pour faire taire cet avertissement précis sans désactiver les autres.
Ces interrupteurs ne filtrent que le panneau du Sandbox. Les avertissements que le moteur enregistre lui-même (boîtes qui débordent de leur colonne dans doc.warnings ; identifiants de ressource, directives, intégrations et identifiants de style inconnus, et grilles de tableau irrégulières dans doc.contentWarnings) y figurent quoi que disent les interrupteurs, et les moteurs de rendu signalent les images qu’ils peignent comme espaces réservés ; voir Avertissements dans le document.
interface WarningsToggleConfig {
missingFont?: boolean;
looseLines?: boolean;
headingHierarchy?: boolean;
consecutiveHeadings?: boolean;
listAfterHeading?: boolean;
designIssues?: boolean;
}| Propriété | Type | Défaut | Description |
|---|---|---|---|
missingFont | boolean | true | Signale qu’une police désignée par la configuration n’a pas pu être chargée dans le navigateur. Repère tôt les fautes de frappe dans fontFamily et les paquets @fontsource/... manquants, avant qu’ils ne se traduisent par des substitutions silencieuses de police de repli dans le rendu. |
looseLines | boolean | true | Signale les lignes justifiées dont l’espacement des mots dépasse debug.looseLineHighlight.threshold. Fonctionne avec le calque : l’avertissement les énumère dans le panneau, le calque les montre en place. |
headingHierarchy | boolean | true | Signale les niveaux de titre qui sautent un rang, par exemple un H1 suivi directement d’un H3. Un trou dans la structure des titres trahit en général une erreur de profondeur ou une mauvaise compréhension du plan du document. |
consecutiveHeadings | boolean | false | Signale un titre immédiatement suivi d’un autre titre, sans paragraphe ni liste entre les deux. Désactivé par défaut, car les titres empilés sont légitimes dans de nombreux modèles (titre + sous-titre, chapitre + épigraphe) ; activez-le pour les manuscrits où chaque titre est censé introduire de la prose. |
listAfterHeading | boolean | false | Signale une liste qui commence immédiatement après un titre, sans paragraphe d’introduction. Désactivé par défaut, car les ouvrages de référence le font couramment ; activez-le pour les textes narratifs où chaque liste doit être encadrée par de la prose. |
designIssues | boolean | true | Signale les problèmes d’intégrité dans les emplacements de maquette : en-têtes et pieds de page, ouverture de partie et verso blanc qui la suit, lignes de partie de la table des matières, emplacements de maquette avancée des titres, et maquette et titres courants de section de chaque style de titre. Couvre les chaînes d’ancrage circulaires et les références d’ancrage orphelines (un élément ancré à un #id qui n’existe plus), un titre sur toute la largeur de la page dont le breakBefore est désactivé, et une maquette avancée activée dont les éléments n’affichent jamais . |
debug: {
warnings: {
missingFont: true,
looseLines: true,
headingHierarchy: true,
consecutiveHeadings: true,
listAfterHeading: false,
designIssues: true,
},
}En plus de ceux-ci, le panneau liste toujours les avertissements que soulève la mise en page elle-même (VDTDocument.warnings), comme un encadré qui déborde de sa colonne (calloutOverflow), et les valeurs de configuration que le moteur a remplacées (VDTDocument.configWarnings, ou collectConfigWarnings(config) ; voir Avertissements de configuration ci-dessous).
#Avertissements de configuration
Huit erreurs dans la configuration elle-même ne passent jamais sous silence, et aucun interrupteur ne les masque. Le moteur n’échoue sur aucune d’elles ; il substitue une valeur, ou ignore le réglage, et le signale :
- Format de numérotation inconnu : un
numberFormatde liste numérotée, unpage.pageNumbering.formatou lecounterFormatd’un type de ressource qui ne correspond à aucune des graphies de format de numérotation. La numérotation se fait en décimal. - Pile de polices dans une famille : un
fontFamily(ou n’importe quel…FontFamily) qui contient une pile de polices CSS. Le texte est composé dans la première famille de la pile (voir Une seule famille parfontFamily). - Colonne latérale sans place : un
sideColumnPercentde mise en page'oneAndHalf'(celui du document, ou lalayoutpropre d’un style de titre) qui laisserait l’une des colonnes sous 1 % de la largeur du contenu, ou qui n’est pas un nombre. Les colonnes sont découpées selon la valeur la plus proche que les deux acceptent, etusedla nomme (sideColumnPercentClamped; voir la mise en page'oneAndHalf'). - Nombre de colonnes hors limites : un
columnCountde mise en page'multiple'(celui du document, ou lalayoutpropre d’un style de titre) qui n’est pas un nombre entier de 3 à 8. La page est découpée selon le nombre valide le plus proche (3 pour une valeur qui n’est pas un nombre), etusedle nomme (columnCountClamped; voir la mise en page'multiple'). - Grille de caractères trop grande : un
cjk.gridavec plus de caractères par ligne ou de lignes par page que les marges ne le permettent. La grille est réglée sur le maximum qui tient, etusednomme ce nombre (cjkGridClamped; voir Grille de caractères). - Réglage de titre inconnu : une clé que n’ont pas
headings,headings.balancing, un niveau de titre, un style de titre ou un style de paragraphe : unletterSpacngmal orthographié, untrackingemprunté à un autre outil, unlevelsur un style de titre, unfontStyle: 'italic'sur un style de paragraphe (qui attenditalic: true). Une tabulation est vérifiée de la même façon (unleadersau lieu deleader). Le moteur l’ignore (jusqu’à postext 1.4, il le faisait sans rien dire).valueest la clé,usedest vide, etsuggestionnomme le réglage le plus proche, quand il n’en diffère que d’une ou deux lettres ou seulement par la casse (unknownConfigKey). - Valeur de réglage inconnue : un réglage qui accepte un mot parmi quelques-uns et qui en contient un autre, comme
direction: 'right'(il accepteauto,ltrourtl). Le moteur lit la valeur par défaut à la place, etusednomme ce qu’elle donne : pourdirection, le sens de la langue du document (unknownConfigValue). Unalignde tabulation qui n’est aucun de ses quatre mots est lu comme'start', et unepositionqui n’est ni une longueur, ni'end', ni un pourcentage fait ignorer la tabulation (usedvaut'none'). Les mots des réglages de bande dessinée sont vérifiés aussi (Bande dessinée › Avertissements de bande dessinée) :usedest la valeur à laquelle le réglage s’est résolu (la valeur par défaut propre d’un style de bulle, pour un style intégré), etsuggestionnomme le mot le plus proche de la valeur, quand il y en a un. Lelevelet lemodedu contrôle du contraste sont vérifiés de la même façon :usedvaut'AA'ou'auto'. - Numéros de ligne en texte vertical :
lineNumbers.enabled: truedans un document composé verticalement (layout.writingMode: 'vertical-rl'). Les pages verticales n’ont pas de numéros de ligne, etusedvautfalse(lineNumbersUnsupported; voir Numéros de ligne). - Habillage en texte vertical : le
defaultPlacement.wrapd’un type de ressource dans un document composé verticalement. Les pages verticales ne composent pas de texte à côté d’une figure, etusedvautnone(wrapUnsupported; voir Format du document › Habillage). Unwrapqui ne nomme aucun côté est une valeur de réglage inconnue.
Le Sandbox les liste dans le panneau Vérifications avec le chemin du réglage. Dans le code, buildDocument les place sur le document sous configWarnings (absent quand la configuration est propre), et collectConfigWarnings(config) les renvoie sans rien mettre en page :
import { buildDocument, collectConfigWarnings } from 'postext';
// Plain JavaScript: in TypeScript, 'roman' does not type-check to begin with.
const config = { bodyText: { fontFamily: 'EB Garamond, serif' }, orderedLists: { numberFormat: 'roman' } };
const doc = buildDocument({ markdown }, config);
doc.configWarnings;
// [{ kind: 'fontFamilyStack', path: 'bodyText.fontFamily', value: 'EB Garamond, serif', used: 'EB Garamond' },
// { kind: 'unknownNumberFormat', path: 'orderedLists.numberFormat', value: 'roman', used: 'arabic' }]
collectConfigWarnings(config); // the same listChaque configuration partielle imbriquée est aussi vérifiée : styles de titre, listes à l’intérieur des parties, htmlViewer.overrides, éléments de maquette.
formatWarning (voir Avertissements dans le document) les décrit aussi, avec le chemin du réglage en tête (bodyText.fontFamily: font stack "EB Garamond, serif" — set in "EB Garamond", headingStyles[0].letterSpacng: unknown setting "letterSpacng" — ignored (did you mean "letterSpacing"?)), si bien qu’un hôte peut journaliser en une seule boucle les trois listes que renvoie une composition.