@openpresentation/opf-render 0.11.3 → 0.11.5

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.
@@ -1,52 +1,180 @@
1
1
  import { fontPolicyFor } from "./font-policy.js";
2
- import { resolvePresentation } from "./svg.js";
2
+ import { pickFace } from "./fonts.js";
3
+ import { renderSvgDeck, resolvePresentation } from "./svg.js";
3
4
  export { lazyFontEntries, lazyFontList } from "./lazy-font-list.js";
4
5
 
5
6
  /**
6
7
  * FF-31: the vendored faces (the open families and Intos) are not in a registry's eager list. Browser hosts load them
7
- * on demand, from separate hash-pinned files, when a document's font families resolve to them. This module holds the
8
- * pure parts (which faces exist, which a presentation needs); fonts-browser.js does the fetching.
8
+ * on demand, from separate hash-pinned files, when a document draws them. This module holds the pure parts (which faces
9
+ * exist, which a presentation needs); fonts-browser.js does the fetching.
10
+ *
11
+ * FF-41: the analysis is face level. `presentationFaces` lists the {family, weight, italic} the renderer draws (resolved as a
12
+ * registry resolves them, on request), `lazyFacesNeeded` picks the vendored faces among them a registry lacks, and
13
+ * `lazyFontsFor` selects the vendored faces a list of face requests resolves to; none of them loads whole families.
9
14
  */
10
15
 
11
16
  const lc = value => String(value).trim().toLowerCase();
12
17
 
13
- /** The font families a presentation's slides resolve (heading, body and code roles), or an empty set for a document that does not resolve. */
14
- export function presentationFamilies(presentation) {
18
+ /**
19
+ * Render options that decide how a document resolves (catalogs, validate, date, ...) are forwarded from the host's
20
+ * `renderSvg` options. The analysis supplies its own measurement and reports nothing: callbacks, the host's registry
21
+ * measurement, embedded fonts, asset resolution and tracing are dropped.
22
+ */
23
+ const NOT_RESOLVE_OPTIONS = new Set(["textMeasurement", "embeddedFonts", "fontFiles", "useBundledFonts", "loadSystemFonts", "onDiagnostic", "trace", "glyphFallback", "imageResolver", "strictAssets", "slideIndex", "signal"]);
24
+ function resolveOptionsOf(options) {
25
+ return Object.fromEntries(Object.entries(options ?? {}).filter(([key]) => !NOT_RESOLVE_OPTIONS.has(key)));
26
+ }
27
+
28
+ /**
29
+ * The font families a presentation's slides resolve (heading, body and code roles of every slide, including per-slide
30
+ * design overrides), as `renderSvg` resolves them with the same `options` (`catalogs`, ...). This is the role families,
31
+ * not what is drawn: use `presentationFaces` for that.
32
+ *
33
+ * A document that does not resolve throws the error `renderSvg` throws for it (an OPFRenderError such as
34
+ * `catalog-resolution-failed` for a layout id no catalog has, or `invalid-opf`), never an empty set: a document whose layout comes only from
35
+ * `options.catalogs` needs those catalogs here too.
36
+ */
37
+ export function presentationFamilies(presentation, options = {}) {
15
38
  const families = new Set();
16
- let resolved;
17
- try { resolved = resolvePresentation(presentation, {}); } catch { return families; }
39
+ const resolved = resolvePresentation(presentation, resolveOptionsOf(options));
18
40
  for (const slide of resolved.slides) for (const family of Object.values(slide.design?.fonts ?? {})) if (typeof family === "string" && family) families.add(family);
19
41
  return families;
20
42
  }
21
43
 
44
+ // A measurement that costs nothing to overflow: text is measured as very narrow, so layout never fails on text that
45
+ // only the real faces would fit. Only the styles it is asked about matter.
46
+ const RECORDED_EM = 0.01;
47
+
48
+ /** The registry's view with faces added: what a registry holding `faces` resolves families to (`pickFace`, its own selection). */
49
+ function registryView({ faces, policy = "none", aliases = new Map(), fallbackFamily }) {
50
+ const pool = [...faces].map(face => ({ ...face, familyGroup: face.familyGroup ?? face.family }));
51
+ return style => {
52
+ const family = style?.fontFamily;
53
+ const { face } = pickFace(pool, family, style, { policy, aliases, fallbackFamily });
54
+ return { ...style, fontFamily: face.family, fontWeight: face.weight, italic: face.italic };
55
+ };
56
+ }
57
+
58
+ /**
59
+ * The faces a preview of the presentation draws, as `[{family, weight, italic}]`, sorted by family, style and weight. It is
60
+ * the renderer's own layout and painting run with a recording measurement, so it follows exactly what `renderSvg` measures
61
+ * and draws: the heading and body roles of every slide that draws them, bold and italic runs of rich text, table and cell
62
+ * styles, header and footer furniture, chart labels, metrics, quotes and timelines, the code role only where code is
63
+ * drawn, per-slide design overrides, font scheme and theme resolution, and script slots (a script run is requested in its
64
+ * slot's family). A role the document does not draw is not requested.
65
+ *
66
+ * Without `registry` the faces are the styles as the document names them: the family a role resolves to, with the weight
67
+ * a use asks for (700 for headings and bold runs, 400 for body, 500 to 800 where a design asks).
68
+ *
69
+ * With `registry` (`{faces, policy, aliases, fallbackFamily}`: the faces a registry holds or could hold, `{family, weight,
70
+ * italic}`, and its substitution options) every style resolves as that registry resolves it (`pickFace`, the registry's own
71
+ * selection: the family or its alias or policy replacement, italic before weight, the nearest weight, ties to the
72
+ * lighter), in the two steps drawing takes: a role's family resolves first, then each use's weight resolves within the
73
+ * family found. The result is the faces the registry paints, for example `Intos 700` for a 600-weight label of an Aptos
74
+ * deck. A style the registry cannot resolve is left as named (drawing reports it).
75
+ *
76
+ * `options` are the `renderSvg` options the document resolves with (`catalogs`, `date`, `validate`, ...). A document that
77
+ * does not resolve throws what `renderSvg` throws for it.
78
+ * @param {unknown} presentation
79
+ * @param {object} [options]
80
+ * @param {{faces: Iterable<{family: string, weight: number, italic: boolean}>, policy?: "none"|"metric"|"visual", aliases?: ReadonlyMap<string, string>, fallbackFamily?: string}} [registry]
81
+ * @returns {{family: string, weight: number, italic: boolean}[]}
82
+ */
83
+ export function presentationFaces(presentation, options = {}, registry) {
84
+ const seen = new Map();
85
+ const resolve = registry ? registryView(registry) : undefined;
86
+ const settle = style => {
87
+ if (!resolve) return { ...style };
88
+ try { return resolve(style); } catch { return { ...style }; }
89
+ };
90
+ const record = style => {
91
+ const family = style?.fontFamily;
92
+ if (typeof family !== "string" || !family.trim() || family.startsWith("+")) return;
93
+ const weight = Number.isFinite(style.fontWeight) ? style.fontWeight : 400, italic = style.italic === true;
94
+ const key = `${lc(family)}\u0000${weight}\u0000${italic}`;
95
+ if (!seen.has(key)) seen.set(key, { family, weight, italic });
96
+ };
97
+ const textMeasurement = {
98
+ measure(text, size, style) { if (text !== "") record(settle(style)); return String(text).length * size * RECORDED_EM; },
99
+ resolveStyle: settle,
100
+ };
101
+ renderSvgDeck(presentation, { ...resolveOptionsOf(options), textMeasurement });
102
+ return [...seen.values()].sort((a, b) => a.family < b.family ? -1 : a.family > b.family ? 1 : Number(a.italic) - Number(b.italic) || a.weight - b.weight);
103
+ }
104
+
105
+ /**
106
+ * The vendored faces (of `lazy`) a presentation draws that the registry does not hold: what a registry loads before it can
107
+ * paint the document as Node paints it with every vendored face loaded. `held` lists the registry's faces
108
+ * (`registry.describeFaces()`), `loaded` the lazy files already loaded; `policy`, `aliases` and `fallbackFamily` are the
109
+ * registry's. `renderOptions` are the `renderSvg` options the document resolves with (`catalogs`, ...), and a document that
110
+ * does not resolve throws what `renderSvg` throws for it. Face level: a bold or italic run added by an edit adds just that face.
111
+ */
112
+ export function lazyFacesNeeded(presentation, renderOptions, { lazy, held, loaded = new Set(), policy = "none", aliases = new Map(), fallbackFamily }) {
113
+ const heldFaces = [...held], heldKeys = new Set(heldFaces.map(faceKeyOf));
114
+ const missing = lazy.filter(face => !heldKeys.has(faceKeyOf(face)) && !loaded.has(face.file));
115
+ const drawn = new Set(presentationFaces(presentation, renderOptions, { faces: [...heldFaces, ...missing], policy, aliases, fallbackFamily }).map(faceKeyOf));
116
+ return missing.filter(face => drawn.has(faceKeyOf(face)));
117
+ }
118
+ function faceKeyOf(face) { return `${lc(face.family)}\u0000${face.weight}\u0000${!!face.italic}`; }
119
+
22
120
  /**
23
121
  * The vendored faces a document needs that the registry does not hold, following the registry's own order and substitution
24
122
  * policy: the family itself, an alias target, then (unless the policy is "none") the declared replacement and, under
25
- * "visual", its alternates. The first candidate the registry already has ends the search (it will resolve to that); the
26
- * first vendored candidate is needed, whole family, so the browser resolves exactly what Node resolves with everything
27
- * loaded, and nothing is downloaded for a family the policy would not resolve.
28
- * @param {Iterable<string>} families families the document resolves
29
- * @param {{lazy: readonly object[], hasFamily: (family: string) => boolean, loaded?: ReadonlySet<string>, policy?: "none"|"metric"|"visual", aliases?: ReadonlyMap<string, string>}} context
123
+ * "visual", its alternates.
124
+ *
125
+ * Entries are face requests `{family, weight, italic}` (from `presentationFaces`) or family names. A face request is
126
+ * resolved exactly as the registry resolves it with every vendored face loaded (`pickFace`, the registry's own selection,
127
+ * over the faces it holds plus the vendored ones): the vendored face it lands on is needed if the registry does not hold
128
+ * it, so a partially loaded family still loads its missing faces, and a face is never fetched for a weight or style the
129
+ * document does not draw. A family name means every face of the family the route resolves to (the whole family, as
130
+ * before FF-41). Nothing is downloaded for a family the policy would not resolve.
131
+ * @param {Iterable<string | {family: string, weight?: number, italic?: boolean}>} entries
132
+ * @param {{lazy: readonly object[], held?: Iterable<{family: string, weight: number, italic: boolean}>, hasFamily?: (family: string) => boolean, loaded?: ReadonlySet<string>, policy?: "none"|"metric"|"visual", aliases?: ReadonlyMap<string, string>, fallbackFamily?: string}} context
133
+ * `held` lists the registry's faces (`registry.describeFaces()`); it is what makes the check face level. Without it a face
134
+ * request falls back to family level with `hasFamily` (a held family needs nothing).
30
135
  */
31
- export function lazyFontsFor(families, { lazy, hasFamily, loaded = new Set(), policy = "visual", aliases = new Map() }) {
136
+ export function lazyFontsFor(entries, { lazy, held, hasFamily, loaded = new Set(), policy = "visual", aliases = new Map(), fallbackFamily }) {
32
137
  const byFamily = new Map();
33
138
  for (const face of lazy) { const list = byFamily.get(lc(face.family)) ?? []; list.push(face); byFamily.set(lc(face.family), list); }
34
- const needed = new Set();
35
- for (const family of families) {
36
- if (hasFamily(family)) continue;
37
- if (byFamily.has(lc(family))) { needed.add(lc(family)); continue; }
139
+ const heldFaces = held === undefined ? undefined : [...held];
140
+ const faceKey = face => `${lc(face.family)}\u0000${face.weight}\u0000${!!face.italic}`;
141
+ const heldKeys = new Set((heldFaces ?? []).map(faceKey));
142
+ const has = hasFamily ?? (family => (heldFaces ?? []).some(face => lc(face.family) === lc(family)));
143
+ const needed = new Set(), neededFiles = new Set();
144
+ // Whole families (a family name, or a face request without a face-level registry view).
145
+ const addFamily = family => {
146
+ // A family the registry holds only in part still needs its other vendored faces (face level, when the registry's faces are known).
147
+ if (has(family)) { if (heldFaces && byFamily.has(lc(family))) needed.add(lc(family)); return; }
148
+ if (byFamily.has(lc(family))) { needed.add(lc(family)); return; }
38
149
  const target = aliases.get(lc(family));
39
- if (target && (hasFamily(target) || byFamily.has(lc(target)))) { if (!hasFamily(target)) needed.add(lc(target)); continue; }
40
- if (policy === "none") continue;
150
+ if (target && (has(target) || byFamily.has(lc(target)))) { if (byFamily.has(lc(target)) && (!has(target) || heldFaces)) needed.add(lc(target)); return; }
151
+ if (policy === "none") return;
41
152
  const row = fontPolicyFor(family), replacement = row?.replacement;
42
153
  const route = [];
43
154
  // Metric mode uses a metric replacement, or a visual one its policy row keeps as a metric-mode fallback; alternates are visual only.
44
155
  if (replacement && (policy === "visual" || replacement.compatibility === "metric" || replacement.metricModeFallback)) route.push(replacement.family);
45
156
  if (policy === "visual") route.push(...(row?.alternates ?? []));
46
157
  for (const candidate of route) {
47
- if (hasFamily(candidate)) break;
158
+ if (has(candidate)) { if (heldFaces && byFamily.has(lc(candidate))) needed.add(lc(candidate)); break; }
48
159
  if (byFamily.has(lc(candidate))) { needed.add(lc(candidate)); break; }
49
160
  }
161
+ };
162
+ // The registry's view with every vendored face added: what Node draws with everything loaded.
163
+ let pool;
164
+ const universe = () => pool ??= [
165
+ ...heldFaces.map(face => ({ ...face, familyGroup: face.family })),
166
+ ...lazy.filter(face => !heldKeys.has(faceKey(face)) && !loaded.has(face.file)).map(face => ({ family: face.family, familyGroup: face.family, weight: face.weight, italic: !!face.italic, lazy: face })),
167
+ ];
168
+ for (const entry of entries) {
169
+ if (typeof entry === "string") { addFamily(entry); continue; }
170
+ if (heldFaces === undefined) { addFamily(entry.family); continue; }
171
+ let picked;
172
+ try { picked = pickFace(universe(), entry.family, { fontFamily: entry.family, fontWeight: entry.weight ?? 400, italic: entry.italic === true }, { policy, aliases, fallbackFamily }); }
173
+ // A face the registry cannot resolve even with every vendored face (unknown family, symbol font, ...) needs nothing here: drawing reports it.
174
+ catch { continue; }
175
+ if (picked.face.lazy) neededFiles.add(picked.face.lazy.file);
50
176
  }
51
- return [...needed].flatMap(family => byFamily.get(family)).filter(face => !loaded.has(face.file));
177
+ const all = [...needed].flatMap(family => byFamily.get(family) ?? []);
178
+ for (const face of lazy) if (neededFiles.has(face.file)) all.push(face);
179
+ return [...new Set(all)].filter(face => !loaded.has(face.file) && !heldKeys.has(faceKey(face)));
52
180
  }
@@ -7,6 +7,7 @@ import * as scriptFontModule from "./script-fonts.js";
7
7
  import { scriptOfCharacter, scriptsOfText } from "./script-fonts.js";
8
8
  // Optional core exports are read from the namespace so an older published core still loads.
9
9
  import * as opfCore from "@openpresentation/opf";
10
+ import { presentationFamilies } from "./lazy-fonts.js";
10
11
 
11
12
  const SCRIPT_ALIASES = Object.freeze({Hira: "Jpan", Kana: "Jpan", Hrkt: "Jpan", Hang: "Kore", Hani: "Hans", Zyyy: "Latn"});
12
13
 
@@ -121,8 +122,12 @@ function scriptOfFamily(family) {
121
122
  * open replacement, so the face is needed even when no drawn character has the script. A slide may override the
122
123
  * scheme (`slide.design`), so each such slide is resolved too. `han` is the CJK script the scheme names, which tells
123
124
  * Han-only text apart when the language does not (a Yu Gothic deck whose language is English).
125
+ *
126
+ * `renderOptions` are the host's `renderSvg` options. Core resolves a font scheme id from the document and its bundled catalogs
127
+ * only, while the renderer also reads `renderOptions.catalogs`; when a host passes catalogs the families the renderer resolves
128
+ * per slide count too, so a scheme that exists only in the host's catalogs and names a script font still loads that font.
124
129
  */
125
- function designScripts(presentation, profile) {
130
+ function designScripts(presentation, profile, renderOptions) {
126
131
  const scripts = new Set();
127
132
  let han;
128
133
  const note = resolved => {
@@ -140,6 +145,9 @@ function designScripts(presentation, profile) {
140
145
  try { note(opfCore.resolveScriptFonts(presentation, { slideIndex })); } catch { /* the renderer reports it when it draws the slide */ }
141
146
  });
142
147
  }
148
+ if (renderOptions?.catalogs) {
149
+ for (const family of presentationFamilies(presentation, renderOptions)) note({ heading: { latin: family }, body: { latin: family } });
150
+ }
143
151
  return { scripts: [...scripts].sort(), han };
144
152
  }
145
153
 
@@ -147,10 +155,13 @@ function designScripts(presentation, profile) {
147
155
  * What a preview of the presentation draws: its script profile, the scripts of its text (the renderer's own
148
156
  * itemization, so language-dependent punctuation counts), the scripts its font schemes need (`design`, for example
149
157
  * Jpan for a Yu Gothic scheme) and the CJK characters that a glyph fallback might have to draw with another CJK face.
158
+ * The text decides, so a document is analyzed without resolving its layouts and catalogs; `renderOptions` (the host's
159
+ * `renderSvg` options) matter only for font schemes the host supplies in `renderOptions.catalogs`, which then resolve
160
+ * like the renderer resolves them; a document that then does not resolve throws what `renderSvg` throws for it.
150
161
  */
151
- export function analyzePresentationScripts(presentation, profile = presentationScriptProfile(presentation)) {
162
+ export function analyzePresentationScripts(presentation, profile = presentationScriptProfile(presentation), renderOptions) {
152
163
  const scripts = new Set(), cjk = new Set();
153
- const design = designScripts(presentation, profile);
164
+ const design = designScripts(presentation, profile, renderOptions);
154
165
  // Han-only text in a deck whose language is not CJK draws with the scheme's own CJK face when the scheme names one.
155
166
  const itemizing = design.han && !cjkKeys.includes(profile?.script) ? { ...profile, script: design.han } : profile;
156
167
  for (const text of drawnStrings(presentation)) {
@@ -166,10 +177,10 @@ export function analyzePresentationScripts(presentation, profile = presentationS
166
177
  * (Japanese, Korean, Simplified or Traditional Chinese) and makes curly quotes, dashes and the ellipsis
167
178
  * East Asian. Text the preview never draws (ids, alt text, sources, assets, catalogs, notes) is ignored.
168
179
  * Greek and Cyrillic add nothing: the office registry always carries Noto Sans (the glyph-fallback face) and Roboto covers them.
169
- * Pass `profile` to reuse a resolved profile.
180
+ * Pass `profile` to reuse a resolved profile. Other options are the host's `renderSvg` options (`catalogs`, see `analyzePresentationScripts`).
170
181
  */
171
- export function detectPresentationScripts(presentation, { profile } = {}) {
172
- return analyzePresentationScripts(presentation, profile).detected;
182
+ export function detectPresentationScripts(presentation, { profile, ...renderOptions } = {}) {
183
+ return analyzePresentationScripts(presentation, profile, renderOptions).detected;
173
184
  }
174
185
 
175
186
  /** The scripts of an analysis that a pinned pack serves (`scripts`, the input for `scriptFontPackages`) and those it does not. */
@@ -186,7 +197,8 @@ export function scriptSelectionOf(analysis) {
186
197
  * Cherokee or Tifinagh, which draw with whatever the design font covers).
187
198
  */
188
199
  export function autoScriptSelection(presentation, options) {
189
- return scriptSelectionOf(analyzePresentationScripts(presentation, options?.profile));
200
+ const { profile, ...renderOptions } = options ?? {};
201
+ return scriptSelectionOf(analyzePresentationScripts(presentation, profile, renderOptions));
190
202
  }
191
203
 
192
204
  /**
@@ -0,0 +1,93 @@
1
+ Copyright 2017 The Playfair Display Project Authors (https://github.com/clauseggers/Playfair-Display), with Reserved Font Name "Playfair Display".
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,48 @@
1
+ {
2
+ "upstream": {
3
+ "source": "https://github.com/clauseggers/Playfair/tree/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/fonts/TTF",
4
+ "commit": "6e115d70ee7ff6ed887babf3829ccd1de65fd2bd",
5
+ "licenseUrl": "https://raw.githubusercontent.com/clauseggers/Playfair/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/OFL.txt"
6
+ },
7
+ "license": "OFL-1.1",
8
+ "licenseFile": "OFL.txt",
9
+ "licenseSha256": "e414e07f7a4da16ed47ebec80d52dd79f21d3ca42bc92385a755d8078a038814",
10
+ "reservedFontNames": [
11
+ "Playfair Display"
12
+ ],
13
+ "copyright": "Copyright 2017 The Playfair Display Project Authors (https://github.com/clauseggers/Playfair-Display), with Reserved Font Name \"Playfair Display\".",
14
+ "faces": [
15
+ {
16
+ "file": "PlayfairDisplay-Regular.ttf",
17
+ "family": "Playfair Display",
18
+ "weight": 400,
19
+ "italic": false,
20
+ "sha256": "70ef3ee8de32dc81c39f2733a4a2a050c7e6ba78a2f1632f9d5c6cfd482c3abb",
21
+ "upstreamUrl": "https://raw.githubusercontent.com/clauseggers/Playfair/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/fonts/TTF/PlayfairDisplay-Regular.ttf"
22
+ },
23
+ {
24
+ "file": "PlayfairDisplay-Italic.ttf",
25
+ "family": "Playfair Display",
26
+ "weight": 400,
27
+ "italic": true,
28
+ "sha256": "30a7eb5a9309754d4b3e205e6435ef07d80e1b86735774b2ace427f6ed61f991",
29
+ "upstreamUrl": "https://raw.githubusercontent.com/clauseggers/Playfair/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/fonts/TTF/PlayfairDisplay-Italic.ttf"
30
+ },
31
+ {
32
+ "file": "PlayfairDisplay-Bold.ttf",
33
+ "family": "Playfair Display",
34
+ "weight": 700,
35
+ "italic": false,
36
+ "sha256": "898a01a59214578e72012131ef4c346844c1fd35613f4ee113a37d61a094a2d0",
37
+ "upstreamUrl": "https://raw.githubusercontent.com/clauseggers/Playfair/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/fonts/TTF/PlayfairDisplay-Bold.ttf"
38
+ },
39
+ {
40
+ "file": "PlayfairDisplay-BoldItalic.ttf",
41
+ "family": "Playfair Display",
42
+ "weight": 700,
43
+ "italic": true,
44
+ "sha256": "bd3b48ca605438de4337d05ece1ecb9e4149a975d3207174f28e02098bbec3ff",
45
+ "upstreamUrl": "https://raw.githubusercontent.com/clauseggers/Playfair/6e115d70ee7ff6ed887babf3829ccd1de65fd2bd/fonts/TTF/PlayfairDisplay-BoldItalic.ttf"
46
+ }
47
+ ]
48
+ }
@@ -0,0 +1,93 @@
1
+ Copyright 2010 The Raleway Project Authors (impallari@gmail.com), with Reserved Font Name "Raleway".
2
+
3
+ This Font Software is licensed under the SIL Open Font License, Version 1.1.
4
+ This license is copied below, and is also available with a FAQ at:
5
+ http://scripts.sil.org/OFL
6
+
7
+
8
+ -----------------------------------------------------------
9
+ SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
10
+ -----------------------------------------------------------
11
+
12
+ PREAMBLE
13
+ The goals of the Open Font License (OFL) are to stimulate worldwide
14
+ development of collaborative font projects, to support the font creation
15
+ efforts of academic and linguistic communities, and to provide a free and
16
+ open framework in which fonts may be shared and improved in partnership
17
+ with others.
18
+
19
+ The OFL allows the licensed fonts to be used, studied, modified and
20
+ redistributed freely as long as they are not sold by themselves. The
21
+ fonts, including any derivative works, can be bundled, embedded,
22
+ redistributed and/or sold with any software provided that any reserved
23
+ names are not used by derivative works. The fonts and derivatives,
24
+ however, cannot be released under any other type of license. The
25
+ requirement for fonts to remain under this license does not apply
26
+ to any document created using the fonts or their derivatives.
27
+
28
+ DEFINITIONS
29
+ "Font Software" refers to the set of files released by the Copyright
30
+ Holder(s) under this license and clearly marked as such. This may
31
+ include source files, build scripts and documentation.
32
+
33
+ "Reserved Font Name" refers to any names specified as such after the
34
+ copyright statement(s).
35
+
36
+ "Original Version" refers to the collection of Font Software components as
37
+ distributed by the Copyright Holder(s).
38
+
39
+ "Modified Version" refers to any derivative made by adding to, deleting,
40
+ or substituting -- in part or in whole -- any of the components of the
41
+ Original Version, by changing formats or by porting the Font Software to a
42
+ new environment.
43
+
44
+ "Author" refers to any designer, engineer, programmer, technical
45
+ writer or other person who contributed to the Font Software.
46
+
47
+ PERMISSION & CONDITIONS
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of the Font Software, to use, study, copy, merge, embed, modify,
50
+ redistribute, and sell modified and unmodified copies of the Font
51
+ Software, subject to the following conditions:
52
+
53
+ 1) Neither the Font Software nor any of its individual components,
54
+ in Original or Modified Versions, may be sold by itself.
55
+
56
+ 2) Original or Modified Versions of the Font Software may be bundled,
57
+ redistributed and/or sold with any software, provided that each copy
58
+ contains the above copyright notice and this license. These can be
59
+ included either as stand-alone text files, human-readable headers or
60
+ in the appropriate machine-readable metadata fields within text or
61
+ binary files as long as those fields can be easily viewed by the user.
62
+
63
+ 3) No Modified Version of the Font Software may use the Reserved Font
64
+ Name(s) unless explicit written permission is granted by the corresponding
65
+ Copyright Holder. This restriction only applies to the primary font name as
66
+ presented to the users.
67
+
68
+ 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
69
+ Software shall not be used to promote, endorse or advertise any
70
+ Modified Version, except to acknowledge the contribution(s) of the
71
+ Copyright Holder(s) and the Author(s) or with their explicit written
72
+ permission.
73
+
74
+ 5) The Font Software, modified or unmodified, in part or in whole,
75
+ must be distributed entirely under this license, and must not be
76
+ distributed under any other license. The requirement for fonts to
77
+ remain under this license does not apply to any document created
78
+ using the Font Software.
79
+
80
+ TERMINATION
81
+ This license becomes null and void if any of the above conditions are
82
+ not met.
83
+
84
+ DISCLAIMER
85
+ THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
86
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
87
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
88
+ OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
89
+ COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
90
+ INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
91
+ DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
92
+ FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
93
+ OTHER DEALINGS IN THE FONT SOFTWARE.
@@ -0,0 +1,48 @@
1
+ {
2
+ "upstream": {
3
+ "source": "https://github.com/googlefonts/Raleway/tree/7e0be846a3097743b9bf442eb8e65bc1fd96c934/fonts/TTF",
4
+ "commit": "7e0be846a3097743b9bf442eb8e65bc1fd96c934",
5
+ "licenseUrl": "https://raw.githubusercontent.com/googlefonts/Raleway/7e0be846a3097743b9bf442eb8e65bc1fd96c934/OFL.txt"
6
+ },
7
+ "license": "OFL-1.1",
8
+ "licenseFile": "OFL.txt",
9
+ "licenseSha256": "7e946cf1171784d1015279e7dc35f827957a6b5d1f1f659ae0c98e5f5e37ed9b",
10
+ "reservedFontNames": [
11
+ "Raleway"
12
+ ],
13
+ "copyright": "Copyright 2010 The Raleway Project Authors (impallari@gmail.com), with Reserved Font Name \"Raleway\".",
14
+ "faces": [
15
+ {
16
+ "file": "Raleway-Regular.ttf",
17
+ "family": "Raleway",
18
+ "weight": 400,
19
+ "italic": false,
20
+ "sha256": "cb70f8815eecd850263d54fa59286377b1d7362bec612e981155a00039d8b513",
21
+ "upstreamUrl": "https://raw.githubusercontent.com/googlefonts/Raleway/7e0be846a3097743b9bf442eb8e65bc1fd96c934/fonts/TTF/Raleway-Regular.ttf"
22
+ },
23
+ {
24
+ "file": "Raleway-Italic.ttf",
25
+ "family": "Raleway",
26
+ "weight": 400,
27
+ "italic": true,
28
+ "sha256": "63f52b6d8e88afa43d94162147ff55846f28af630d834018de5cb7ccc75a8ee8",
29
+ "upstreamUrl": "https://raw.githubusercontent.com/googlefonts/Raleway/7e0be846a3097743b9bf442eb8e65bc1fd96c934/fonts/TTF/Raleway-Italic.ttf"
30
+ },
31
+ {
32
+ "file": "Raleway-Bold.ttf",
33
+ "family": "Raleway",
34
+ "weight": 700,
35
+ "italic": false,
36
+ "sha256": "6894481ab1c298e9c66f23455ecf05ccb25393d719a6b2d63428358c0409d2d0",
37
+ "upstreamUrl": "https://raw.githubusercontent.com/googlefonts/Raleway/7e0be846a3097743b9bf442eb8e65bc1fd96c934/fonts/TTF/Raleway-Bold.ttf"
38
+ },
39
+ {
40
+ "file": "Raleway-BoldItalic.ttf",
41
+ "family": "Raleway",
42
+ "weight": 700,
43
+ "italic": true,
44
+ "sha256": "57eb1a701136eca30b52a4847edcec93daa53f0b5597dd98dbc0b07f475ce44a",
45
+ "upstreamUrl": "https://raw.githubusercontent.com/googlefonts/Raleway/7e0be846a3097743b9bf442eb8e65bc1fd96c934/fonts/TTF/Raleway-BoldItalic.ttf"
46
+ }
47
+ ]
48
+ }
Binary file
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpresentation/opf-render",
3
- "version": "0.11.3",
3
+ "version": "0.11.5",
4
4
  "description": "Deterministic local OPF renderer for SVG, PNG, and PDF output.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -56,9 +56,9 @@
56
56
  "sideEffects": false,
57
57
  "scripts": {
58
58
  "build": "node scripts/build.mjs",
59
- "typecheck": "node --check src/index.js && node --check scripts/build.mjs && node --check scripts/validate-package.mjs && node --check test/smoke.mjs && node --check test/golden.mjs && node --check src/fonts.js && node --check src/script-fonts.js && node --check src/script-font-pack.js && node --check test/script-fonts.mjs && node --check test/glyph-fallback.mjs && node --check test/script-fonts-browser.mjs && node --check test/script-fonts-auto.mjs && node --check test/script-fonts-auto-robust.mjs && node --check test/script-fonts-auto-browser.mjs && node --check src/fonts-node.js && node --check src/font-compatibility.js && node --check test/office-fonts.mjs && node --check test/font-policy.mjs && node --check test/open-fonts.mjs && node --check test/aptos-preview.mjs && node --check test/aptos-preview-browser.mjs && node --check test/lazy-fonts.mjs && node --check test/lazy-fonts-browser.mjs && node --check test/lazy-face-fallback.mjs && node --check test/lazy-face-fallback-browser.mjs && node --check src/font-policy.js && node --check scripts/update-font-policy.mjs && node --check src/fonts-browser.js && node --check test/fonts-browser.mjs && node --check src/svg.js && node --check src/raster.js && node --check src/raster-images.js && node --check test/webp.mjs && node --check test/jpeg-orientation.mjs && node --check scripts/build-browser-check.mjs && node --check test/jpeg-browser.js && node --check test/rich-table.mjs && node --check test/rich-tab.mjs && node --check test/rich-tab-browser.mjs && node --check test/rich-tab-estimated-browser.mjs && node --check test/styled-table.mjs && node --check test/color-references.mjs && node --check test/default-font-scheme.mjs && node --check test/chart-colors.mjs && node --check test/chart-axis.mjs && node --check src/charts.js && node --check test/chart-types.mjs && node --check test/chart-scale.mjs && node --check test/chart-catalog.mjs && node --check test/image-placeholders.mjs && node --check test/image-placeholders-browser.mjs && node --check test/accepted-text.mjs && node --check test/accepted-text-fixtures.mjs && node --check test/accepted-text-browser.mjs && node --check test/rich-spacing-browser.mjs && node --check test/rich-flow-browser.mjs && node --check test/rich-flow-review-sheets.mjs && node --check test/furniture.mjs && node --check test/socials.mjs && node --check test/slide-image.mjs && node --check test/slide-image-treatments.mjs && node --check test/item-alignment.mjs && node --check test/cover-centering.mjs && node --check scripts/font-license.mjs && node --check test/font-licenses.mjs && node --check scripts/check-font-hotlinks.mjs && node --check scripts/check-font-hotlinks.test.mjs",
59
+ "typecheck": "node --check src/index.js && node --check scripts/build.mjs && node --check scripts/validate-package.mjs && node --check test/smoke.mjs && node --check test/golden.mjs && node --check src/fonts.js && node --check src/script-fonts.js && node --check src/script-font-pack.js && node --check test/script-fonts.mjs && node --check test/glyph-fallback.mjs && node --check test/script-fonts-browser.mjs && node --check test/script-fonts-auto.mjs && node --check test/script-fonts-auto-robust.mjs && node --check test/mongolian-shaping.mjs && node --check test/script-fonts-auto-browser.mjs && node --check src/fonts-node.js && node --check src/font-compatibility.js && node --check test/office-fonts.mjs && node --check test/font-policy.mjs && node --check test/open-fonts.mjs && node --check test/aptos-preview.mjs && node --check test/aptos-preview-browser.mjs && node --check test/lazy-fonts.mjs && node --check test/lazy-faces.mjs && node --check test/lazy-fonts-browser.mjs && node --check test/lazy-face-fallback.mjs && node --check test/lazy-face-fallback-browser.mjs && node --check src/font-policy.js && node --check scripts/update-font-policy.mjs && node --check src/fonts-browser.js && node --check test/fonts-browser.mjs && node --check src/svg.js && node --check src/raster.js && node --check src/raster-images.js && node --check test/webp.mjs && node --check test/jpeg-orientation.mjs && node --check scripts/build-browser-check.mjs && node --check test/jpeg-browser.js && node --check test/rich-table.mjs && node --check test/rich-tab.mjs && node --check test/rich-tab-browser.mjs && node --check test/rich-tab-estimated-browser.mjs && node --check test/styled-table.mjs && node --check test/color-references.mjs && node --check test/default-font-scheme.mjs && node --check test/chart-colors.mjs && node --check test/chart-axis.mjs && node --check src/charts.js && node --check test/chart-types.mjs && node --check test/chart-scale.mjs && node --check test/chart-catalog.mjs && node --check test/image-placeholders.mjs && node --check test/image-placeholders-browser.mjs && node --check test/accepted-text.mjs && node --check test/accepted-text-fixtures.mjs && node --check test/accepted-text-browser.mjs && node --check test/rich-spacing-browser.mjs && node --check test/rich-flow-browser.mjs && node --check test/rich-flow-review-sheets.mjs && node --check test/furniture.mjs && node --check test/socials.mjs && node --check test/slide-image.mjs && node --check test/slide-image-treatments.mjs && node --check test/item-alignment.mjs && node --check test/cover-centering.mjs && node --check scripts/font-license.mjs && node --check test/font-licenses.mjs && node --check scripts/check-font-hotlinks.mjs && node --check scripts/check-font-hotlinks.test.mjs && node --check test/gallery-layout-alignment.mjs",
60
60
  "validate": "node scripts/validate-package.mjs",
61
- "test": "npm run build && npm run check:fonts && node test/furniture.mjs && node test/socials.mjs && node test/font-outlines.mjs && node test/accepted-text.mjs && node test/image-placeholders.mjs && node test/slide-image.mjs && node test/slide-image-treatments.mjs && node test/chart-colors.mjs && node test/chart-axis.mjs && node test/chart-types.mjs && node test/chart-scale.mjs && node test/chart-catalog.mjs && node test/smoke.mjs && node test/webp.mjs && node test/jpeg-orientation.mjs && node test/fonts.mjs && node test/office-fonts.mjs && node test/font-policy.mjs && node test/open-fonts.mjs && node test/aptos-preview.mjs && node test/lazy-fonts.mjs && node test/lazy-face-fallback.mjs && node test/timeline.mjs && node test/quote-footer.mjs && node test/shared-quote.mjs && node test/rich-trace.mjs && node test/rich-table.mjs && node test/rich-tab.mjs && node test/color-references.mjs && node test/default-font-scheme.mjs && node test/golden-gate.mjs && node test/golden.mjs && node test/fonts-browser.mjs && node test/script-fonts.mjs && node test/glyph-fallback.mjs && node test/script-fonts-auto.mjs && node test/script-fonts-auto-robust.mjs && node test/design-preview.mjs && node test/item-alignment.mjs && node test/cover-centering.mjs && npm run build:browser-check && npm run test:styled-table",
61
+ "test": "npm run build && npm run check:fonts && node test/furniture.mjs && node test/socials.mjs && node test/font-outlines.mjs && node test/accepted-text.mjs && node test/image-placeholders.mjs && node test/slide-image.mjs && node test/slide-image-treatments.mjs && node test/chart-colors.mjs && node test/chart-axis.mjs && node test/chart-types.mjs && node test/chart-scale.mjs && node test/chart-catalog.mjs && node test/smoke.mjs && node test/webp.mjs && node test/jpeg-orientation.mjs && node test/fonts.mjs && node test/office-fonts.mjs && node test/font-policy.mjs && node test/open-fonts.mjs && node test/aptos-preview.mjs && node test/lazy-fonts.mjs && node test/lazy-faces.mjs && node test/lazy-face-fallback.mjs && node test/timeline.mjs && node test/quote-footer.mjs && node test/shared-quote.mjs && node test/rich-trace.mjs && node test/rich-table.mjs && node test/rich-tab.mjs && node test/color-references.mjs && node test/default-font-scheme.mjs && node test/golden-gate.mjs && node test/golden.mjs && node test/fonts-browser.mjs && node test/script-fonts.mjs && node test/glyph-fallback.mjs && node test/script-fonts-auto.mjs && node test/script-fonts-auto-robust.mjs && node test/mongolian-shaping.mjs && node test/design-preview.mjs && node test/item-alignment.mjs && node test/gallery-layout-alignment.mjs && node test/cover-centering.mjs && npm run build:browser-check && npm run test:styled-table",
62
62
  "check:fonts": "node test/font-licenses.mjs && npm run check:font-hotlinks",
63
63
  "check:font-hotlinks": "node --test scripts/check-font-hotlinks.test.mjs && node scripts/check-font-hotlinks.mjs",
64
64
  "test:golden": "npm run build && node test/golden.mjs",