@superdoc-dev/fonts 0.2.0 → 0.3.0
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/LICENSE +661 -0
- package/README.md +19 -82
- package/assets/LICENSES.md +21 -1
- package/assets/OFL.txt +11 -3
- package/dist/cdn-entry.d.ts +1 -1
- package/dist/cdn-entry.js +7 -7
- package/dist/curation.d.ts +1 -0
- package/dist/curation.js +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/superdoc-fonts.min.js +1 -1
- package/dist/superdoc-fonts.min.js.map +1 -1
- package/package.json +16 -6
- package/src/cdn-entry.test.ts +3 -3
- package/src/cdn-entry.ts +7 -7
- package/src/curation.ts +5 -4
- package/src/index.test.ts +1 -1
- package/src/index.ts +6 -6
package/README.md
CHANGED
|
@@ -1,99 +1,36 @@
|
|
|
1
|
-
# @superdoc
|
|
1
|
+
# @superdoc/fonts
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
proprietary font (Carlito for Calibri, Liberation Serif for Times New Roman, and so on). This
|
|
5
|
-
package holds the `.woff2` binaries and hands SuperDoc a URL for each face that your bundler
|
|
6
|
-
emits and rewrites automatically.
|
|
3
|
+
Optional font substitutes for SuperDoc, including Carlito for Calibri, Caladea for Cambria, and Liberation Serif for Times New Roman. The package contains WOFF2 assets and their license texts.
|
|
7
4
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
## Why a separate package
|
|
13
|
-
|
|
14
|
-
The pack is about 6 MB of font binaries. Keeping it out of the `superdoc` core means the core
|
|
15
|
-
stays small, and apps that do not need the fallbacks do not pay for them. The faces still load
|
|
16
|
-
lazily in the browser: only the few a document actually uses are fetched.
|
|
17
|
-
|
|
18
|
-
## Usage
|
|
5
|
+
```sh
|
|
6
|
+
npm install superdoc @superdoc/fonts
|
|
7
|
+
```
|
|
19
8
|
|
|
20
9
|
```js
|
|
21
10
|
import { SuperDoc } from 'superdoc';
|
|
22
|
-
import
|
|
11
|
+
import 'superdoc/style.css';
|
|
12
|
+
import { superdocFonts } from '@superdoc/fonts';
|
|
23
13
|
|
|
24
|
-
new SuperDoc({
|
|
14
|
+
const superdoc = new SuperDoc({
|
|
25
15
|
selector: '#editor',
|
|
26
|
-
document: '
|
|
27
|
-
fonts:
|
|
16
|
+
document: '/sample.docx',
|
|
17
|
+
fonts: superdocFonts,
|
|
28
18
|
});
|
|
29
19
|
```
|
|
30
20
|
|
|
31
|
-
|
|
21
|
+
Create an element with `id="editor"` and serve your document at `/sample.docx`. Your bundler resolves the package's font URLs; no manual font copy step is needed. SuperDoc loads the faces needed by the document. Allow their served origin in your Content Security Policy and configure CORS when serving them from another origin.
|
|
32
22
|
|
|
33
|
-
|
|
34
|
-
import { superdocFonts } from '@superdoc-dev/fonts';
|
|
23
|
+
For plain script integrations, load the version-pinned `dist/superdoc-fonts.min.js` browser build and pass `SuperDocFonts.superdocFonts`. Keep the package's `assets/` directory beside `dist/` when self-hosting it.
|
|
35
24
|
|
|
36
|
-
|
|
37
|
-
```
|
|
25
|
+
The pack supplies substitutes, not proprietary Microsoft font files, and does not cover every family. It does not guarantee identical Word rendering. Inspect `superdoc.fonts.getReport()` and compare line and page breaks for your documents. Use licensed original files through `fonts.families` when needed.
|
|
38
26
|
|
|
39
|
-
|
|
40
|
-
written as `new URL('../assets/<file>', import.meta.url)`, which Vite, Webpack 5, Next, Nuxt,
|
|
41
|
-
esbuild, and Parcel all detect, emit, and rewrite to the final hashed path.
|
|
27
|
+
## Migrating from @superdoc-dev/fonts
|
|
42
28
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
same API, and the faces resolve relative to the script, so there is no bundler and no path config:
|
|
47
|
-
|
|
48
|
-
```html
|
|
49
|
-
<script src="https://cdn.jsdelivr.net/npm/superdoc/dist/superdoc.min.js"></script>
|
|
50
|
-
<script src="https://cdn.jsdelivr.net/npm/@superdoc-dev/fonts/dist/superdoc-fonts.min.js"></script>
|
|
51
|
-
<script>
|
|
52
|
-
new SuperDoc({
|
|
53
|
-
selector: '#editor',
|
|
54
|
-
document: 'contract.docx',
|
|
55
|
-
fonts: SuperDocFonts.superdocFonts, // or SuperDocFonts.createSuperDocFonts({ exclude: [...] })
|
|
56
|
-
});
|
|
57
|
-
</script>
|
|
29
|
+
```sh
|
|
30
|
+
npm uninstall @superdoc-dev/fonts
|
|
31
|
+
npm install @superdoc/fonts
|
|
58
32
|
```
|
|
59
33
|
|
|
60
|
-
|
|
61
|
-
works too: keep the package's `dist/` and `assets/` in their relative layout, since the faces resolve
|
|
62
|
-
to `../assets/` next to `superdoc-fonts.min.js`.
|
|
63
|
-
|
|
64
|
-
### Choosing which fonts
|
|
65
|
-
|
|
66
|
-
`superdocFonts` enables every reviewed family. To narrow the set, use `createSuperDocFonts` and name
|
|
67
|
-
the families by their Word name (`Calibri`, not the substitute `Carlito`):
|
|
68
|
-
|
|
69
|
-
```js
|
|
70
|
-
import { createSuperDocFonts } from '@superdoc-dev/fonts';
|
|
71
|
-
|
|
72
|
-
// Everything except a couple:
|
|
73
|
-
new SuperDoc({ selector: '#editor', document, fonts: createSuperDocFonts({ exclude: ['Cooper Black'] }) });
|
|
74
|
-
|
|
75
|
-
// Or only an explicit set:
|
|
76
|
-
new SuperDoc({ selector: '#editor', document, fonts: createSuperDocFonts({ include: ['Calibri', 'Cambria'] }) });
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
`include` is an allow-list; `exclude` keeps everything but the named families. Curation drives the
|
|
80
|
-
toolbar list and which families SuperDoc substitutes. Your own licensed fonts stay separate
|
|
81
|
-
(`fonts.families`).
|
|
82
|
-
|
|
83
|
-
### Hosting the assets another way
|
|
84
|
-
|
|
85
|
-
If you serve the fonts from a CDN or a signed path instead, you do not need this package's
|
|
86
|
-
resolver. Point SuperDoc at your location with `fonts.assetBaseUrl` or your own
|
|
87
|
-
`fonts.resolveAssetUrl`.
|
|
88
|
-
|
|
89
|
-
## Versioning
|
|
90
|
-
|
|
91
|
-
`@superdoc-dev/fonts` and `superdoc` version independently, but they share the bundled font set.
|
|
92
|
-
Update them together. If the two drift, the resolver throws on an unknown face filename rather
|
|
93
|
-
than degrading silently, so a mismatch surfaces immediately instead of turning into a missing
|
|
94
|
-
font at render time.
|
|
95
|
-
|
|
96
|
-
## Licenses
|
|
34
|
+
For prereleases, install `@superdoc/fonts@next`.
|
|
97
35
|
|
|
98
|
-
|
|
99
|
-
in `assets/`.
|
|
36
|
+
Change imports from `@superdoc-dev/fonts` to `@superdoc/fonts`. The `superdocFonts`, `createSuperDocFonts`, and `resolveBundledFontAssetUrl` exports retain the same usage. Update CDN or self-hosted paths too, and avoid loading both packages. New stable releases retain the old name as a deprecated compatibility mirror; existing installations keep working.
|
package/assets/LICENSES.md
CHANGED
|
@@ -15,6 +15,9 @@ provenance on 2026-06-10. TeX Gyre Bonum was added from CTAN TeX Gyre
|
|
|
15
15
|
provenance on 2026-06-10. URW Gothic and Selawik were added from DocFonts
|
|
16
16
|
corpus provenance on 2026-06-10._
|
|
17
17
|
|
|
18
|
+
_Noto Sans Symbols 2 was added from the official notofonts/symbols v2.008
|
|
19
|
+
release on 2026-08-18 as SuperDoc's core Unicode-symbol fallback._
|
|
20
|
+
|
|
18
21
|
## Scope (read first)
|
|
19
22
|
|
|
20
23
|
This record applies to the font software listed below **in every form in which
|
|
@@ -61,6 +64,7 @@ Machine-readable asset metadata: `font-assets.manifest.json`.
|
|
|
61
64
|
| Cardo | Garamond | OFL-1.1 | none | Regular 1.0451; Bold 1.0011; Italic 0.991 | google/fonts c89741abbf4eeabce432c3ed2fd7dc28b022701e, ofl/cardo |
|
|
62
65
|
| Comic Relief | Comic Sans MS | OFL-1.1 | none | 1.200 | google/fonts c89741abbf4eeabce432c3ed2fd7dc28b022701e, ofl/comicrelief |
|
|
63
66
|
| Noto Sans | Tahoma | OFL-1.1 | none | 2.015 | google/fonts c89741abbf4eeabce432c3ed2fd7dc28b022701e, ofl/notosans |
|
|
67
|
+
| Noto Sans Symbols 2 | Unicode symbols | OFL-1.1 | none | 2.008 | github.com/notofonts/symbols release v2.008 |
|
|
64
68
|
| Selawik | Segoe UI | OFL-1.1 | "Selawik" | 1.01 | github.com/microsoft/Selawik release 1.01 |
|
|
65
69
|
| Noto Sans Mono | Lucida Console | OFL-1.1 | none | 2.014 | google/fonts c89741abbf4eeabce432c3ed2fd7dc28b022701e, ofl/notosansmono |
|
|
66
70
|
| Inconsolata SemiExpanded | Consolas | OFL-1.1 | none | 3.001 | google/fonts c89741abbf4eeabce432c3ed2fd7dc28b022701e, ofl/inconsolata/static |
|
|
@@ -197,6 +201,16 @@ License description: This Font Software is licensed under the SIL Open Font Lice
|
|
|
197
201
|
|
|
198
202
|
No OFL Reserved Font Name is declared in these files.
|
|
199
203
|
|
|
204
|
+
**Noto Sans Symbols 2** - OFL-1.1
|
|
205
|
+
|
|
206
|
+
```text
|
|
207
|
+
Copyright 2022 The Noto Project Authors (https://github.com/notofonts/symbols)
|
|
208
|
+
License description: This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
This copyright notice comes from the official release's `OFL.txt`. No OFL
|
|
212
|
+
Reserved Font Name is declared there.
|
|
213
|
+
|
|
200
214
|
**Selawik** - OFL-1.1
|
|
201
215
|
|
|
202
216
|
```text
|
|
@@ -259,6 +273,12 @@ weights. Noto Sans and Noto Sans Mono are also instanced at normal width. These
|
|
|
259
273
|
instances keep the upstream family and license notices, omit WOFF2 metadata, and
|
|
260
274
|
are not subsetted.
|
|
261
275
|
|
|
276
|
+
Noto Sans Symbols 2 is an unmodified, non-subset format conversion from the
|
|
277
|
+
v2.008 release's unhinted TrueType source. Its source SHA-256 is
|
|
278
|
+
`c4a0a80f0041ce4be81e2478faad22776d23edb98ae3f0d19bd37044820ecf9d`; the
|
|
279
|
+
distributed WOFF2 SHA-256 is
|
|
280
|
+
`39029a9928c61b81e63d3e2f3428da05984b970aa47fb3cb022dab5068fa6d61`.
|
|
281
|
+
|
|
262
282
|
Because the static-source font data is unchanged except for WOFF2 compression
|
|
263
283
|
and the metadata block is omitted, those conversions are **not "Modified
|
|
264
284
|
Versions"** under OFL-1.1 (OFL FAQ 2.2.1) and lawfully retain the original font
|
|
@@ -293,7 +313,7 @@ change.
|
|
|
293
313
|
|
|
294
314
|
- OFL-1.1 (Carlito, Liberation, Caprasimo, Archivo Black, Bacasime Antique,
|
|
295
315
|
Oregano Italic, Gelasio, Cardo, Comic Relief, Noto Sans, Selawik, Noto Sans
|
|
296
|
-
Mono, Inconsolata SemiExpanded, PT Sans, PT Sans Narrow): `OFL.txt` in this
|
|
316
|
+
Mono, Inconsolata SemiExpanded, PT Sans, PT Sans Narrow, Noto Sans Symbols 2): `OFL.txt` in this
|
|
297
317
|
directory. The copyright notices above are also stacked at the top of that
|
|
298
318
|
file.
|
|
299
319
|
- Apache-2.0 (Caladea): `Apache-2.0.txt` in this directory.
|
package/assets/OFL.txt
CHANGED
|
@@ -4,9 +4,11 @@ This is the license text covering the OFL-1.1 fonts bundled in this directory
|
|
|
4
4
|
(Carlito, Liberation Sans, Liberation Serif, Liberation Mono, Caprasimo,
|
|
5
5
|
Bacasime Antique, Oregano Italic, Gelasio, Cardo, Comic Relief, Noto Sans,
|
|
6
6
|
Selawik, Noto Sans Mono, Inconsolata SemiExpanded, PT Sans, Archivo Black, PT
|
|
7
|
-
Sans Narrow). Copyright notices and any Reserved Font Name
|
|
8
|
-
are reproduced
|
|
9
|
-
|
|
7
|
+
Sans Narrow, Noto Sans Symbols 2). Copyright notices and any Reserved Font Name
|
|
8
|
+
statements are reproduced below so they travel with this license text. The
|
|
9
|
+
existing notices came from the fonts' own name tables; the Noto Sans Symbols 2
|
|
10
|
+
notice came from its official release OFL.txt. LICENSES.md restates them for
|
|
11
|
+
convenience.
|
|
10
12
|
Official OFL text: https://openfontlicense.org/open-font-license-official-text/
|
|
11
13
|
|
|
12
14
|
-----------------------------------------------------------
|
|
@@ -71,6 +73,12 @@ Noto Sans:
|
|
|
71
73
|
Licensed under the SIL Open Font License, Version 1.1.
|
|
72
74
|
(These v2.015 files declare no OFL Reserved Font Name.)
|
|
73
75
|
|
|
76
|
+
Noto Sans Symbols 2:
|
|
77
|
+
Copyright 2022 The Noto Project Authors
|
|
78
|
+
(https://github.com/notofonts/symbols)
|
|
79
|
+
Licensed under the SIL Open Font License, Version 1.1.
|
|
80
|
+
(This v2.008 file declares no OFL Reserved Font Name.)
|
|
81
|
+
|
|
74
82
|
Selawik:
|
|
75
83
|
© 2015 Microsoft Corporation (www.microsoft.com), with Reserved Font Name
|
|
76
84
|
"Selawik". Selawik is a trademark of Microsoft Corporation in the United
|
package/dist/cdn-entry.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type BundledFontAssetContext, type SuperDocFontsConfig, type SuperDocFontsOptions } from './curation.js';
|
|
2
2
|
/**
|
|
3
3
|
* Resolve a bundled face filename to a URL relative to THIS script. Throws on an unknown file
|
|
4
|
-
* (a version mismatch between `@superdoc
|
|
4
|
+
* (a version mismatch between `@superdoc/fonts` and `superdoc`) and on a missing script URL,
|
|
5
5
|
* matching the bundler entry's fail-loud-not-silent contract.
|
|
6
6
|
*
|
|
7
7
|
* @beta
|
package/dist/cdn-entry.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser / `<script>` (IIFE) entry for `@superdoc
|
|
2
|
+
* Browser / `<script>` (IIFE) entry for `@superdoc/fonts`, built to
|
|
3
3
|
* `dist/superdoc-fonts.min.js` and exposed as the `SuperDocFonts` global.
|
|
4
4
|
*
|
|
5
5
|
* Unlike the bundler entry ({@link "./index"}), it resolves the `.woff2` relative to its OWN
|
|
6
6
|
* `<script>` (`document.currentScript`) instead of `import.meta.url`, so a plain CDN / self-host
|
|
7
7
|
* `<script>` tag works with no bundler:
|
|
8
8
|
*
|
|
9
|
-
* <script src="https://cdn.jsdelivr.net/npm/superdoc/dist/superdoc.min.js"></script>
|
|
10
|
-
* <script src="https://cdn.jsdelivr.net/npm/@superdoc
|
|
9
|
+
* <script src="https://cdn.jsdelivr.net/npm/superdoc@next/dist-cdn/superdoc.min.js"></script>
|
|
10
|
+
* <script src="https://cdn.jsdelivr.net/npm/@superdoc/fonts/dist/superdoc-fonts.min.js"></script>
|
|
11
11
|
* <script>
|
|
12
12
|
* new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: SuperDocFonts.superdocFonts });
|
|
13
13
|
* </script>
|
|
@@ -30,19 +30,19 @@ const SCRIPT_SRC = currentScript?.src ?? '';
|
|
|
30
30
|
const KNOWN_FILES = new Set(BUNDLED_FONT_FILES);
|
|
31
31
|
/**
|
|
32
32
|
* Resolve a bundled face filename to a URL relative to THIS script. Throws on an unknown file
|
|
33
|
-
* (a version mismatch between `@superdoc
|
|
33
|
+
* (a version mismatch between `@superdoc/fonts` and `superdoc`) and on a missing script URL,
|
|
34
34
|
* matching the bundler entry's fail-loud-not-silent contract.
|
|
35
35
|
*
|
|
36
36
|
* @beta
|
|
37
37
|
*/
|
|
38
38
|
export function resolveBundledFontAssetUrl(context) {
|
|
39
39
|
if (!KNOWN_FILES.has(context.file)) {
|
|
40
|
-
throw new Error(`[@superdoc
|
|
41
|
-
`${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc
|
|
40
|
+
throw new Error(`[@superdoc/fonts] no bundled asset for "${context.file}". This pack ships ` +
|
|
41
|
+
`${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc/fonts and ` +
|
|
42
42
|
`superdoc are likely version-mismatched. Align their versions.`);
|
|
43
43
|
}
|
|
44
44
|
if (!SCRIPT_SRC) {
|
|
45
|
-
throw new Error('[@superdoc
|
|
45
|
+
throw new Error('[@superdoc/fonts] could not determine the script URL to resolve bundled fonts from. ' +
|
|
46
46
|
'Load superdoc-fonts.min.js with a normal <script src="..."> tag.');
|
|
47
47
|
}
|
|
48
48
|
return new URL(`../assets/${context.file}`, SCRIPT_SRC).href;
|
package/dist/curation.d.ts
CHANGED
package/dist/curation.js
CHANGED
|
@@ -18,7 +18,7 @@ export function resolveCuration(options = {}) {
|
|
|
18
18
|
// wins. Reject at the API boundary (this runs in the consumer's setup code, so it fails fast and
|
|
19
19
|
// clearly) rather than picking one arbitrarily.
|
|
20
20
|
if (include && exclude) {
|
|
21
|
-
throw new Error('[@superdoc
|
|
21
|
+
throw new Error('[@superdoc/fonts] createSuperDocFonts: pass `include` OR `exclude`, not both. ' +
|
|
22
22
|
'`include` is an allow-list (only those families resolve and appear in the toolbar); ' +
|
|
23
23
|
'`exclude` keeps everything but the named families.');
|
|
24
24
|
}
|
|
@@ -40,11 +40,11 @@ function normalizeNameList(value, field) {
|
|
|
40
40
|
if (value == null)
|
|
41
41
|
return undefined;
|
|
42
42
|
if (!Array.isArray(value)) {
|
|
43
|
-
throw new Error(`[@superdoc
|
|
43
|
+
throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${field}\` must be an array of Word font names.`);
|
|
44
44
|
}
|
|
45
45
|
const names = value.map((name) => (typeof name === 'string' ? name.trim() : '')).filter(Boolean);
|
|
46
46
|
if (names.length !== value.length) {
|
|
47
|
-
throw new Error(`[@superdoc
|
|
47
|
+
throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${field}\` must contain only non-empty font name strings ` +
|
|
48
48
|
`(e.g. ["Calibri", "Cambria"]).`);
|
|
49
49
|
}
|
|
50
50
|
return names.length ? names : undefined;
|
|
@@ -97,6 +97,6 @@ function assertKnownFamilies(names, field) {
|
|
|
97
97
|
const suggestion = closestKnownFamily(name);
|
|
98
98
|
return suggestion ? `"${name}" (did you mean "${suggestion}"?)` : `"${name}"`;
|
|
99
99
|
});
|
|
100
|
-
throw new Error(`[@superdoc
|
|
100
|
+
throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${field}\` names a font SuperDoc does not bundle: ${hints.join(', ')}. ` +
|
|
101
101
|
`Curate by Word family name. Bundled families: ${BUNDLED_FAMILY_NAMES.join(', ')}.`);
|
|
102
102
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@superdoc
|
|
2
|
+
* `@superdoc/fonts` - the reviewed metric-compatible font substitutes SuperDoc renders for
|
|
3
3
|
* proprietary Word fonts (Carlito for Calibri, Liberation Serif for Times New Roman, etc.).
|
|
4
4
|
*
|
|
5
5
|
* Optional: install it to make the bundled fallbacks load automatically in any bundler app, with
|
|
@@ -36,10 +36,10 @@ export type { BundledFontFamilyName } from './bundled-families.js';
|
|
|
36
36
|
* Pass as SuperDoc's `fonts.resolveAssetUrl` so the reviewed fallback pack loads from THIS
|
|
37
37
|
* package's emitted assets, with no manual copy step and no `assetBaseUrl`:
|
|
38
38
|
*
|
|
39
|
-
* import { resolveBundledFontAssetUrl } from '@superdoc
|
|
39
|
+
* import { resolveBundledFontAssetUrl } from '@superdoc/fonts';
|
|
40
40
|
* new SuperDoc({ selector: '#editor', document, fonts: { resolveAssetUrl: resolveBundledFontAssetUrl } });
|
|
41
41
|
*
|
|
42
|
-
* Throws on an unknown file, which signals a version mismatch between `@superdoc
|
|
42
|
+
* Throws on an unknown file, which signals a version mismatch between `@superdoc/fonts` and
|
|
43
43
|
* the `superdoc` core manifest rather than silently degrading to the logical font name.
|
|
44
44
|
*
|
|
45
45
|
* @beta
|
|
@@ -55,7 +55,7 @@ export declare const superdocFonts: SuperDocFontsConfig;
|
|
|
55
55
|
/**
|
|
56
56
|
* Build a curated `fonts` config: the bundled pack, narrowed to the families you choose.
|
|
57
57
|
*
|
|
58
|
-
* import { createSuperDocFonts } from '@superdoc
|
|
58
|
+
* import { createSuperDocFonts } from '@superdoc/fonts';
|
|
59
59
|
* new SuperDoc({
|
|
60
60
|
* selector: '#editor',
|
|
61
61
|
* document,
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `@superdoc
|
|
2
|
+
* `@superdoc/fonts` - the reviewed metric-compatible font substitutes SuperDoc renders for
|
|
3
3
|
* proprietary Word fonts (Carlito for Calibri, Liberation Serif for Times New Roman, etc.).
|
|
4
4
|
*
|
|
5
5
|
* Optional: install it to make the bundled fallbacks load automatically in any bundler app, with
|
|
@@ -34,10 +34,10 @@ export { BUNDLED_FAMILY_NAMES } from './bundled-families.js';
|
|
|
34
34
|
* Pass as SuperDoc's `fonts.resolveAssetUrl` so the reviewed fallback pack loads from THIS
|
|
35
35
|
* package's emitted assets, with no manual copy step and no `assetBaseUrl`:
|
|
36
36
|
*
|
|
37
|
-
* import { resolveBundledFontAssetUrl } from '@superdoc
|
|
37
|
+
* import { resolveBundledFontAssetUrl } from '@superdoc/fonts';
|
|
38
38
|
* new SuperDoc({ selector: '#editor', document, fonts: { resolveAssetUrl: resolveBundledFontAssetUrl } });
|
|
39
39
|
*
|
|
40
|
-
* Throws on an unknown file, which signals a version mismatch between `@superdoc
|
|
40
|
+
* Throws on an unknown file, which signals a version mismatch between `@superdoc/fonts` and
|
|
41
41
|
* the `superdoc` core manifest rather than silently degrading to the logical font name.
|
|
42
42
|
*
|
|
43
43
|
* @beta
|
|
@@ -45,9 +45,9 @@ export { BUNDLED_FAMILY_NAMES } from './bundled-families.js';
|
|
|
45
45
|
export function resolveBundledFontAssetUrl(context) {
|
|
46
46
|
const url = BUNDLED_FONT_ASSET_URLS[context.file];
|
|
47
47
|
if (!url) {
|
|
48
|
-
throw new Error(`[@superdoc
|
|
48
|
+
throw new Error(`[@superdoc/fonts] no bundled asset for "${context.file}". This pack ships ` +
|
|
49
49
|
`${Object.keys(BUNDLED_FONT_ASSET_URLS).length} faces; the file is unknown, so ` +
|
|
50
|
-
`@superdoc
|
|
50
|
+
`@superdoc/fonts and superdoc are likely version-mismatched. Align their versions.`);
|
|
51
51
|
}
|
|
52
52
|
return url;
|
|
53
53
|
}
|
|
@@ -63,7 +63,7 @@ export const superdocFonts = {
|
|
|
63
63
|
/**
|
|
64
64
|
* Build a curated `fonts` config: the bundled pack, narrowed to the families you choose.
|
|
65
65
|
*
|
|
66
|
-
* import { createSuperDocFonts } from '@superdoc
|
|
66
|
+
* import { createSuperDocFonts } from '@superdoc/fonts';
|
|
67
67
|
* new SuperDoc({
|
|
68
68
|
* selector: '#editor',
|
|
69
69
|
* document,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var SuperDocFonts=(function(f){Object.defineProperty(f,Symbol.toStringTag,{value:"Module"});
|
|
1
|
+
var SuperDocFonts=(function(f){Object.defineProperty(f,Symbol.toStringTag,{value:"Module"});var d=Object.freeze(["ArchivoBlack-Regular.woff2","BacasimeAntique-Regular.woff2","C059-BdIta.woff2","C059-Bold.woff2","C059-Italic.woff2","C059-Roman.woff2","Caladea-Bold.woff2","Caladea-BoldItalic.woff2","Caladea-Italic.woff2","Caladea-Regular.woff2","Caprasimo-Regular.woff2","Cardo-Bold.woff2","Cardo-Italic.woff2","Cardo-Regular.woff2","Carlito-Bold.woff2","Carlito-BoldItalic.woff2","Carlito-Italic.woff2","Carlito-Regular.woff2","ComicRelief-Bold.woff2","ComicRelief-Regular.woff2","Gelasio-Bold.woff2","Gelasio-BoldItalic.woff2","Gelasio-Italic.woff2","Gelasio-Regular.woff2","InconsolataSemiExpanded-Bold.woff2","InconsolataSemiExpanded-Regular.woff2","LiberationMono-Bold.woff2","LiberationMono-BoldItalic.woff2","LiberationMono-Italic.woff2","LiberationMono-Regular.woff2","LiberationSans-Bold.woff2","LiberationSans-BoldItalic.woff2","LiberationSans-Italic.woff2","LiberationSans-Regular.woff2","LiberationSansNarrow-Bold.woff2","LiberationSansNarrow-BoldItalic.woff2","LiberationSansNarrow-Italic.woff2","LiberationSansNarrow-Regular.woff2","LiberationSerif-Bold.woff2","LiberationSerif-BoldItalic.woff2","LiberationSerif-Italic.woff2","LiberationSerif-Regular.woff2","NotoSans-Bold.woff2","NotoSans-BoldItalic.woff2","NotoSans-Italic.woff2","NotoSans-Regular.woff2","NotoSansMono-Bold.woff2","NotoSansMono-Regular.woff2","OreganoItalic-Regular.woff2","PTSans-Bold.woff2","PTSans-BoldItalic.woff2","PTSans-Italic.woff2","PTSans-Regular.woff2","PTSansNarrow-Bold.woff2","PTSansNarrow-Regular.woff2","Selawik-Bold.woff2","Selawik-Regular.woff2","TeXGyreBonum-Bold.woff2","TeXGyreBonum-BoldItalic.woff2","TeXGyreBonum-Italic.woff2","TeXGyreBonum-Regular.woff2","URWGothic-Book.woff2","URWGothic-BookOblique.woff2","URWGothic-Demi.woff2","URWGothic-DemiOblique.woff2"]),s=Object.freeze(["Arial","Arial Black","Arial MT","Arial Narrow","Baskerville Old Face","Bookman Old Style","Brush Script MT","Calibri","Calibri Light","Cambria","Century","Century Gothic","Century Schoolbook","Comic Sans MS","Consolas","Cooper Black","Courier","Courier New","Garamond","Georgia","Gill Sans MT Condensed","Helvetica","ITC Bookman","Lucida Console","Segoe UI","Tahoma","Times","Times New Roman","Trebuchet MS","Verdana"]);function B(o={}){const r=w(o.include,"include"),e=w(o.exclude,"exclude");if(r&&e)throw new Error("[@superdoc/fonts] createSuperDocFonts: pass `include` OR `exclude`, not both. `include` is an allow-list (only those families resolve and appear in the toolbar); `exclude` keeps everything but the named families.");return r&&m(r,"include"),e&&m(e,"exclude"),r?{bundled:{include:r}}:e?{bundled:{exclude:e}}:{}}function w(o,r){if(o==null)return;if(!Array.isArray(o))throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${r}\` must be an array of Word font names.`);const e=o.map(a=>typeof a=="string"?a.trim():"").filter(Boolean);if(e.length!==o.length)throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${r}\` must contain only non-empty font name strings (e.g. ["Calibri", "Cambria"]).`);return e.length?e:void 0}function c(o){return o.trim().replace(/^["']|["']$/g,"").toLowerCase()}var g=new Set(s.map(c));function h(o,r){const e=o.length,a=r.length;if(Math.abs(e-a)>2)return 3;let n=Array.from({length:a+1},(t,l)=>l);for(let t=1;t<=e;t+=1){const l=[t];for(let i=1;i<=a;i+=1){const R=o[t-1]===r[i-1]?0:1;l[i]=Math.min(l[i-1]+1,n[i]+1,n[i-1]+R)}n=l}return n[a]}function b(o){const r=c(o);let e=null,a=3;for(const n of s){const t=h(r,c(n));t<a&&(a=t,e=n)}return e}function m(o,r){const e=o.filter(n=>!g.has(c(n)));if(e.length===0)return;const a=e.map(n=>{const t=b(n);return t?`"${n}" (did you mean "${t}"?)`:`"${n}"`});throw new Error(`[@superdoc/fonts] createSuperDocFonts: \`${r}\` names a font SuperDoc does not bundle: ${a.join(", ")}. Curate by Word family name. Bundled families: ${s.join(", ")}.`)}var S=(typeof document<"u"?document.currentScript:null)?.src??"",C=new Set(d);function u(o){if(!C.has(o.file))throw new Error(`[@superdoc/fonts] no bundled asset for "${o.file}". This pack ships ${d.length} faces; the file is unknown, so @superdoc/fonts and superdoc are likely version-mismatched. Align their versions.`);if(!S)throw new Error('[@superdoc/fonts] could not determine the script URL to resolve bundled fonts from. Load superdoc-fonts.min.js with a normal <script src="..."> tag.');return new URL(`../assets/${o.file}`,S).href}var p={resolveAssetUrl:u};function I(o={}){return{resolveAssetUrl:u,...B(o)}}return f.BUNDLED_FAMILY_NAMES=s,f.createSuperDocFonts=I,f.resolveBundledFontAssetUrl=u,f.superdocFonts=p,f})({});
|
|
2
2
|
|
|
3
3
|
//# sourceMappingURL=superdoc-fonts.min.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"superdoc-fonts.min.js","names":["BUNDLED_FONT_FILES: readonly string[]","KNOWN_FAMILY_KEYS: ReadonlySet<string>","best: string | null","SCRIPT_SRC: string","KNOWN_FILES: ReadonlySet<string>","superdocFonts: SuperDocFontsConfig"],"sources":["../src/bundled-files.ts","../src/bundled-families.ts","../src/curation.ts","../src/cdn-entry.ts"],"sourcesContent":["/**\n * GENERATED by scripts/generate-asset-urls.mjs - do not edit by hand.\n *\n * The flat list of bundled .woff2 filenames, with NO `import.meta.url` (unlike asset-urls.ts).\n * The browser/IIFE entry (cdn-entry.ts) imports this to validate face files and to resolve them\n * relative to its own <script>, since import.meta.url is not available in an IIFE bundle.\n */\nexport const BUNDLED_FONT_FILES: readonly string[] = Object.freeze([\n 'ArchivoBlack-Regular.woff2',\n 'BacasimeAntique-Regular.woff2',\n 'C059-BdIta.woff2',\n 'C059-Bold.woff2',\n 'C059-Italic.woff2',\n 'C059-Roman.woff2',\n 'Caladea-Bold.woff2',\n 'Caladea-BoldItalic.woff2',\n 'Caladea-Italic.woff2',\n 'Caladea-Regular.woff2',\n 'Caprasimo-Regular.woff2',\n 'Cardo-Bold.woff2',\n 'Cardo-Italic.woff2',\n 'Cardo-Regular.woff2',\n 'Carlito-Bold.woff2',\n 'Carlito-BoldItalic.woff2',\n 'Carlito-Italic.woff2',\n 'Carlito-Regular.woff2',\n 'ComicRelief-Bold.woff2',\n 'ComicRelief-Regular.woff2',\n 'Gelasio-Bold.woff2',\n 'Gelasio-BoldItalic.woff2',\n 'Gelasio-Italic.woff2',\n 'Gelasio-Regular.woff2',\n 'InconsolataSemiExpanded-Bold.woff2',\n 'InconsolataSemiExpanded-Regular.woff2',\n 'LiberationMono-Bold.woff2',\n 'LiberationMono-BoldItalic.woff2',\n 'LiberationMono-Italic.woff2',\n 'LiberationMono-Regular.woff2',\n 'LiberationSans-Bold.woff2',\n 'LiberationSans-BoldItalic.woff2',\n 'LiberationSans-Italic.woff2',\n 'LiberationSans-Regular.woff2',\n 'LiberationSansNarrow-Bold.woff2',\n 'LiberationSansNarrow-BoldItalic.woff2',\n 'LiberationSansNarrow-Italic.woff2',\n 'LiberationSansNarrow-Regular.woff2',\n 'LiberationSerif-Bold.woff2',\n 'LiberationSerif-BoldItalic.woff2',\n 'LiberationSerif-Italic.woff2',\n 'LiberationSerif-Regular.woff2',\n 'NotoSans-Bold.woff2',\n 'NotoSans-BoldItalic.woff2',\n 'NotoSans-Italic.woff2',\n 'NotoSans-Regular.woff2',\n 'NotoSansMono-Bold.woff2',\n 'NotoSansMono-Regular.woff2',\n 'OreganoItalic-Regular.woff2',\n 'PTSans-Bold.woff2',\n 'PTSans-BoldItalic.woff2',\n 'PTSans-Italic.woff2',\n 'PTSans-Regular.woff2',\n 'PTSansNarrow-Bold.woff2',\n 'PTSansNarrow-Regular.woff2',\n 'Selawik-Bold.woff2',\n 'Selawik-Regular.woff2',\n 'TeXGyreBonum-Bold.woff2',\n 'TeXGyreBonum-BoldItalic.woff2',\n 'TeXGyreBonum-Italic.woff2',\n 'TeXGyreBonum-Regular.woff2',\n 'URWGothic-Book.woff2',\n 'URWGothic-BookOblique.woff2',\n 'URWGothic-Demi.woff2',\n 'URWGothic-DemiOblique.woff2',\n]);\n","/**\n * GENERATED by scripts/generate-bundled-families.ts - do not edit by hand.\n *\n * The Word family names a document can curate via createSuperDocFonts({ include / exclude }), mirrored\n * from @superdoc/font-system's runtime curation set (every logical family the resolver substitutes to a\n * bundled face, including category fallbacks like Verdana). A name outside this set is a typo or an\n * unbundled font, so createSuperDocFonts rejects it instead of silently dropping the intended fonts.\n */\nexport const BUNDLED_FAMILY_NAMES = Object.freeze([\n 'Arial',\n 'Arial Black',\n 'Arial MT',\n 'Arial Narrow',\n 'Baskerville Old Face',\n 'Bookman Old Style',\n 'Brush Script MT',\n 'Calibri',\n 'Calibri Light',\n 'Cambria',\n 'Century',\n 'Century Gothic',\n 'Century Schoolbook',\n 'Comic Sans MS',\n 'Consolas',\n 'Cooper Black',\n 'Courier',\n 'Courier New',\n 'Garamond',\n 'Georgia',\n 'Gill Sans MT Condensed',\n 'Helvetica',\n 'ITC Bookman',\n 'Lucida Console',\n 'Segoe UI',\n 'Tahoma',\n 'Times',\n 'Times New Roman',\n 'Trebuchet MS',\n 'Verdana',\n] as const);\n\n/**\n * Union of the Word family names the bundled pack can curate, for autocomplete on\n * createSuperDocFonts({ include / exclude }). Those options also accept any string (case- and\n * quote-insensitive, validated at runtime), so a list built from dynamic config still type-checks.\n */\nexport type BundledFontFamilyName = (typeof BUNDLED_FAMILY_NAMES)[number];\n","/**\n * Resolver-independent curation + validation shared by the two entries: the bundler entry\n * (`index.ts`, asset URLs via `import.meta.url`) and the browser/IIFE entry (`cdn-entry.ts`, URLs\n * relative to its own `<script>`). Each entry supplies only its own asset-URL resolver; the\n * `include` / `exclude` validation lives here once so the two entries can never drift.\n *\n * @beta\n */\nimport { BUNDLED_FAMILY_NAMES, type BundledFontFamilyName } from './bundled-families.js';\n\n/**\n * Minimal structural shape of SuperDoc's bundled-font asset context. Kept LOCAL so this package\n * has no dependency on `@superdoc/font-system`; only `file` is read. Assignable to SuperDoc's\n * `FontAssetUrlResolver` by structural typing.\n *\n * @beta\n */\nexport interface BundledFontAssetContext {\n /** Asset filename, e.g. `Carlito-Regular.woff2`. */\n file: string;\n family?: string;\n weight?: string;\n style?: 'normal' | 'italic';\n source?: string;\n}\n\n/** Per-face asset-URL resolver: maps a bundled face filename to a URL the browser can fetch. */\nexport type BundledFontAssetResolver = (context: BundledFontAssetContext) => string;\n\n/**\n * Choose which bundled families SuperDoc advertises and renders, by LOGICAL Word family name\n * (`\"Calibri\"`, never the physical `\"Carlito\"`).\n *\n * @beta\n */\nexport interface SuperDocFontsOptions {\n /**\n * Allow-list: ONLY these logical families are active, e.g. `['Calibri', 'Cambria']`. Autocompletes\n * the bundled names, but also accepts any string (case- and quote-insensitive, validated at\n * runtime), so a list built from dynamic config still type-checks.\n */\n include?: readonly (BundledFontFamilyName | (string & {}))[];\n /** Block-list: every bundled family EXCEPT these, e.g. `['Cooper Black', 'Brush Script MT']`. */\n exclude?: readonly (BundledFontFamilyName | (string & {}))[];\n}\n\n/**\n * The `fonts` config the entries return: the bundled-asset resolver plus the curation.\n * Structurally assignable to SuperDoc's `fonts` option.\n *\n * @beta\n */\nexport interface SuperDocFontsConfig {\n resolveAssetUrl: BundledFontAssetResolver;\n bundled?: { include?: string[]; exclude?: string[] };\n}\n\n/**\n * Validate the curation options and return the `{ bundled? }` slice (no resolver). Each entry\n * spreads this into its own `{ resolveAssetUrl, ...resolveCuration(options) }`.\n */\nexport function resolveCuration(options: SuperDocFontsOptions = {}): {\n bundled?: { include?: string[]; exclude?: string[] };\n} {\n const include = normalizeNameList(options.include, 'include');\n const exclude = normalizeNameList(options.exclude, 'exclude');\n // include and exclude are mutually exclusive intents; accepting both silently would hide which one\n // wins. Reject at the API boundary (this runs in the consumer's setup code, so it fails fast and\n // clearly) rather than picking one arbitrarily.\n if (include && exclude) {\n throw new Error(\n '[@superdoc-dev/fonts] createSuperDocFonts: pass `include` OR `exclude`, not both. ' +\n '`include` is an allow-list (only those families resolve and appear in the toolbar); ' +\n '`exclude` keeps everything but the named families.',\n );\n }\n // Reject names SuperDoc does not bundle. This runs in the consumer's setup code, so it fails fast\n // and clearly - especially for `include`, where a typo would otherwise silently hide the fonts the\n // consumer meant to keep. (Raw `fonts.bundled` set directly stays lenient and only warns.)\n if (include) assertKnownFamilies(include, 'include');\n if (exclude) assertKnownFamilies(exclude, 'exclude');\n if (include) return { bundled: { include } };\n if (exclude) return { bundled: { exclude } };\n return {};\n}\n\n/** Validate and clean a curation list: an array of non-empty strings, or omitted. Throws on misuse. */\nfunction normalizeNameList(value: readonly string[] | undefined, field: 'include' | 'exclude'): string[] | undefined {\n if (value == null) return undefined;\n if (!Array.isArray(value)) {\n throw new Error(`[@superdoc-dev/fonts] createSuperDocFonts: \\`${field}\\` must be an array of Word font names.`);\n }\n const names = value.map((name) => (typeof name === 'string' ? name.trim() : '')).filter(Boolean);\n if (names.length !== value.length) {\n throw new Error(\n `[@superdoc-dev/fonts] createSuperDocFonts: \\`${field}\\` must contain only non-empty font name strings ` +\n `(e.g. [\"Calibri\", \"Cambria\"]).`,\n );\n }\n return names.length ? names : undefined;\n}\n\n/** Normalize a family name for matching: trim, strip surrounding quotes, lowercase. */\nfunction normalizeKey(name: string): string {\n return name\n .trim()\n .replace(/^[\"']|[\"']$/g, '')\n .toLowerCase();\n}\n\nconst KNOWN_FAMILY_KEYS: ReadonlySet<string> = new Set(BUNDLED_FAMILY_NAMES.map(normalizeKey));\n\n/** Bounded Levenshtein distance between two short strings, for a \"did you mean\" hint on a typo. */\nfunction editDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n if (Math.abs(m - n) > 2) return 3;\n let prev = Array.from({ length: n + 1 }, (_, i) => i);\n for (let i = 1; i <= m; i += 1) {\n const curr = [i];\n for (let j = 1; j <= n; j += 1) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);\n }\n prev = curr;\n }\n return prev[n];\n}\n\n/** The closest bundled family within edit distance 2, or null - so a typo gets a concrete suggestion. */\nfunction closestKnownFamily(name: string): string | null {\n const key = normalizeKey(name);\n let best: string | null = null;\n let bestDist = 3;\n for (const family of BUNDLED_FAMILY_NAMES) {\n const dist = editDistance(key, normalizeKey(family));\n if (dist < bestDist) {\n bestDist = dist;\n best = family;\n }\n }\n return best;\n}\n\n/** Throw on any curation name SuperDoc does not bundle, with a suggestion and the full valid list. */\nfunction assertKnownFamilies(names: readonly string[], field: 'include' | 'exclude'): void {\n const unknown = names.filter((name) => !KNOWN_FAMILY_KEYS.has(normalizeKey(name)));\n if (unknown.length === 0) return;\n const hints = unknown.map((name) => {\n const suggestion = closestKnownFamily(name);\n return suggestion ? `\"${name}\" (did you mean \"${suggestion}\"?)` : `\"${name}\"`;\n });\n throw new Error(\n `[@superdoc-dev/fonts] createSuperDocFonts: \\`${field}\\` names a font SuperDoc does not bundle: ${hints.join(', ')}. ` +\n `Curate by Word family name. Bundled families: ${BUNDLED_FAMILY_NAMES.join(', ')}.`,\n );\n}\n","/**\n * Browser / `<script>` (IIFE) entry for `@superdoc-dev/fonts`, built to\n * `dist/superdoc-fonts.min.js` and exposed as the `SuperDocFonts` global.\n *\n * Unlike the bundler entry ({@link \"./index\"}), it resolves the `.woff2` relative to its OWN\n * `<script>` (`document.currentScript`) instead of `import.meta.url`, so a plain CDN / self-host\n * `<script>` tag works with no bundler:\n *\n * <script src=\"https://cdn.jsdelivr.net/npm/superdoc/dist/superdoc.min.js\"></script>\n * <script src=\"https://cdn.jsdelivr.net/npm/@superdoc-dev/fonts/dist/superdoc-fonts.min.js\"></script>\n * <script>\n * new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: SuperDocFonts.superdocFonts });\n * </script>\n *\n * The faces ship in the package's `assets/` dir and this bundle in `dist/`, so a face resolves to\n * `../assets/<file>` relative to the script. On a public CDN (jsDelivr / unpkg) the whole package\n * is served, so that resolves with no setup; self-hosting requires the `dist/` and `assets/` dirs\n * to keep their relative layout.\n *\n * @beta\n */\nimport { BUNDLED_FONT_FILES } from './bundled-files.js';\nimport {\n resolveCuration,\n type BundledFontAssetContext,\n type SuperDocFontsConfig,\n type SuperDocFontsOptions,\n} from './curation.js';\n\n// Capture the executing <script> src at load. `document.currentScript` is valid while this\n// top-level IIFE runs and null later (e.g. in async callbacks), so it MUST be read here, at module\n// eval, not inside the resolver. Duck-typed (no `instanceof HTMLScriptElement`) so the module also\n// evaluates under a non-DOM test environment where that constructor is absent.\nconst currentScript = typeof document !== 'undefined' ? (document.currentScript as { src?: string } | null) : null;\nconst SCRIPT_SRC: string = currentScript?.src ?? '';\n\nconst KNOWN_FILES: ReadonlySet<string> = new Set(BUNDLED_FONT_FILES);\n\n/**\n * Resolve a bundled face filename to a URL relative to THIS script. Throws on an unknown file\n * (a version mismatch between `@superdoc-dev/fonts` and `superdoc`) and on a missing script URL,\n * matching the bundler entry's fail-loud-not-silent contract.\n *\n * @beta\n */\nexport function resolveBundledFontAssetUrl(context: BundledFontAssetContext): string {\n if (!KNOWN_FILES.has(context.file)) {\n throw new Error(\n `[@superdoc-dev/fonts] no bundled asset for \"${context.file}\". This pack ships ` +\n `${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc-dev/fonts and ` +\n `superdoc are likely version-mismatched. Align their versions.`,\n );\n }\n if (!SCRIPT_SRC) {\n throw new Error(\n '[@superdoc-dev/fonts] could not determine the script URL to resolve bundled fonts from. ' +\n 'Load superdoc-fonts.min.js with a normal <script src=\"...\"> tag.',\n );\n }\n return new URL(`../assets/${context.file}`, SCRIPT_SRC).href;\n}\n\n/**\n * Drop-in value for SuperDoc's `fonts` config: `new SuperDoc({ fonts: SuperDocFonts.superdocFonts })`.\n *\n * @beta\n */\nexport const superdocFonts: SuperDocFontsConfig = { resolveAssetUrl: resolveBundledFontAssetUrl };\n\n/**\n * Build a curated `fonts` config: the bundled pack narrowed to the families you choose. Same API\n * and validation as the bundler entry's `createSuperDocFonts`; only the resolver differs.\n *\n * new SuperDoc({ fonts: SuperDocFonts.createSuperDocFonts({ exclude: ['Cooper Black'] }) });\n *\n * @beta\n */\nexport function createSuperDocFonts(options: SuperDocFontsOptions = {}): SuperDocFontsConfig {\n return { resolveAssetUrl: resolveBundledFontAssetUrl, ...resolveCuration(options) };\n}\n\nexport type { BundledFontAssetContext, SuperDocFontsConfig, SuperDocFontsOptions };\nexport { BUNDLED_FAMILY_NAMES } from './bundled-families.js';\nexport type { BundledFontFamilyName } from './bundled-families.js';\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"superdoc-fonts.min.js","names":[],"sources":["../src/bundled-files.ts","../src/bundled-families.ts","../src/curation.ts","../src/cdn-entry.ts"],"sourcesContent":["/**\n * GENERATED by scripts/generate-asset-urls.mjs - do not edit by hand.\n *\n * The flat list of bundled .woff2 filenames, with NO `import.meta.url` (unlike asset-urls.ts).\n * The browser/IIFE entry (cdn-entry.ts) imports this to validate face files and to resolve them\n * relative to its own <script>, since import.meta.url is not available in an IIFE bundle.\n */\nexport const BUNDLED_FONT_FILES: readonly string[] = Object.freeze([\n 'ArchivoBlack-Regular.woff2',\n 'BacasimeAntique-Regular.woff2',\n 'C059-BdIta.woff2',\n 'C059-Bold.woff2',\n 'C059-Italic.woff2',\n 'C059-Roman.woff2',\n 'Caladea-Bold.woff2',\n 'Caladea-BoldItalic.woff2',\n 'Caladea-Italic.woff2',\n 'Caladea-Regular.woff2',\n 'Caprasimo-Regular.woff2',\n 'Cardo-Bold.woff2',\n 'Cardo-Italic.woff2',\n 'Cardo-Regular.woff2',\n 'Carlito-Bold.woff2',\n 'Carlito-BoldItalic.woff2',\n 'Carlito-Italic.woff2',\n 'Carlito-Regular.woff2',\n 'ComicRelief-Bold.woff2',\n 'ComicRelief-Regular.woff2',\n 'Gelasio-Bold.woff2',\n 'Gelasio-BoldItalic.woff2',\n 'Gelasio-Italic.woff2',\n 'Gelasio-Regular.woff2',\n 'InconsolataSemiExpanded-Bold.woff2',\n 'InconsolataSemiExpanded-Regular.woff2',\n 'LiberationMono-Bold.woff2',\n 'LiberationMono-BoldItalic.woff2',\n 'LiberationMono-Italic.woff2',\n 'LiberationMono-Regular.woff2',\n 'LiberationSans-Bold.woff2',\n 'LiberationSans-BoldItalic.woff2',\n 'LiberationSans-Italic.woff2',\n 'LiberationSans-Regular.woff2',\n 'LiberationSansNarrow-Bold.woff2',\n 'LiberationSansNarrow-BoldItalic.woff2',\n 'LiberationSansNarrow-Italic.woff2',\n 'LiberationSansNarrow-Regular.woff2',\n 'LiberationSerif-Bold.woff2',\n 'LiberationSerif-BoldItalic.woff2',\n 'LiberationSerif-Italic.woff2',\n 'LiberationSerif-Regular.woff2',\n 'NotoSans-Bold.woff2',\n 'NotoSans-BoldItalic.woff2',\n 'NotoSans-Italic.woff2',\n 'NotoSans-Regular.woff2',\n 'NotoSansMono-Bold.woff2',\n 'NotoSansMono-Regular.woff2',\n 'OreganoItalic-Regular.woff2',\n 'PTSans-Bold.woff2',\n 'PTSans-BoldItalic.woff2',\n 'PTSans-Italic.woff2',\n 'PTSans-Regular.woff2',\n 'PTSansNarrow-Bold.woff2',\n 'PTSansNarrow-Regular.woff2',\n 'Selawik-Bold.woff2',\n 'Selawik-Regular.woff2',\n 'TeXGyreBonum-Bold.woff2',\n 'TeXGyreBonum-BoldItalic.woff2',\n 'TeXGyreBonum-Italic.woff2',\n 'TeXGyreBonum-Regular.woff2',\n 'URWGothic-Book.woff2',\n 'URWGothic-BookOblique.woff2',\n 'URWGothic-Demi.woff2',\n 'URWGothic-DemiOblique.woff2',\n]);\n","/**\n * GENERATED by scripts/generate-bundled-families.ts - do not edit by hand.\n *\n * The Word family names a document can curate via createSuperDocFonts({ include / exclude }), mirrored\n * from @superdoc/font-system's runtime curation set (every logical family the resolver substitutes to a\n * bundled face, including category fallbacks like Verdana). A name outside this set is a typo or an\n * unbundled font, so createSuperDocFonts rejects it instead of silently dropping the intended fonts.\n */\nexport const BUNDLED_FAMILY_NAMES = Object.freeze([\n 'Arial',\n 'Arial Black',\n 'Arial MT',\n 'Arial Narrow',\n 'Baskerville Old Face',\n 'Bookman Old Style',\n 'Brush Script MT',\n 'Calibri',\n 'Calibri Light',\n 'Cambria',\n 'Century',\n 'Century Gothic',\n 'Century Schoolbook',\n 'Comic Sans MS',\n 'Consolas',\n 'Cooper Black',\n 'Courier',\n 'Courier New',\n 'Garamond',\n 'Georgia',\n 'Gill Sans MT Condensed',\n 'Helvetica',\n 'ITC Bookman',\n 'Lucida Console',\n 'Segoe UI',\n 'Tahoma',\n 'Times',\n 'Times New Roman',\n 'Trebuchet MS',\n 'Verdana',\n] as const);\n\n/**\n * Union of the Word family names the bundled pack can curate, for autocomplete on\n * createSuperDocFonts({ include / exclude }). Those options also accept any string (case- and\n * quote-insensitive, validated at runtime), so a list built from dynamic config still type-checks.\n */\nexport type BundledFontFamilyName = (typeof BUNDLED_FAMILY_NAMES)[number];\n","/**\n * Resolver-independent curation + validation shared by the two entries: the bundler entry\n * (`index.ts`, asset URLs via `import.meta.url`) and the browser/IIFE entry (`cdn-entry.ts`, URLs\n * relative to its own `<script>`). Each entry supplies only its own asset-URL resolver; the\n * `include` / `exclude` validation lives here once so the two entries can never drift.\n *\n * @beta\n */\nimport { BUNDLED_FAMILY_NAMES, type BundledFontFamilyName } from './bundled-families.js';\n\n/**\n * Minimal structural shape of SuperDoc's bundled-font asset context. Kept LOCAL so this package\n * has no dependency on `@superdoc/font-system`; only `file` is read. Assignable to SuperDoc's\n * `FontAssetUrlResolver` by structural typing.\n *\n * @beta\n */\nexport interface BundledFontAssetContext {\n /** Asset filename, e.g. `Carlito-Regular.woff2`. */\n file: string;\n family?: string;\n weight?: string;\n style?: 'normal' | 'italic';\n source?: string;\n}\n\n/** Per-face asset-URL resolver: maps a bundled face filename to a URL the browser can fetch. */\nexport type BundledFontAssetResolver = (context: BundledFontAssetContext) => string;\n\n/**\n * Choose which bundled families SuperDoc advertises and renders, by LOGICAL Word family name\n * (`\"Calibri\"`, never the physical `\"Carlito\"`).\n *\n * @beta\n */\nexport interface SuperDocFontsOptions {\n /**\n * Allow-list: ONLY these logical families are active, e.g. `['Calibri', 'Cambria']`. Autocompletes\n * the bundled names, but also accepts any string (case- and quote-insensitive, validated at\n * runtime), so a list built from dynamic config still type-checks.\n */\n include?: readonly (BundledFontFamilyName | (string & {}))[];\n /** Block-list: every bundled family EXCEPT these, e.g. `['Cooper Black', 'Brush Script MT']`. */\n exclude?: readonly (BundledFontFamilyName | (string & {}))[];\n}\n\n/**\n * The `fonts` config the entries return: the bundled-asset resolver plus the curation.\n * Structurally assignable to SuperDoc's `fonts` option.\n *\n * @beta\n */\nexport interface SuperDocFontsConfig {\n resolveAssetUrl: BundledFontAssetResolver;\n bundled?: { include?: string[]; exclude?: string[] };\n [key: string]: unknown;\n}\n\n/**\n * Validate the curation options and return the `{ bundled? }` slice (no resolver). Each entry\n * spreads this into its own `{ resolveAssetUrl, ...resolveCuration(options) }`.\n */\nexport function resolveCuration(options: SuperDocFontsOptions = {}): {\n bundled?: { include?: string[]; exclude?: string[] };\n} {\n const include = normalizeNameList(options.include, 'include');\n const exclude = normalizeNameList(options.exclude, 'exclude');\n // include and exclude are mutually exclusive intents; accepting both silently would hide which one\n // wins. Reject at the API boundary (this runs in the consumer's setup code, so it fails fast and\n // clearly) rather than picking one arbitrarily.\n if (include && exclude) {\n throw new Error(\n '[@superdoc/fonts] createSuperDocFonts: pass `include` OR `exclude`, not both. ' +\n '`include` is an allow-list (only those families resolve and appear in the toolbar); ' +\n '`exclude` keeps everything but the named families.',\n );\n }\n // Reject names SuperDoc does not bundle. This runs in the consumer's setup code, so it fails fast\n // and clearly - especially for `include`, where a typo would otherwise silently hide the fonts the\n // consumer meant to keep. (Raw `fonts.bundled` set directly stays lenient and only warns.)\n if (include) assertKnownFamilies(include, 'include');\n if (exclude) assertKnownFamilies(exclude, 'exclude');\n if (include) return { bundled: { include } };\n if (exclude) return { bundled: { exclude } };\n return {};\n}\n\n/** Validate and clean a curation list: an array of non-empty strings, or omitted. Throws on misuse. */\nfunction normalizeNameList(value: readonly string[] | undefined, field: 'include' | 'exclude'): string[] | undefined {\n if (value == null) return undefined;\n if (!Array.isArray(value)) {\n throw new Error(`[@superdoc/fonts] createSuperDocFonts: \\`${field}\\` must be an array of Word font names.`);\n }\n const names = value.map((name) => (typeof name === 'string' ? name.trim() : '')).filter(Boolean);\n if (names.length !== value.length) {\n throw new Error(\n `[@superdoc/fonts] createSuperDocFonts: \\`${field}\\` must contain only non-empty font name strings ` +\n `(e.g. [\"Calibri\", \"Cambria\"]).`,\n );\n }\n return names.length ? names : undefined;\n}\n\n/** Normalize a family name for matching: trim, strip surrounding quotes, lowercase. */\nfunction normalizeKey(name: string): string {\n return name\n .trim()\n .replace(/^[\"']|[\"']$/g, '')\n .toLowerCase();\n}\n\nconst KNOWN_FAMILY_KEYS: ReadonlySet<string> = new Set(BUNDLED_FAMILY_NAMES.map(normalizeKey));\n\n/** Bounded Levenshtein distance between two short strings, for a \"did you mean\" hint on a typo. */\nfunction editDistance(a: string, b: string): number {\n const m = a.length;\n const n = b.length;\n if (Math.abs(m - n) > 2) return 3;\n let prev = Array.from({ length: n + 1 }, (_, i) => i);\n for (let i = 1; i <= m; i += 1) {\n const curr = [i];\n for (let j = 1; j <= n; j += 1) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(curr[j - 1] + 1, prev[j] + 1, prev[j - 1] + cost);\n }\n prev = curr;\n }\n return prev[n];\n}\n\n/** The closest bundled family within edit distance 2, or null - so a typo gets a concrete suggestion. */\nfunction closestKnownFamily(name: string): string | null {\n const key = normalizeKey(name);\n let best: string | null = null;\n let bestDist = 3;\n for (const family of BUNDLED_FAMILY_NAMES) {\n const dist = editDistance(key, normalizeKey(family));\n if (dist < bestDist) {\n bestDist = dist;\n best = family;\n }\n }\n return best;\n}\n\n/** Throw on any curation name SuperDoc does not bundle, with a suggestion and the full valid list. */\nfunction assertKnownFamilies(names: readonly string[], field: 'include' | 'exclude'): void {\n const unknown = names.filter((name) => !KNOWN_FAMILY_KEYS.has(normalizeKey(name)));\n if (unknown.length === 0) return;\n const hints = unknown.map((name) => {\n const suggestion = closestKnownFamily(name);\n return suggestion ? `\"${name}\" (did you mean \"${suggestion}\"?)` : `\"${name}\"`;\n });\n throw new Error(\n `[@superdoc/fonts] createSuperDocFonts: \\`${field}\\` names a font SuperDoc does not bundle: ${hints.join(', ')}. ` +\n `Curate by Word family name. Bundled families: ${BUNDLED_FAMILY_NAMES.join(', ')}.`,\n );\n}\n","/**\n * Browser / `<script>` (IIFE) entry for `@superdoc/fonts`, built to\n * `dist/superdoc-fonts.min.js` and exposed as the `SuperDocFonts` global.\n *\n * Unlike the bundler entry ({@link \"./index\"}), it resolves the `.woff2` relative to its OWN\n * `<script>` (`document.currentScript`) instead of `import.meta.url`, so a plain CDN / self-host\n * `<script>` tag works with no bundler:\n *\n * <script src=\"https://cdn.jsdelivr.net/npm/superdoc@next/dist-cdn/superdoc.min.js\"></script>\n * <script src=\"https://cdn.jsdelivr.net/npm/@superdoc/fonts/dist/superdoc-fonts.min.js\"></script>\n * <script>\n * new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: SuperDocFonts.superdocFonts });\n * </script>\n *\n * The faces ship in the package's `assets/` dir and this bundle in `dist/`, so a face resolves to\n * `../assets/<file>` relative to the script. On a public CDN (jsDelivr / unpkg) the whole package\n * is served, so that resolves with no setup; self-hosting requires the `dist/` and `assets/` dirs\n * to keep their relative layout.\n *\n * @beta\n */\nimport { BUNDLED_FONT_FILES } from './bundled-files.js';\nimport {\n resolveCuration,\n type BundledFontAssetContext,\n type SuperDocFontsConfig,\n type SuperDocFontsOptions,\n} from './curation.js';\n\n// Capture the executing <script> src at load. `document.currentScript` is valid while this\n// top-level IIFE runs and null later (e.g. in async callbacks), so it MUST be read here, at module\n// eval, not inside the resolver. Duck-typed (no `instanceof HTMLScriptElement`) so the module also\n// evaluates under a non-DOM test environment where that constructor is absent.\nconst currentScript = typeof document !== 'undefined' ? (document.currentScript as { src?: string } | null) : null;\nconst SCRIPT_SRC: string = currentScript?.src ?? '';\n\nconst KNOWN_FILES: ReadonlySet<string> = new Set(BUNDLED_FONT_FILES);\n\n/**\n * Resolve a bundled face filename to a URL relative to THIS script. Throws on an unknown file\n * (a version mismatch between `@superdoc/fonts` and `superdoc`) and on a missing script URL,\n * matching the bundler entry's fail-loud-not-silent contract.\n *\n * @beta\n */\nexport function resolveBundledFontAssetUrl(context: BundledFontAssetContext): string {\n if (!KNOWN_FILES.has(context.file)) {\n throw new Error(\n `[@superdoc/fonts] no bundled asset for \"${context.file}\". This pack ships ` +\n `${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc/fonts and ` +\n `superdoc are likely version-mismatched. Align their versions.`,\n );\n }\n if (!SCRIPT_SRC) {\n throw new Error(\n '[@superdoc/fonts] could not determine the script URL to resolve bundled fonts from. ' +\n 'Load superdoc-fonts.min.js with a normal <script src=\"...\"> tag.',\n );\n }\n return new URL(`../assets/${context.file}`, SCRIPT_SRC).href;\n}\n\n/**\n * Drop-in value for SuperDoc's `fonts` config: `new SuperDoc({ fonts: SuperDocFonts.superdocFonts })`.\n *\n * @beta\n */\nexport const superdocFonts: SuperDocFontsConfig = { resolveAssetUrl: resolveBundledFontAssetUrl };\n\n/**\n * Build a curated `fonts` config: the bundled pack narrowed to the families you choose. Same API\n * and validation as the bundler entry's `createSuperDocFonts`; only the resolver differs.\n *\n * new SuperDoc({ fonts: SuperDocFonts.createSuperDocFonts({ exclude: ['Cooper Black'] }) });\n *\n * @beta\n */\nexport function createSuperDocFonts(options: SuperDocFontsOptions = {}): SuperDocFontsConfig {\n return { resolveAssetUrl: resolveBundledFontAssetUrl, ...resolveCuration(options) };\n}\n\nexport type { BundledFontAssetContext, SuperDocFontsConfig, SuperDocFontsOptions };\nexport { BUNDLED_FAMILY_NAMES } from './bundled-families.js';\nexport type { BundledFontFamilyName } from './bundled-families.js';\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@superdoc-dev/fonts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Optional bundled metric-compatible font substitutes for SuperDoc, shipped as bundler-resolvable assets.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN assets/LICENSES.md",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/superdoc/docx-editor.git",
|
|
10
|
+
"directory": "packages/fonts"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/superdoc/docx-editor/tree/main/packages/fonts#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/superdoc/docx-editor/issues"
|
|
15
|
+
},
|
|
7
16
|
"publishConfig": {
|
|
8
17
|
"access": "public"
|
|
9
18
|
},
|
|
@@ -28,15 +37,16 @@
|
|
|
28
37
|
"devDependencies": {
|
|
29
38
|
"@types/node": "22.19.2",
|
|
30
39
|
"typescript": "^5.9.2",
|
|
31
|
-
"vite": "
|
|
40
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@0.2.7",
|
|
41
|
+
"vite-plus": "0.2.7"
|
|
32
42
|
},
|
|
33
43
|
"scripts": {
|
|
34
44
|
"sync": "node scripts/sync-assets.mjs",
|
|
35
45
|
"generate": "node scripts/generate-asset-urls.mjs && pnpm exec tsx scripts/generate-bundled-families.ts",
|
|
36
46
|
"check:families": "pnpm exec tsx scripts/check-bundled-families.ts",
|
|
37
|
-
"build:cdn": "
|
|
38
|
-
"build": "node scripts/sync-assets.mjs && node scripts/generate-asset-urls.mjs && tsc --project tsconfig.json &&
|
|
47
|
+
"build:cdn": "vp build",
|
|
48
|
+
"build": "node scripts/sync-assets.mjs && node scripts/generate-asset-urls.mjs && tsc --project tsconfig.json && vp build",
|
|
39
49
|
"typecheck": "tsc --noEmit",
|
|
40
|
-
"test": "
|
|
50
|
+
"test": "vp test"
|
|
41
51
|
}
|
|
42
|
-
}
|
|
52
|
+
}
|
package/src/cdn-entry.test.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from '
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vite-plus/test';
|
|
2
2
|
|
|
3
3
|
// cdn-entry resolves faces relative to its own <script> (document.currentScript), captured at module
|
|
4
4
|
// eval. The fonts test env is `node` (no document), so we stub a minimal document.currentScript and
|
|
5
5
|
// re-import the module per case to re-run that capture, mirroring what the browser sees.
|
|
6
|
-
const SCRIPT = 'https://cdn.jsdelivr.net/npm/@superdoc
|
|
7
|
-
const ASSET_BASE = 'https://cdn.jsdelivr.net/npm/@superdoc
|
|
6
|
+
const SCRIPT = 'https://cdn.jsdelivr.net/npm/@superdoc/fonts@0.1.0/dist/superdoc-fonts.min.js';
|
|
7
|
+
const ASSET_BASE = 'https://cdn.jsdelivr.net/npm/@superdoc/fonts@0.1.0/assets/';
|
|
8
8
|
|
|
9
9
|
describe('cdn-entry (browser/IIFE): script-relative resolver', () => {
|
|
10
10
|
beforeEach(() => {
|
package/src/cdn-entry.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Browser / `<script>` (IIFE) entry for `@superdoc
|
|
2
|
+
* Browser / `<script>` (IIFE) entry for `@superdoc/fonts`, built to
|
|
3
3
|
* `dist/superdoc-fonts.min.js` and exposed as the `SuperDocFonts` global.
|
|
4
4
|
*
|
|
5
5
|
* Unlike the bundler entry ({@link "./index"}), it resolves the `.woff2` relative to its OWN
|
|
6
6
|
* `<script>` (`document.currentScript`) instead of `import.meta.url`, so a plain CDN / self-host
|
|
7
7
|
* `<script>` tag works with no bundler:
|
|
8
8
|
*
|
|
9
|
-
* <script src="https://cdn.jsdelivr.net/npm/superdoc/dist/superdoc.min.js"></script>
|
|
10
|
-
* <script src="https://cdn.jsdelivr.net/npm/@superdoc
|
|
9
|
+
* <script src="https://cdn.jsdelivr.net/npm/superdoc@next/dist-cdn/superdoc.min.js"></script>
|
|
10
|
+
* <script src="https://cdn.jsdelivr.net/npm/@superdoc/fonts/dist/superdoc-fonts.min.js"></script>
|
|
11
11
|
* <script>
|
|
12
12
|
* new SuperDoc({ selector: '#editor', document: 'contract.docx', fonts: SuperDocFonts.superdocFonts });
|
|
13
13
|
* </script>
|
|
@@ -38,7 +38,7 @@ const KNOWN_FILES: ReadonlySet<string> = new Set(BUNDLED_FONT_FILES);
|
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
40
|
* Resolve a bundled face filename to a URL relative to THIS script. Throws on an unknown file
|
|
41
|
-
* (a version mismatch between `@superdoc
|
|
41
|
+
* (a version mismatch between `@superdoc/fonts` and `superdoc`) and on a missing script URL,
|
|
42
42
|
* matching the bundler entry's fail-loud-not-silent contract.
|
|
43
43
|
*
|
|
44
44
|
* @beta
|
|
@@ -46,14 +46,14 @@ const KNOWN_FILES: ReadonlySet<string> = new Set(BUNDLED_FONT_FILES);
|
|
|
46
46
|
export function resolveBundledFontAssetUrl(context: BundledFontAssetContext): string {
|
|
47
47
|
if (!KNOWN_FILES.has(context.file)) {
|
|
48
48
|
throw new Error(
|
|
49
|
-
`[@superdoc
|
|
50
|
-
`${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc
|
|
49
|
+
`[@superdoc/fonts] no bundled asset for "${context.file}". This pack ships ` +
|
|
50
|
+
`${BUNDLED_FONT_FILES.length} faces; the file is unknown, so @superdoc/fonts and ` +
|
|
51
51
|
`superdoc are likely version-mismatched. Align their versions.`,
|
|
52
52
|
);
|
|
53
53
|
}
|
|
54
54
|
if (!SCRIPT_SRC) {
|
|
55
55
|
throw new Error(
|
|
56
|
-
'[@superdoc
|
|
56
|
+
'[@superdoc/fonts] could not determine the script URL to resolve bundled fonts from. ' +
|
|
57
57
|
'Load superdoc-fonts.min.js with a normal <script src="..."> tag.',
|
|
58
58
|
);
|
|
59
59
|
}
|