Kapitel 8 · Teil II · Das Handwerk
Konfiguration: Ressourcen und Tabellen
Ressourcentypen und ihre Nummerierung, Tabellen- und Legendenstile, einfarbige Diagramme und gedruckte Videos
Kurz gesagt
Diese Seite behandelt die Einstellungen für Abbildungen, Tabellen, Diagramme und Videos. Postext nennt sie Ressourcen und nummeriert jede Art für sich. Sie legen fest, wie Tabellen aussehen: ihre Linien, ihre Flächen, ihre Schrift und wie sie sich über Seiten verteilen. Sie legen fest, wie die Legende einer Abbildung oder Tabelle gesetzt wird. Außerdem können Sie Diagramme in einer einzigen Druckfarbe drucken und wählen, wie ein Video auf Papier erscheint.
#Ressourcentypen
Ein Ressourcentyp ist eine frei definierbare Kategorie – Abbildung, Tabelle, Diagramm, Listing … –, die bestimmt, wie die Ressourcen dieser Art nummeriert, mit Legenden versehen und referenziert werden. Die Liste steht in config.resourceTypes; die Sandbox bearbeitet sie unter Gestaltung → Abbildungen & Tabellen → Nummerierung und Platzierung.
Ist config.resourceTypes nicht gesetzt, bringt Postext drei eingebaute Standardtypen mit: Abbildung, Tabelle und Video, jeder für sich nach {h1}.{n} nummeriert (mit Neubeginn bei jeder Überschrift der Ebene 1) und mit Dezimalzählern. Eine Liste ohne den Typ video – ein Buch, das gespeichert wurde, bevor es Videos gab – nummeriert Video-Ressourcen vom Typ video trotzdem: Für sie wird der eingebaute Videotyp ergänzt (effectiveResourceTypes(config, resources)), und defaultVideoResourceType(locale) liefert ihn einzeln. Benannt werden sie in der Sprache des Dokuments: config.locale, sonst bodyText.hyphenation.locale, sonst Englisch (siehe Dokumentsprache).
Die eingebauten Standardtypen richten sich nach der Sprache. Die exportierte Funktion defaultResourceTypes(locale = 'en') übersetzt die Typnamen, Kurzbezeichnungen und Legendenpräfixe in die Sprache des Dokuments – Englisch ergibt Figure/Fig. und Table/Tab., Spanisch Figura/Fig. und Tabla/Tabla; Französisch, Deutsch, Italienisch, Portugiesisch, Katalanisch und Niederländisch haben ihre eigenen (die Tabelle unter Dokumentsprache führt sie auf). Regionale Tags wie es-ES werden über die Sprache aufgelöst, und jede Sprache ohne Übersetzungen fällt auf Englisch zurück. Das Nummerierungsverhalten (numberingTemplate: '{h1}.{n}', resetOn: 'h1', Dezimalzähler) ist sprachunabhängig. Jeder Aufruf liefert neue Objekte, Sie können das Ergebnis also frei verändern:
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', … }]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 hat dieselbe Form, die eine Ressource in ihrem eigenen placement setzt. position wählt die Art des freien Platzes, den ein Gleitobjekt einnehmen darf – auto (der Standard) nimmt den ersten nach dem ersten Verweis, top / bottom beschränken es auf diese Art von Band, here bettet die Ressource in den Text ein. span legt die Ausdehnung des Gleitobjekts fest: eine Spalte, die volle Inhaltsbreite oder die nur für Gleitobjekte bestimmte Seitenspalte eines Layouts mit anderthalb Spalten. rotate dreht die Ressource um eine Vierteldrehung und macht sie zu einem Gleitobjekt über die ganze Seitenbreite auf einer eigenen Seite. width verschmälert ein Gleitobjekt auf einen Bruchteil seiner Spalte (oder der Seite bei einem Gleitobjekt über die ganze Seitenbreite) – etwa eine kleine Tabelle in einer breiten Spalte. align gibt an, wo ein solches schmaleres Gleitobjekt sitzt – standardmäßig links, mittig oder rechts – und wo ein Bild, das schmaler als sein Platz ist, darin sitzt: eine Bitmap, die kleiner als die Spalte ist, oder ein Bild, das layout.fitFiguresToPage verkleinert hat. Legende und Anmerkung behalten die Satzbreite des Platzes. (Bis postext 1.4 wurde ein solches Bild immer linksbündig gesetzt.) captionSide setzt die Legende neben die Abbildung in die nur für Gleitobjekte bestimmte Seitenspalte eines Layouts mit anderthalb Spalten (layout.sideColumnRole: 'floats'), auf Höhe der Oberkante der Abbildung (ihrer Unterkante bei einem Gleitobjekt unten); es gilt für Spalten-Gleitobjekte und seit postext 1.28 auch für eine im Text gesetzte Ressource (position: 'here', eine Spalte breit, ohne Textumfluss), deren Legende und Anmerkung in der Seitenspalte auf Höhe der Oberkante ihres Körpers stehen, wo diese Spalte daneben frei ist, und unter dem Körper, wo sie es nicht ist (layout.inlineCaptionSide, standardmäßig eingeschaltet; false beschränkt seitliche Legenden auf Spalten-Gleitobjekte); eine Seite ohne eine solche Spalte setzt die Legende unter die Abbildung. Setzen weder die Ressource noch ihr Typ eine Platzierung, gilt der eingebaute Standard auto / column. shrink ('never', 'page', 'slot') und minScale (0,7, wenn nicht gesetzt) verkleinern ein gleitendes Bild auf den Raum seines Platzes, statt es weiterzuschieben, und captionMeasure: 'body' setzt Legende und Anmerkung eines Bildes, das schmaler als sein Platz ist, auf die Breite des Bildes (siehe Dokumentformat › Platzierung); layout.floatShrink liefert den Dokumentstandard für die ersten beiden. wrap setzt eine eingebettete Ressource oder ein einspaltiges Gleitobjekt an eine Seite seiner Spalte, und der Text läuft daneben, mit dem Abstand wrapGap; layout.wrap enthält die Standardwerte (siehe Dokumentformat › Textumfluss). citingPage lässt ein Gleitobjekt mit top oder auto die Seite oder Spalte anführen, auf der seine verweisende Zeile landet, statt den ersten freien Platz danach zu nehmen; layout.floatsAtCitingPage liefert den Dokumentstandard und layout.maxTopFraction den Anteil der Spalte, den es einnehmen darf (siehe Dokumentformat › Platzierung).
columns (seit postext 1.18) legt ein Gleitobjekt mit span: 'column' auf einer mehrspaltigen Seite über so viele benachbarte Spalten: ein Bild über zwei der fünf Spalten einer Zeitung. Seine Satzbreite sind diese Spalten samt den Spaltenabständen dazwischen. Es nimmt den Kopf einer Folge leerer Spalten ein, die auf gleicher Höhe beginnen, oder den Fuß der verweisenden Spalte und der leeren Spalten danach; so viele Spalten, wie die Seite hat, oder mehr machen es zu einem Gleitobjekt über die ganze Seitenbreite. Es wird ignoriert bei den Ausdehnungen 'page' und 'side', bei einer gedrehten Ressource (rotate) und bei einer eingebetteten Ressource (here), und captionSide gilt nur für ein Gleitobjekt von einer Spalte Breite.
| Eigenschaft | Typ | Beschreibung |
|---|---|---|
id | string | Stabiler Bezeichner, auf den das typeId jeder Ressource verweist. Wird einmal beim Anlegen des Typs gesetzt; wer einen Typ löscht, auf den noch Ressourcen verweisen, löst die Warnung verwaister Typ aus. |
name | string | Anzeigename im Singular. Wird vom Verweis mit style="full" verwendet (z. B. Figure 1.7). |
namePlural | string (optional) | Anzeigename im Plural, für Beschriftungen der Oberfläche und Ressourcenlisten. |
shortLabel | string | Kompakte Abkürzung für den Standardstil des Verweises im Text (z. B. Fig. 1.7). |
numberingTemplate | string | Vorlage für die berechnete Nummer. Siehe Platzhalter der Vorlage weiter unten. Übliche Formen sind (kapitelbezogen, z. B. 2.3) und (eine einzige fortlaufende Zählung). |
resetOn | ResourceCounterReset | 'never' ergibt eine fortlaufende Zählung über das ganze Dokument; 'h1'..'h6' setzen den Zähler jedes Mal zurück, wenn eine Überschrift dieser Ebene (oder einer übergeordneten) auftritt. Wählen Sie die Überschriftenebene, die in der Vorlage vorkommt – z. B. mit resetOn: 'h1'. |
counterFormat | ResourceCounterFormat | Wie der Zähler dargestellt wird: dezimal (1, 2, 3), römisch klein/groß (i, ii / I, II) oder alphabetisch klein/groß (a, b / A, B). Die Schreibweisen für Seiten und Listen werden ebenfalls angenommen ('lower-roman', 'arabic' …; siehe Schreibweisen der Nummernformate); ein unbekannter Wert zählt dezimal und wird gemeldet. Überschriften-Platzhalter ( …) werden immer dezimal dargestellt. |
captionPrefix | string | Text, der der Bildunterschrift bzw. Tabellenüberschrift vorangestellt wird. Die berechnete Nummer folgt dem Präfix – eine Legende erscheint als . , z. B. Figure 1.7. The original plan. Ein Typ mit leerem numberingTemplate hat keine Nummer, und seine Legende lautet . . Leerzeichen am Ende des Präfixes entfallen, und ein Präfix, das bereits auf ., :, !, ? oder … endet (oder auf deren Form in voller Breite), erhält keinen zweiten Punkt: Pl. Lines at 0°. |
defaultPlacement | ResourcePlacement (optional) | Platzierung für Ressourcen dieses Typs, die kein eigenes placement setzen: position, span, rotate, width, align, captionSide und columns, jedes unabhängig aufgelöst. Setzen weder die Ressource noch der Typ ein Feld, gilt der eingebaute Standard: auto / column, aufrecht, volle Breite, linksbündig, Legende unter der Abbildung. Siehe Nummerierung und Verweise weiter unten für die Auflösungskette und Dokumentformat › Ressourcen für die Wirkung jedes Werts, auch bei gedrehten Ressourcen. |
captionStyle | CaptionStyleConfig (optional) | Teilweise Überschreibung des Legendenstils für Ressourcen dieses Typs. Nur die gesetzten Schlüssel ersetzen den globalen captionStyle; alles andere wird geerbt (eine überschriebene color bestimmt auch die Farben von Bezeichnung und Anmerkung, sofern diese nicht ausdrücklich gesetzt sind). Typischer Einsatz: Tabellen mit Überschrift oben auf einem farbigen Balken, während Abbildungen ihre Legende unten behalten. Palettenverweise werden wie jede andere Farbe aufgelöst. |
#Platzhalter der Vorlage
numberingTemplate wird mit derselben Engine dargestellt wie die Nummerierung der Überschriften (siehe Überschriften). Sie kennt zwei Arten von Platzhaltern:
{n}– der Zähler des Typs, formatiert nachcounterFormat. Dieser Wert steigt mit jeder Ressource und wird gemäßresetOnzurückgesetzt.{h1}…{h6}– die an der Stelle des ersten Verweises geltenden Überschriftennummern, dezimal, sofern der Platzhalter keinen Stil nennt.{h1}ist die aktuelle Nummer der Überschrift der Ebene 1,{h2}die der Ebene 2 und so weiter.{h1:A},{h2:i},{n:i}– ein Platzhalter, gefolgt von einem Doppelpunkt und einem Stil, wird in diesem Stil geschrieben, und zwar in jedem, den eine Überschriftenvorlage annimmt:1,01,A,a,I,i, ein Name eines Nummerierungsformats wieupper-roman, ein Ein-Zeichen-Platzhalter wie一oder①oder ein ausgeschriebener Stil wieWords. Bei{n}hat der Stil für diesen Platzhalter Vorrang vorcounterFormat. Ein unbekannter Stil zählt dezimal. Seit postext 1.28.
Jeder andere Text wird wörtlich übernommen. Ein Backslash maskiert ein wörtliches {, } oder \. Hat ein Überschriften-Platzhalter keinen gültigen Wert (z. B. {h1} vor der ersten Überschrift der Ebene 1), entfällt er samt dem angrenzenden Trennzeichen – {h1}.{n} wird so sauber zum bloßen Zähler.
Eine leere Vorlage ('') druckt keine Nummer, der Typ zählt seine Ressourcen aber dennoch: Eine Legende lautet Do. Lines at 0°, und ein :ref druckt nur die Bezeichnung (Do). Bis postext 1.4 lautete eine solche Legende Do .Lines at 0°, und der Verweis endete mit einem geschützten Leerzeichen.
| Vorlage | Mit h1 = 2, Zähler = 3 | Hinweise |
|---|---|---|
| 3 | Eine einzige fortlaufende Zählung. Mit resetOn: 'never' kombinieren. |
| 2.3 | Kapitelbezogen. Mit resetOn: 'h1' kombinieren. |
| 2.0.3 | Abschnittsbezogen. Mit resetOn: 'h2' kombinieren. |
| B.3 | Mit Buchstaben, für die Anhänge. Mit resetOn: 'h1' kombinieren. |
Anhänge. Ein Buch, dessen Anhänge über einen Überschriftenstil mit Buchstaben gezählt werden (numberingTemplate: 'Appendix {1:A}', mit startAt=1 beim ersten), gibt ihren Abbildungen und Tabellen einen eigenen Typ, { ...table, id: 'table-a', numberingTemplate: '{h1:A}.{n}', resetOn: 'h1' }. Ein Typ dient allen Anhängen: Er druckt Table A.1, A.2 und B.1, in der Legende wie in :ref. Ein schlichtes {h1} druckt dort die Nummer der Überschrift dezimal (Table 1.1).
#Nummerierung und Verweise
Die Nummer, die ein Ressourcentyp erzeugt, ist das, was :ref druckt und dem das Legendenpräfix vorangeht. :ref{id} ist die Hauptform: Der erste Verweis in Lesereihenfolge bindet die Ressource ein, die dann auf den ersten freien Platz nach diesem Verweis gleitet – an den Fuß der verweisenden Spalte, an Kopf oder Fuß der nächsten leeren Spalte oder in ein Band der nächsten Seite (gemäß ihrer aufgelösten Platzierung – position: 'auto' | 'top' | 'bottom' | 'here' und span: 'column' | 'page' | 'side', dazu rotate, width, align und captionSide, aufgelöst pro Ressource, dann über defaultPlacement des Typs, dann über den eingebauten Standard auto / column; 'top' / 'bottom' beschränken die Suche auf diese Art von Platz). Die Blockeinbettung ::resource{id} ist optional und nur für placement.position: 'here' nötig – eine nicht gleitende Einbettung an genau einer Stelle des Textflusses. Die vollständige Grammatik auf der Dokumentseite – beide Formen sowie die Optionen style und text von :ref – ist unter Dokumentformat › Ressourcen beschrieben, einschließlich der Frage, wie die Reihenfolge der ersten Verweise die Zählung bestimmt.
Das entspricht der Nummerierung der Überschriften: So wie eine Überschriftenebene ein numberingTemplate trägt, trägt auch ein Ressourcentyp eines – der Ressourcenzähler ({n}) steigt aber mit jedem ersten Verweis statt mit jeder Überschrift, und resetOn bindet ihn wieder an die Gliederung der Überschriften.
#Was nummeriert wird
Eine Ressource wird nummeriert, wenn der Text auf sie verweist – mit :ref oder mit einer Einbettung ::resource –, in der Reihenfolge dieser ersten Verweise und unabhängig von ihrer Platzierung: gleitend, eingebettet (here), in der Seitenspalte oder gedreht. Eine Ressource, die nur eine Gestaltung zeichnet – ein Element image eines Kapitelauftakts, eines Kolumnentitels oder einer Teiltitelseite –, oder auf die nichts verweist, erhält keine Nummer und lässt den Zähler ihres Typs unverändert. In einem Fotoessay, dessen randabfallende Tafeln Auftaktbilder sind und dessen einzige kleinere Tafel ein zitiertes Gleitobjekt ist, ist dieses Gleitobjekt also Tafel I, wie viele Tafeln die Auftakte auch davor gezeigt haben; nummerieren Sie die Auftakttafeln in ihrer Gestaltung (mit einem Attribut wie {attr.plate}) und behalten Sie den Zähler den Tafeln vor, die der Text zitiert.
In einem Buch, das Kapitel für Kapitel umbrochen wird (die Sandbox, buildBundle oder buildDocument mit den Zählern, die continuationAfter() weiterreicht), zählt der erste Verweis im ganzen Buch: Eine Ressource behält die Nummer, die sie in dem Kapitel erhalten hat, das zuerst auf sie verweist, und nur dieses Kapitel platziert sie. Das :ref eines späteren Kapitels druckt diese Nummer und platziert nichts, und eine Einbettung ::resource einer gleitenden Ressource ist dort nur ein weiterer Verweis (eine eingebettete Ressource mit here wird weiterhin dort gesetzt, wo sie steht). Ein solcher Verweis verlinkt auf die Abbildung, wo sich die Abbildung in derselben Ausgabe befindet: Ein PDF des ganzen Buchs verlinkt ihn auf die Seite des früheren Kapitels. Ein einzeln gerendertes Kapitel, in HTML oder PDF, setzt ihn als schlichten Text in der Linkfarbe, da seine Abbildung nicht in diesem Dokument steht. Ein Host, der das HTML der Kapitel auf einer Seite zusammenführt, übergibt renderToHtml die von den Kapiteln verankerten Ressourcen als refTargets, und ein solcher Verweis verlinkt wieder auf die Abbildung des früheren Kapitels:
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('');Geändert in postext 1.5: Bis 1.4 ließ jedes Kapitel, das auf eine Abbildung verwies, sie erneut gleiten, und das HTML jedes :ref war ein Link, ob seine Abbildung auf der Seite stand oder nicht.
{h1} ist die fortlaufende Zählung der Überschriften der Ebene 1: Jede H1 erhöht sie, sofern ihr Überschriftenstil nicht numbered: false setzt – ein leeres numberingTemplate blendet die Nummer der Überschrift aus, hält die Zählung aber nicht an. Ein Artikel, dessen einzige H1 sein Titel ist, nummeriert seine Abbildungen mit den eingebauten Typen {h1}.{n} daher 1.1, 1.2 … Zwei Wege, um Abbildung 1, 2 … zu drucken:
- ein Typ, nummeriert mit
{n}undresetOn: 'never'(mitresetOn: 'h1'begänne die Zählung bei jeder H1 neu); - ein Überschriftenstil mit
numbered: falsefür den Titel und jede andere H1, die nicht zählen soll: Eine solche Überschrift erhöht{h1}nicht, sondern lässt es, wie es war – leer vor der ersten gezählten H1, wo{h1}.{n}zum bloßen Zähler wird –, und löst nieresetOn: 'h1'aus, die Zählung läuft also über sie hinweg weiter. Nach# Introductionund deren Abbildung 1.1 ist die erste Abbildung unter einem nicht nummerierten# Appendixdie 1.2, nicht die 2.1.
// Figure 1, 2, 3… in a single-article document
resourceTypes: defaultResourceTypes('en').map((t) => ({ ...t, numberingTemplate: '{n}', resetOn: 'never' })),#Tabellenstil
Die Eigenschaft tableStyle steuert Typografie und Schmuck der Tabellenressourcen – aller Tabellen, sofern eine nicht einen benannten Tabellenstil wählt. Kopf- und Inhaltszellen werden unabhängig gestaltet. Schriftfamilie, Schriftgröße und Farben erben, wenn sie nicht gesetzt sind, die Werte des aufgelösten Fließtexts; ein Dokument ohne tableStyle setzt Tabellen also in der Typografie des Fließtexts.
const config: PostextConfig = {
tableStyle: {
headerBold: true,
headerBackground: { hex: '#f0f0f0', model: 'hex' },
borders: true,
borderWidth: { value: 0.75, unit: 'pt' },
},
};| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
bodyFontFamily | string | Schrift des Fließtexts | Schriftfamilie der Inhaltszellen. |
bodyFontSize | Dimension | Schriftgröße des Fließtexts | Schriftgröße der Inhaltszellen. |
bodyColor | ColorValue | Farbe des Fließtexts | Textfarbe der Inhaltszellen. |
headerFontFamily | string | Schrift des Fließtexts | Schriftfamilie der Kopfzellen. |
headerFontSize | Dimension | Schriftgröße des Fließtexts | Schriftgröße der Kopfzellen. |
headerColor | ColorValue | Farbe des Fließtexts | Textfarbe der Kopfzellen. |
headerBold | boolean | true | Kopfzellen fett setzen. |
headerItalic | boolean | false | Kopfzellen kursiv setzen. |
headerLetterSpacing | Dimension | 0pt | Laufweite nach jedem Zeichen einer Kopfzelle, Leerzeichen eingeschlossen, wie CSS letter-spacing. Positive Werte sperren die Buchstaben (ein Kopf in Versalien verlangt meist 0.05em bis 0.1em), negative Werte ziehen sie zusammen. Ein em entspricht der Schriftgröße des Kopfs. Die Kopfzeilen werden damit gemessen, sie umbrechen, zentrieren und richten sich also mit der Sperrung aus, und Canvas, HTML und PDF zeichnen sie gleich. Es gilt für jede Kopfzelle: die Kopfzeilen und jede mit isHeader markierte Zelle. |
headerTextTransform | 'none' | 'uppercase' | 'none' | Die Kopfzellen in Versalien setzen. Der Text behält seine Länge, sodass die Sandbox jeden Buchstaben weiterhin der Quelle zuordnet: Ein Buchstabe, dessen Großbuchstabe länger ist (ß), bleibt, wie er ist. Ressourcenverweise behalten ihre Bezeichnung. |
headerBackgroundEnabled | boolean | true | Eine Fläche hinter die Kopfzeile legen. |
headerBackground | ColorValue | #f0f0f0 | Flächenfarbe der Kopfzeile. |
bodyBackgroundEnabled | boolean | false | Eine Fläche hinter die Inhaltszeilen legen. |
bodyBackground | ColorValue | #ffffff | Flächenfarbe der Inhaltszeilen (nur gezeichnet, wenn eingeschaltet). |
bodyAlternateBackgroundEnabled | boolean | false | Zebrastreifen: jede zweite Inhaltszeile mit bodyAlternateBackground füllen. Siehe Zebrastreifen. |
bodyAlternateBackground | ColorValue | #f2f2f2 | Fläche der abwechselnden Inhaltszeilen (nur gezeichnet, wenn eingeschaltet). |
borders | boolean | true | Zellrahmen zeichnen. |
borderColor | ColorValue | Farbe des Fließtexts | Farbe der Rahmenlinien. |
borderWidth | Dimension | 0.75pt | Stärke der Rahmenlinien (≈ 1 px bei 96 DPI; skaliert mit der DPI der Seite). Wird von 'booktabs' nicht verwendet, das eigene Stärken hat. |
cellPadding | Dimension | 0.375em | Innenabstand jeder Zelle. |
rules | 'grid' | 'horizontal' | 'outer' | 'none' | 'booktabs' | 'grid' | Welche Linien gezeichnet werden, wenn borders eingeschaltet ist: das volle Zellraster, nur waagerechte Linien (Ober- und Unterkante jeder Zeile, keine senkrechten), nur der äußere Rahmen, keine oder die drei Linien einer Zeitschriftentabelle (siehe Booktabs-Linien). |
borderRadius | Dimension | 0 | Eckenradius des äußeren Tabellenrahmens. Der Rahmen wird gerundet gezeichnet (mit den Linien grid oder outer), die Zellflächen und der Kopfhintergrund werden darauf beschnitten – auch mit rules: 'none' oder ausgeschalteten Rahmen –, und waagerechte Linien werden an seiner Außenkontur gekürzt; die inneren Linien bleiben gerade. Eine über Seiten geteilte Tabelle rundet die oberen Ecken ihres ersten Teils und die unteren ihres letzten. Begrenzt auf die halbe Breite und Höhe der Tabelle. Linien mit 'booktabs' bleiben gerade (die Flächen werden trotzdem beschnitten). |
heavyRuleWidth | Dimension | 0.08em | Booktabs: die Linien über der Tabelle und unter ihrer letzten Zeile. Ein em entspricht der Schriftgröße der Inhaltszellen. |
lightRuleWidth | Dimension | 0.05em | Booktabs: die Linie unter den Kopfzeilen und die Gruppenlinien. |
spanRuleWidth | Dimension | 0.03em | Booktabs: die Linien unter Kopfzellen, die mehrere Spalten überspannen. |
spanRules | 'trimmed' | 'full' | 'none' | 'trimmed' | Booktabs: die Linien unter Kopfzellen, die mehrere Spalten überspannen, über der letzten Kopfzeile: an beiden Enden um spanRuleTrim gekürzt, über die ganze Zelle oder keine. |
spanRuleTrim | Dimension | 0.5em | Booktabs: um wie viel eine gekürzte Spannlinie an jedem Ende verkürzt wird. |
groupRules | boolean | false | Booktabs: eine dünne Linie über jeder Inhaltszeile, die eine Gruppe anführt. |
continuedFootRule | 'bottom' | 'light' | 'none' | 'light' | Booktabs: was einen Teil einer geteilten Tabelle abschließt, die auf der Folgeseite weitergeht. |
overflow | 'split' | 'clip' | 'hide' | 'split' | Was mit einer Tabelle geschieht, die höher als die Seite ist: sie auf den folgenden Seiten fortsetzen, nur die passenden Zeilen behalten oder sie weglassen. Mit splitInline auch mit einer im Text gesetzten Tabelle, die nicht in den Rest ihrer Spalte passt. Siehe unten. |
splitInline | boolean | true | overflow auch auf mit here platzierte Tabellen anwenden: Eine eingebettete Tabelle, die nicht in den restlichen Raum ihrer Spalte passt, wird zwischen Zeilen geteilt und am Kopf der nächsten Spalte fortgesetzt. false schiebt eine solche Tabelle ganz in die nächste Spalte, wie bis postext 1.24; Konfigurationen früherer Versionen, deren Kapitel eine Ressource einbetten, werden mit false gelesen. Siehe Tabellen, die höher als die Seite sind. Seit postext 1.25. |
continuedSuffix | string | '(cont.)' | Wird kursiv, nach einem Leerzeichen, an die Legende jedes fortgesetzten Teils einer geteilten Tabelle angehängt; ein Suffix, das mit einem chinesischen Zeichen oder einem Zeichen voller Breite beginnt ('(续)'), wird ohne Abstand an die Legende gesetzt. |
continuesMarkerEnabled | boolean | true | Unter jeden Teil, der auf der nächsten Seite weitergeht, einen Hinweis setzen. |
continuesMarker | string | 'Continued' / 'Continúa' | Text dieses Hinweises, rechtsbündig unter den Teil in der Schrift der Anmerkung gesetzt (siehe Legendenstil). Der Standard folgt der Sprache des Dokuments (siehe Dokumentsprache für die acht Sprachen). |
Rahmenstärken bleiben gebrochen: Eine Linie von 0.5pt wird im PDF und auf dem Bildschirm als Haarlinie gezeichnet, statt auf ein volles Pixel aufgerundet zu werden (die Untergrenze liegt bei 0,25 px).
#Zebrastreifen
Lange Datentabellen lassen sich quer leichter verfolgen, wenn jede zweite Zeile getönt ist. bodyAlternateBackgroundEnabled schaltet die Streifen ein, bodyAlternateBackground setzt ihre Farbe:
const config: PostextConfig = {
tableStyle: {
bodyBackgroundEnabled: true,
bodyBackground: { hex: '#ffffff', model: 'hex' },
bodyAlternateBackgroundEnabled: true,
bodyAlternateBackground: { hex: '#eef3fa', model: 'hex' },
},
};Gezählt wird ab der ersten Zeile nach den Kopfzeilen (TableModel.headerRowCount oder die führenden Zeilen aus Kopfzellen): Diese Zeile behält bodyBackground – oder keine Fläche, solange bodyBackgroundEnabled ausgeschaltet ist –, die nächste erhält die abwechselnde Fläche und so weiter. Die Zählung folgt dem Tabellenmodell, nicht der Seite; eine über Seiten geteilte Tabelle behält also auf jeder Seite den Streifen jeder Zeile, und eine über Zeilen verbundene Zelle nimmt den Streifen ihrer ersten Zeile an. Kopfzellen behalten die Kopffläche, ein eigenes background einer Zelle hat Vorrang vor beiden, und eine an die Palette gebundene Farbe folgt der Palette. Ein benannter Tabellenstil setzt die beiden Felder wie jedes andere, sodass ein Stil gestreift sein kann, während die übrigen Tabellen des Dokuments es nicht sind; in der Sandbox sind das der Schalter Zebrastreifen und seine Farbe unter Inhaltszellen.
Im VDT tragen die Zellen der abwechselnden Zeilen alternate: true, und das Tabellenlayout trägt bodyAlternateBackground. tableCellFill(table, cell) liefert die Fläche, mit der eine Zelle gezeichnet wird – ihre eigene, die des Kopfs, die abwechselnde oder die der Inhaltszeilen –, und genau diese zeichnen Canvas, HTML und PDF. Benachbarte Flächen stoßen ohne Fuge aneinander: Ein Browser mit gebrochenem Pixelverhältnis oder ein PDF-Betrachter glättet jede Fläche für sich und ließe die Seite durch eine Haarlinie zwischen zwei Zellen durchscheinen; daher zeichnen die HTML- und PDF-Ausgaben tableCellFillRects(table) – die Fläche jeder Zelle mit einem Streifen über jede Kante, die sie mit einer später gezeichneten Zelle teilt, die ihn dann überdeckt –, und der Canvas rastet seine Flächen auf Gerätepixel ein.
#Booktabs-Linien
Tabellen in Zeitschriften und Lehrbüchern werden meist mit drei Linien und ohne senkrechte Linien gesetzt: einer kräftigen Linie über der Tabelle, einer dünnen unter dem Kopf und einer kräftigen unter der letzten Zeile, dazu kurze Linien unter den Köpfen, die mehrere Spalten zusammenfassen (das LaTeX-Paket booktabs: \toprule, \midrule, \cmidrule, \bottomrule). rules: 'booktabs' zeichnet dieses Muster:
const config: PostextConfig = {
tableStyle: {
rules: 'booktabs',
borderColor: { hex: '#000000', model: 'hex' },
headerBackgroundEnabled: false,
},
};- Die Linie über der Tabelle und die unter ihrer letzten Zeile sind
heavyRuleWidthstark (0.08em), die Linie unter den KopfzeilenlightRuleWidth(0.05em). Eine Tabelle ohne Kopfzeilen hat keine Kopflinie. - Eine Kopfzelle, die über der letzten Kopfzeile mehrere Spalten überspannt, erhält darunter eine Linie der Stärke
spanRuleWidth(0.03em). MitspanRules: 'trimmed'(dem Standard) wird die Linie an beiden Enden umspanRuleTrim(0.5em) gekürzt, sodass sich die Linien unter zwei benachbarten Köpfen nicht berühren;'full'führt sie über die ganze Zelle,'none'lässt sie weg. groupRules: truefügt über jeder Inhaltszeile, die eine Gruppe anführt (eine einzelne Zelle über die ganze Tabelle oder eine Zeile aus Kopfzellen), eine dünne Linie hinzu, es sei denn, die Zeile eröffnet die Tabelle oder eine Seite, wo bereits die Kopflinie steht.- Die Stärken werden gegen die Schriftgröße der Inhaltszellen (
bodyFontSize) aufgelöst, eine größere Kopfschrift macht die Kopflinie also nicht dicker. Eine Stärke von0lässt die betreffende Linie entfallen. - Die Linien nehmen
borderColor(eine an die Palette gebundene Farbe folgt der Palette und:::part palette), undborders: falseschaltet sie aus.borderWidthgilt nicht, ebenso wenigborderRadius: Die Linien bleiben gerade, während die Zellflächen weiterhin auf den gerundeten Rahmen beschnitten werden. Kopfflächen, Zebrastreifen und ein eigenesbackgroundeiner Zelle wirken wie bei den anderen Mustern, unter den Linien. - Eine über Seiten geteilte Tabelle wiederholt ihre Kopfzeilen in jedem Teil, jeder Teil beginnt also mit der kräftigen Linie und der Kopflinie. Die kräftige Linie unter der letzten Zeile schließt nur den letzten Teil ab; ein Teil, der auf der Folgeseite weitergeht, endet mit
continuedFootRule: einer dünnen Linie ('light', der Standard), der kräftigen Linie ('bottom') oder keiner ('none').
Das Layout berechnet die Linien einmal. Die VDT-Tabelle trägt sie als strokes ({ x1, y1, x2, y2, widthPx }, relativ zur linken oberen Ecke des Tabellenkörpers), und Canvas, HTML-Betrachter, PDF und EPUB mit festem Layout zeichnen genau diese; in einem getaggten PDF sind sie Layout-Artefakte. Das umfließende EPUB schreibt sie als CSS-Rahmen der Tabelle und ihres Kopfs, die gekürzten Linien als Hintergrundlinien. In der Sandbox zeigt Booktabs in der Auswahl Linien diese Felder und blendet Rahmenstärke und Eckenradius aus.
#Benannte Tabellenstile
Selten setzt ein Dokument alle Tabellen gleich: eine Checkliste in einem marineblauen Raster mit gerundetem Rahmen, eine Optionszeile nur mit äußerem Rahmen, eine Datentabelle mit schlichten waagerechten Linien. tableStyles deklariert benannte Varianten, und eine Tabellenressource wählt eine davon mit table.styleId. Jedes Feld, das ein Stil nicht setzt, wird zuerst aus tableStyle und danach aus dem Fließtext gelesen; ein Stil nennt also nur, was seine Tabellen unterscheidet. Eine Tabelle ohne styleId oder mit einer ID, die kein Stil deklariert, behält tableStyle – ein Dokument ohne tableStyles erscheint genau wie zuvor.
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' },
};Jeder Eintrag nimmt jedes Feld von tableStyle sowie id (worauf table.styleId verweist) und einen optionalen name für den Editor (standardmäßig die ID). Alles, was ein Stil setzen kann, gilt pro Tabelle – Typografie, Flächen, Rahmen, Linien, Eckenradius, Innenabstand und das Überlaufverhalten samt seinen Fortsetzungstexten. resolveTableStylesConfig(styles, tableStyle, resolvedBodyText, locale?) liefert die aufgelöste Liste, pickTableStyle(resolved, styleId) den Stil, in dem eine Tabelle gesetzt wird, und stripTableStylesDefaults entfernt die nicht gesetzten Felder (es behält ein Feld, das seinem eingebauten Standard gleicht, denn dieses überschreibt weiterhin einen abweichenden Wert von tableStyle). In einem umfließenden EPUB ist ein benannter Stil eine Klasse der Tabelle (pt-table-<id>), gestaltet vom Stylesheet des Buchs.
#Tabellen, die höher als die Seite sind
Eine gleitende Tabelle, die nicht auf die frische Seite passt, die ihr angeboten wird, wird weder gestaucht noch läuft sie über: Mit overflow: 'split' (dem Standard) teilt die Engine sie zwischen Zeilen an der letzten Kante, die auf die Seite passt, und setzt sie auf so vielen folgenden Seiten fort wie nötig. Jeder fortgesetzte Teil wiederholt die Kopfzeilen der Tabelle (TableModel.headerRowCount oder, wenn nicht gesetzt, die führenden Zeilen aus Kopfzellen) und trägt erneut die Legende, mit continuedSuffix nach der Beschreibung – „Table 6-4. Title (cont.)“. Jeder Teil, der weitergeht, erhält continuesMarker darunter, rechtsbündig, in der Schrift der Anmerkung; die Anmerkung der Tabelle wird für den letzten Teil zurückgehalten. Ein Schnitt verläuft nie durch eine verbundene Zelle (ein Rowspan wandert ganz in den nächsten Teil), und eine Zeile, die die Zeilen darunter anführt – eine einzelne Zelle über die ganze Tabelle –, wird in den nächsten Teil mitgenommen, statt allein am Fuß einer Seite zu stehen. Eine Booktabs-Tabelle schließt jeden weitergehenden Teil mit continuedFootRule ab (siehe Booktabs-Linien).
Wo der erste Teil endet. Eine Tabelle, der nach ihrem Verweis der Kopf einer leeren Spalte angeboten wird, nimmt die Zeilen, die dort passen, und geht im nächsten Platz weiter. Sie füllt die Spalte bis zum Fuß, wenn sie die Spalte für sich hat: Ein Teil, der weniger als drei Zeilen Fließtext darunter ließe, nimmt auch diese, statt einen Textrest zu hinterlassen. Enthält die Spalte bereits ein anderes Gleitobjekt-Band – etwa eine Abbildung über die ganze Seitenbreite am Kopf der Seite –, endet der Teil stattdessen mindestens drei Zeilen Fließtext vor dem Fuß; das ist der Raum für Text, den jedes Gleitobjekt lässt, wenn es eine Spalte mit einem anderen teilt, sodass die Spalte mit etwas Text unter der Tabelle endet statt nur mit Gleitobjekten. Damit eine lange Tabelle bis zum Fuß ihrer Spalte läuft, verweisen Sie auf sie dort, wo die Seite, auf der sie beginnt, kein anderes Gleitobjekt trägt (etwa nach der Seite einer Abbildung über die ganze Seitenbreite), oder passen Sie ihre Zeilen der Spalte an.
'clip' behält die führenden Zeilen, die auf die Seite passen, und verwirft den Rest stillschweigend (die Anmerkung schließt den Teil dennoch ab); 'hide' lässt die Tabelle ganz weg. Beide gelten nur, wenn die Tabelle höher als eine Seite ist: Eine Tabelle, die passt, wird in jedem Modus ganz platziert.
Im Text gesetzte Tabellen. Eine mit here platzierte Tabelle (eingebettet mit ::resource) folgt seit postext 1.25 denselben Regeln (splitInline, standardmäßig eingeschaltet). Passt sie nicht in den restlichen Raum ihrer Spalte, wird sie zwischen Zeilen geteilt: Der erste Teil behält den Gleitobjektabstand darüber und mindestens die Kopfzeilen und zwei Inhaltszeilen (sind es weniger, beginnt die ganze Tabelle wie bisher in der nächsten Spalte), jeder spätere Teil eröffnet die nächste Spalte ohne Abstand darüber, gesetzt auf die Breite dieser Spalte (ein Layout mit anderthalb Spalten setzt einen Teil in der schmalen Spalte auf deren Breite), und der Text nach der Zeile ::resource folgt dem letzten Teil. Wiederholter Kopf, Legende mit Suffix, Hinweis, Anmerkung am letzten Teil, der Rest von drei Zeilen und die Schnitte, die verbundene Zellen und Gruppenköpfe respektieren, sind die einer gleitenden Tabelle. Eine Tabelle mit weniger als fünf Inhaltszeilen wird nie geteilt. 'clip' behält die führenden Zeilen einer eingebetteten Tabelle, die höher als eine Spalte ist, gesetzt am Kopf einer Spalte; 'hide' lässt eine solche Tabelle weg; eine kürzere wandert in beiden Modi ganz in die nächste Spalte. Eine Seite, die eine eingebettete Tabelle eröffnet, hält nur den Raum ihres ersten Teils frei von den Gleitobjekten, die sie aufnimmt, sodass eine wartende Abbildung über die ganze Seitenbreite diese Seite anführt und die Tabelle darunter weitergeht. Eingebettete Tabellen auf einer vertikalen Seite und Tabellen in einem Kasten werden nicht geteilt. splitInline: false schiebt eine eingebettete Tabelle ganz in die nächste Spalte, wie bis postext 1.24.
Die Fortsetzungstexte richten sich standardmäßig nach der Sprache des Dokuments (locale, sonst die Sprache der Silbentrennung): Englisch (cont.) / Continued, Spanisch (cont.) / Continúa, entsprechend auf Französisch, Deutsch, Italienisch, Portugiesisch, Katalanisch und Niederländisch (aufgeführt unter Dokumentsprache).
Zellinhalt ist Inline-Markdown, und ein Zeilenumbruch in einer Zelle – ein Zeilenvorschub oder \\ wie in Legenden und Anmerkungen – beginnt einen neuen Absatz. Ein Absatz, der mit einem Aufzählungszeichen oder Strich (•, -, *, –) oder einer Zahl (1., 1)) gefolgt von einem Leerzeichen beginnt, wird als Listeneintrag gesetzt: Das Zeichen wird so gezeichnet, wie es geschrieben ist, der Text hängt um den Wert unorderedLists.gap des Dokuments davon ab, umbrochene Zeilen fluchten mit dem Text, und zwei führende Leerzeichen verschachteln eine Ebene. Eine Zelle, geschrieben als • Ofrece elección\n• Acomoda a personas diestras y zurdas, ergibt also eine Liste mit zwei Einträgen. Eine Zeile aus nichts als gewöhnlichen Leerzeichen fügt nichts hinzu; eine Zeile mit einem geschützten Leerzeichen (U+00A0) ist eine Zeile der Zelle, wie in CommonMark, sodass 1\n gefolgt von einem geschützten Leerzeichen die Zeile zwei Zeilen hoch macht. Ein geschütztes Leerzeichen am Ende des Zelltexts behält seine Breite: 760 mit einem geschützten Leerzeichen, rechtsbündig über (231), endet ein Leerzeichen vor der Kante, was die 0 nahe an die 1 rückt. Genau fluchten die Ziffern nur, wo das Leerzeichen so breit ist wie die Klammer, und in den meisten Schriften ist es schmaler. (Bis postext 1.4 entfielen beide.)
Spaltenbreiten gehören zum Tabellenmodell, nicht zum Stil: TableModel.columnWidths ist ein optionales Array relativer Gewichte, eines pro Spalte, beim Umbruch normalisiert – [2, 1, 1] gibt der ersten Spalte die halbe Breite. Ein fehlendes Array, eine falsche Länge oder ein nicht positives Gewicht fallen auf eine gleichmäßige Aufteilung zurück. Der Tabelleneditor hält das Array stimmig, wenn Spalten hinzugefügt oder entfernt werden.
#Tabellenmodelle aufbauen
Ein TableModel ist ein zeilenweises Raster, und jede Zelle wird nach ihrem Platz darin gesetzt: rows[r][c] steht in Spalte c. Eine verbundene Zelle behält die von ihr überdeckten Zellen daher im Raster, jede mit hiddenBy auf ihre Hauptzelle markiert – anders als eine HTML-Tabelle, die sie weglässt. Die aus postext exportierten Modellhelfer erhalten diese Form; es sind reine Funktionen, die ein neues Modell liefern: mergeCells(model, { start, end }) und unmergeCell(model, at), addRow, addColumn, removeRow, removeColumn, setCellContent, setCellImage, setCellBackground und setAlignment. Die vier Helfer für Zeilen und Spalten halten Verbindungen ganz: Eine innerhalb eines verbundenen Blocks hinzugefügte Zeile oder Spalte verbreitert ihn, eine davor hinzugefügte verschiebt ihn, eine daraus entfernte verkleinert ihn – ein Block, der seine erste Zeile oder Spalte verliert, behält seinen Inhalt in seiner neuen linken oberen Zelle –, und jedes hiddenBy zeigt weiterhin auf seine Hauptzelle.
parseTSV(text, options?) baut ein Modell aus tabulatorgetrenntem Text – einem aus einer Tabellenkalkulation eingefügten Bereich: Zeilen werden an Zeilenumbrüchen getrennt, Zellen an Tabulatoren, und kurze Zeilen werden aufgefüllt, damit das Raster rechteckig ist. headerRows macht die führenden Zeilen zu Kopfzeilen: Ihre Zellen erhalten isHeader und das Modell headerRowCount, sodass eine über Seiten geteilte Tabelle sie wiederholt.
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) prüft das Raster. Für ein einwandfreies Modell liefert es eine leere Liste, andernfalls jede Stelle, an der das Raster bricht, in Zeilenreihenfolge: spanOverlap, eine sichtbare Zelle unter dem colSpan / rowSpan einer anderen Zelle (coveredBy nennt diese Zelle) – was eine nach HTML-Art weggelassene überdeckte Zelle bewirkt, da jede Zelle danach auf die Verbindung rutscht –, und missingCells, eine Zeile, die vor der letzten Spalte endet, ohne dass eine Verbindung den Rest überdeckt, was ein Loch hinterlässt.
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 }]Eine vom Dokument verwendete Tabelle, deren Raster solche Probleme hat, wird in doc.contentWarnings als raggedTableGrid gemeldet (siehe Warnungen im Dokument).
#Legendenstil
Die Eigenschaft captionStyle steuert die Legenden der Ressourcen (die Zeile Figure 1 — … unter – oder über – Bildern, SVGs und Tabellen). Nummerierte Bezeichnung und Beschreibung teilen Schriftart und Schriftgröße – eine Vorgabe der Engine –, die Bezeichnung kann aber eigene Schriftstärke, Kursivierung und Farbe haben. Schriftfamilie, Schriftgröße und Farbe erben, wenn nicht gesetzt, die Werte des Fließtexts. Die Legende kann über der Ressource stehen (bei Tabellen üblich) und auf einem farbigen Balken über die Breite des Blocks gesetzt werden; eine optionale kleinere Anmerkung (Quellenangabe, Bildnachweis – Resource.note) wird über das Unterobjekt note gestaltet. Ein Ressourcentyp kann jedes dieser Felder für seine eigenen Ressourcen über ResourceType.captionStyle überschreiben (siehe Ressourcentypen).
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' },
},
};| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
fontFamily | string | Schrift des Fließtexts | Schriftfamilie der Legende (Bezeichnung und Beschreibung). |
fontSize | Dimension | Schriftgröße des Fließtexts | Schriftgröße der Legende (Bezeichnung und Beschreibung). |
color | ColorValue | Farbe des Fließtexts | Textfarbe der Beschreibung. |
align | 'left' | 'center' | 'right' | 'justify' | 'start' | 'end' | 'left' | Waagerechte Ausrichtung der Legendenzeilen. 'justify' treibt jede Zeile außer der letzten auf die volle Breite aus. Auf einem Legendenbalken richten sich die Zeilen innerhalb seines Innenabstands aus; eine seitliche Legende richtet sich innerhalb ihrer eigenen Breite aus. |
gap | Dimension | 0.75em | Senkrechter Abstand zwischen der Ressource und ihrer Legende. |
labelBold | boolean | true | Die nummerierte Bezeichnung (z. B. Figure 1) fett setzen. |
labelItalic | boolean | false | Die nummerierte Bezeichnung kursiv setzen. |
labelColor | ColorValue | color der Legende | Farbe der nummerierten Bezeichnung. |
descriptionItalic | boolean | false | Den Beschreibungstext kursiv setzen. |
position | 'above' | 'below' | 'below' | Wo die Legende steht. Mit 'above' kommt die Legende (samt Balken) zuerst, und der Körper der Ressource rückt um die Höhe der Legende plus gap nach unten; die Anmerkung steht dann unter dem Körper. |
backgroundEnabled | boolean | false | Einen Balken hinter die Legende legen. Der Balken reicht über die volle Breite des Blocks und umschließt die Legendenzeilen plus padding auf jeder Seite. |
background | ColorValue | Hauptfarbe der Palette | Flächenfarbe des Balkens (nur gezeichnet, wenn eingeschaltet). |
padding | Dimension | 0.35em | Innenabstand zwischen der Kante des Balkens und dem Legendentext. Wird ignoriert, wenn der Balken ausgeschaltet ist. |
note | object | — | Gestaltung der Anmerkung der Ressource – siehe die Untertabelle unten. |
labelNumberGap | string | geschütztes Leerzeichen; '' in einem japanischen Dokument | Was zwischen Bezeichnung und Nummer steht, in der Legende und in einem :ref im Text: Figure 1.7, Fig. 1.7. Chinesisch und Japanisch setzen beide ohne Abstand: '' ergibt 图1-1 und ist der Standard in einem japanischen Dokument (図1-1). |
labelSeparator | string | '. '; ' ' in einem japanischen Dokument | Was der Nummer folgt, vor der Beschreibung: Figure 1.7. A caption. Chinesische Legenden nehmen ein ideografisches Leerzeichen, ' ' (图1-1 标题), japanische standardmäßig ebenso (図1-1 東京の地図, JLReq §4.3). Eine Bezeichnung ohne Nummer behält ihre eigene Regel: ein Punkt, es sei denn, das Präfix endet bereits mit einem. |
Das Unterobjekt note gestaltet Resource.note, einen kurzen Text (Quelle, Bildnachweis, eine Bemerkung), der in kleinerer Schrift unter die Ressource gesetzt wird. Er nimmt dieselben Inline-Auszeichnungen und :ref-Verweise an wie die Legende und erbt deren Schrift. Er steht unter der Legende, wenn die Legende unten steht, und unter dem Körper der Ressource, wenn sie oben steht; seine Höhe zählt zum Block, eine Ressource mit Anmerkung gleitet also als eine Einheit.
| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
note.fontSize | Dimension | 0,85 × Schriftgröße der Legende | Schriftgröße der Anmerkung. |
note.color | ColorValue | color der Legende | Textfarbe der Anmerkung. |
note.italic | boolean | false | Die Anmerkung kursiv setzen. |
note.gap | Dimension | 0.35em | Abstand zwischen der Anmerkung und dem, was ihr vorangeht (Legende oder Körper). |
note.align | 'left' | 'center' | 'right' | 'justify' | 'start' | 'end' | 'left' | Waagerechte Ausrichtung der Anmerkungszeilen, wie align bei der Legende. |
Überschreibungen pro Typ werden mit mergeCaptionStyle(resolvedCaptionStyle, override, palette?) zusammengeführt, das für Hosts exportiert wird, die dieselbe Auflösung außerhalb der Pipeline brauchen.
#Diagrammstil
Die Eigenschaft diagramStyle steuert, wie eingebettete SVG-Diagramme (Ressourcen mit kind: 'svg') eingefärbt werden und in welchen Schriften ihr Text gesetzt wird. Der Einfarbmodus ist ein Umfärbedurchgang, der jede Farbe eines Diagramms auf einen Tonwert einer einzigen Druckfarbe abbildet, sodass Abbildungen getreu wiedergegeben werden, wenn das Dokument mit einer einzigen Schmuckfarbe gedruckt wird. Eingebettete Schriften bringen in jedes SVG die Schnitte mit, die sein Text nennt, sodass seine Beschriftungen auf dem Canvas, in HTML und in EPUB in den Schriften des Dokuments gesetzt werden (siehe Schriften in SVG-Text).
const config: PostextConfig = {
diagramStyle: {
singleInk: true,
inkColor: { hex: '#295AA3', model: 'hex' },
},
};| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
singleInk | boolean | false | Jedes eingebettete SVG-Diagramm auf Tonwerte einer einzigen Druckfarbe umfärben. |
inkColor | ColorValue | Hauptfarbe (#295AA3) | Die Druckfarbe. Standard ist die Hauptfarbe der Palette des Dokuments (über paletteId: 'main-color' an die Palette gebunden); wer das Farbfeld der Palette austauscht, tönt also die Diagramme zusammen mit Überschriften und fettem Text neu. |
inlineFonts | boolean | true | In jedes SVG die Schnitte, die sein Text nennt (font-family), als @font-face-Data-URIs einbetten, bevor es als Bild gezeigt wird: auf dem Canvas, in HTML, in EPUB und im Raster-Ersatz des PDF. Wird nie in die gespeicherte Datei geschrieben. Eine Ressource verzichtet darauf mit svg.inlineFonts: false (seit postext 1.25). |
#Wie der Einfarbmodus arbeitet
Ist singleInk eingeschaltet, wird jede Farbe im SVG-Markup in einen Tonwert von inkColor umgeschrieben, dessen Stärke 1 − relative Leuchtdichte beträgt (Koeffizienten nach Rec. 709, angewandt auf die gammakodierten Kanäle – eine wahrnehmungsnahe Näherung, die für die Tonwertabbildung völlig genügt). Die Abbildung erhält den wahrgenommenen Helligkeitswert: Weiß wird zu Papierweiß, Schwarz zur vollen Druckfarbe, und helle Flächen bleiben hell, unabhängig von ihrem ursprünglichen Farbton. Ein blassgelber Hintergrund wird zu einem blassen Tonwert der Druckfarbe; eine dunkle Kontur nähert sich der vollen Druckfarbe.
Das Umfärben übernimmt die exportierte Funktion applySingleInkToSvg(svgText, inkHex), die ohne DOM auf dem SVG-Markup als Text arbeitet:
- Hex-Literale
#rgb/#rgba/#rrggbb/#rrggbbaa, die Funktionenrgb()/rgba()undhsl()/hsla()werden umgeschrieben, wo immer sie vorkommen – Präsentationsattribute, Inline-style, Verläufe,<defs>. Die Funktionen dürfen ganzzahlige, dezimale oder prozentuale Kanäle und die Komma- oder Leerzeichensyntax verwenden, sodass auchrgb(11.37%, 20%, 50.59%)(wie Cairo es schreibt) undrgb(51 102 153 / 50%)umgefärbt werden. Eine getönte Funktion wird alsrgb(…)oderrgba(…)zurückgeschrieben. - Die Schlüsselwörter
whiteundblackwerden nur dort ersetzt, wo sie als Farbwerte stehen (fill,stroke,stop-color,flood-color,color– als Attribute oder Eigenschaften im Inline-Stil), nie in Textinhalten oder Beschriftungen. none,transparentundcurrentColorbleiben unberührt, ebenso die übrigen benannten Farben (red,steelblue…) und das Standardschwarz einer Form oder eines Texts ohne Füllung. Geben Sie solchen Elementen eine ausdrückliche Farbe, damit sie umgefärbt werden.- Alphakanäle bleiben erhalten (die Halbbytes von
#rgba/#rrggbbaaund die Alphakomponenten vonrgba(…)werden unverändert mitgeführt; ein prozentuales Alpha wird als Zahl geschrieben). - Lässt sich
inkHexnicht auswerten, wird die Eingabe unverändert zurückgegeben. - Das Ergebnis trägt
data-postext-single-ink="#…"(die Druckfarbe) an seinem Wurzelelement<svg>, und Markup, das diese Markierung bereits trägt, wird so zurückgegeben, wie es ist, gleich welche Druckfarbe es nennt. Die Abbildung ist nicht idempotent – ein zweiter Durchgang hellt jede Farbe auf, Schwarz kommt bei etwa zwei Dritteln der Druckfarbe heraus –, daher wird ein Bild einmal umgefärbt, gleich ob Ihr Code oder eine der Ausgaben es zuerst erreicht. (Die Markierung ist neu in postext 1.5; von 1.4 umgefärbtes Markup hat keine.)
import { applySingleInkToSvg } from 'postext';
const recoloured = applySingleInkToSvg(svgText, '#295AA3');
applySingleInkToSvg(recoloured, '#295AA3') === recoloured; // true: never twiceDer Einfarbmodus gilt in allen drei Ausgaben: Die PDF-Ausgabe färbt die SVG-Bytes um, die resourceBytes ihr übergibt, bevor sie sie als Vektoren zeichnet, und die Canvas- und HTML-Ausgaben tönen die SVG-Bilder, die sie zeichnen, wenn Sie es verlangen (siehe Einfarbmodus auf dem Canvas und in HTML); das exportierte PDF entspricht also der Vorschau auf dem Bildschirm.
Auflöser und Bereiniger entsprechen denen der anderen Abschnitte, neben den Typen DiagramStyleConfig / ResolvedDiagramStyleConfig:
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#Einfarbmodus auf dem Canvas und in HTML
Die Canvas- und HTML-Ausgaben erhalten Bilder bereits dekodiert (registerResourceImage) oder als URLs (resourceImageUrl), nicht als SVG-Markup. Auf Anforderung wenden sie dieselbe Abbildung auf das an, was sie zeichnen:
- Canvas (
renderPage,renderPageToCanvas,renderToCanvas). Jedes SVG-Bild, für das die Tönung gilt – eine Abbildung, das Bild einer Tabellenzelle, ein Gestaltungsbild, ein Kastensymbol oder -marker –, wird in seiner platzierten Größe gerastert und seine Pixel werden auf die Druckfarbe getönt, gleich ob es als<img>oder alsImageBitmapregistriert wurde. Die getönte Bitmap wird wie jedes Vektorraster zwischengespeichert. Ein Bitmap-Bild wird nie getönt. - HTML (
renderToHtml,renderToHtmlIndexed). Jedes SVG-<img>erhältfilter: url(#pt-ink-…), das auf einefeColorMatrixverweist, die seine Seite mitführt: ein<svg>ohne Größe, das den<filter>enthält, als Erstes auf der Seite steht und in der indizierten Ausgabe Teil desdecorationHtmlder Seite ist. Jede Seite trägt ihn, solange der Einfarbmodus gilt, ob sie ein Bild enthält oder nicht, sodass ein Host, der Blöcke einzeln austauscht, nie ein Bild einbringt, dessen Filter fehlt.
Nie zweimal getönt. Bis postext 1.4 zeichneten die Canvas- und HTML-Ausgaben Bilder so, wie sie übergeben wurden; Hosts färbten das Markup daher selbst mit applySingleInkToSvg um, bevor sie es übergaben. Die Paket-Adapter und die Sandbox tun das noch immer, weil der Markup-Durchgang genau die Farben des PDF ergibt (siehe den letzten Absatz unten). Ein Bild wird daher einmal getönt, nach drei Regeln, die in allen drei Ausgaben gelten:
- Markiertes Markup bleibt unberührt. Die PDF-Ausgabe färbt
resourceBytesmitapplySingleInkToSvgum, bereits umgefärbte SVG-Bytes werden also so gezeichnet, wie sie sind. Auf dem Canvas und in HTML wird ein Bild, das aus einer SVG-Data-URI geladen wurde, deren Markup die Markierung trägt, ebenfalls nie getönt. - Aus, sofern nicht verlangt, in postext 1.x. Der Canvas tönt ein SVG-Bild, das ohne eigenes Flag registriert wurde, nur, wenn der Render-Aufruf
singleInk: trueübergibt (RenderPageOptions), und eines, das mitregisterResourceImage(id, img, { singleInk: true })registriert wurde, bei jedem Render-Aufruf. Die HTML-Ausgabe tönt, wennrenderToHtmlsingleInk: trueerhält oder wenn sein AuflöserresourceImageUrlsingleInk: trueträgt. Ein für 1.4 geschriebener Host, der das Markup umfärbt und das dekodierte Bild ohne Flag registriert, behält seine Ausgabe. Das nächste Hauptrelease wird standardmäßig tönen. singleInk: falsewird nie getönt. Hinter einer Blob- oder Netzwerk-URL lässt sich das Markup nicht zurücklesen; ein Bild, das Sie selbst umgefärbt haben und auf diesem Weg dekodieren, wird daher mitsingleInk: falseregistriert, wie esregisterBundleImagesund die Sandbox tun.bundleImageUrl(bundle)liefert einen Auflöser, dersingleInk: falseträgt, undbundleResourceBytesübergibt dem PDF die eigenen Bytes des Pakets, die die PDF-Ausgabe einmal umfärbt.
Beide Ausgaben kennen die Art jedes Bildes aus dem VDT: Eine Abbildung und ein Zellbild tragen die Art ihrer Ressource, und ein Block mit Gestaltungsbild trägt imageKind ('svg' oder 'bitmap'), beim Umbruch von seiner Ressource übernommen. Bei einem VDT, der erstellt wurde, bevor es imageKind gab, behandelt der Canvas ein als Vektorquelle registriertes Gestaltungsbild als SVG, und die HTML-Ausgabe eines, dessen URL eine SVG-Data-URI ist oder auf .svg endet.
Färben Sie entweder das Markup selbst um oder lassen Sie die Ausgaben das unveränderte Bild tönen, nicht beides:
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 übernimmt seinen Standardwert für singleInk aus dem eigenen Flag des Auflösers, bundleImageUrl(bundle) braucht also keine Option.
Für jede Farbe, die der Markup-Durchgang umschreibt (Hex-, rgb()- und hsl()-Werte, white und black; siehe Wie der Einfarbmodus arbeitet), ergibt die Pixelabbildung dasselbe Ergebnis, geglättete Kanten und Verläufe eingeschlossen. Die beiden unterscheiden sich dort, wo der Markup-Durchgang eine Farbe unberührt lässt: Benannte Farben außer white und black, currentColor, Formen und Text ohne Füllung (im Standardschwarz gezeichnet) und im SVG eingebettete Bitmaps werden auf dem Bildschirm getönt, behalten im PDF aber ihre Farbe. Geben Sie jedem Element eines Diagramms eine ausdrückliche Farbe als Hex-, rgb()- oder hsl()-Wert, um eine identische Ausgabe zu erhalten. Kann der Canvas die Pixel nicht zurücklesen (ein <img> von einem anderen Ursprung, ohne CORS geladen), wird das Bild ungetönt gezeichnet.
#Schriften in SVG-Text
Ein SVG-Bild wird über ein Bild gezeigt: ein <img> auf dem Canvas, in HTML und in EPUB. Ein Bilddokument sieht die Webschriften der Seite nicht, sodass <text font-family="IBM Plex Sans"> auf eine Systemschrift zurückfiele. Seit postext 1.25 bettet die Engine die vom Text genannten Schnitte in das Markup ein, bevor das Bild dekodiert oder als URL herausgegeben wird: eine @font-face-Regel pro Schriftdatei, ihre Bytes als Data-URI, in einem <style> direkt nach dem Wurzel-Tag <svg>. Das PDF braucht nichts davon: Es setzt SVG-Text als echten Text in seinen eingebetteten Schriften (siehe Ressourcenbytes und Druckoriginale).
Was der Text verlangt, wird aus font-family, font-weight, font-style und font gelesen, als Attribute, in style-Attributen und von umschließenden Gruppen geerbt; eine <style>-Regel, die eine Familie nennt, zählt ebenfalls. Generische Familien (serif, sans-serif …) und Text in <title> oder <desc> bleiben außen vor, und eine Familie, die das SVG selbst mit @font-face deklariert, bleibt unberührt. Ein Textlauf geht seine Liste font-family bis zur ersten Familie durch, die einen Schnitt hat. Zuerst wird für den Einfarbmodus umgefärbt, danach kommen die Schriften.
Die Schnitte stammen von einem Provider mit dem Vertrag von PdfFontProvider aus postext-pdf, sodass ein Provider beiden dient: Er wird mit Familie, Schriftstärke und Stil sowie den Zeichen aufgerufen, die das SVG in diesem Schnitt setzt, und antwortet mit einer oder mehreren Dateien. Eine Familie, die in Unicode-Range-Teilen ausgeliefert wird (Fontsource, Google Fonts), wird mit den Teilen beantwortet, die diese Zeichen brauchen, sodass ein SVG mit lateinischen Beschriftungen nur die Datei latin mitführt. Der Standard-Provider liest das Schriftregister der Engine: loadBundleFonts registriert dort die Schnitte eines Pakets, und ein Host registriert seine eigenen mit registerFontBytes(family, weight, style, bytes, { unicodeRange }) oder mit registerFontUrl(…) für eine Datei, die beim ersten Bedarf eines SVG geladen wird. Eine Familie, die niemand registriert hat, wird in den @font-face-Regeln der lesbaren Stylesheets der Seite gesucht. Ein FontFace, das aus Bytes zu document.fonts hinzugefügt wurde, behält keine Bytes, die Engine kann es also nicht zurücklesen: Registrieren Sie auch diese Schnitte.
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);Wo es geschieht:
- Canvas.
registerSvgImage(fileId, svgText, options)färbt um (inkHex), bettet ein (fonts, ein Provider;inlineFonts: falseüberspringt das), dekodiert und registriert das Bild als Vektorquelle und liefert, was aus jedem Schnitt geworden ist.registerBundleImages(bundle)tut dasselbe für die SVGs eines Pakets, zuerst aus den eigenen Schnitten des Pakets.prepareSvgMarkup(svgText, options)liefert das vorbereitete Markup für einen Host, der selbst dekodiert. - HTML.
bundleImageUrl(bundle)liefert SVG-Markup mit eingebetteten Schnitten des Pakets.renderToHtml(doc, { inlineSvgFonts: true })bettet in die SVG-data:-URIs ein, dieresourceImageUrlliefert, und zwar aus den Schnitten, die das Register im Speicher hält (oderinlineSvgFonts: { fonts, maxBytes, withhold }). Eine Objekt-URL lässt sich nicht synchron lesen; ein Host, der Blob-URLs ausliefert, bettet daher ein, bevor er sie erzeugt. - EPUB.
postext-epubbettet aus denfontsdes Buchs ein, dann aussvgFonts.provider, bevor es ein SVG schreibt (siehe EPUB-Bücher). - PDF. SVG-Text wird als echter Text in den eingebetteten Schriften gesetzt. Ein
<style>, das nur@font-face-Regeln enthält (von einem Autor eingebettete Schnitte), lässt die Abbildung nicht mehr auf ein Raster zurückfallen. Fällt eine Abbildung doch zurück (ein Filter, ein Verlauf), wird ihr Raster mit den aus demfontProviderdes PDF eingebetteten Schnitten erzeugt.
Auch die Funktionen der unteren Ebene werden exportiert: svgFontRequests(svgText) listet Familien, Schriftstärke, Stil und Zeichen jedes Textlaufs; inlineSvgFonts(svgText, provider, options) und inlineSvgFontsSync(svgText, syncProvider, options) liefern das Markup; inlineSvgFontsDetailed fügt einen Bericht zu jedem Schnitt hinzu (inlined, declared, unavailable, withheld, tooLarge).
| Option | Typ | Standard | Beschreibung |
|---|---|---|---|
maxBytes | number | 2 MiB | Höchstmenge an Schrift-Bytes, die in ein SVG eingebettet werden (vor Base64, das ein Drittel hinzufügt). Schnitte, die zusammen darüber liegen, werden gar nicht eingebettet, und svgFontsTooLarge wird gemeldet. |
formats | ('woff2' | 'woff' | 'ttf' | 'otf')[] | alle vier | Die einzubettenden Dateiformate; Dateien anderer Formate werden übersprungen. |
withhold | (family) => boolean | keine | Familien, die aus einer Datei herausgehalten werden, die die App verlässt (nicht weitergebbar). Ihr Verweis bleibt, und der Leser fällt auf eine Ersatzschrift zurück; onWithheld(family) wird über jede informiert. |
onWarning | (warning) => void | keine | Wird über eine Familie ohne Schnitt (svgFontUnavailable) und über die Größengrenze (svgFontsTooLarge) informiert. |
Verzichten. diagramStyle.inlineFonts: false lässt jedes SVG so, wie es gespeichert ist; svg.inlineFonts: false an einer Ressource lässt diese Byte für Byte unverändert, für ein SVG, das seine eigenen Schnitte mitbringt oder sich nicht ändern darf. Ein Paket schreibt den Verzicht der Ressource als "inlineFonts": false in seine preset.json.
Lizenzen. Das Einbetten legt Schriftdateien in Bilder, die die App verlassen können (ein HTML-Export, ein EPUB). Es geschieht, wenn ein Bild gezeigt oder exportiert wird, nie in den gespeicherten Ressourcen-Bytes, und withhold hält die Familien heraus, deren Lizenz die Weitergabe nicht erlaubt: Der EPUB-Writer hält die mit redistributable: false markierten Schnitte zurück, die Sandbox die so markierten eigenen Familien.
#Videostil
Die Eigenschaft videoStyle legt fest, wie Video-Ressourcen gedruckt werden – das Abspielzeichen und der QR-Code über dem Posterbild und ob das Posterbild auf das Video verlinkt – und was ihre Player im HTML-Betrachter und in EPUB anbieten.
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 },
},
};| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
playMark | VideoPlayMarkConfig | siehe unten | Das auf das Posterbild gedruckte Zeichen, das anzeigt, dass es abgespielt werden kann. |
qr | VideoQrConfig | siehe unten | Der auf das Posterbild gedruckte QR-Code: Er öffnet die YouTube- oder Vimeo-Seite des Videos oder die Produktionsadresse einer Datei. |
linkPoster | boolean | true | Das Posterbild zu einem Link auf das Video machen: eine Link-Annotation darüber im PDF und ein <a> darum in HTML und EPUB, wo immer das Posterbild gezeigt wird. |
html | 'player' · 'poster' | 'player' | Was die HTML-Ausgabe für ein Video setzt: seinen Player oder das gedruckte Posterbild mit seinen Überlagerungen. |
player | VideoPlayerOptions | siehe unten | Die Player-Optionen aller Videos; das eigene video.player eines Videos wird darübergelegt. |
#Abspielzeichen
| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
enabled | boolean | true | Das Zeichen drucken. |
shape | 'circle' · 'rounded' · 'triangle' | 'circle' | Eine Scheibe mit Dreieck, ein abgerundetes Rechteck mit Dreieck (1,45-mal so breit wie hoch) oder das Dreieck allein, in der Hintergrundfarbe umrandet. |
position | VideoOverlayPosition | 'center' | 'center', eine Ecke ('top-left', 'top-right', 'bottom-left', 'bottom-right') oder die Mitte einer Seite ('top', 'bottom', 'left', 'right'). Die Positionen sind physisch: Die obere rechte Ecke ist auch in einem Buch mit Leserichtung von rechts nach links die obere rechte Ecke. |
size | Dimension | 12mm | Höhe des Zeichens; nie mehr als 40 % der kürzeren Seite des Posterbilds. |
inset | Dimension | 4mm | Abstand von den Kanten des Posterbilds an einer Ecke oder Seite. |
color | ColorValue | Weiß | Das Dreieck. |
background | ColorValue | Hauptfarbe | Die Scheibe oder das Rechteck dahinter; die Umrandung des Dreiecks, wenn es allein steht. Standardmäßig an die Palette gebunden. |
backgroundOpacity | number | 0.9 | Deckkraft des Hintergrunds, 0–1. |
#QR-Code
| Eigenschaft | Typ | Standard | Beschreibung |
|---|---|---|---|
enabled | boolean | true | Den Code drucken. Eine Datei ohne Produktionsadresse erhält keinen. |
position | VideoOverlayPosition | 'bottom-right' | Wie beim Abspielzeichen. Geben Sie beiden unterschiedliche Positionen. |
size | Dimension | 18mm | Seitenlänge des Codes samt Ruhezone; nie mehr als 45 % der kürzeren Seite des Posterbilds. Handykameras lesen Module ab einem Drittel Millimeter: Eine Adresse von 30 Zeichen ergibt einen Code mit 29 Modulen, 18 mm mit einer Ruhezone von 2 ergeben also Module von 0,55 mm. |
inset | Dimension | 3mm | Abstand von den Kanten des Posterbilds. |
errorCorrection | 'L' · 'M' · 'Q' · 'H' | 'M' | Wie viel des Codes beschädigt oder verdeckt sein darf, ohne dass er unlesbar wird: etwa 7 %, 15 %, 25 % oder 30 %. Wird von selbst angehoben, solange der Code dieselbe Zahl an Modulen behält. |
quietZone | number | 2 | Helle Module um den Code, auf seiner Platte (0–8). Die Platte hebt sich vom Posterbild ab, die vier Module, die der Standard auf offenem Papier verlangt, sind also nicht nötig. |
color | ColorValue | Schwarz | Die dunklen Module. Halten Sie sie dunkel auf heller Platte: Die meisten Lesegeräte lesen keine invertierten Codes. |
background | ColorValue | Weiß | Die Platte. |
radius | Dimension | 1mm | Eckenradius der Platte. |
Der Code wird von der Engine selbst kodiert (encodeQr(text, level): Byte-Modus, UTF-8, Versionen 1 bis 40, die Maske mit der geringsten Strafpunktzahl) und als Vektoren gezeichnet: Der Canvas füllt einen Pfad aus Modulfolgen, das PDF ein drawSvgPath und HTML ein <path> mit shape-rendering="crispEdges", sodass er in jeder Druckgröße scharf bleibt.
#Player-Optionen
VideoPlayerOptions, in videoStyle.player und im video.player jedes Videos. Der HTML5-Player einer Datei beachtet sie alle; die Player von YouTube und Vimeo beachten, was ihre Einbettungsparameter zulassen.
| Eigenschaft | Standard | Beachtet von | Beschreibung |
|---|---|---|---|
controls | true | YouTube, Vimeo, Dateien | Die Bedienelemente des Players zeigen. |
download | true | Dateien | Die Download-Schaltfläche des Browsers anbieten (controlslist="nodownload", wenn ausgeschaltet). Das blendet die Schaltfläche aus, schützt die Datei aber nicht. YouTube und Vimeo bieten nie einen Download an. |
fullscreen | true | YouTube, Vimeo, Dateien | Vollbild anbieten (fs=0, allowfullscreen des iframe, nofullscreen). |
playbackRate | true | Vimeo, Dateien | Das Geschwindigkeitsmenü anbieten (speed=0, noplaybackrate). |
pictureInPicture | true | Vimeo, Dateien | Bild-in-Bild anbieten (pip=0, disablepictureinpicture). |
remotePlayback | true | Dateien | Die Übertragung auf einen anderen Bildschirm anbieten (disableremoteplayback). |
autoplay | false | YouTube, Vimeo, Dateien | Von selbst abspielen, immer stumm, wie Browser es verlangen. |
muted | false | YouTube, Vimeo, Dateien | Ohne Ton starten. |
loop | false | YouTube, Vimeo, Dateien | Am Ende erneut von vorn abspielen. |
exclusive | true | Folio, HTML-Betrachter, EPUB (wo Skripte laufen); Dateien | Der Start dieses Videos hält die anderen sichtbaren an, sodass immer nur eines läuft. false lässt es neben den anderen laufen: die stummen Endlosclips einer Seite, mehrere gleichzeitig. Seit postext 1.18. |
preload | 'metadata' | Dateien | Wie viel der Browser vor dem Abspielen lädt: 'none', 'metadata' oder 'auto'. |
privacy | true | YouTube, Vimeo | Einbettungen mit erweitertem Datenschutz: YouTube über youtube-nocookie.com, Vimeo mit dnt=1. |
Ein EPUB behält nur die Attribute, die sein Schema kennt: Eine Datei spielt mit controls, autoplay, muted, loop, playsinline und preload, dazu der Markierung data-pt-alongside, und das Lesesystem entscheidet über den Rest.
Ein Video, das nicht exklusiv ist, trägt in der HTML-Ausgabe data-pt-alongside. coordinateVideoPlayback(root) hält die Player unter root (dem Element, das die Ausgabe von renderToHtml enthält) an die Regel: Der Start eines exklusiven Videos hält jedes andere laufende an, und der Start eines, das daneben läuft, hält nur die exklusiven an. Die Funktion liefert eine Funktion zurück, die das Lauschen beendet. playsAlongside(el) und videosToPause(started, videos, alongside) stellen dieselbe Regel einem Host mit eigenen Playern bereit. In Folio startet ein Video, das von selbst und neben den anderen läuft (autoplay mit exclusive: false), stumm, sobald seine Seite ins Bild kommt, und hält an, wenn die Seite weggeblättert wird, mehrere gleichzeitig, und loop spielt es erneut von vorn ab. Eine EPUB-Seite oder ein EPUB-Kapitel mit zu koordinierenden Videos (zwei oder mehr, eines davon exklusiv) verlinkt dieselbe Regel als kleines Skript, scripts/videos.js (der Export VIDEO_PLAYBACK_SCRIPT), und das Paket deklariert dieses Dokument als scripted. Ein Lesesystem, das Skripte ausführt, hält die Videos dieses Dokuments an die Regel, nicht aber die einer gegenüberliegenden Seite, die ein anderes Dokument ist; eines, das keine Skripte ausführt, spielt jedes Video nach dessen eigenen Bedingungen ab, wie es die Player von YouTube und Vimeo immer tun.
Auflöser und Bereiniger entsprechen denen der anderen Abschnitte, neben den Typen VideoStyleConfig / ResolvedVideoStyleConfig:
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