webfont 12.1.1 → 12.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/README.md +111 -0
- package/dist/cli.mjs +22 -9
- package/dist/index.js +1 -1
- package/dist/index.mjs +11 -1
- package/dist/src/index.d.mts +2 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/types/Format.d.mts +5 -3
- package/dist/src/types/Format.d.ts +5 -3
- package/dist/src/types/InitialOptions.d.mts +2 -0
- package/dist/src/types/InitialOptions.d.ts +2 -0
- package/dist/src/types/OptionsBase.d.mts +3 -1
- package/dist/src/types/OptionsBase.d.ts +3 -1
- package/dist/src/types/TtfPostProcessFn.d.mts +12 -0
- package/dist/src/types/TtfPostProcessFn.d.ts +12 -0
- package/dist/src/types/WebfontOptions.d.mts +1 -0
- package/dist/src/types/WebfontOptions.d.ts +1 -0
- package/dist/src/types/index.d.mts +1 -0
- package/dist/src/types/index.d.ts +1 -0
- package/package.json +8 -6
- package/dist/templates/index.d.mts +0 -19
- package/dist/templates/index.d.ts +0 -19
package/README.md
CHANGED
|
@@ -190,6 +190,71 @@ const remote = await webfont({
|
|
|
190
190
|
});
|
|
191
191
|
```
|
|
192
192
|
|
|
193
|
+
### Autohinting
|
|
194
|
+
|
|
195
|
+
webfont does not bundle a hinting engine — [`ttfautohint`](https://www.freetype.org/ttfautohint/) is a native binary, so it stays out of the core install. Run it yourself through the [`ttfPostProcess`](#ttfpostprocess) hook: it receives the generated **TTF before** WOFF/WOFF2/EOT are derived, so the hinted outlines flow into every format.
|
|
196
|
+
|
|
197
|
+
**Option A — npm wrapper (no system install).** The [`ttfautohint`](https://www.npmjs.com/package/ttfautohint) package ships a prebuilt binary and a Buffer API:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npm i -D ttfautohint
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```js
|
|
204
|
+
import { webfont } from "webfont";
|
|
205
|
+
import TTFAutohint from "ttfautohint";
|
|
206
|
+
|
|
207
|
+
await webfont({
|
|
208
|
+
files: "src/svg-icons/**/*.svg",
|
|
209
|
+
formats: ["ttf", "woff", "woff2", "eot"],
|
|
210
|
+
// `icon: true` applies icon-font-tuned hinting metrics
|
|
211
|
+
ttfPostProcess: (ttf) => TTFAutohint.transform(ttf, { icon: true }),
|
|
212
|
+
});
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
`TTFAutohint.transform(buffer, options)` returns the hinted `Buffer`, which webfont uses as the TTF and as the source for the other formats.
|
|
216
|
+
|
|
217
|
+
**Option B — system binary (no extra npm dependency).** If `ttfautohint` is already installed (Homebrew, apt, …), pipe the buffer through it:
|
|
218
|
+
|
|
219
|
+
```js
|
|
220
|
+
import { execFileSync } from "node:child_process";
|
|
221
|
+
import { webfont } from "webfont";
|
|
222
|
+
|
|
223
|
+
const autohint = (ttf) =>
|
|
224
|
+
execFileSync("ttfautohint", ["-W", "-i", "-s", "-x", "24", "-l", "12", "-r", "48"], {
|
|
225
|
+
input: ttf,
|
|
226
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
await webfont({
|
|
230
|
+
files: "src/svg-icons/**/*.svg",
|
|
231
|
+
formats: ["ttf", "woff2"],
|
|
232
|
+
ttfPostProcess: (ttf) => autohint(ttf),
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**CLI.** Flags can't carry a function, but webfont loads a JS config via cosmiconfig — put the hook in `webfont.config.js`:
|
|
237
|
+
|
|
238
|
+
```js
|
|
239
|
+
// webfont.config.js
|
|
240
|
+
const TTFAutohint = require("ttfautohint");
|
|
241
|
+
|
|
242
|
+
module.exports = {
|
|
243
|
+
files: "src/svg-icons/**/*.svg",
|
|
244
|
+
formats: ["ttf", "woff2"],
|
|
245
|
+
ttfPostProcess: (ttf) => TTFAutohint.transform(ttf, { icon: true }),
|
|
246
|
+
};
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
then run `webfont`.
|
|
250
|
+
|
|
251
|
+
Notes:
|
|
252
|
+
|
|
253
|
+
- The hook is **opt-in**; webfont core stays free of native dependencies.
|
|
254
|
+
- CI must have the binary available — the npm wrapper installs one; the system-binary option requires `ttfautohint` on `PATH`.
|
|
255
|
+
- The callback may be async: return a `Promise<Buffer | Uint8Array>` if your tool is asynchronous.
|
|
256
|
+
- See [#749](https://github.com/itgalaxy/webfont/issues/749) for autohinting tracking and a possible first-party companion package.
|
|
257
|
+
|
|
193
258
|
### Options
|
|
194
259
|
|
|
195
260
|
#### `files`
|
|
@@ -435,6 +500,24 @@ Do **not** use `Math.random()` in `fontName` — that renames both font files an
|
|
|
435
500
|
|
|
436
501
|
See [TROUBLESHOOTING.md](./TROUBLESHOOTING.md) — “Icon details missing after export”.
|
|
437
502
|
|
|
503
|
+
#### `ttfPostProcess`
|
|
504
|
+
|
|
505
|
+
- Type: `function`
|
|
506
|
+
- Default: `undefined`
|
|
507
|
+
- Description: Post-process the generated **TTF** buffer **after** it is built and **before** webfont derives WOFF/WOFF2/EOT from it (SVG pipeline only). The callback receives `(ttf, { fontName, formats })` and returns the new font bytes (`Buffer` or `Uint8Array`, sync or async). Every derived format is produced from the returned buffer. This is a **caller-owned** extension point — webfont bundles nothing here, so optional/native steps such as **autohinting** (`ttfautohint`) live in **your** project or a separate package, keeping the core free of native dependencies (same philosophy as [`glyphContentTransformFn`](#glyphcontenttransformfn) and [ADR 0011](docs/adr/0011-no-svg-outline-stroke-dependency.md); see [#749](https://github.com/itgalaxy/webfont/issues/749)). See the [Autohinting](#autohinting) recipe for npm-wrapper, system-binary, and CLI variants.
|
|
508
|
+
- Example (autohinting — **install the hinting tool in your app**, not in webfont):
|
|
509
|
+
|
|
510
|
+
```js
|
|
511
|
+
import { webfont } from "webfont";
|
|
512
|
+
import { autohint } from "some-ttfautohint-wrapper";
|
|
513
|
+
|
|
514
|
+
await webfont({
|
|
515
|
+
files: "src/svg-icons/**/*.svg",
|
|
516
|
+
formats: ["ttf", "woff2"],
|
|
517
|
+
ttfPostProcess: async (ttf) => autohint(ttf),
|
|
518
|
+
});
|
|
519
|
+
```
|
|
520
|
+
|
|
438
521
|
#### `metadataProvider`
|
|
439
522
|
|
|
440
523
|
- Type: `function`
|
|
@@ -462,6 +545,24 @@ Do **not** use `Math.random()` in `fontName` — that renames both font files an
|
|
|
462
545
|
|
|
463
546
|
`webfont()` resolves to an object with generated font buffers (and optional `template` output). The `config` property contains the **effective options** used for the run (defaults, discovered config, and any options you passed in), plus optional **output metadata** when a configuration file was found or loaded.
|
|
464
547
|
|
|
548
|
+
#### TypeScript
|
|
549
|
+
|
|
550
|
+
`Result` and `ResultConfig` are exported from the package entry, so you can annotate `webfont()` output directly instead of relying on `ReturnType` inference:
|
|
551
|
+
|
|
552
|
+
```ts
|
|
553
|
+
import { webfont, type Result, type ResultConfig } from "webfont";
|
|
554
|
+
|
|
555
|
+
const result: Result = await webfont({
|
|
556
|
+
files: "src/svg-icons/**/*.svg",
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
const config: ResultConfig | undefined = result.config;
|
|
560
|
+
|
|
561
|
+
if (config?.filePath) {
|
|
562
|
+
console.log(`Loaded config from ${config.filePath}`);
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
465
566
|
#### `result.config.filePath`
|
|
466
567
|
|
|
467
568
|
- Type: `string` | `undefined`
|
|
@@ -523,6 +624,12 @@ These can be appended to [webfont options](#options). These are passed directly
|
|
|
523
624
|
- Default: `false`
|
|
524
625
|
- Description: Calculate the bounds of a glyph and center it horizontally.
|
|
525
626
|
|
|
627
|
+
#### `svgicons2svgfont.centerVertically`
|
|
628
|
+
|
|
629
|
+
- Type: `boolean`
|
|
630
|
+
- Default: `false`
|
|
631
|
+
- Description: Center the glyphs vertically in the generated font.
|
|
632
|
+
|
|
526
633
|
#### `svgicons2svgfont.normalize`
|
|
527
634
|
|
|
528
635
|
- Type: `boolean`
|
|
@@ -693,6 +800,10 @@ If you're using cross-env:
|
|
|
693
800
|
|
|
694
801
|
Calculate the bounds of a glyph and center it horizontally.
|
|
695
802
|
|
|
803
|
+
--center-vertically
|
|
804
|
+
|
|
805
|
+
Center the glyphs vertically in the generated font.
|
|
806
|
+
|
|
696
807
|
--normalize
|
|
697
808
|
|
|
698
809
|
Normalize icons by scaling them to the height of the highest icon.
|
package/dist/cli.mjs
CHANGED
|
@@ -27,7 +27,7 @@ import { Readable as ge } from "stream";
|
|
|
27
27
|
import _e from "svg2ttf";
|
|
28
28
|
//#region package.json
|
|
29
29
|
var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w, T, E, Oe, ke, Ae = r((() => {
|
|
30
|
-
ve = "webfont", ye = "12.
|
|
30
|
+
ve = "webfont", ye = "12.3.0", be = "Generator of fonts from SVG icons; decompress WOFF/WOFF2 to embedded TTF/OTF (not TTF↔OTF transcoding)", xe = {
|
|
31
31
|
lib: "dist",
|
|
32
32
|
source: "src"
|
|
33
33
|
}, Se = [
|
|
@@ -65,11 +65,13 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
65
65
|
clean: "rm -rf dist/ temp/",
|
|
66
66
|
demo: "node dist/cli.mjs './src/fixtures/svg-icons/*.svg' -d demo -t html --normalize --center-horizontally",
|
|
67
67
|
lint: "biome check .",
|
|
68
|
+
"lint:suppressions": "node scripts/check-no-suppressions.mjs",
|
|
69
|
+
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
68
70
|
depcheck: "knip",
|
|
69
71
|
prebuild: "npm run clean && npm run lint",
|
|
70
72
|
prepare: "lefthook install",
|
|
71
73
|
predemo: "npm run build",
|
|
72
|
-
prepublishOnly: "npm run build && npm run test:package",
|
|
74
|
+
prepublishOnly: "npm whoami && npm run build && npm run test:package",
|
|
73
75
|
pretest: "npm run build",
|
|
74
76
|
prettify: "biome check --write .",
|
|
75
77
|
test: "vitest run src",
|
|
@@ -108,11 +110,11 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
108
110
|
"@types/wawoff2": "1.0.2",
|
|
109
111
|
"@types/xml2js": "0.4.14",
|
|
110
112
|
"@vitest/coverage-v8": "4.1.9",
|
|
111
|
-
"is-eot": "
|
|
113
|
+
"is-eot": "1.0.0",
|
|
112
114
|
"is-svg": "6.1.0",
|
|
113
|
-
"is-ttf": "
|
|
114
|
-
"is-woff": "
|
|
115
|
-
"is-woff2": "
|
|
115
|
+
"is-ttf": "0.2.2",
|
|
116
|
+
"is-woff": "1.0.3",
|
|
117
|
+
"is-woff2": "1.0.0",
|
|
116
118
|
knip: "6.24.0",
|
|
117
119
|
lefthook: "2.1.9",
|
|
118
120
|
publint: "0.3.21",
|
|
@@ -186,9 +188,10 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
186
188
|
keywords: Oe
|
|
187
189
|
};
|
|
188
190
|
})), je, Me, Ne = r((() => {
|
|
189
|
-
je = "\n Usage: webfont [input] [options]\n\n Input: File(s) or glob(s).\n\n SVG icons: one or more `.svg` files (default pipeline).\n Webfont decompression: one or more `.woff` / `.woff2` paths, globs, or http(s) URLs.\n You must have rights to any font file you process (see NOTICE.md).\n\n If an input argument is wrapped in quotation marks, it will be passed to \"fast-glob\"\n for cross-platform glob support.\n\n Options:\n\n --config\n\n Path to a specific configuration file (JSON, YAML, or CommonJS)\n or the name of a module in `node_modules` that points to one.\n If no `--config` argument is provided, webfont will search for\n configuration files in the following places, in this order:\n - a `webfont` property in `package.json`\n - a `.webfontrc` file (with or without filename extension:\n `.json`, `.yaml`, and `.js` are available)\n - a `webfont.config.js` file exporting a JS object\n The search will begin in the working directory and move up the\n directory tree until a configuration file is found.\n\n -u, --fontName\n\n The font family name you want, default: \"webfont\".\n\n -h, --help\n\n Output usage information.\n\n -v, --version\n\n Output the version number.\n\n -f, --formats\n\n Font formats to generate. Pass a JSON array (e.g. '[\"woff2\"]') or a\n comma-separated list (e.g. woff2 or svg, ttf, woff2).\n SVG input: svg, ttf, eot, woff, woff2 (not otf).\n WOFF/WOFF2 input: ttf and/or otf matching the embedded SFNT flavor.\n\n -d, --dest\n\n Destination for generated fonts.\n\n -m, --dest-create\n\n Create destination directory if it does not exist.\n\n -t, --template\n\n Built-in template name(s) ('css', 'scss', 'styl', 'html', 'json') or path to a custom template.\n Pass a JSON array (e.g. '[\"html\",\"scss\"]') or comma-separated list for multiple outputs.\n\n -s, --destTemplate\n\n Destination for generated template. If not passed used `dest` argument value.\n\n -c, --templateClassName\n\n Class name in css template.\n\n -p, --templateFontPath\n\n Font path in css template.\n\n -n, --templateFontName\n\n Font name in css template.\n\n --templateCacheString\n\n Specify cache string in scss/css template.\n\n --no-sort\n\n Keeps the files in the same order of entry\n\n --ligatures\n\n Add OpenType ligature glyphs (icon names as text). Off by default — large\n icon sets can hang Firefox on Windows (#558). Prefer class + codepoint CSS.\n\n --unicode-range\n\n Emit unicode-range in built-in @font-face rules (computed from glyph code points).\n Off by default — enabling may prevent ligature names from rendering; see README.\n\n --no-template-font-ligatures\n\n Omit font-feature-settings: \"liga\" from the built-in HTML preview template\n\n --optimize-svg\n\n Run a conservative SVGO pass on each SVG before font generation\n (does not convert strokes to fills; use glyphContentTransformFn for that)\n\n --verbose\n\n Tell me everything!.\n\n --svg-diagnose\n\n (Alpha) Scan SVG icons for icon-font incompatibilities (stroke-only paths,\n fill-rule: evenodd, unsupported elements) and log warnings.\n\n For \"svgicons2svgfont\":\n\n --fontId\n\n The font id you want, default as \"--fontName\".\n\n --fontStyle\n\n The font style you want.\n\n --fontWeight\n\n The font weight you want.\n\n --fixedWidth\n\n Creates a monospace font of the width of the largest input icon.\n\n --centerHorizontally\n\n Calculate the bounds of a glyph and center it horizontally.\n\n --normalize\n\n Normalize icons by scaling them to the height of the highest icon.\n\n --fontHeight\n\n The outputted font height [MAX(icons.height)].\n\n --round\n\n Setup the SVG path rounding [10e12].\n\n --descent\n\n The font descent [0].\n\n --ascent\n\n The font ascent [height - descent].\n\n --startUnicode\n\n The start unicode codepoint for files without prefix [0xEA01].\n\n --prependUnicode\n\n Prefix files with their automatically allocated unicode codepoint.\n\n --metadata\n\n Content of the metadata tag.\n\n --addHashInFontUrl\n\n Append an MD5 content hash to font URLs in built-in templates\n (?v=[hash]) while keeping output filenames stable (fontName.woff2, etc.).\n Use with a fixed fontName — do not randomize fontName for cache busting.\n", Me = {
|
|
191
|
+
je = "\n Usage: webfont [input] [options]\n\n Input: File(s) or glob(s).\n\n SVG icons: one or more `.svg` files (default pipeline).\n Webfont decompression: one or more `.woff` / `.woff2` paths, globs, or http(s) URLs.\n You must have rights to any font file you process (see NOTICE.md).\n\n If an input argument is wrapped in quotation marks, it will be passed to \"fast-glob\"\n for cross-platform glob support.\n\n Options:\n\n --config\n\n Path to a specific configuration file (JSON, YAML, or CommonJS)\n or the name of a module in `node_modules` that points to one.\n If no `--config` argument is provided, webfont will search for\n configuration files in the following places, in this order:\n - a `webfont` property in `package.json`\n - a `.webfontrc` file (with or without filename extension:\n `.json`, `.yaml`, and `.js` are available)\n - a `webfont.config.js` file exporting a JS object\n The search will begin in the working directory and move up the\n directory tree until a configuration file is found.\n\n -u, --fontName\n\n The font family name you want, default: \"webfont\".\n\n -h, --help\n\n Output usage information.\n\n -v, --version\n\n Output the version number.\n\n -f, --formats\n\n Font formats to generate. Pass a JSON array (e.g. '[\"woff2\"]') or a\n comma-separated list (e.g. woff2 or svg, ttf, woff2).\n SVG input: svg, ttf, eot, woff, woff2 (not otf).\n WOFF/WOFF2 input: ttf and/or otf matching the embedded SFNT flavor.\n\n -d, --dest\n\n Destination for generated fonts.\n\n -m, --dest-create\n\n Create destination directory if it does not exist.\n\n -t, --template\n\n Built-in template name(s) ('css', 'scss', 'styl', 'html', 'json') or path to a custom template.\n Pass a JSON array (e.g. '[\"html\",\"scss\"]') or comma-separated list for multiple outputs.\n\n -s, --destTemplate\n\n Destination for generated template. If not passed used `dest` argument value.\n\n -c, --templateClassName\n\n Class name in css template.\n\n -p, --templateFontPath\n\n Font path in css template.\n\n -n, --templateFontName\n\n Font name in css template.\n\n --templateCacheString\n\n Specify cache string in scss/css template.\n\n --no-sort\n\n Keeps the files in the same order of entry\n\n --ligatures\n\n Add OpenType ligature glyphs (icon names as text). Off by default — large\n icon sets can hang Firefox on Windows (#558). Prefer class + codepoint CSS.\n\n --unicode-range\n\n Emit unicode-range in built-in @font-face rules (computed from glyph code points).\n Off by default — enabling may prevent ligature names from rendering; see README.\n\n --no-template-font-ligatures\n\n Omit font-feature-settings: \"liga\" from the built-in HTML preview template\n\n --optimize-svg\n\n Run a conservative SVGO pass on each SVG before font generation\n (does not convert strokes to fills; use glyphContentTransformFn for that)\n\n --verbose\n\n Tell me everything!.\n\n --svg-diagnose\n\n (Alpha) Scan SVG icons for icon-font incompatibilities (stroke-only paths,\n fill-rule: evenodd, unsupported elements) and log warnings.\n\n For \"svgicons2svgfont\":\n\n --fontId\n\n The font id you want, default as \"--fontName\".\n\n --fontStyle\n\n The font style you want.\n\n --fontWeight\n\n The font weight you want.\n\n --fixedWidth\n\n Creates a monospace font of the width of the largest input icon.\n\n --centerHorizontally\n\n Calculate the bounds of a glyph and center it horizontally.\n\n --centerVertically\n\n Center the glyphs vertically in the generated font.\n\n --normalize\n\n Normalize icons by scaling them to the height of the highest icon.\n\n --fontHeight\n\n The outputted font height [MAX(icons.height)].\n\n --round\n\n Setup the SVG path rounding [10e12].\n\n --descent\n\n The font descent [0].\n\n --ascent\n\n The font ascent [height - descent].\n\n --startUnicode\n\n The start unicode codepoint for files without prefix [0xEA01].\n\n --prependUnicode\n\n Prefix files with their automatically allocated unicode codepoint.\n\n --metadata\n\n Content of the metadata tag.\n\n --addHashInFontUrl\n\n Append an MD5 content hash to font URLs in built-in templates\n (?v=[hash]) while keeping output filenames stable (fontName.woff2, etc.).\n Use with a fixed fontName — do not randomize fontName for cache busting.\n", Me = {
|
|
190
192
|
ascent: { type: "string" },
|
|
191
193
|
centerHorizontally: { type: "boolean" },
|
|
194
|
+
centerVertically: { type: "boolean" },
|
|
192
195
|
config: { type: "string" },
|
|
193
196
|
descent: { type: "string" },
|
|
194
197
|
dest: {
|
|
@@ -494,6 +497,7 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
494
497
|
}, kt = (e) => ({
|
|
495
498
|
ascent: e.ascent,
|
|
496
499
|
centerHorizontally: e.centerHorizontally,
|
|
500
|
+
centerVertically: e.centerVertically,
|
|
497
501
|
descent: e.descent,
|
|
498
502
|
fixedWidth: e.fixedWidth,
|
|
499
503
|
fontHeight: e.fontHeight,
|
|
@@ -536,6 +540,7 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
536
540
|
})), Ft, It = r((() => {
|
|
537
541
|
Ft = () => ({
|
|
538
542
|
centerHorizontally: !1,
|
|
543
|
+
centerVertically: !1,
|
|
539
544
|
descent: 0,
|
|
540
545
|
fixedWidth: !1,
|
|
541
546
|
fontHeight: void 0,
|
|
@@ -751,7 +756,15 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
751
756
|
t.formatsOptions?.ttf && (c = t.formatsOptions.ttf);
|
|
752
757
|
let l = await Cn(s, t);
|
|
753
758
|
en(l, s);
|
|
754
|
-
let u = Tn(l, c)
|
|
759
|
+
let u = Tn(l, c);
|
|
760
|
+
if (t.ttfPostProcess) {
|
|
761
|
+
let e = await t.ttfPostProcess(u, {
|
|
762
|
+
fontName: t.fontName,
|
|
763
|
+
formats: t.formats
|
|
764
|
+
});
|
|
765
|
+
u = Buffer.from(e);
|
|
766
|
+
}
|
|
767
|
+
let d = {
|
|
755
768
|
config: t,
|
|
756
769
|
glyphsData: s,
|
|
757
770
|
hash: me.createHash("md5").update(l).digest("hex"),
|
|
@@ -906,7 +919,7 @@ var ve, ye, be, xe, Se, Ce, we, Te, Ee, De, p, m, h, g, _, v, y, b, x, S, C, w,
|
|
|
906
919
|
"template"
|
|
907
920
|
], $n = (e) => {
|
|
908
921
|
let t = {};
|
|
909
|
-
typeof e.flags.config == "string" && (t.configFile = ee.silent(process.cwd(), e.flags.config) || d.join(process.cwd(), e.flags.config)), e.flags.fontName && (t.fontName = e.flags.fontName), e.flags.formats && (t.formats = Kn(e.flags.formats)), e.flags.dest && (t.dest = e.flags.dest), e.flags.destCreate && (t.destCreate = e.flags.destCreate), e.flags.template && (t.template = Jn(e.flags.template)), e.flags.templateClassName && (t.templateClassName = e.flags.templateClassName), e.flags.templateFontPath && (t.templateFontPath = e.flags.templateFontPath), e.flags.templateFontName && (t.templateFontName = e.flags.templateFontName), e.flags.templateCacheString && (t.templateCacheString = e.flags.templateCacheString), e.flags.destTemplate && (t.destTemplate = e.flags.destTemplate), e.flags.verbose && (t.verbose = e.flags.verbose), e.flags.fontId && (t.fontId = e.flags.fontId), e.flags.fontStyle && (t.fontStyle = e.flags.fontStyle), e.flags.fontWeight && (t.fontWeight = e.flags.fontWeight), e.flags.fixedWidth && (t.fixedWidth = e.flags.fixedWidth), e.flags.centerHorizontally && (t.centerHorizontally = e.flags.centerHorizontally), e.flags.normalize && (t.normalize = e.flags.normalize), e.flags.optimizeSvg && (t.optimizeSvg = e.flags.optimizeSvg), e.flags.fontHeight && (t.fontHeight = e.flags.fontHeight), e.flags.round && (t.round = e.flags.round), e.flags.descent && (t.descent = e.flags.descent), e.flags.ascent && (t.ascent = e.flags.ascent), e.flags.startUnicode && (t.startUnicode = e.flags.startUnicode), e.flags.prependUnicode && (t.prependUnicode = e.flags.prependUnicode), e.flags.metadata && (t.metadata = e.flags.metadata), e.flags.sort === !1 && (t.sort = e.flags.sort), e.flags.ligatures && (t.ligatures = e.flags.ligatures), e.flags.unicodeRange && (t.unicodeRange = e.flags.unicodeRange), e.flags.templateFontLigatures === !1 && (t.templateFontLigatures = e.flags.templateFontLigatures), e.flags.addHashInFontUrl && (t.addHashInFontUrl = e.flags.addHashInFontUrl);
|
|
922
|
+
typeof e.flags.config == "string" && (t.configFile = ee.silent(process.cwd(), e.flags.config) || d.join(process.cwd(), e.flags.config)), e.flags.fontName && (t.fontName = e.flags.fontName), e.flags.formats && (t.formats = Kn(e.flags.formats)), e.flags.dest && (t.dest = e.flags.dest), e.flags.destCreate && (t.destCreate = e.flags.destCreate), e.flags.template && (t.template = Jn(e.flags.template)), e.flags.templateClassName && (t.templateClassName = e.flags.templateClassName), e.flags.templateFontPath && (t.templateFontPath = e.flags.templateFontPath), e.flags.templateFontName && (t.templateFontName = e.flags.templateFontName), e.flags.templateCacheString && (t.templateCacheString = e.flags.templateCacheString), e.flags.destTemplate && (t.destTemplate = e.flags.destTemplate), e.flags.verbose && (t.verbose = e.flags.verbose), e.flags.fontId && (t.fontId = e.flags.fontId), e.flags.fontStyle && (t.fontStyle = e.flags.fontStyle), e.flags.fontWeight && (t.fontWeight = e.flags.fontWeight), e.flags.fixedWidth && (t.fixedWidth = e.flags.fixedWidth), e.flags.centerHorizontally && (t.centerHorizontally = e.flags.centerHorizontally), e.flags.centerVertically && (t.centerVertically = e.flags.centerVertically), e.flags.normalize && (t.normalize = e.flags.normalize), e.flags.optimizeSvg && (t.optimizeSvg = e.flags.optimizeSvg), e.flags.fontHeight && (t.fontHeight = e.flags.fontHeight), e.flags.round && (t.round = e.flags.round), e.flags.descent && (t.descent = e.flags.descent), e.flags.ascent && (t.ascent = e.flags.ascent), e.flags.startUnicode && (t.startUnicode = e.flags.startUnicode), e.flags.prependUnicode && (t.prependUnicode = e.flags.prependUnicode), e.flags.metadata && (t.metadata = e.flags.metadata), e.flags.sort === !1 && (t.sort = e.flags.sort), e.flags.ligatures && (t.ligatures = e.flags.ligatures), e.flags.unicodeRange && (t.unicodeRange = e.flags.unicodeRange), e.flags.templateFontLigatures === !1 && (t.templateFontLigatures = e.flags.templateFontLigatures), e.flags.addHashInFontUrl && (t.addHashInFontUrl = e.flags.addHashInFontUrl);
|
|
910
923
|
let n = Wn(e.flags);
|
|
911
924
|
return n && (t.svgTools = n), t;
|
|
912
925
|
}, Z = (e) => {
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./parseTemplateOption-BmH_pcQh.js");let t=require("cosmiconfig"),n=require("deepmerge");n=e.r(n);let r=require("path");r=e.r(r);let i=require("globby"),a=require("fs/promises");a=e.r(a);let o=require("ttf2woff");o=e.r(o);let s=require("wawoff2");s=e.r(s);let c=require("ttf2eot");c=e.r(c);let l=require("fontverter");l=e.r(l);let u=require("fs"),d=require("xml2js");d=e.r(d);let f=require("p-limit");f=e.r(f);let p=require("svgicons2svgfont"),m=require("crypto");m=e.r(m);let ee=require("svgo"),te=require("stream"),h=require("svg2ttf");h=e.r(h);var ne=/^https?:\/\//iu,g=e=>ne.test(e),_=e=>{if(g(e))try{return r.default.extname(new URL(e).pathname).toLowerCase()}catch{return``}return r.default.extname(e).toLowerCase()},v=async e=>(await Promise.all(e.map(e=>g(e)?Promise.resolve([e]):(0,i.globby)(e)))).flat(),re=1330926671,ie=1953658213,ae=65536,y=e=>{if(e.length<4)throw Error(`SFNT buffer is too short to read flavor`);let t=e.readUInt32BE(0);if(t===re)return`otf`;if(t===ie||t===ae)return`ttf`;throw Error(`Unsupported SFNT flavor 0x${t.toString(16)}`)},oe=e=>Buffer.from((0,c.default)(e)),b=e=>oe(e),x=(e,t={})=>Buffer.from((0,o.default)(e,t).buffer),S=async e=>Buffer.from(await s.default.compress(e)),C=new Set([`.woff`,`.woff2`]),w=`.svg`,T=`.ttf`,E=[`svg`,`ttf`,`eot`,`woff`,`woff2`],D=e=>e===w,O=e=>e===T,k=e=>C.has(e),se=e=>D(e)||k(e)||O(e),ce=e=>{if(e.length===0)return`empty`;let t=e.map(e=>_(e));if(!t.every(se))return`empty`;let n=t.some(D),r=t.some(k),i=t.some(O);return[n,r,i].filter(Boolean).length>1?`mixed`:r?`webfont`:i?`ttf`:n?`svg`:`empty`},A=e=>{if(e.includes(`otf`))throw Error(`OTF output is only supported when converting WOFF/WOFF2 input. Request "ttf" for SVG icons, or pass a .woff/.woff2 file.`)},j=(e,t)=>t===`svg`?e.filter(e=>_(e)===w):t===`webfont`?e.filter(e=>C.has(_(e))):t===`ttf`?e.filter(e=>_(e)===T):[],M=new Set([`ttf`,`eot`,`woff`,`woff2`]),N=e=>{let t=e.filter(e=>M.has(e));if(e.length===E.length&&E.every(t=>e.includes(t)))return[`woff`,`woff2`];if(t.length===0)throw Error(`formats must include at least one of "ttf", "eot", "woff", or "woff2" when converting TTF input`);return[...new Set(t)]},P=e=>{let t=e.filter(e=>e===`ttf`||e===`otf`);if(e.length===E.length&&E.every(t=>e.includes(t)))return[`ttf`];if(t.length===0)throw Error(`formats must include "ttf" and/or "otf" when converting WOFF/WOFF2 input`);return[...new Set(t)]},F=e=>{if(e.length===0)throw Error(`No TTF files matched`)},I=e=>{if(e.template)throw Error(`Templates are not supported when converting TTF input`);if(e.glyphTransformFn)throw Error(`glyphTransformFn is not supported when converting TTF input`);if(e.glyphContentTransformFn)throw Error(`glyphContentTransformFn is not supported when converting TTF input`)},L=(e,t)=>{let n;try{n=y(e)}catch{throw Error(`Input is not a valid TrueType font: ${t}`)}if(n!==`ttf`)throw Error(`OpenType (OTF) input is not supported for webfont encoding. Use a .ttf file for ${t}.`)},R=async(e,t,n,r)=>{if(n===`ttf`){e.ttf=t;return}if(n===`eot`){e.eot=b(t);return}if(n===`woff`){let n;typeof r.metadata==`string`&&(n=r.metadata),e.woff=x(t,{metadata:n});return}e.woff2=await S(t)},z=async(e,t,n,r)=>{if(g(e))throw Error(`Remote TTF URLs are not supported. Download the file first: ${e}`);r&&console.log(`Encoding ${e}...`);let i=await a.readFile(e);L(i,e);let o={source:e};return await Promise.all(t.map(e=>R(o,i,e,n))),o},B=async(e,t)=>{I(t),F(e);let n=N(t.formats),r=await Promise.all(e.map(e=>z(e,n,t,t.verbose))),i={config:{...t},transcodedFonts:r};if(r.length===1){let[e]=r;i.ttf=e.ttf,i.eot=e.eot,i.woff=e.woff,i.woff2=e.woff2}return i},V=e.n(((e,t)=>{t.exports=function(e){return!e||e.length<8?!1:e[0]===119&&e[1]===79&&e[2]===70&&e[3]===70&&e[4]===0&&e[5]===1&&e[6]===0&&e[7]===0||e[4]===79&&e[5]===84&&e[6]===84&&e[7]===79}})),H=e.n(((e,t)=>{t.exports=function(e){return!e||e.length<8?!1:e[0]===119&&e[1]===79&&e[2]===70&&e[3]===50&&e[4]===0&&e[5]===1&&e[6]===0&&e[7]===0}})),U=e.r(V()),W=e.r(H()),G=(e,t)=>{let n=_(t);if(n===`.woff2`&&!(0,W.default)(e))throw Error(`URL did not return a valid WOFF2 font: ${t}`);if(n===`.woff`&&!(0,U.default)(e))throw Error(`URL did not return a valid WOFF font: ${t}`);if(e.length===0)throw Error(`URL returned an empty response: ${t}`)},le=async e=>{let t;try{t=await fetch(e)}catch(t){let n=String(t);throw t instanceof Error&&(n=t.message),Error(`Failed to fetch font URL ${e}: ${n}`)}if(!t.ok)throw Error(`Failed to fetch font URL ${e}: HTTP ${t.status} ${t.statusText}`);let n=await t.arrayBuffer(),r=Buffer.from(n);return G(r,e),r},ue=e=>{if(e.length===0)throw Error(`No WOFF or WOFF2 files matched`)},de=e=>{if(e.template)throw Error(`Templates are not supported when converting WOFF/WOFF2 input`);if(e.glyphTransformFn)throw Error(`glyphTransformFn is not supported when converting WOFF/WOFF2 input`);if(e.glyphContentTransformFn)throw Error(`glyphContentTransformFn is not supported when converting WOFF/WOFF2 input`)},fe=e=>{let{decompressed:t,sfnt:n,format:r,flavor:i,source:a}=e;if(r===`ttf`&&i!==`ttf`)throw Error(`Input decompresses to OpenType (OTF). Request "otf" format instead of "ttf" for ${a}.`);if(r===`otf`&&i!==`otf`)throw Error(`Input decompresses to TrueType (TTF). Request "ttf" format instead of "otf" for ${a}.`);if(r===`ttf`){t.ttf=n;return}t.otf=n},pe=e=>g(e)?le(e):a.readFile(e),me=async(e,t,n)=>{n&&console.log(`Decompressing ${e}...`);let r=await pe(e),i=Buffer.from(await l.default.convert(r,`sfnt`)),a=y(i),o={source:e};for(let n of t)fe({decompressed:o,sfnt:i,format:n,flavor:a,source:e});return o},he=async(e,t)=>{de(t),ue(e);let n=P(t.formats),r=await Promise.all(e.map(e=>me(e,n,t.verbose))),i={config:{...t},decompressedFonts:r};return r.length===1&&(i.ttf=r[0].ttf,i.otf=r[0].otf),i},ge=f.default,_e=e=>({prependUnicode:!!e.prependUnicode,startUnicode:Number(e.startUnicode)}),ve=e=>{if(e==null)return;if(typeof e==`number`)return Number.isFinite(e)?e:void 0;let t=e.trim();if(t.length===0)return;let n=Number(t);if(Number.isFinite(n))return n},ye=e=>({ascent:e.ascent,centerHorizontally:e.centerHorizontally,descent:e.descent,fixedWidth:e.fixedWidth,fontHeight:e.fontHeight,fontId:e.fontId,fontName:e.fontName,fontStyle:e.fontStyle,fontWeight:e.fontWeight,metadata:e.metadata,normalize:e.normalize,round:ve(e.round)}),be=e=>e===void 0?[]:Array.isArray(e)?e:[e],xe=e=>({name:e.name,unicode:be(e.unicode)}),Se=(e,t)=>{let n=t.metadataProvider||(0,p.getMetadataService)(_e(t)),r=new d.default.Parser,i=ge(t.maxConcurrency);return Promise.all(e.map(e=>i(()=>new Promise((t,n)=>{let i=(0,u.createReadStream)(e),a=``;i.on(`error`,e=>n(e)).on(`data`,e=>{a+=e.toString()}).on(`end`,()=>a.length===0?n(Error(`Empty file ${e}`)):r.parseString(a,r=>r?n(r):t({contents:a,srcPath:e})))})))).then(e=>{let r=e;t.sort&&(r=e.sort((e,t)=>(0,p.fileSorter)(e.srcPath,t.srcPath)));let{ligatures:i}=t;return Promise.all(r.map(e=>new Promise((t,r)=>{n(e.srcPath,(n,a)=>{if(n)return r(n);if(!a)return r(Error(`Missing metadata for ${e.srcPath}`));let o=xe(a);return i&&o.unicode.push(a.name.replace(/-/gu,`_`)),e.metadata=o,t(e)})})))})},Ce=()=>({centerHorizontally:!1,descent:0,fixedWidth:!1,fontHeight:void 0,fontId:void 0,fontName:`webfont`,fontStyle:``,fontWeight:``,formats:[`svg`,`ttf`,`eot`,`woff`,`woff2`],formatsOptions:{ttf:{copyright:null,ts:null,version:null}},ligatures:!1,maxConcurrency:100,metadata:void 0,normalize:!1,prependUnicode:!1,round:0x9184e72a000,sort:!0,startUnicode:59905,templateFontPath:`./`,unicodeRange:!1,verbose:!1}),we=e=>{if(!e?.files)throw Error("You must pass webfont a `files` glob");return{...Ce(),...e}},Te=()=>({multipass:!1,plugins:[`removeDoctype`,`removeXMLProcInst`,`removeComments`,`removeMetadata`,`removeEditorsNSData`,`removeDesc`,`cleanupAttrs`,`removeUnusedNS`]}),Ee=e=>{let t=Te();return e?{...t,...e,plugins:e.plugins??t.plugins}:t},De=(e,t,n)=>(0,ee.optimize)(e,{...Ee(n),path:t}).data,Oe=(e,t)=>e.map(e=>({...e,contents:De(e.contents,e.srcPath,t)})),ke=(e,t)=>t&&e>2e3,Ae=e=>`Warning: ${e} glyphs with ligatures enabled may cause severe browser slowdown or hangs (especially Firefox on Windows). Ligatures are off by default; enable only if needed: --ligatures or ligatures: true. See TROUBLESHOOTING.md and https://github.com/itgalaxy/webfont/issues/558`,je=/<glyph\b([^>/]*)(?:\/>|>)/giu,Me=/\bglyph-name=["']([^"']+)["']/iu,Ne=/\bd=["']([^"']*)["']/iu,Pe=e=>{let t=[];for(let n of e.matchAll(je)){let e=n[1]??``,r=Me.exec(e);r&&(Ne.exec(e)?.[1]??``).trim().length===0&&t.push(r[1])}return t},Fe=(e,t)=>{for(let n of t){let t=n.metadata?.name;if(t&&(e===t||e.startsWith(`${t}-`)))return n.srcPath}},Ie=(e,t)=>{let n=new Set,r=[];for(let i of e){let e=Fe(i,t),a=e??i;n.has(a)||(n.add(a),e?r.push(`${i} (${e})`):r.push(i))}return r.join(`; `)},Le=(e,t)=>{let n=Pe(e);if(n.length===0)return;let r=Ie(n,t);throw Error(`Empty glyph path(s) in SVG font output for: ${r}. Stroke-only SVGs (fill="none" with stroke) often produce empty glyphs because svgicons2svgfont does not convert strokes. Convert strokes to filled paths in your design tool, preprocess with glyphContentTransformFn (for example svg-outline-stroke), or run with --svg-diagnose for compatibility warnings. See TROUBLESHOOTING.md ("Stroke-only SVGs produce blank icons").`)},Re=/fill-rule\s*:\s*evenodd|fill-rule\s*=\s*["']evenodd["']/iu,ze=e=>Re.test(e),Be=/\bstroke\s*=|\bstroke\s*:/iu,Ve=/fill\s*=\s*["']none["']|fill\s*:\s*none/iu,He=/<(line|polyline|clipPath)\b/iu,Ue=/<use\b/iu,We=e=>Be.test(e)?Ve.test(e):!1,Ge=e=>He.test(e),Ke=e=>Ue.test(e),K=(e,t)=>{switch(e){case`evenodd-fill-rule`:return`[webfont:diagnose] ${t} uses fill-rule: evenodd. Icon fonts render glyphs with the nonzero fill rule, so holes and counter-shapes can disappear. See TROUBLESHOOTING.md ("Icon details missing after export").`;case`stroke-only`:return`[webfont:diagnose] ${t} uses stroke-based paths (fill="none"). svgicons2svgfont ignores stroke; outlines may render as solid shapes or lose detail. Preprocess with glyphContentTransformFn (for example svg-outline-stroke) before conversion. See TROUBLESHOOTING.md ("Icon details missing after export").`;case`unsupported-element`:return`[webfont:diagnose] ${t} contains <line>, <polyline>, or <clipPath>. These elements are poorly supported in icon fonts; results may differ from the browser preview. Convert to filled paths or preprocess with glyphContentTransformFn.`;case`use-reference`:return`[webfont:diagnose] ${t} contains <use> (symbol/instance references). svgicons2svgfont does not resolve <use> or apply transform on references — the glyph may be empty or wrong. Flatten to paths in your editor, or preprocess with SVGO / glyphContentTransformFn before conversion. See TROUBLESHOOTING.md ("SVG transform and <use> references", #612).`;default:return e}},q=(e,t)=>{let n=[];return ze(t)&&n.push({code:`evenodd-fill-rule`,message:K(`evenodd-fill-rule`,e),srcPath:e}),We(t)&&n.push({code:`stroke-only`,message:K(`stroke-only`,e),srcPath:e}),Ge(t)&&n.push({code:`unsupported-element`,message:K(`unsupported-element`,e),srcPath:e}),Ke(t)&&n.push({code:`use-reference`,message:K(`use-reference`,e),srcPath:e}),n},J=e=>e.flatMap(e=>q(e.srcPath,e.contents)),qe=(e,t)=>t.diagnose?!0:!!(t.verbose&&e.code===`evenodd-fill-rule`),Je=e=>{if(!e||!e.diagnose)return;let t={diagnose:!0};return e.onMessage&&(t.onMessage=e.onMessage),t},Ye=(e,t,n={})=>{let r=Je(t),i=J(e),{reporter:a,verbose:o=!1}=n;for(let e of i)qe(e,{diagnose:r?.diagnose,verbose:o})&&a?.(e.message);let s=[];return r?.diagnose&&(s=i),{diagnostics:s,glyphs:e}},Xe=(e,t,n={})=>{let{diagnostics:r,glyphs:i}=Ye(e,t,n);return{diagnostics:r,glyphs:i}},Ze=(e,t)=>{let n=``;return new Promise((r,i)=>{t.verbose&&console.log(`Generating SVG font...`);let a=new p.SVGIcons2SVGFontStream(ye(t)).on(`finish`,()=>r(n)).on(`data`,e=>{n+=e}).on(`error`,e=>i(e));e.forEach(e=>{let t=new te.Readable;t.push(e.contents),t.push(null),t.metadata=e.metadata??{name:``,unicode:[]},a.write(t)}),a.end()})},Qe=(e,t={})=>Buffer.from((0,h.default)(e,t).buffer),$e=e=>b(e),et=(e,t)=>x(e,t),tt=e=>S(e),nt=async(e,t)=>{let n=e=>{if(t.svgTools?.onMessage){t.svgTools.onMessage(e);return}(t.svgTools?.diagnose||t.verbose)&&console.log(e)},r=!!(t.svgTools?.onMessage||t.svgTools?.diagnose||t.verbose),i;r&&(i=n);let{diagnostics:a,glyphs:o}=Xe(e,t.svgTools,{reporter:i,verbose:t.verbose}),s=o;if(t.optimizeSvg&&(s=Oe(s,t.svgoConfig)),t.glyphContentTransformFn){let e=t.glyphContentTransformFn;s=await Promise.all(s.map(async t=>{let n=await e(t);return{...t,contents:n}}))}if(t.glyphTransformFn){let e=t.glyphTransformFn;s=await Promise.all(s.map(async t=>{let n=await e(t.metadata??{name:``,unicode:[]});return{...t,metadata:n}}))}ke(s.length,t.ligatures)&&console.log(Ae(s.length));let c={};t.formatsOptions?.ttf&&(c=t.formatsOptions.ttf);let l=await Ze(s,t);Le(l,s);let u=Qe(l,c),d={config:t,glyphsData:s,hash:m.default.createHash(`md5`).update(l).digest(`hex`),svg:l,ttf:u};a.length>0&&(d.svgDiagnostics=a);let{formats:f}=t;if(f.includes(`eot`)&&(d.eot=$e(u)),f.includes(`woff`)){let e;typeof t.metadata==`string`&&(e=t.metadata),d.woff=et(u,{metadata:e})}if(f.includes(`woff2`)&&(d.woff2=Buffer.from(await tt(u))),t.template){let{renderTemplates:e}=await Promise.resolve().then(()=>require("./renderTemplates-zCYCzeOt.js")),{templates:n,usedBuildInTemplate:r}=e(t,d,f);n.length>0&&(d.templates=n,d.template=n[0]?.content,d.usedBuildInTemplate=r)}return f.includes(`svg`)||delete d.svg,f.includes(`ttf`)||delete d.ttf,f.includes(`otf`)||delete d.otf,d},Y=new Set([`eot`,`otf`,`svg`,`ttf`,`woff`,`woff2`]),rt=[...Y].join(`, `),it=e=>{if(typeof e!=`string`||!Y.has(e))throw Error(`Invalid format "${String(e)}". Expected one of: ${rt}`);return e},X=e=>{if(e.length===0)throw Error(`formats must not be empty`);return e.map(it)},at=e=>{if(!Array.isArray(e))throw Error(`formats must be an array of format names (e.g. ["woff2", "svg"])`);return X(e)},Z=(e,t)=>{if(t!==void 0&&typeof t!=`string`)throw Error(`${e} must be a string`)},ot=(e,t)=>{if(t!==void 0&&typeof t!=`boolean`&&typeof t!=`string`)throw Error(`${e} must be a boolean or string`)},Q=(e,t)=>{if(t!==void 0&&typeof t!=`boolean`)throw Error(`${e} must be a boolean`)},st=(e,t)=>{if(t!==void 0&&(typeof t!=`object`||!t||Array.isArray(t)))throw Error(`${e} must be an object`)},ct=e=>{if(typeof e==`string`){if(e.length===0)throw Error(`files must not be empty`);return}if(Array.isArray(e)){if(e.length===0)throw Error(`files must not be empty`);if(!e.every(e=>typeof e==`string`))throw Error(`files must be a string or an array of strings`);return}throw Error(`files must be a string or an array of strings`)},lt=t=>(ct(t.files),t.formats=at(t.formats),Z(`fontName`,t.fontName),ot(`unicodeRange`,t.unicodeRange),Q(`optimizeSvg`,t.optimizeSvg),st(`svgoConfig`,t.svgoConfig),Q(`templateFontLigatures`,t.templateFontLigatures),t.template!==void 0&&e.t(t.template),Z(`templateFontPath`,t.templateFontPath),t),ut=e=>`filepath`in e,dt=async e=>{let n=(0,t.cosmiconfig)(`webfont`,{searchStrategy:`global`});if(e.configFile){let t=r.default.resolve(process.cwd(),e.configFile);return await n.load(t)??{}}return await n.search(process.cwd())??{}},$=async e=>{let t=we(e);delete t.filePath;let r=await dt({configFile:t.configFile}),i;ut(r)&&(t=(0,n.default)(t,r.config,{arrayMerge:(e,t)=>t}),i=r.filepath),t=lt(t);let a;a=Array.isArray(t.files)?t.files:[t.files];let o=await v(a),s=ce(o);if(s===`mixed`)throw Error(`Cannot mix SVG icons, TTF fonts, and WOFF/WOFF2 files in the same run`);if(s===`empty`)throw Error(`Files glob patterns specified did not match any supported files`);if(s===`webfont`){let e=await he(j(o,s),t);return i&&(e.config={...t,filePath:i}),e}if(s===`ttf`){let e=await B(j(o,s),t);return i&&(e.config={...t,filePath:i}),e}A(t.formats);let c=await nt(await Se(j(o,`svg`),t),t);return i?c.config={...t,filePath:i}:c.config=t,c},ft=$;exports.default=ft,exports.diagnoseGlyphsData=J,exports.diagnoseSvgContents=q,exports.webfont=$;
|
|
1
|
+
Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:`Module`}});const e=require("./parseTemplateOption-BmH_pcQh.js");let t=require("cosmiconfig"),n=require("deepmerge");n=e.r(n);let r=require("path");r=e.r(r);let i=require("globby"),a=require("fs/promises");a=e.r(a);let o=require("ttf2woff");o=e.r(o);let s=require("wawoff2");s=e.r(s);let c=require("ttf2eot");c=e.r(c);let l=require("fontverter");l=e.r(l);let u=require("fs"),d=require("xml2js");d=e.r(d);let f=require("p-limit");f=e.r(f);let p=require("svgicons2svgfont"),m=require("crypto");m=e.r(m);let ee=require("svgo"),te=require("stream"),h=require("svg2ttf");h=e.r(h);var ne=/^https?:\/\//iu,g=e=>ne.test(e),_=e=>{if(g(e))try{return r.default.extname(new URL(e).pathname).toLowerCase()}catch{return``}return r.default.extname(e).toLowerCase()},v=async e=>(await Promise.all(e.map(e=>g(e)?Promise.resolve([e]):(0,i.globby)(e)))).flat(),re=1330926671,ie=1953658213,ae=65536,y=e=>{if(e.length<4)throw Error(`SFNT buffer is too short to read flavor`);let t=e.readUInt32BE(0);if(t===re)return`otf`;if(t===ie||t===ae)return`ttf`;throw Error(`Unsupported SFNT flavor 0x${t.toString(16)}`)},oe=e=>Buffer.from((0,c.default)(e)),b=e=>oe(e),x=(e,t={})=>Buffer.from((0,o.default)(e,t).buffer),S=async e=>Buffer.from(await s.default.compress(e)),C=new Set([`.woff`,`.woff2`]),w=`.svg`,T=`.ttf`,E=[`svg`,`ttf`,`eot`,`woff`,`woff2`],D=e=>e===w,O=e=>e===T,k=e=>C.has(e),se=e=>D(e)||k(e)||O(e),ce=e=>{if(e.length===0)return`empty`;let t=e.map(e=>_(e));if(!t.every(se))return`empty`;let n=t.some(D),r=t.some(k),i=t.some(O);return[n,r,i].filter(Boolean).length>1?`mixed`:r?`webfont`:i?`ttf`:n?`svg`:`empty`},A=e=>{if(e.includes(`otf`))throw Error(`OTF output is only supported when converting WOFF/WOFF2 input. Request "ttf" for SVG icons, or pass a .woff/.woff2 file.`)},j=(e,t)=>t===`svg`?e.filter(e=>_(e)===w):t===`webfont`?e.filter(e=>C.has(_(e))):t===`ttf`?e.filter(e=>_(e)===T):[],M=new Set([`ttf`,`eot`,`woff`,`woff2`]),N=e=>{let t=e.filter(e=>M.has(e));if(e.length===E.length&&E.every(t=>e.includes(t)))return[`woff`,`woff2`];if(t.length===0)throw Error(`formats must include at least one of "ttf", "eot", "woff", or "woff2" when converting TTF input`);return[...new Set(t)]},P=e=>{let t=e.filter(e=>e===`ttf`||e===`otf`);if(e.length===E.length&&E.every(t=>e.includes(t)))return[`ttf`];if(t.length===0)throw Error(`formats must include "ttf" and/or "otf" when converting WOFF/WOFF2 input`);return[...new Set(t)]},F=e=>{if(e.length===0)throw Error(`No TTF files matched`)},I=e=>{if(e.template)throw Error(`Templates are not supported when converting TTF input`);if(e.glyphTransformFn)throw Error(`glyphTransformFn is not supported when converting TTF input`);if(e.glyphContentTransformFn)throw Error(`glyphContentTransformFn is not supported when converting TTF input`)},L=(e,t)=>{let n;try{n=y(e)}catch{throw Error(`Input is not a valid TrueType font: ${t}`)}if(n!==`ttf`)throw Error(`OpenType (OTF) input is not supported for webfont encoding. Use a .ttf file for ${t}.`)},R=async(e,t,n,r)=>{if(n===`ttf`){e.ttf=t;return}if(n===`eot`){e.eot=b(t);return}if(n===`woff`){let n;typeof r.metadata==`string`&&(n=r.metadata),e.woff=x(t,{metadata:n});return}e.woff2=await S(t)},z=async(e,t,n,r)=>{if(g(e))throw Error(`Remote TTF URLs are not supported. Download the file first: ${e}`);r&&console.log(`Encoding ${e}...`);let i=await a.readFile(e);L(i,e);let o={source:e};return await Promise.all(t.map(e=>R(o,i,e,n))),o},B=async(e,t)=>{I(t),F(e);let n=N(t.formats),r=await Promise.all(e.map(e=>z(e,n,t,t.verbose))),i={config:{...t},transcodedFonts:r};if(r.length===1){let[e]=r;i.ttf=e.ttf,i.eot=e.eot,i.woff=e.woff,i.woff2=e.woff2}return i},V=e.n(((e,t)=>{t.exports=function(e){return!e||e.length<8?!1:e[0]===119&&e[1]===79&&e[2]===70&&e[3]===70&&e[4]===0&&e[5]===1&&e[6]===0&&e[7]===0||e[4]===79&&e[5]===84&&e[6]===84&&e[7]===79}})),H=e.n(((e,t)=>{t.exports=function(e){return!e||e.length<8?!1:e[0]===119&&e[1]===79&&e[2]===70&&e[3]===50&&e[4]===0&&e[5]===1&&e[6]===0&&e[7]===0}})),U=e.r(V()),W=e.r(H()),G=(e,t)=>{let n=_(t);if(n===`.woff2`&&!(0,W.default)(e))throw Error(`URL did not return a valid WOFF2 font: ${t}`);if(n===`.woff`&&!(0,U.default)(e))throw Error(`URL did not return a valid WOFF font: ${t}`);if(e.length===0)throw Error(`URL returned an empty response: ${t}`)},le=async e=>{let t;try{t=await fetch(e)}catch(t){let n=String(t);throw t instanceof Error&&(n=t.message),Error(`Failed to fetch font URL ${e}: ${n}`)}if(!t.ok)throw Error(`Failed to fetch font URL ${e}: HTTP ${t.status} ${t.statusText}`);let n=await t.arrayBuffer(),r=Buffer.from(n);return G(r,e),r},ue=e=>{if(e.length===0)throw Error(`No WOFF or WOFF2 files matched`)},de=e=>{if(e.template)throw Error(`Templates are not supported when converting WOFF/WOFF2 input`);if(e.glyphTransformFn)throw Error(`glyphTransformFn is not supported when converting WOFF/WOFF2 input`);if(e.glyphContentTransformFn)throw Error(`glyphContentTransformFn is not supported when converting WOFF/WOFF2 input`)},fe=e=>{let{decompressed:t,sfnt:n,format:r,flavor:i,source:a}=e;if(r===`ttf`&&i!==`ttf`)throw Error(`Input decompresses to OpenType (OTF). Request "otf" format instead of "ttf" for ${a}.`);if(r===`otf`&&i!==`otf`)throw Error(`Input decompresses to TrueType (TTF). Request "ttf" format instead of "otf" for ${a}.`);if(r===`ttf`){t.ttf=n;return}t.otf=n},pe=e=>g(e)?le(e):a.readFile(e),me=async(e,t,n)=>{n&&console.log(`Decompressing ${e}...`);let r=await pe(e),i=Buffer.from(await l.default.convert(r,`sfnt`)),a=y(i),o={source:e};for(let n of t)fe({decompressed:o,sfnt:i,format:n,flavor:a,source:e});return o},he=async(e,t)=>{de(t),ue(e);let n=P(t.formats),r=await Promise.all(e.map(e=>me(e,n,t.verbose))),i={config:{...t},decompressedFonts:r};return r.length===1&&(i.ttf=r[0].ttf,i.otf=r[0].otf),i},ge=f.default,_e=e=>({prependUnicode:!!e.prependUnicode,startUnicode:Number(e.startUnicode)}),ve=e=>{if(e==null)return;if(typeof e==`number`)return Number.isFinite(e)?e:void 0;let t=e.trim();if(t.length===0)return;let n=Number(t);if(Number.isFinite(n))return n},ye=e=>({ascent:e.ascent,centerHorizontally:e.centerHorizontally,centerVertically:e.centerVertically,descent:e.descent,fixedWidth:e.fixedWidth,fontHeight:e.fontHeight,fontId:e.fontId,fontName:e.fontName,fontStyle:e.fontStyle,fontWeight:e.fontWeight,metadata:e.metadata,normalize:e.normalize,round:ve(e.round)}),be=e=>e===void 0?[]:Array.isArray(e)?e:[e],xe=e=>({name:e.name,unicode:be(e.unicode)}),Se=(e,t)=>{let n=t.metadataProvider||(0,p.getMetadataService)(_e(t)),r=new d.default.Parser,i=ge(t.maxConcurrency);return Promise.all(e.map(e=>i(()=>new Promise((t,n)=>{let i=(0,u.createReadStream)(e),a=``;i.on(`error`,e=>n(e)).on(`data`,e=>{a+=e.toString()}).on(`end`,()=>a.length===0?n(Error(`Empty file ${e}`)):r.parseString(a,r=>r?n(r):t({contents:a,srcPath:e})))})))).then(e=>{let r=e;t.sort&&(r=e.sort((e,t)=>(0,p.fileSorter)(e.srcPath,t.srcPath)));let{ligatures:i}=t;return Promise.all(r.map(e=>new Promise((t,r)=>{n(e.srcPath,(n,a)=>{if(n)return r(n);if(!a)return r(Error(`Missing metadata for ${e.srcPath}`));let o=xe(a);return i&&o.unicode.push(a.name.replace(/-/gu,`_`)),e.metadata=o,t(e)})})))})},Ce=()=>({centerHorizontally:!1,centerVertically:!1,descent:0,fixedWidth:!1,fontHeight:void 0,fontId:void 0,fontName:`webfont`,fontStyle:``,fontWeight:``,formats:[`svg`,`ttf`,`eot`,`woff`,`woff2`],formatsOptions:{ttf:{copyright:null,ts:null,version:null}},ligatures:!1,maxConcurrency:100,metadata:void 0,normalize:!1,prependUnicode:!1,round:0x9184e72a000,sort:!0,startUnicode:59905,templateFontPath:`./`,unicodeRange:!1,verbose:!1}),we=e=>{if(!e?.files)throw Error("You must pass webfont a `files` glob");return{...Ce(),...e}},Te=()=>({multipass:!1,plugins:[`removeDoctype`,`removeXMLProcInst`,`removeComments`,`removeMetadata`,`removeEditorsNSData`,`removeDesc`,`cleanupAttrs`,`removeUnusedNS`]}),Ee=e=>{let t=Te();return e?{...t,...e,plugins:e.plugins??t.plugins}:t},De=(e,t,n)=>(0,ee.optimize)(e,{...Ee(n),path:t}).data,Oe=(e,t)=>e.map(e=>({...e,contents:De(e.contents,e.srcPath,t)})),ke=(e,t)=>t&&e>2e3,Ae=e=>`Warning: ${e} glyphs with ligatures enabled may cause severe browser slowdown or hangs (especially Firefox on Windows). Ligatures are off by default; enable only if needed: --ligatures or ligatures: true. See TROUBLESHOOTING.md and https://github.com/itgalaxy/webfont/issues/558`,je=/<glyph\b([^>/]*)(?:\/>|>)/giu,Me=/\bglyph-name=["']([^"']+)["']/iu,Ne=/\bd=["']([^"']*)["']/iu,Pe=e=>{let t=[];for(let n of e.matchAll(je)){let e=n[1]??``,r=Me.exec(e);r&&(Ne.exec(e)?.[1]??``).trim().length===0&&t.push(r[1])}return t},Fe=(e,t)=>{for(let n of t){let t=n.metadata?.name;if(t&&(e===t||e.startsWith(`${t}-`)))return n.srcPath}},Ie=(e,t)=>{let n=new Set,r=[];for(let i of e){let e=Fe(i,t),a=e??i;n.has(a)||(n.add(a),e?r.push(`${i} (${e})`):r.push(i))}return r.join(`; `)},Le=(e,t)=>{let n=Pe(e);if(n.length===0)return;let r=Ie(n,t);throw Error(`Empty glyph path(s) in SVG font output for: ${r}. Stroke-only SVGs (fill="none" with stroke) often produce empty glyphs because svgicons2svgfont does not convert strokes. Convert strokes to filled paths in your design tool, preprocess with glyphContentTransformFn (for example svg-outline-stroke), or run with --svg-diagnose for compatibility warnings. See TROUBLESHOOTING.md ("Stroke-only SVGs produce blank icons").`)},Re=/fill-rule\s*:\s*evenodd|fill-rule\s*=\s*["']evenodd["']/iu,ze=e=>Re.test(e),Be=/\bstroke\s*=|\bstroke\s*:/iu,Ve=/fill\s*=\s*["']none["']|fill\s*:\s*none/iu,He=/<(line|polyline|clipPath)\b/iu,Ue=/<use\b/iu,We=e=>Be.test(e)?Ve.test(e):!1,Ge=e=>He.test(e),Ke=e=>Ue.test(e),K=(e,t)=>{switch(e){case`evenodd-fill-rule`:return`[webfont:diagnose] ${t} uses fill-rule: evenodd. Icon fonts render glyphs with the nonzero fill rule, so holes and counter-shapes can disappear. See TROUBLESHOOTING.md ("Icon details missing after export").`;case`stroke-only`:return`[webfont:diagnose] ${t} uses stroke-based paths (fill="none"). svgicons2svgfont ignores stroke; outlines may render as solid shapes or lose detail. Preprocess with glyphContentTransformFn (for example svg-outline-stroke) before conversion. See TROUBLESHOOTING.md ("Icon details missing after export").`;case`unsupported-element`:return`[webfont:diagnose] ${t} contains <line>, <polyline>, or <clipPath>. These elements are poorly supported in icon fonts; results may differ from the browser preview. Convert to filled paths or preprocess with glyphContentTransformFn.`;case`use-reference`:return`[webfont:diagnose] ${t} contains <use> (symbol/instance references). svgicons2svgfont does not resolve <use> or apply transform on references — the glyph may be empty or wrong. Flatten to paths in your editor, or preprocess with SVGO / glyphContentTransformFn before conversion. See TROUBLESHOOTING.md ("SVG transform and <use> references", #612).`;default:return e}},q=(e,t)=>{let n=[];return ze(t)&&n.push({code:`evenodd-fill-rule`,message:K(`evenodd-fill-rule`,e),srcPath:e}),We(t)&&n.push({code:`stroke-only`,message:K(`stroke-only`,e),srcPath:e}),Ge(t)&&n.push({code:`unsupported-element`,message:K(`unsupported-element`,e),srcPath:e}),Ke(t)&&n.push({code:`use-reference`,message:K(`use-reference`,e),srcPath:e}),n},J=e=>e.flatMap(e=>q(e.srcPath,e.contents)),qe=(e,t)=>t.diagnose?!0:!!(t.verbose&&e.code===`evenodd-fill-rule`),Je=e=>{if(!e||!e.diagnose)return;let t={diagnose:!0};return e.onMessage&&(t.onMessage=e.onMessage),t},Ye=(e,t,n={})=>{let r=Je(t),i=J(e),{reporter:a,verbose:o=!1}=n;for(let e of i)qe(e,{diagnose:r?.diagnose,verbose:o})&&a?.(e.message);let s=[];return r?.diagnose&&(s=i),{diagnostics:s,glyphs:e}},Xe=(e,t,n={})=>{let{diagnostics:r,glyphs:i}=Ye(e,t,n);return{diagnostics:r,glyphs:i}},Ze=(e,t)=>{let n=``;return new Promise((r,i)=>{t.verbose&&console.log(`Generating SVG font...`);let a=new p.SVGIcons2SVGFontStream(ye(t)).on(`finish`,()=>r(n)).on(`data`,e=>{n+=e}).on(`error`,e=>i(e));e.forEach(e=>{let t=new te.Readable;t.push(e.contents),t.push(null),t.metadata=e.metadata??{name:``,unicode:[]},a.write(t)}),a.end()})},Qe=(e,t={})=>Buffer.from((0,h.default)(e,t).buffer),$e=e=>b(e),et=(e,t)=>x(e,t),tt=e=>S(e),nt=async(e,t)=>{let n=e=>{if(t.svgTools?.onMessage){t.svgTools.onMessage(e);return}(t.svgTools?.diagnose||t.verbose)&&console.log(e)},r=!!(t.svgTools?.onMessage||t.svgTools?.diagnose||t.verbose),i;r&&(i=n);let{diagnostics:a,glyphs:o}=Xe(e,t.svgTools,{reporter:i,verbose:t.verbose}),s=o;if(t.optimizeSvg&&(s=Oe(s,t.svgoConfig)),t.glyphContentTransformFn){let e=t.glyphContentTransformFn;s=await Promise.all(s.map(async t=>{let n=await e(t);return{...t,contents:n}}))}if(t.glyphTransformFn){let e=t.glyphTransformFn;s=await Promise.all(s.map(async t=>{let n=await e(t.metadata??{name:``,unicode:[]});return{...t,metadata:n}}))}ke(s.length,t.ligatures)&&console.log(Ae(s.length));let c={};t.formatsOptions?.ttf&&(c=t.formatsOptions.ttf);let l=await Ze(s,t);Le(l,s);let u=Qe(l,c);if(t.ttfPostProcess){let e=await t.ttfPostProcess(u,{fontName:t.fontName,formats:t.formats});u=Buffer.from(e)}let d={config:t,glyphsData:s,hash:m.default.createHash(`md5`).update(l).digest(`hex`),svg:l,ttf:u};a.length>0&&(d.svgDiagnostics=a);let{formats:f}=t;if(f.includes(`eot`)&&(d.eot=$e(u)),f.includes(`woff`)){let e;typeof t.metadata==`string`&&(e=t.metadata),d.woff=et(u,{metadata:e})}if(f.includes(`woff2`)&&(d.woff2=Buffer.from(await tt(u))),t.template){let{renderTemplates:e}=await Promise.resolve().then(()=>require("./renderTemplates-zCYCzeOt.js")),{templates:n,usedBuildInTemplate:r}=e(t,d,f);n.length>0&&(d.templates=n,d.template=n[0]?.content,d.usedBuildInTemplate=r)}return f.includes(`svg`)||delete d.svg,f.includes(`ttf`)||delete d.ttf,f.includes(`otf`)||delete d.otf,d},Y=new Set([`eot`,`otf`,`svg`,`ttf`,`woff`,`woff2`]),rt=[...Y].join(`, `),it=e=>{if(typeof e!=`string`||!Y.has(e))throw Error(`Invalid format "${String(e)}". Expected one of: ${rt}`);return e},X=e=>{if(e.length===0)throw Error(`formats must not be empty`);return e.map(it)},at=e=>{if(!Array.isArray(e))throw Error(`formats must be an array of format names (e.g. ["woff2", "svg"])`);return X(e)},Z=(e,t)=>{if(t!==void 0&&typeof t!=`string`)throw Error(`${e} must be a string`)},ot=(e,t)=>{if(t!==void 0&&typeof t!=`boolean`&&typeof t!=`string`)throw Error(`${e} must be a boolean or string`)},Q=(e,t)=>{if(t!==void 0&&typeof t!=`boolean`)throw Error(`${e} must be a boolean`)},st=(e,t)=>{if(t!==void 0&&(typeof t!=`object`||!t||Array.isArray(t)))throw Error(`${e} must be an object`)},ct=e=>{if(typeof e==`string`){if(e.length===0)throw Error(`files must not be empty`);return}if(Array.isArray(e)){if(e.length===0)throw Error(`files must not be empty`);if(!e.every(e=>typeof e==`string`))throw Error(`files must be a string or an array of strings`);return}throw Error(`files must be a string or an array of strings`)},lt=t=>(ct(t.files),t.formats=at(t.formats),Z(`fontName`,t.fontName),ot(`unicodeRange`,t.unicodeRange),Q(`optimizeSvg`,t.optimizeSvg),st(`svgoConfig`,t.svgoConfig),Q(`templateFontLigatures`,t.templateFontLigatures),t.template!==void 0&&e.t(t.template),Z(`templateFontPath`,t.templateFontPath),t),ut=e=>`filepath`in e,dt=async e=>{let n=(0,t.cosmiconfig)(`webfont`,{searchStrategy:`global`});if(e.configFile){let t=r.default.resolve(process.cwd(),e.configFile);return await n.load(t)??{}}return await n.search(process.cwd())??{}},$=async e=>{let t=we(e);delete t.filePath;let r=await dt({configFile:t.configFile}),i;ut(r)&&(t=(0,n.default)(t,r.config,{arrayMerge:(e,t)=>t}),i=r.filepath),t=lt(t);let a;a=Array.isArray(t.files)?t.files:[t.files];let o=await v(a),s=ce(o);if(s===`mixed`)throw Error(`Cannot mix SVG icons, TTF fonts, and WOFF/WOFF2 files in the same run`);if(s===`empty`)throw Error(`Files glob patterns specified did not match any supported files`);if(s===`webfont`){let e=await he(j(o,s),t);return i&&(e.config={...t,filePath:i}),e}if(s===`ttf`){let e=await B(j(o,s),t);return i&&(e.config={...t,filePath:i}),e}A(t.formats);let c=await nt(await Se(j(o,`svg`),t),t);return i?c.config={...t,filePath:i}:c.config=t,c},ft=$;exports.default=ft,exports.diagnoseGlyphsData=J,exports.diagnoseSvgContents=q,exports.webfont=$;
|
package/dist/index.mjs
CHANGED
|
@@ -191,6 +191,7 @@ var v = Object.create, y = Object.defineProperty, b = Object.getOwnPropertyDescr
|
|
|
191
191
|
}, je = (e) => ({
|
|
192
192
|
ascent: e.ascent,
|
|
193
193
|
centerHorizontally: e.centerHorizontally,
|
|
194
|
+
centerVertically: e.centerVertically,
|
|
194
195
|
descent: e.descent,
|
|
195
196
|
fixedWidth: e.fixedWidth,
|
|
196
197
|
fontHeight: e.fontHeight,
|
|
@@ -229,6 +230,7 @@ var v = Object.create, y = Object.defineProperty, b = Object.getOwnPropertyDescr
|
|
|
229
230
|
});
|
|
230
231
|
}, Fe = () => ({
|
|
231
232
|
centerHorizontally: !1,
|
|
233
|
+
centerVertically: !1,
|
|
232
234
|
descent: 0,
|
|
233
235
|
fixedWidth: !1,
|
|
234
236
|
fontHeight: void 0,
|
|
@@ -418,7 +420,15 @@ var v = Object.create, y = Object.defineProperty, b = Object.getOwnPropertyDescr
|
|
|
418
420
|
t.formatsOptions?.ttf && (c = t.formatsOptions.ttf);
|
|
419
421
|
let l = await lt(s, t);
|
|
420
422
|
Ye(l, s);
|
|
421
|
-
let u = ut(l, c)
|
|
423
|
+
let u = ut(l, c);
|
|
424
|
+
if (t.ttfPostProcess) {
|
|
425
|
+
let e = await t.ttfPostProcess(u, {
|
|
426
|
+
fontName: t.fontName,
|
|
427
|
+
formats: t.formats
|
|
428
|
+
});
|
|
429
|
+
u = Buffer.from(e);
|
|
430
|
+
}
|
|
431
|
+
let d = {
|
|
422
432
|
config: t,
|
|
423
433
|
glyphsData: s,
|
|
424
434
|
hash: te.createHash("md5").update(l).digest("hex"),
|
package/dist/src/index.d.mts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { webfont } from './standalone/index.mjs';
|
|
2
2
|
export { diagnoseGlyphsData, diagnoseSvgContents } from './lib/svgDiagnostics/diagnoseSvgContents.mjs';
|
|
3
3
|
export { webfont } from './standalone/index.mjs';
|
|
4
|
+
export type { Result } from './types/Result.mjs';
|
|
5
|
+
export type { ResultConfig } from './types/ResultConfig.mjs';
|
|
4
6
|
export type { SvgDiagnosticCode, SvgGlyphDiagnostic, SvgToolsOptions } from './types/SvgToolsOptions.mjs';
|
|
5
7
|
export default webfont;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { webfont } from './standalone';
|
|
2
2
|
export { diagnoseGlyphsData, diagnoseSvgContents } from './lib/svgDiagnostics/diagnoseSvgContents';
|
|
3
3
|
export { webfont } from './standalone';
|
|
4
|
+
export type { Result } from './types/Result';
|
|
5
|
+
export type { ResultConfig } from './types/ResultConfig';
|
|
4
6
|
export type { SvgDiagnosticCode, SvgGlyphDiagnostic, SvgToolsOptions } from './types/SvgToolsOptions';
|
|
5
7
|
export default webfont;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export type Format = "eot" | "otf" | "woff" | "woff2" | "svg" | "ttf";
|
|
2
2
|
export type Formats = Array<Format>;
|
|
3
3
|
type FormatOption = {
|
|
4
|
-
copyright
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
copyright?: string | null;
|
|
5
|
+
description?: string | null;
|
|
6
|
+
ts?: number | null;
|
|
7
|
+
url?: string | null;
|
|
8
|
+
version?: string | null;
|
|
7
9
|
};
|
|
8
10
|
export type FormatsOptions = Partial<Record<Format, FormatOption>>;
|
|
9
11
|
export {};
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export type Format = "eot" | "otf" | "woff" | "woff2" | "svg" | "ttf";
|
|
2
2
|
export type Formats = Array<Format>;
|
|
3
3
|
type FormatOption = {
|
|
4
|
-
copyright
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
copyright?: string | null;
|
|
5
|
+
description?: string | null;
|
|
6
|
+
ts?: number | null;
|
|
7
|
+
url?: string | null;
|
|
8
|
+
version?: string | null;
|
|
7
9
|
};
|
|
8
10
|
export type FormatsOptions = Partial<Record<Format, FormatOption>>;
|
|
9
11
|
export {};
|
|
@@ -2,9 +2,11 @@ import { GlyphContentTransformFn } from './GlyphContentTransformFn.mjs';
|
|
|
2
2
|
import { GlyphTransformFn } from './GlyphTransformFn.mjs';
|
|
3
3
|
import { MetadataProvider } from './MetadataProvider.mjs';
|
|
4
4
|
import { OptionsBase } from './OptionsBase.mjs';
|
|
5
|
+
import { TtfPostProcessFn } from './TtfPostProcessFn.mjs';
|
|
5
6
|
export type InitialOptions = OptionsBase & {
|
|
6
7
|
files: string | Array<string>;
|
|
7
8
|
glyphContentTransformFn?: GlyphContentTransformFn;
|
|
8
9
|
glyphTransformFn?: GlyphTransformFn;
|
|
9
10
|
metadataProvider?: MetadataProvider;
|
|
11
|
+
ttfPostProcess?: TtfPostProcessFn;
|
|
10
12
|
};
|
|
@@ -2,9 +2,11 @@ import { GlyphContentTransformFn } from './GlyphContentTransformFn';
|
|
|
2
2
|
import { GlyphTransformFn } from './GlyphTransformFn';
|
|
3
3
|
import { MetadataProvider } from './MetadataProvider';
|
|
4
4
|
import { OptionsBase } from './OptionsBase';
|
|
5
|
+
import { TtfPostProcessFn } from './TtfPostProcessFn';
|
|
5
6
|
export type InitialOptions = OptionsBase & {
|
|
6
7
|
files: string | Array<string>;
|
|
7
8
|
glyphContentTransformFn?: GlyphContentTransformFn;
|
|
8
9
|
glyphTransformFn?: GlyphTransformFn;
|
|
9
10
|
metadataProvider?: MetadataProvider;
|
|
11
|
+
ttfPostProcess?: TtfPostProcessFn;
|
|
10
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TemplateOption } from '../lib/parseTemplateOption.mjs';
|
|
2
|
-
import { Formats } from './Format.mjs';
|
|
2
|
+
import { Formats, FormatsOptions } from './Format.mjs';
|
|
3
3
|
import { SvgToolsOptions } from './SvgToolsOptions.mjs';
|
|
4
4
|
export type OptionsBase = {
|
|
5
5
|
configFile?: string;
|
|
@@ -7,6 +7,7 @@ export type OptionsBase = {
|
|
|
7
7
|
destCreate?: boolean;
|
|
8
8
|
fontName?: string | unknown;
|
|
9
9
|
formats?: Formats;
|
|
10
|
+
formatsOptions?: FormatsOptions;
|
|
10
11
|
template?: TemplateOption;
|
|
11
12
|
templateClassName?: string | unknown;
|
|
12
13
|
templateFontPath?: string;
|
|
@@ -19,6 +20,7 @@ export type OptionsBase = {
|
|
|
19
20
|
fontWeight?: string | unknown;
|
|
20
21
|
fixedWidth?: string | unknown;
|
|
21
22
|
centerHorizontally?: boolean | unknown;
|
|
23
|
+
centerVertically?: boolean | unknown;
|
|
22
24
|
normalize?: boolean;
|
|
23
25
|
fontHeight?: string | unknown;
|
|
24
26
|
round?: string | number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TemplateOption } from '../lib/parseTemplateOption';
|
|
2
|
-
import { Formats } from './Format';
|
|
2
|
+
import { Formats, FormatsOptions } from './Format';
|
|
3
3
|
import { SvgToolsOptions } from './SvgToolsOptions';
|
|
4
4
|
export type OptionsBase = {
|
|
5
5
|
configFile?: string;
|
|
@@ -7,6 +7,7 @@ export type OptionsBase = {
|
|
|
7
7
|
destCreate?: boolean;
|
|
8
8
|
fontName?: string | unknown;
|
|
9
9
|
formats?: Formats;
|
|
10
|
+
formatsOptions?: FormatsOptions;
|
|
10
11
|
template?: TemplateOption;
|
|
11
12
|
templateClassName?: string | unknown;
|
|
12
13
|
templateFontPath?: string;
|
|
@@ -19,6 +20,7 @@ export type OptionsBase = {
|
|
|
19
20
|
fontWeight?: string | unknown;
|
|
20
21
|
fixedWidth?: string | unknown;
|
|
21
22
|
centerHorizontally?: boolean | unknown;
|
|
23
|
+
centerVertically?: boolean | unknown;
|
|
22
24
|
normalize?: boolean;
|
|
23
25
|
fontHeight?: string | unknown;
|
|
24
26
|
round?: string | number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Formats } from './Format.mjs';
|
|
2
|
+
export type TtfPostProcessContext = {
|
|
3
|
+
fontName: string;
|
|
4
|
+
formats: Formats;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Post-process the generated TTF buffer before webfont derives WOFF/WOFF2/EOT
|
|
8
|
+
* from it. Runs only in the SVG pipeline. Return the (possibly rewritten) font
|
|
9
|
+
* bytes. Enables optional, caller-owned steps such as autohinting without the
|
|
10
|
+
* core taking a native dependency (see ADR 0011 for the analogous stroke case).
|
|
11
|
+
*/
|
|
12
|
+
export type TtfPostProcessFn = (_ttf: Buffer, _context: TtfPostProcessContext) => Buffer | Uint8Array | Promise<Buffer | Uint8Array>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Formats } from './Format';
|
|
2
|
+
export type TtfPostProcessContext = {
|
|
3
|
+
fontName: string;
|
|
4
|
+
formats: Formats;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Post-process the generated TTF buffer before webfont derives WOFF/WOFF2/EOT
|
|
8
|
+
* from it. Runs only in the SVG pipeline. Return the (possibly rewritten) font
|
|
9
|
+
* bytes. Enables optional, caller-owned steps such as autohinting without the
|
|
10
|
+
* core taking a native dependency (see ADR 0011 for the analogous stroke case).
|
|
11
|
+
*/
|
|
12
|
+
export type TtfPostProcessFn = (_ttf: Buffer, _context: TtfPostProcessContext) => Buffer | Uint8Array | Promise<Buffer | Uint8Array>;
|
|
@@ -8,6 +8,7 @@ import { MetadataProvider } from './MetadataProvider.mjs';
|
|
|
8
8
|
import { SvgToolsOptions } from './SvgToolsOptions.mjs';
|
|
9
9
|
export interface WebfontOptions extends InitialOptions {
|
|
10
10
|
centerHorizontally: boolean;
|
|
11
|
+
centerVertically: boolean;
|
|
11
12
|
descent: number;
|
|
12
13
|
fixedWidth: boolean;
|
|
13
14
|
fontHeight: unknown;
|
|
@@ -8,6 +8,7 @@ import { MetadataProvider } from './MetadataProvider';
|
|
|
8
8
|
import { SvgToolsOptions } from './SvgToolsOptions';
|
|
9
9
|
export interface WebfontOptions extends InitialOptions {
|
|
10
10
|
centerHorizontally: boolean;
|
|
11
|
+
centerVertically: boolean;
|
|
11
12
|
descent: number;
|
|
12
13
|
fixedWidth: boolean;
|
|
13
14
|
fontHeight: unknown;
|
|
@@ -5,4 +5,5 @@ export type { GlyphMetadata } from './GlyphMetadata.mjs';
|
|
|
5
5
|
export type { GlyphTransformFn } from './GlyphTransformFn.mjs';
|
|
6
6
|
export type { InitialOptions } from './InitialOptions.mjs';
|
|
7
7
|
export type { MetadataProvider } from './MetadataProvider.mjs';
|
|
8
|
+
export type { TtfPostProcessContext, TtfPostProcessFn } from './TtfPostProcessFn.mjs';
|
|
8
9
|
export type { WebfontOptions } from './WebfontOptions.mjs';
|
|
@@ -5,4 +5,5 @@ export type { GlyphMetadata } from './GlyphMetadata';
|
|
|
5
5
|
export type { GlyphTransformFn } from './GlyphTransformFn';
|
|
6
6
|
export type { InitialOptions } from './InitialOptions';
|
|
7
7
|
export type { MetadataProvider } from './MetadataProvider';
|
|
8
|
+
export type { TtfPostProcessContext, TtfPostProcessFn } from './TtfPostProcessFn';
|
|
8
9
|
export type { WebfontOptions } from './WebfontOptions';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webfont",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.3.0",
|
|
4
4
|
"description": "Generator of fonts from SVG icons; decompress WOFF/WOFF2 to embedded TTF/OTF (not TTF↔OTF transcoding)",
|
|
5
5
|
"directories": {
|
|
6
6
|
"lib": "dist",
|
|
@@ -52,11 +52,13 @@
|
|
|
52
52
|
"clean": "rm -rf dist/ temp/",
|
|
53
53
|
"demo": "node dist/cli.mjs './src/fixtures/svg-icons/*.svg' -d demo -t html --normalize --center-horizontally",
|
|
54
54
|
"lint": "biome check .",
|
|
55
|
+
"lint:suppressions": "node scripts/check-no-suppressions.mjs",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
55
57
|
"depcheck": "knip",
|
|
56
58
|
"prebuild": "npm run clean && npm run lint",
|
|
57
59
|
"prepare": "lefthook install",
|
|
58
60
|
"predemo": "npm run build",
|
|
59
|
-
"prepublishOnly": "npm run build && npm run test:package",
|
|
61
|
+
"prepublishOnly": "npm whoami && npm run build && npm run test:package",
|
|
60
62
|
"pretest": "npm run build",
|
|
61
63
|
"prettify": "biome check --write .",
|
|
62
64
|
"test": "vitest run src",
|
|
@@ -97,11 +99,11 @@
|
|
|
97
99
|
"@types/wawoff2": "1.0.2",
|
|
98
100
|
"@types/xml2js": "0.4.14",
|
|
99
101
|
"@vitest/coverage-v8": "4.1.9",
|
|
100
|
-
"is-eot": "
|
|
102
|
+
"is-eot": "1.0.0",
|
|
101
103
|
"is-svg": "6.1.0",
|
|
102
|
-
"is-ttf": "
|
|
103
|
-
"is-woff": "
|
|
104
|
-
"is-woff2": "
|
|
104
|
+
"is-ttf": "0.2.2",
|
|
105
|
+
"is-woff": "1.0.3",
|
|
106
|
+
"is-woff2": "1.0.0",
|
|
105
107
|
"knip": "6.24.0",
|
|
106
108
|
"lefthook": "2.1.9",
|
|
107
109
|
"publint": "0.3.21",
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare const getTemplateDirectory: () => string;
|
|
2
|
-
export declare const getTemplateFilePath: (template: string) => string;
|
|
3
|
-
export declare const getBuiltInTemplates: () => {
|
|
4
|
-
css: {
|
|
5
|
-
path: string;
|
|
6
|
-
};
|
|
7
|
-
html: {
|
|
8
|
-
path: string;
|
|
9
|
-
};
|
|
10
|
-
json: {
|
|
11
|
-
path: string;
|
|
12
|
-
};
|
|
13
|
-
scss: {
|
|
14
|
-
path: string;
|
|
15
|
-
};
|
|
16
|
-
styl: {
|
|
17
|
-
path: string;
|
|
18
|
-
};
|
|
19
|
-
};
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export declare const getTemplateDirectory: () => string;
|
|
2
|
-
export declare const getTemplateFilePath: (template: string) => string;
|
|
3
|
-
export declare const getBuiltInTemplates: () => {
|
|
4
|
-
css: {
|
|
5
|
-
path: string;
|
|
6
|
-
};
|
|
7
|
-
html: {
|
|
8
|
-
path: string;
|
|
9
|
-
};
|
|
10
|
-
json: {
|
|
11
|
-
path: string;
|
|
12
|
-
};
|
|
13
|
-
scss: {
|
|
14
|
-
path: string;
|
|
15
|
-
};
|
|
16
|
-
styl: {
|
|
17
|
-
path: string;
|
|
18
|
-
};
|
|
19
|
-
};
|