@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.
Files changed (71) hide show
  1. package/README.md +18 -10
  2. package/dist/font-manifest.js +457 -41
  3. package/dist/font-policy.js +6 -6
  4. package/dist/fonts.js +6 -1
  5. package/dist/script-font-pack.js +48 -6
  6. package/fonts/anton/Anton-Regular.ttf +0 -0
  7. package/fonts/anton/OFL.txt +93 -0
  8. package/fonts/anton/PROVENANCE.json +21 -0
  9. package/fonts/archivo-narrow/ArchivoNarrow_400Regular.ttf +0 -0
  10. package/fonts/archivo-narrow/ArchivoNarrow_400Regular_Italic.ttf +0 -0
  11. package/fonts/archivo-narrow/ArchivoNarrow_700Bold.ttf +0 -0
  12. package/fonts/archivo-narrow/ArchivoNarrow_700Bold_Italic.ttf +0 -0
  13. package/fonts/archivo-narrow/OFL.txt +93 -0
  14. package/fonts/archivo-narrow/PROVENANCE.json +47 -0
  15. package/fonts/barlow/Barlow-Bold.ttf +0 -0
  16. package/fonts/barlow/Barlow-BoldItalic.ttf +0 -0
  17. package/fonts/barlow/Barlow-Italic.ttf +0 -0
  18. package/fonts/barlow/Barlow-Regular.ttf +0 -0
  19. package/fonts/barlow/OFL.txt +93 -0
  20. package/fonts/barlow/PROVENANCE.json +45 -0
  21. package/fonts/bitter/Bitter_400Regular.ttf +0 -0
  22. package/fonts/bitter/Bitter_400Regular_Italic.ttf +0 -0
  23. package/fonts/bitter/Bitter_700Bold.ttf +0 -0
  24. package/fonts/bitter/Bitter_700Bold_Italic.ttf +0 -0
  25. package/fonts/bitter/OFL.txt +94 -0
  26. package/fonts/bitter/PROVENANCE.json +49 -0
  27. package/fonts/eb-garamond/EBGaramond_400Regular.ttf +0 -0
  28. package/fonts/eb-garamond/EBGaramond_400Regular_Italic.ttf +0 -0
  29. package/fonts/eb-garamond/EBGaramond_700Bold.ttf +0 -0
  30. package/fonts/eb-garamond/EBGaramond_700Bold_Italic.ttf +0 -0
  31. package/fonts/eb-garamond/OFL.txt +93 -0
  32. package/fonts/eb-garamond/PROVENANCE.json +47 -0
  33. package/fonts/figtree/Figtree_400Regular.ttf +0 -0
  34. package/fonts/figtree/Figtree_400Regular_Italic.ttf +0 -0
  35. package/fonts/figtree/Figtree_700Bold.ttf +0 -0
  36. package/fonts/figtree/Figtree_700Bold_Italic.ttf +0 -0
  37. package/fonts/figtree/OFL.txt +93 -0
  38. package/fonts/figtree/PROVENANCE.json +47 -0
  39. package/fonts/libre-caslon-text/LibreCaslonText_400Regular.ttf +0 -0
  40. package/fonts/libre-caslon-text/LibreCaslonText_400Regular_Italic.ttf +0 -0
  41. package/fonts/libre-caslon-text/LibreCaslonText_700Bold.ttf +0 -0
  42. package/fonts/libre-caslon-text/OFL.txt +93 -0
  43. package/fonts/libre-caslon-text/PROVENANCE.json +39 -0
  44. package/fonts/red-hat-display/OFL.txt +2 -2
  45. package/fonts/red-hat-display/PROVENANCE.json +57 -16
  46. package/fonts/red-hat-display/RedHatDisplay_300Light.ttf +0 -0
  47. package/fonts/red-hat-display/RedHatDisplay_300Light_Italic.ttf +0 -0
  48. package/fonts/red-hat-display/RedHatDisplay_400Regular.ttf +0 -0
  49. package/fonts/red-hat-display/RedHatDisplay_400Regular_Italic.ttf +0 -0
  50. package/fonts/red-hat-display/RedHatDisplay_600SemiBold.ttf +0 -0
  51. package/fonts/red-hat-display/RedHatDisplay_600SemiBold_Italic.ttf +0 -0
  52. package/fonts/red-hat-display/RedHatDisplay_700Bold.ttf +0 -0
  53. package/fonts/red-hat-display/RedHatDisplay_700Bold_Italic.ttf +0 -0
  54. package/fonts/red-hat-text/OFL.txt +2 -2
  55. package/fonts/red-hat-text/PROVENANCE.json +28 -11
  56. package/fonts/red-hat-text/RedHatText_400Regular.ttf +0 -0
  57. package/fonts/red-hat-text/RedHatText_400Regular_Italic.ttf +0 -0
  58. package/fonts/red-hat-text/RedHatText_700Bold.ttf +0 -0
  59. package/fonts/red-hat-text/RedHatText_700Bold_Italic.ttf +0 -0
  60. package/fonts/work-sans/OFL.txt +93 -0
  61. package/fonts/work-sans/PROVENANCE.json +47 -0
  62. package/fonts/work-sans/WorkSans_400Regular.ttf +0 -0
  63. package/fonts/work-sans/WorkSans_400Regular_Italic.ttf +0 -0
  64. package/fonts/work-sans/WorkSans_700Bold.ttf +0 -0
  65. package/fonts/work-sans/WorkSans_700Bold_Italic.ttf +0 -0
  66. package/package.json +4 -3
  67. package/fonts/red-hat-display/RedHatDisplay-Bold.ttf +0 -0
  68. package/fonts/red-hat-display/RedHatDisplay-Light.ttf +0 -0
  69. package/fonts/red-hat-display/RedHatDisplay-Regular.ttf +0 -0
  70. package/fonts/red-hat-text/RedHatText-Bold.ttf +0 -0
  71. 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 35 vendored faces of the open families that font schemes select (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.
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 names two Red Hat families as replacements for Segoe UI and Tahoma. 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:
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 | RedHatOfficial/RedHatFont 5.0.0, pinned commit | 300, 400, 700 |
139
- | Red Hat Text | RedHatOfficial/RedHatFont 5.0.0, pinned commit | 400, 700 |
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 four families have none; their files are the instanced statics of the `@expo-google-fonts` packages, whose notice and version `PROVENANCE.json` records.
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. Their italic files are left out because resvg ranks by the OS/2 italic bit, which upstream's regular italic does not set (it would paint bold italic), and no 600 face is vendored because upstream's SemiBold declares OS/2 weight 707, which resvg would rank above Bold. Italic falls back to upright (`styleFallback`) and Segoe UI Semibold to Bold, both reported visual. A style a family lacks is not synthesized: Bebas Neue bold draws the regular face and reports `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.
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 35 vendored faces are 7.4 MiB and are the only bytes added; the published tarball grows from 79 kB to 3.9 MB, and there are no new dependencies. 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.
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