@openpresentation/opf-render 0.11.0 → 0.11.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -10
- package/dist/font-manifest.js +457 -41
- package/dist/font-policy.js +6 -6
- package/dist/fonts.js +6 -1
- package/dist/script-font-pack.js +48 -6
- package/fonts/anton/Anton-Regular.ttf +0 -0
- package/fonts/anton/OFL.txt +93 -0
- package/fonts/anton/PROVENANCE.json +21 -0
- package/fonts/archivo-narrow/ArchivoNarrow_400Regular.ttf +0 -0
- package/fonts/archivo-narrow/ArchivoNarrow_400Regular_Italic.ttf +0 -0
- package/fonts/archivo-narrow/ArchivoNarrow_700Bold.ttf +0 -0
- package/fonts/archivo-narrow/ArchivoNarrow_700Bold_Italic.ttf +0 -0
- package/fonts/archivo-narrow/OFL.txt +93 -0
- package/fonts/archivo-narrow/PROVENANCE.json +47 -0
- package/fonts/barlow/Barlow-Bold.ttf +0 -0
- package/fonts/barlow/Barlow-BoldItalic.ttf +0 -0
- package/fonts/barlow/Barlow-Italic.ttf +0 -0
- package/fonts/barlow/Barlow-Regular.ttf +0 -0
- package/fonts/barlow/OFL.txt +93 -0
- package/fonts/barlow/PROVENANCE.json +45 -0
- package/fonts/bitter/Bitter_400Regular.ttf +0 -0
- package/fonts/bitter/Bitter_400Regular_Italic.ttf +0 -0
- package/fonts/bitter/Bitter_700Bold.ttf +0 -0
- package/fonts/bitter/Bitter_700Bold_Italic.ttf +0 -0
- package/fonts/bitter/OFL.txt +94 -0
- package/fonts/bitter/PROVENANCE.json +49 -0
- package/fonts/eb-garamond/EBGaramond_400Regular.ttf +0 -0
- package/fonts/eb-garamond/EBGaramond_400Regular_Italic.ttf +0 -0
- package/fonts/eb-garamond/EBGaramond_700Bold.ttf +0 -0
- package/fonts/eb-garamond/EBGaramond_700Bold_Italic.ttf +0 -0
- package/fonts/eb-garamond/OFL.txt +93 -0
- package/fonts/eb-garamond/PROVENANCE.json +47 -0
- package/fonts/figtree/Figtree_400Regular.ttf +0 -0
- package/fonts/figtree/Figtree_400Regular_Italic.ttf +0 -0
- package/fonts/figtree/Figtree_700Bold.ttf +0 -0
- package/fonts/figtree/Figtree_700Bold_Italic.ttf +0 -0
- package/fonts/figtree/OFL.txt +93 -0
- package/fonts/figtree/PROVENANCE.json +47 -0
- package/fonts/libre-caslon-text/LibreCaslonText_400Regular.ttf +0 -0
- package/fonts/libre-caslon-text/LibreCaslonText_400Regular_Italic.ttf +0 -0
- package/fonts/libre-caslon-text/LibreCaslonText_700Bold.ttf +0 -0
- package/fonts/libre-caslon-text/OFL.txt +93 -0
- package/fonts/libre-caslon-text/PROVENANCE.json +39 -0
- package/fonts/red-hat-display/OFL.txt +2 -2
- package/fonts/red-hat-display/PROVENANCE.json +57 -16
- package/fonts/red-hat-display/RedHatDisplay_300Light.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_300Light_Italic.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_400Regular.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_400Regular_Italic.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_600SemiBold.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_600SemiBold_Italic.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_700Bold.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay_700Bold_Italic.ttf +0 -0
- package/fonts/red-hat-text/OFL.txt +2 -2
- package/fonts/red-hat-text/PROVENANCE.json +28 -11
- package/fonts/red-hat-text/RedHatText_400Regular.ttf +0 -0
- package/fonts/red-hat-text/RedHatText_400Regular_Italic.ttf +0 -0
- package/fonts/red-hat-text/RedHatText_700Bold.ttf +0 -0
- package/fonts/red-hat-text/RedHatText_700Bold_Italic.ttf +0 -0
- package/fonts/work-sans/OFL.txt +93 -0
- package/fonts/work-sans/PROVENANCE.json +47 -0
- package/fonts/work-sans/WorkSans_400Regular.ttf +0 -0
- package/fonts/work-sans/WorkSans_400Regular_Italic.ttf +0 -0
- package/fonts/work-sans/WorkSans_700Bold.ttf +0 -0
- package/fonts/work-sans/WorkSans_700Bold_Italic.ttf +0 -0
- package/package.json +4 -3
- package/fonts/red-hat-display/RedHatDisplay-Bold.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay-Light.ttf +0 -0
- package/fonts/red-hat-display/RedHatDisplay-Regular.ttf +0 -0
- package/fonts/red-hat-text/RedHatText-Bold.ttf +0 -0
- package/fonts/red-hat-text/RedHatText-Regular.ttf +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Aptos previews with Intos.** The Office pack includes Intos, Intos Display, Intos Narrow and Intos Serif (16 faces, about 12 MB, vendored under `fonts/intos/`, SIL OFL 1.1, pinned to upstream commit fef9315c14da9e4b23b4c3cac8e718998d4e4736 and per-file SHA-256, unmodified from the upstream files). They are the metric-compatible previews for Aptos, Aptos Display, Aptos Narrow and Aptos Serif, the default `aptos` font scheme: 0.000% mean and maximum width difference against Aptos 2.01 in all four styles, with equal vertical metrics. The letter shapes are Intos's own, not Aptos's. The exported PPTX still names Aptos; no Aptos file is bundled or embedded. A registry built without these faces (the base pack) has no Aptos substitute: visual policy falls back to Roboto or Carlito. Like the open families, Intos is `embed: "used"`: it is not in `registry.embeddedFonts` (the 33 eager npm faces), `prepareNodeFonts().options.embeddedFonts` supplies it, and an SVG embeds only the Intos faces its text draws. `registry.lazyFonts` lists the 51 vendored faces (35 open, 16 Intos) with package-relative file and sha256, and `loadBrowserFontRegistry(faces, {lazyFontsBaseUrl})` loads them on demand: `await registry.ensureLazyFonts(presentation)` fetches and verifies only the files the document's font families resolve to (the default Aptos scheme: Intos and Intos Display, 8 files, 5.9 MB), then adds them to the document and the registry together so measurement and painting never disagree. Hosts copy the vendored directories next to the page.
|
|
4
4
|
|
|
5
|
-
Version 0.11.0 requires `@openpresentation/opf` ^0.11.2 (cover centering, Intos Aptos previews, lazy font loading, automatic script fonts and glyph fallback); use it with PPTX 0.11.0 and editor 0.10.0 so preview and export resolve the same core. Version 0.10.0 required `@openpresentation/opf` ^0.11.1 (font policy table, script fonts and right-to-left paragraphs, socials, slide-image treatments, formatted slide-number and date furniture with the host `date` option, per-item alignment). See the changelog for the intentional preview-output changes.
|
|
5
|
+
Version 0.11.2 makes `scripts: 'auto'` load the script faces a font scheme names and adds `details.loadedFaceHasGlyph` to `missing-glyph` (no export change). Version 0.11.1 adds the open replacement font families the policy routes to and complete Red Hat styles (no API change). Version 0.11.0 requires `@openpresentation/opf` ^0.11.2 (cover centering, Intos Aptos previews, lazy font loading, automatic script fonts and glyph fallback); use it with PPTX 0.11.0 and editor 0.10.0 so preview and export resolve the same core. Version 0.10.0 required `@openpresentation/opf` ^0.11.1 (font policy table, script fonts and right-to-left paragraphs, socials, slide-image treatments, formatted slide-number and date furniture with the host `date` option, per-item alignment). See the changelog for the intentional preview-output changes.
|
|
6
6
|
|
|
7
7
|
Version 0.9.0 required `@openpresentation/opf` ^0.11.0 and resolved content ColorRef / `variables` through core `resolveColorRef()`. Authored `#RRGGBB` paint stays authored. It retains the existing rendering APIs.
|
|
8
8
|
|
|
@@ -40,7 +40,7 @@ const pptx = await toPptx(presentation, options);
|
|
|
40
40
|
console.log(registry.substitutions);
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
-
The default `pack: 'base'` contains nine Roboto/Roboto Mono faces and suits a document using `design.fontScheme: 'roboto'`. The Office pack includes 24 Office-substitute faces plus
|
|
43
|
+
The default `pack: 'base'` contains nine Roboto/Roboto Mono faces and suits a document using `design.fontScheme: 'roboto'`. The Office pack includes 24 Office-substitute faces plus 70 vendored faces of the open families that font schemes select and the open replacements the font policy routes to (below) and the 16 vendored Intos faces that preview the Aptos family (below), and defaults to metric substitution policy. Its four Carlito faces are the byte-identical upstream release (OFL reserves the name "Carlito", so a subset or conversion could not keep it); visual substitution remains explicit. Neither helper changes the document's authored font scheme or installs system fonts. The authored (selected) font is the source of truth. Licensed fonts are never bundled, so these packs supply open look-alikes for previews and SVG: metric-compatible where one exists (Carlito for Calibri, Intos for Aptos), visual-only where none does yet (a documented fallback and known layout-fidelity gap). The PPTX exporter still writes the selected name; see the [OPF font policy](https://github.com/OpenPresentation/opf/blob/main/docs/font-fidelity.md#font-policy-ff-31). Missing resources, changed bytes/notices, and unexpected package versions fail with actionable font errors. Requested/resolved substitution records remain on `registry.substitutions`; source paths appear where the caller supplies them. Font coverage, variant naming, shaping, and native fidelity retain their documented limits.
|
|
44
44
|
|
|
45
45
|
Default PNG/PDF raster loading now uses the same complete nine-face base pack, fixing omitted semibold and italic faces. Custom raster callers may still set `useBundledFonts: false`. Font files must stay available and unchanged for subsequent raster calls. `node scripts/update-font-manifest.mjs` is an explicit maintenance operation requiring review of font bytes, style metadata, licenses and raster changes; builds and installs never regenerate the expected hashes.
|
|
46
46
|
|
|
@@ -123,7 +123,7 @@ Each entry contains `url` or `data: Uint8Array`, with optional `family`, `weight
|
|
|
123
123
|
|
|
124
124
|
## Open font-scheme families (FF-31)
|
|
125
125
|
|
|
126
|
-
Font schemes select openly licensed Latin families that no Office substitute covers, and the font policy
|
|
126
|
+
Font schemes select openly licensed Latin families that no Office substitute covers, and the font policy routes proprietary families to open replacements (Red Hat for Segoe UI and Tahoma and, since FF-43, Barlow, Anton, Figtree, Work Sans, EB Garamond, Archivo Narrow, Libre Caslon Text and Bitter). The office pack vendors them as static faces (`fonts/<family>/`: only the used faces, the upstream OFL notice as `OFL.txt` and a generated `PROVENANCE.json`), so `loadOfficeFontRegistry()` and `prepareNodeFonts({ pack: 'office' })` resolve each to its own face, and a strict registry no longer throws `font-unavailable` for them:
|
|
127
127
|
|
|
128
128
|
| Family | Vendored from | Faces |
|
|
129
129
|
|---|---|---|
|
|
@@ -135,16 +135,24 @@ Font schemes select openly licensed Latin families that no Office substitute cov
|
|
|
135
135
|
| Lora | cyrealtype/Lora-Cyrillic v3.021, pinned commit, `fonts/ttf` | 400, 700, italics |
|
|
136
136
|
| Merriweather Sans | SorkinType/Merriweather-Sans, pinned commit, `fonts/ttf` | 400, 700, italics |
|
|
137
137
|
| Source Sans 3 (also answers to Source Sans Pro) | adobe-fonts/source-sans tag 3.052R, pinned commit, `TTF` | 400, 700, italics |
|
|
138
|
-
| Red Hat Display |
|
|
139
|
-
| Red Hat Text |
|
|
138
|
+
| Red Hat Display | `@expo-google-fonts/red-hat-display@0.4.1` (instanced statics; no Reserved Font Name) | 300, 400, 600, 700, italics (FF-43) |
|
|
139
|
+
| Red Hat Text | `@expo-google-fonts/red-hat-text@0.4.1` (same) | 400, 700, italics (FF-43) |
|
|
140
|
+
| Barlow | google/fonts `ofl/barlow` at a pinned commit (byte-identical statics) | 400, 700, italics (Grandview, Franklin Gothic) |
|
|
141
|
+
| Anton | google/fonts `ofl/anton` at a pinned commit (byte-identical) | 400 (Impact; the family has no other style) |
|
|
142
|
+
| Figtree | `@expo-google-fonts/figtree@0.4.1` (instanced statics) | 400, 700, italics (Tenorite, Trebuchet MS) |
|
|
143
|
+
| Work Sans | `@expo-google-fonts/work-sans@0.4.2` (same) | 400, 700, italics (Century Gothic, Lucida Sans) |
|
|
144
|
+
| EB Garamond | `@expo-google-fonts/eb-garamond@0.4.3` (same) | 400, 700, italics (Garamond) |
|
|
145
|
+
| Archivo Narrow | `@expo-google-fonts/archivo-narrow@0.4.2` (same) | 400, 700, italics (Arial Narrow) |
|
|
146
|
+
| Libre Caslon Text | `@expo-google-fonts/libre-caslon-text@0.4.0` (same) | 400, 400 italic, 700 (Baskerville Old Face, Bookman Old Style) |
|
|
147
|
+
| Bitter | `@expo-google-fonts/bitter@0.4.2` (instanced statics named "Bitter"; the OFL reserves "Bitter Pro") | 400, 700, italics (Rockwell) |
|
|
140
148
|
|
|
141
|
-
All are SIL OFL 1.1, and each manifest entry records the SPDX id read from the shipped notice, its Reserved Font Names, the upstream project and copyright line. An OFL Reserved Font Name stops a modified version from using the reserved name, so the families that have one (PT Serif, Lora, Merriweather Sans, Source Sans 3) are the copyright holder's byte-identical files: every face records `upstreamFile { url, sha256 }` with a commit-pinned URL and a sha256 equal to the face's own, and `test/font-licenses.mjs` enforces it. The other
|
|
149
|
+
All are SIL OFL 1.1, and each manifest entry records the SPDX id read from the shipped notice, its Reserved Font Names, the upstream project and copyright line. An OFL Reserved Font Name stops a modified version from using the reserved name, so the families that have one (PT Serif, Lora, Merriweather Sans, Source Sans 3) are the copyright holder's byte-identical files: every face records `upstreamFile { url, sha256 }` with a commit-pinned URL and a sha256 equal to the face's own, and `test/font-licenses.mjs` enforces it. The other families have none, except Bitter (Reserved Font Name "Bitter Pro"); their files are either google/fonts statics (Barlow and Anton: byte-identical, also pinned by `upstreamFile`) or the instanced statics of the `@expo-google-fonts` packages, whose notice and version `PROVENANCE.json` records.
|
|
142
150
|
|
|
143
|
-
Not bundled: **Raleway** and **Playfair Display**. Their upstream releases ship only variable fonts, and the Node raster engine (resvg 2.6.2) ignores the weight axis: weights 400 and 700 rendered byte-identically, and Raleway's default instance is Thin. Bundling the instanced statics would modify them under their Reserved Font Names. They keep failing with "no face" until the raster engine supports variable weights or upstream publishes statics.
|
|
151
|
+
Not bundled: **Raleway** and **Playfair Display**. Their upstream releases ship only variable fonts, and the Node raster engine (resvg 2.6.2) ignores the weight axis: weights 400 and 700 rendered byte-identically, and Raleway's default instance is Thin. Bundling the instanced statics would modify them under their Reserved Font Names. They keep failing with "no face" until the raster engine supports variable weights or upstream publishes statics. **Bitter** (the Rockwell replacement) reserves the name "Bitter Pro". OFL only stops a modified font from carrying its Reserved Font Name in its family or file name, so the instanced statics, named "Bitter", are allowed; `test/font-licenses.mjs` implements exactly that name-contains rule for instanced faces (an instanced face named Carlito, Raleway, Lora or Playfair Display still fails, and a family that must keep its reserved name ships the unmodified upstream file). **Libre Caslon Text** has no bold italic (its static releases and the Google Fonts instances stop at Regular, Italic and Bold): a bold italic request draws the real italic and reports `visual`; bold is never synthesized.
|
|
144
152
|
|
|
145
|
-
Source Sans Pro was renamed Source Sans 3. A request for the old name draws the Source Sans 3 faces through a built-in alias (`renamedFrom` in the manifest) and is reported `visual`, in any substitution policy, because the releases differ (bold advances by about 0.7%). Source Sans 3 itself resolves exact and is also the declared replacement for Candara, Corbel, Gill Sans MT and Seaford. Red Hat Display and Text are the declared replacements for Segoe UI and Tahoma.
|
|
153
|
+
Source Sans Pro was renamed Source Sans 3. A request for the old name draws the Source Sans 3 faces through a built-in alias (`renamedFrom` in the manifest) and is reported `visual`, in any substitution policy, because the releases differ (bold advances by about 0.7%). Source Sans 3 itself resolves exact and is also the declared replacement for Candara, Corbel, Gill Sans MT and Seaford. Red Hat Display and Text are the declared replacements for Segoe UI and Tahoma. The RedHatFont repository's own static files cannot be used: the Regular, Light and SemiBold italics (and Red Hat Text Italic) do not set the OS/2 italic bit (only the Bold Italic files do), Red Hat Display SemiBold declares weight 707 and Bold 799 (Red Hat Text Bold declares 700), so in resvg a 600 request paints as Bold and the regular and bold italics paint as one face (probed). The vendored Red Hat faces are therefore the correctly labelled instanced statics of `@expo-google-fonts` (Red Hat has no Reserved Font Name): Segoe UI Semibold draws a real 600 (and 600 italic), and Segoe UI, Segoe UI Light and Tahoma draw real italics, none synthesized. Trade-off: the shipped Red Hat Display Bold (Google Fonts weight 700 instance) is about 2.5% narrower than the RedHatFont Bold it replaces, so the Segoe UI Bold preview moves from +0.6% to -1.8% mean width against Segoe UI Bold 5.71 (mean absolute 0.95% to 1.86%, max 6.0% to 5.5%); the regular widths are identical. A style a family lacks is not synthesized: Bebas Neue and Anton bold draw the regular face and report `visual`, and an italic request throws `font-style-unavailable`, as for Roboto Mono. A test renders every vendored face through resvg and checks that exactly that face paints.
|
|
146
154
|
|
|
147
|
-
The
|
|
155
|
+
The 70 vendored faces are 12.0 MiB (FF-43 added 35 faces, 4.6 MiB uncompressed and about 2.4 MB in the tarball; the first 35 were 7.4 MiB) and are the only bytes added; there are no new dependencies. Browser hosts fetch them lazily by family, so the eager list stays the 33 Office and base faces. Every face and notice is checked against its manifest sha256 when loaded (`font-integrity-mismatch`, `font-resource-unavailable`), and `npm run test:packed` verifies the packed copies. `node scripts/update-font-manifest.mjs --vendor` re-downloads each recorded commit (or npm version), reads the license from the shipped notice, refuses a non-permissive one (only OFL-1.1, Apache-2.0, MIT and UFL-1.0 are allowed), copies only the listed faces and rewrites the hashes and provenance; `.gitattributes` keeps the binaries byte-exact.
|
|
148
156
|
|
|
149
157
|
Embedding: open faces are flagged `embed: "used"`. `registry.embeddedFonts` stays the 33 Office and base faces, while `prepareNodeFonts().options.embeddedFonts` (or `registry.selectEmbeddedFonts`) supplies every face and `renderSvg` embeds an open face only when the slide's text names its family, so a Montserrat slide carries Montserrat and not the whole pack. Raster output reads the files from `fontFiles`. `includeOpenFonts: false` leaves the open families out of the office pack entirely.
|
|
150
158
|
|
|
@@ -168,7 +176,7 @@ const png = await svgToPng(slides[0], options);
|
|
|
168
176
|
|
|
169
177
|
### Load only the script faces a document uses (`scripts: 'auto'`)
|
|
170
178
|
|
|
171
|
-
Hosts do not need to detect scripts themselves. `scripts: 'auto'` reads the presentation's drawn text and loads only the faces for the scripts it uses: a Latin, Greek or Cyrillic deck loads none, a Japanese deck loads Noto Sans JP, an Arabic deck the three Arabic packages. Text decides, so a deck whose `language` is `ja` but whose text is Latin still loads nothing. The document language only tells Han text apart (through core `resolveScriptFonts`, the same profile the renderer plans with; a core without it treats Han as Simplified Chinese, as the renderer does). Only drawn text counts (titles, text, list items, runs, table cells, chart labels, code, quotes, metrics, furniture); ids, image alt text and sources, URLs, assets, catalogs, speaker notes, `extensions`, a slide's `beat` and the deck's own name, description, filename, author, speaker, audience, purpose, tone, takeaway, duration, tags and narrative are ignored. The organization and a slide's `section` count only when a design turns on that generated header or footer field. Detection itemizes text exactly as drawing does, so with an East Asian language the curly quotes, dashes and ellipsis count as East Asian. `detectPresentationScripts(presentation)` and `autoScriptSelection(presentation)` (from `/fonts-node` and `/fonts-browser`) return the decision.
|
|
179
|
+
Hosts do not need to detect scripts themselves. `scripts: 'auto'` reads the presentation's drawn text and loads only the faces for the scripts it uses: a Latin, Greek or Cyrillic deck loads none, a Japanese deck loads Noto Sans JP, an Arabic deck the three Arabic packages. Text decides, so a deck whose `language` is `ja` but whose text is Latin still loads nothing. The one exception is a font scheme that names a script font (Yu Gothic, Meiryo, Malgun Gothic, Microsoft YaHei, Arabic Typesetting, Mangal or a pinned Noto family, on the deck or on a slide's `design`): its Latin text previews with that font's open replacement, so its face loads whatever the text, and Han-only text in such a deck draws with the scheme's CJK face. `detected` still lists only what the text draws; `scripts` is what to load. The document language only tells Han text apart (through core `resolveScriptFonts`, the same profile the renderer plans with; a core without it treats Han as Simplified Chinese, as the renderer does). Only drawn text counts (titles, text, list items, runs, table cells, chart labels, code, quotes, metrics, furniture); ids, image alt text and sources, URLs, assets, catalogs, speaker notes, `extensions`, a slide's `beat` and the deck's own name, description, filename, author, speaker, audience, purpose, tone, takeaway, duration, tags and narrative are ignored. The organization and a slide's `section` count only when a design turns on that generated header or footer field. Detection itemizes text exactly as drawing does, so with an East Asian language the curly quotes, dashes and ellipsis count as East Asian. `detectPresentationScripts(presentation)` and `autoScriptSelection(presentation)` (from `/fonts-node` and `/fonts-browser`) return the decision.
|
|
172
180
|
|
|
173
181
|
```js
|
|
174
182
|
// Node: pass the presentation with scripts: 'auto'. Auto never fails on a package that is not installed
|