webfont 11.2.20 → 12.0.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.
Files changed (39) hide show
  1. package/NOTICE.md +153 -0
  2. package/README.md +135 -28
  3. package/dist/cli.mjs +628 -0
  4. package/dist/index.js +1 -5022
  5. package/dist/src/index.d.ts +2 -2
  6. package/dist/src/lib/execCLI/index.d.ts +3 -4
  7. package/dist/src/lib/inputSource.d.ts +5 -0
  8. package/dist/src/lib/p-limit/index.d.ts +2 -0
  9. package/dist/src/lib/sfnt/flavor.d.ts +2 -0
  10. package/dist/src/lib/svgicons2svgfont/index.d.ts +9 -0
  11. package/dist/src/lib/ttf2eot/index.d.ts +2 -0
  12. package/dist/src/standalone/convertWebfontInput.d.ts +3 -0
  13. package/dist/src/standalone/fetchWebfontUrl.d.ts +1 -0
  14. package/dist/src/standalone/glyphsData.d.ts +2 -2
  15. package/dist/src/standalone/index.d.ts +3 -3
  16. package/dist/src/standalone/inputMode.d.ts +7 -0
  17. package/dist/src/standalone/options.d.ts +3 -3
  18. package/dist/src/standalone/templateFonts.d.ts +3 -0
  19. package/dist/src/standalone/toTtf.d.ts +4 -0
  20. package/dist/src/types/DecompressedFont.d.ts +5 -0
  21. package/dist/src/types/Format.d.ts +4 -4
  22. package/dist/src/types/GlyphData.d.ts +2 -2
  23. package/dist/src/types/GlyphMetadata.d.ts +1 -1
  24. package/dist/src/types/GlyphTransformFn.d.ts +2 -2
  25. package/dist/src/types/InitialOptions.d.ts +5 -4
  26. package/dist/src/types/MetadataProvider.d.ts +5 -0
  27. package/dist/src/types/OptionsBase.d.ts +3 -2
  28. package/dist/src/types/Result.d.ts +8 -5
  29. package/dist/src/types/ResultConfig.d.ts +4 -0
  30. package/dist/src/types/WebfontOptions.d.ts +29 -3
  31. package/dist/src/types/index.d.ts +7 -6
  32. package/package.json +52 -57
  33. package/dist/cli.js +0 -5314
  34. package/dist/jest.config.d.ts +0 -3
  35. package/dist/src/cli/index.d.ts +0 -1
  36. package/dist/src/cli/index.test.d.ts +0 -1
  37. package/dist/src/cli/meow/index.d.ts +0 -104
  38. package/dist/src/index.test.d.ts +0 -1
  39. package/dist/src/standalone/index.test.d.ts +0 -1
package/dist/cli.mjs ADDED
@@ -0,0 +1,628 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath as e } from "node:url";
3
+ const t = e(import.meta.url), n = e(new URL(".", import.meta.url));
4
+ import { pathToFileURL as r } from "node:url";
5
+ import i from "meow";
6
+ import * as a from "fs";
7
+ import { createReadStream as o } from "fs";
8
+ import * as s from "path";
9
+ import c from "path";
10
+ import l from "resolve-from";
11
+ import { globby as u } from "globby";
12
+ import { cosmiconfig as d } from "cosmiconfig";
13
+ import ee from "crypto";
14
+ import f from "deepmerge";
15
+ import p from "nunjucks";
16
+ import { Readable as m } from "stream";
17
+ import h from "ttf2woff";
18
+ import g from "wawoff2";
19
+ import { SVGIcons2SVGFontStream as te, fileSorter as _, getMetadataService as v } from "svgicons2svgfont";
20
+ import y from "ttf2eot";
21
+ import b from "fontverter";
22
+ import * as ne from "fs/promises";
23
+ import re from "xml2js";
24
+ import ie from "p-limit";
25
+ import ae from "svg2ttf";
26
+ //#region \0rolldown/runtime.js
27
+ var oe = Object.create, x = Object.defineProperty, se = Object.getOwnPropertyDescriptor, ce = Object.getOwnPropertyNames, le = Object.getPrototypeOf, ue = Object.prototype.hasOwnProperty, S = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), C = (e, t, n, r) => {
28
+ if (t && typeof t == "object" || typeof t == "function") for (var i = ce(t), a = 0, o = i.length, s; a < o; a++) s = i[a], !ue.call(e, s) && s !== n && x(e, s, {
29
+ get: ((e) => t[e]).bind(null, s),
30
+ enumerable: !(r = se(t, s)) || r.enumerable
31
+ });
32
+ return e;
33
+ }, w = (e, t, n) => (n = e == null ? {} : oe(le(e)), C(t || !e || !e.__esModule ? x(n, "default", {
34
+ value: e,
35
+ enumerable: !0
36
+ }) : n, e)), T = {
37
+ name: "webfont",
38
+ version: "12.0.0",
39
+ description: "Generator of fonts from SVG icons; decompress WOFF/WOFF2 to embedded TTF/OTF (not TTF↔OTF transcoding)",
40
+ directories: {
41
+ lib: "dist",
42
+ source: "src"
43
+ },
44
+ files: [
45
+ "dist",
46
+ "dist/src/index.d.ts",
47
+ "templates",
48
+ "!**/__tests__",
49
+ "!**/__mocks__",
50
+ "README.md",
51
+ "NOTICE.md"
52
+ ],
53
+ main: "dist/index.js",
54
+ bin: "dist/cli.mjs",
55
+ source: "src/index.ts",
56
+ types: "dist/src/index.d.ts",
57
+ typings: "dist/src/index.d.ts",
58
+ scripts: {
59
+ build: "vite build --mode library && vite build --mode cli",
60
+ clean: "rm -rf dist/ temp/",
61
+ demo: "node dist/cli.mjs './src/fixtures/svg-icons/*.svg' -d demo -t html --normalize --center-horizontally",
62
+ lint: "biome check .",
63
+ depcheck: "knip",
64
+ prebuild: "npm run clean && npm run lint",
65
+ prepare: "lefthook install",
66
+ predemo: "npm run build",
67
+ prepublishOnly: "npm run build",
68
+ pretest: "npm run build",
69
+ prettify: "biome check --write .",
70
+ test: "vitest run src",
71
+ testc: "vitest run src --coverage",
72
+ "test-debug": "vitest run src --no-file-parallelism",
73
+ testu: "vitest run src -u"
74
+ },
75
+ dependencies: {
76
+ cosmiconfig: "9.0.2",
77
+ deepmerge: "^4.2.2",
78
+ fontverter: "2.0.0",
79
+ globby: "16.2.0",
80
+ meow: "14.1.0",
81
+ nunjucks: "3.2.4",
82
+ "p-limit": "7.3.0",
83
+ "resolve-from": "^5.0.0",
84
+ svg2ttf: "^6.1.0",
85
+ svgicons2svgfont: "^16.0.0",
86
+ ttf2eot: "3.1.0",
87
+ ttf2woff: "^3.0.0",
88
+ wawoff2: "2.0.0",
89
+ xml2js: "0.6.2"
90
+ },
91
+ devDependencies: {
92
+ "@biomejs/biome": "2.5.2",
93
+ "@types/node": "^22.15.0",
94
+ "@types/nunjucks": "3.2.6",
95
+ "@types/rimraf": "latest",
96
+ "@types/svg2ttf": "5.0.3",
97
+ "@types/ttf2eot": "2.0.2",
98
+ "@types/ttf2woff": "2.0.4",
99
+ "@types/wawoff2": "1.0.2",
100
+ "@types/xml2js": "0.4.14",
101
+ "@vitest/coverage-v8": "4.1.9",
102
+ "fast-glob": "3.2.12",
103
+ "is-eot": "latest",
104
+ "is-svg": "6.1.0",
105
+ "is-ttf": "latest",
106
+ "is-woff": "latest",
107
+ "is-woff2": "latest",
108
+ knip: "6.24.0",
109
+ lefthook: "2.1.9",
110
+ rimraf: "latest",
111
+ typescript: "6.0.3",
112
+ vite: "8.1.3",
113
+ "vite-plugin-checker": "0.14.4",
114
+ "vite-plugin-dts": "5.0.3",
115
+ vitest: "4.1.9"
116
+ },
117
+ overrides: {
118
+ "fast-glob": "3.2.12",
119
+ minimatch: "10.2.5",
120
+ "test-exclude": "7.0.2",
121
+ "woff2sfnt-sfnt2woff": "1.0.0"
122
+ },
123
+ repository: {
124
+ type: "git",
125
+ url: "git+https://github.com/itgalaxy/webfont.git"
126
+ },
127
+ author: "itgalaxy <development@itgalaxy.company>",
128
+ license: "MIT",
129
+ contributors: [{
130
+ name: "Alexander Krasnoyarov",
131
+ email: "alexander.krasnoyarov@itgalaxy.company",
132
+ url: "https://vk.com/sterling_archer"
133
+ }, {
134
+ name: "Jimmy Andrade",
135
+ email: "webfont@jimmyandrade.com",
136
+ url: "https://github.com/jimmyandrade"
137
+ }],
138
+ bugs: { url: "https://github.com/itgalaxy/webfont/issues" },
139
+ homepage: "https://github.com/itgalaxy/webfont#readme",
140
+ engines: { node: ">= 24.14.0" },
141
+ keywords: [
142
+ "cli",
143
+ "standalone",
144
+ "font",
145
+ "fonts",
146
+ "webfont",
147
+ "webfonts",
148
+ "svg",
149
+ "ttf",
150
+ "woff",
151
+ "woff2",
152
+ "otf",
153
+ "ttf2eot",
154
+ "ttf2woff",
155
+ "ttf2svg",
156
+ "svg2ttf",
157
+ "css",
158
+ "scss",
159
+ "builder",
160
+ "generator"
161
+ ]
162
+ }, E = "\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 Type of template ('css', 'scss', 'styl') or path to custom template.\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 --no-ligatures\n\n Prevents adding ligature unicode\n\n --verbose\n\n Tell me everything!.\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 Generated font url will be : [webfont].[ext]?v=[hash]\n", D = {
163
+ ascent: { type: "string" },
164
+ centerHorizontally: { type: "boolean" },
165
+ config: { type: "string" },
166
+ descent: { type: "string" },
167
+ dest: {
168
+ shortFlag: "d",
169
+ default: process.cwd(),
170
+ type: "string"
171
+ },
172
+ destCreate: {
173
+ shortFlag: "m",
174
+ default: !1,
175
+ type: "boolean"
176
+ },
177
+ destTemplate: {
178
+ shortFlag: "s",
179
+ type: "string"
180
+ },
181
+ fixedWidth: { type: "boolean" },
182
+ fontHeight: { type: "string" },
183
+ fontId: { type: "string" },
184
+ fontName: {
185
+ shortFlag: "u",
186
+ type: "string"
187
+ },
188
+ fontStyle: { type: "string" },
189
+ fontWeight: { type: "string" },
190
+ formats: {
191
+ shortFlag: "f",
192
+ type: "string"
193
+ },
194
+ help: {
195
+ shortFlag: "h",
196
+ type: "boolean"
197
+ },
198
+ ligatures: {
199
+ default: !0,
200
+ type: "boolean"
201
+ },
202
+ metadata: { type: "string" },
203
+ normalize: { type: "boolean" },
204
+ prependUnicode: { type: "boolean" },
205
+ round: { type: "string" },
206
+ sort: {
207
+ default: !0,
208
+ type: "boolean"
209
+ },
210
+ startUnicode: { type: "string" },
211
+ template: {
212
+ shortFlag: "t",
213
+ type: "string"
214
+ },
215
+ templateClassName: {
216
+ shortFlag: "c",
217
+ type: "string"
218
+ },
219
+ templateFontName: {
220
+ shortFlag: "n",
221
+ type: "string"
222
+ },
223
+ addHashInFontUrl: {
224
+ default: !1,
225
+ type: "boolean"
226
+ },
227
+ templateFontPath: {
228
+ shortFlag: "p",
229
+ type: "string"
230
+ },
231
+ templateCacheString: {
232
+ default: "",
233
+ type: "string"
234
+ },
235
+ verbose: {
236
+ default: !1,
237
+ type: "boolean"
238
+ },
239
+ version: {
240
+ shortFlag: "v",
241
+ type: "boolean"
242
+ }
243
+ }, O = { url: r(t).href }, k = ((e = process.argv.slice(2)) => i(E, {
244
+ argv: [...e],
245
+ autoHelp: !1,
246
+ autoVersion: !1,
247
+ flags: D,
248
+ importMeta: O,
249
+ pkg: T
250
+ }))(), A = /^https?:\/\//iu, j = (e) => A.test(e), M = (e) => {
251
+ if (j(e)) try {
252
+ return c.extname(new URL(e).pathname).toLowerCase();
253
+ } catch {
254
+ return "";
255
+ }
256
+ return c.extname(e).toLowerCase();
257
+ }, N = async (e) => (await Promise.all(e.map((e) => j(e) ? Promise.resolve([e]) : u(e)))).flat(), P = (e) => {
258
+ let t = e;
259
+ j(e) && (t = new URL(e).pathname);
260
+ let n = c.basename(t), r = M(e);
261
+ return r === ".woff2" ? n.slice(0, -6) : r === ".woff" ? n.slice(0, -5) : n.replace(/\.[^.]+$/u, "");
262
+ }, F = {
263
+ ".woff": "-woff",
264
+ ".woff2": "-woff2"
265
+ }, I = (e) => {
266
+ let t = e.map((e) => P(e)), n = /* @__PURE__ */ new Map();
267
+ for (let e of t) n.set(e, (n.get(e) ?? 0) + 1);
268
+ return e.map((e, r) => {
269
+ let i = t[r], a = (n.get(i) ?? 0) > 1, o = M(e);
270
+ return a ? `${i}${F[o] ?? `-${r + 1}`}` : i;
271
+ });
272
+ }, L = () => c.resolve(n, "../templates"), R = (e) => `${L()}/template.${e}.njk`, z = () => {
273
+ let e = L();
274
+ return {
275
+ css: { path: c.join(e, "template.css.njk") },
276
+ html: { path: c.join(e, "template.html.njk") },
277
+ json: { path: c.join(e, "template.json.njk") },
278
+ scss: { path: c.join(e, "template.scss.njk") },
279
+ styl: { path: c.join(e, "template.styl.njk") }
280
+ };
281
+ }, B = (e) => ({
282
+ prependUnicode: !!e.prependUnicode,
283
+ startUnicode: Number(e.startUnicode)
284
+ }), V = (e) => ({
285
+ ascent: e.ascent,
286
+ centerHorizontally: e.centerHorizontally,
287
+ descent: e.descent,
288
+ fixedWidth: e.fixedWidth,
289
+ fontHeight: e.fontHeight,
290
+ fontId: e.fontId,
291
+ fontName: e.fontName,
292
+ fontStyle: e.fontStyle,
293
+ fontWeight: e.fontWeight,
294
+ metadata: e.metadata,
295
+ normalize: e.normalize,
296
+ round: e.round
297
+ }), H = (e) => Buffer.from(y(e)), U = 1330926671, de = 1953658213, fe = 65536, pe = (e) => {
298
+ if (e.length < 4) throw Error("SFNT buffer is too short to read flavor");
299
+ let t = e.readUInt32BE(0);
300
+ if (t === U) return "otf";
301
+ if (t === de || t === fe) return "ttf";
302
+ throw Error(`Unsupported SFNT flavor 0x${t.toString(16)}`);
303
+ }, me = /* @__PURE__ */ S(((e, t) => {
304
+ t.exports = function(e) {
305
+ 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;
306
+ };
307
+ })), he = /* @__PURE__ */ S(((e, t) => {
308
+ t.exports = function(e) {
309
+ 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;
310
+ };
311
+ })), ge = /* @__PURE__ */ w(me()), _e = /* @__PURE__ */ w(he()), ve = (e, t) => {
312
+ let n = M(t);
313
+ if (n === ".woff2" && !(0, _e.default)(e)) throw Error(`URL did not return a valid WOFF2 font: ${t}`);
314
+ if (n === ".woff" && !(0, ge.default)(e)) throw Error(`URL did not return a valid WOFF font: ${t}`);
315
+ if (e.length === 0) throw Error(`URL returned an empty response: ${t}`);
316
+ }, ye = async (e) => {
317
+ let t;
318
+ try {
319
+ t = await fetch(e);
320
+ } catch (t) {
321
+ let n = String(t);
322
+ throw t instanceof Error && (n = t.message), Error(`Failed to fetch font URL ${e}: ${n}`);
323
+ }
324
+ if (!t.ok) throw Error(`Failed to fetch font URL ${e}: HTTP ${t.status} ${t.statusText}`);
325
+ let n = await t.arrayBuffer(), r = Buffer.from(n);
326
+ return ve(r, e), r;
327
+ }, W = /* @__PURE__ */ new Set([".woff", ".woff2"]), G = ".svg", K = [
328
+ "svg",
329
+ "ttf",
330
+ "eot",
331
+ "woff",
332
+ "woff2"
333
+ ], q = (e) => e === G, J = (e) => W.has(e), be = (e) => q(e) || J(e), xe = (e) => {
334
+ if (e.length === 0) return "empty";
335
+ let t = e.map((e) => M(e));
336
+ if (!t.every(be)) return "empty";
337
+ let n = t.some(q), r = t.some(J);
338
+ return n && r ? "mixed" : r ? "webfont" : n ? "svg" : "empty";
339
+ }, Se = (e) => {
340
+ 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.");
341
+ }, Y = (e, t) => t === "svg" ? e.filter((e) => M(e) === G) : t === "webfont" ? e.filter((e) => W.has(M(e))) : [], Ce = (e) => {
342
+ let t = e.filter((e) => e === "ttf" || e === "otf");
343
+ if (e.length === K.length && K.every((t) => e.includes(t))) return ["ttf"];
344
+ if (t.length === 0) throw Error("formats must include \"ttf\" and/or \"otf\" when converting WOFF/WOFF2 input");
345
+ return [...new Set(t)];
346
+ }, we = (e) => {
347
+ if (e.length === 0) throw Error("No WOFF or WOFF2 files matched");
348
+ }, Te = (e) => {
349
+ if (e.template) throw Error("Templates are not supported when converting WOFF/WOFF2 input");
350
+ if (e.glyphTransformFn) throw Error("glyphTransformFn is not supported when converting WOFF/WOFF2 input");
351
+ }, Ee = (e) => {
352
+ let { decompressed: t, sfnt: n, format: r, flavor: i, source: a } = e;
353
+ if (r === "ttf" && i !== "ttf") throw Error(`Input decompresses to OpenType (OTF). Request "otf" format instead of "ttf" for ${a}.`);
354
+ if (r === "otf" && i !== "otf") throw Error(`Input decompresses to TrueType (TTF). Request "ttf" format instead of "otf" for ${a}.`);
355
+ if (r === "ttf") {
356
+ t.ttf = n;
357
+ return;
358
+ }
359
+ t.otf = n;
360
+ }, De = (e) => j(e) ? ye(e) : ne.readFile(e), Oe = async (e, t, n) => {
361
+ n && console.log(`Decompressing ${e}...`);
362
+ let r = await De(e), i = Buffer.from(await b.convert(r, "sfnt")), a = pe(i), o = { source: e };
363
+ for (let n of t) Ee({
364
+ decompressed: o,
365
+ sfnt: i,
366
+ format: n,
367
+ flavor: a,
368
+ source: e
369
+ });
370
+ return o;
371
+ }, ke = async (e, t) => {
372
+ Te(t), we(e);
373
+ let n = Ce(t.formats), r = await Promise.all(e.map((e) => Oe(e, n, t.verbose))), i = {
374
+ config: { ...t },
375
+ decompressedFonts: r
376
+ };
377
+ return r.length === 1 && (i.ttf = r[0].ttf, i.otf = r[0].otf), i;
378
+ }, Ae = ie, je = (e) => e === void 0 ? [] : Array.isArray(e) ? e : [e], Me = (e) => ({
379
+ name: e.name,
380
+ unicode: je(e.unicode)
381
+ }), Ne = (e, t) => {
382
+ let n = t.metadataProvider || v(B(t)), r = new re.Parser(), i = Ae(t.maxConcurrency);
383
+ return Promise.all(e.map((e) => i(() => new Promise((t, n) => {
384
+ let i = o(e), a = "";
385
+ i.on("error", (e) => n(e)).on("data", (e) => {
386
+ a += e.toString();
387
+ }).on("end", () => a.length === 0 ? n(/* @__PURE__ */ Error(`Empty file ${e}`)) : r.parseString(a, (r) => r ? n(r) : t({
388
+ contents: a,
389
+ srcPath: e
390
+ })));
391
+ })))).then((e) => {
392
+ let r = e;
393
+ t.sort && (r = e.sort((e, t) => _(e.srcPath, t.srcPath)));
394
+ let { ligatures: i } = t;
395
+ return Promise.all(r.map((e) => new Promise((t, r) => {
396
+ n(e.srcPath, (n, a) => {
397
+ if (n) return r(n);
398
+ if (!a) return r(/* @__PURE__ */ Error(`Missing metadata for ${e.srcPath}`));
399
+ let o = Me(a);
400
+ return i && o.unicode.push(a.name.replace(/-/gu, "_")), e.metadata = o, t(e);
401
+ });
402
+ })));
403
+ });
404
+ }, Pe = (e) => {
405
+ if (!e?.files) throw Error("You must pass webfont a `files` glob");
406
+ return {
407
+ centerHorizontally: !1,
408
+ descent: 0,
409
+ fixedWidth: !1,
410
+ fontHeight: void 0,
411
+ fontId: void 0,
412
+ fontName: "webfont",
413
+ fontStyle: "",
414
+ fontWeight: "",
415
+ formats: [
416
+ "svg",
417
+ "ttf",
418
+ "eot",
419
+ "woff",
420
+ "woff2"
421
+ ],
422
+ formatsOptions: { ttf: {
423
+ copyright: null,
424
+ ts: null,
425
+ version: null
426
+ } },
427
+ ligatures: !0,
428
+ maxConcurrency: 100,
429
+ metadata: void 0,
430
+ normalize: !1,
431
+ prependUnicode: !1,
432
+ round: 0x9184e72a000,
433
+ sort: !0,
434
+ startUnicode: 59905,
435
+ templateFontPath: "./",
436
+ verbose: !1,
437
+ ...e
438
+ };
439
+ }, Fe = (e, t) => {
440
+ if (e === "woff2") {
441
+ if (!t.woff2) throw Error("Missing woff2 buffer for template rendering");
442
+ return Buffer.from(t.woff2).toString("base64");
443
+ }
444
+ let n = t[e];
445
+ if (!n) throw Error(`Missing ${e} buffer for template rendering`);
446
+ return n.toString("base64");
447
+ }, Ie = (e, t = {}) => Buffer.from(ae(e, t).buffer), Le = (e) => "filepath" in e, Re = async (e) => {
448
+ let t = d("webfont", { searchStrategy: "global" });
449
+ if (e.configFile) {
450
+ let n = c.resolve(process.cwd(), e.configFile);
451
+ return await t.load(n) ?? {};
452
+ }
453
+ return await t.search(process.cwd()) ?? {};
454
+ }, ze = (e, t) => {
455
+ let n = "";
456
+ return new Promise((r, i) => {
457
+ t.verbose && console.log("Generating SVG font...");
458
+ let a = new te(V(t)).on("finish", () => r(n)).on("data", (e) => {
459
+ n += e;
460
+ }).on("error", (e) => i(e));
461
+ e.forEach((e) => {
462
+ let t = new m();
463
+ t.push(e.contents), t.push(null), t.metadata = e.metadata ?? {
464
+ name: "",
465
+ unicode: []
466
+ }, a.write(t);
467
+ }), a.end();
468
+ });
469
+ }, Be = (e) => H(e), Ve = (e, t) => Buffer.from(h(e, t).buffer), He = (e) => g.compress(e), Ue = async (e) => {
470
+ let t = Pe(e);
471
+ delete t.filePath;
472
+ let r = await Re({ configFile: t.configFile }), i;
473
+ Le(r) && (t = f(t, r.config, { arrayMerge: (e, t) => t }), i = r.filepath);
474
+ let a;
475
+ a = Array.isArray(t.files) ? t.files : [t.files];
476
+ let o = await N(a), s = xe(o);
477
+ if (s === "mixed") throw Error("Cannot mix SVG icons with WOFF/WOFF2 font files in the same run");
478
+ if (s === "empty") throw Error("Files glob patterns specified did not match any supported files");
479
+ if (s === "webfont") {
480
+ let e = await ke(Y(o, s), t);
481
+ return i && (e.config = {
482
+ ...t,
483
+ filePath: i
484
+ }), e;
485
+ }
486
+ Se(t.formats);
487
+ let l = await Ne(Y(o, "svg"), t);
488
+ if (t.glyphTransformFn) {
489
+ let e = t.glyphTransformFn, n = l.map(async (t) => {
490
+ let n = await e(t.metadata ?? {
491
+ name: "",
492
+ unicode: []
493
+ });
494
+ return {
495
+ ...t,
496
+ metadata: n
497
+ };
498
+ });
499
+ l = await Promise.all(n);
500
+ }
501
+ let u = {};
502
+ t.formatsOptions?.ttf && (u = t.formatsOptions.ttf);
503
+ let d = await ze(l, t), m = Ie(d, u), h = {
504
+ glyphsData: l,
505
+ hash: ee.createHash("md5").update(d).digest("hex"),
506
+ svg: d,
507
+ ttf: m
508
+ }, { formats: g } = t;
509
+ if (g.includes("eot") && (h.eot = Be(m)), g.includes("woff")) {
510
+ let e;
511
+ typeof t.metadata == "string" && (e = t.metadata), h.woff = Ve(m, { metadata: e });
512
+ }
513
+ if (g.includes("woff2") && (h.woff2 = Buffer.from(await He(m))), t.template) {
514
+ let e = z(), r;
515
+ if (Object.keys(e).includes(t.template)) {
516
+ h.usedBuildInTemplate = !0;
517
+ let e = c.resolve(n, "../..");
518
+ p.configure(e), r = R(t.template);
519
+ } else {
520
+ let e = c.resolve(t.template);
521
+ p.configure(c.dirname(e)), r = c.resolve(e);
522
+ }
523
+ let i = {};
524
+ t.addHashInFontUrl && (i = { hash: h.hash });
525
+ let a = f.all([
526
+ { glyphs: h.glyphsData?.map((e) => e.metadata) ?? [] },
527
+ t,
528
+ {
529
+ cacheString: t.templateCacheString || Date.now(),
530
+ className: t.templateClassName || t.fontName,
531
+ fontName: t.templateFontName || t.fontName,
532
+ fontPath: t.templateFontPath.replace(/\/?$/u, "/")
533
+ },
534
+ i,
535
+ { fonts: Object.fromEntries(new Map(g.map((e) => [e, () => Fe(e, h)]))) }
536
+ ]);
537
+ h.template = p.render(r, a);
538
+ }
539
+ return g.includes("svg") || delete h.svg, g.includes("ttf") || delete h.ttf, g.includes("otf") || delete h.otf, i ? h.config = {
540
+ ...t,
541
+ filePath: i
542
+ } : h.config = t, h;
543
+ }, X = /* @__PURE__ */ new Set([
544
+ "eot",
545
+ "otf",
546
+ "svg",
547
+ "ttf",
548
+ "woff",
549
+ "woff2"
550
+ ]), Z = (e) => {
551
+ if (typeof e != "string" || !X.has(e)) throw Error(`Invalid format "${String(e)}". Expected one of: ${[...X].join(", ")}`);
552
+ return e;
553
+ }, We = (e) => {
554
+ let t = e.trim();
555
+ if (t.startsWith("{") || t.startsWith("[")) {
556
+ let e = JSON.parse(t);
557
+ if (!Array.isArray(e)) throw Error("formats must be a JSON array");
558
+ return e.map(Z);
559
+ }
560
+ if (t.length === 0) throw Error("formats must not be empty");
561
+ return t.split(",").map((e) => Z(e.trim()));
562
+ }, Ge = [
563
+ "svg",
564
+ "ttf",
565
+ "otf",
566
+ "eot",
567
+ "woff",
568
+ "woff2",
569
+ "hash",
570
+ "template"
571
+ ], Q = (e) => {
572
+ let t = {};
573
+ return typeof e.flags.config == "string" && (t.configFile = l.silent(process.cwd(), e.flags.config) || s.join(process.cwd(), e.flags.config)), e.flags.fontName && (t.fontName = e.flags.fontName), e.flags.formats && (t.formats = We(e.flags.formats)), e.flags.dest && (t.dest = e.flags.dest), e.flags.destCreate && (t.destCreate = e.flags.destCreate), e.flags.template && (t.template = 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.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 === !1 && (t.ligatures = e.flags.ligatures), e.flags.addHashInFontUrl && (t.addHashInFontUrl = e.flags.addHashInFontUrl), t;
574
+ }, $ = (e) => {
575
+ if (!e.config) throw Error("Missing config in webfont result");
576
+ return e.config;
577
+ }, Ke = (e, t) => (e.config = {
578
+ ...$(e),
579
+ dest: t.dest,
580
+ destTemplate: t.destTemplate
581
+ }, e), qe = (e, t) => {
582
+ if (!e.template) return;
583
+ let n = t.dest ?? process.cwd(), r;
584
+ return r = typeof t.destTemplate == "string" ? t.destTemplate : n, e.usedBuildInTemplate && typeof t.template == "string" ? s.join(r, `${t.fontName}.${t.template}`) : typeof t.template == "string" ? s.join(r, s.basename(t.template).replace(".njk", "")) : r;
585
+ }, Je = (e, t, n, r) => {
586
+ let i = n.fontName, a = n.dest ?? process.cwd();
587
+ return e === "template" ? s.resolve(r ?? a) : e === "hash" ? s.resolve(s.join(a, `${i}.hash`)) : s.resolve(s.join(a, `${i}.${e}`));
588
+ }, Ye = (e) => /* @__PURE__ */ Error(`Destination directory "${e}" does not exist. Use --dest-create (-m) to create it.`), Xe = async (e, t) => {
589
+ try {
590
+ await a.promises.access(e, a.constants.F_OK);
591
+ } catch {
592
+ if (t) {
593
+ await a.promises.mkdir(e, { recursive: !0 });
594
+ return;
595
+ }
596
+ throw Ye(e);
597
+ }
598
+ }, Ze = (e, t, n) => e.length === 1 && n.fontName ? n.fontName : I(e.map((e) => e.source))[e.indexOf(t)] ?? n.fontName, Qe = async (e, t, n) => {
599
+ await Promise.all(e.flatMap((r) => {
600
+ let i = Ze(e, r, t), o = [];
601
+ return r.ttf && o.push(a.promises.writeFile(s.resolve(s.join(n, `${i}.ttf`)), r.ttf)), r.otf && o.push(a.promises.writeFile(s.resolve(s.join(n, `${i}.otf`)), r.otf)), o;
602
+ }));
603
+ }, $e = async (e) => {
604
+ let t = $(e), n = t.dest ?? process.cwd(), r = qe(e, t);
605
+ return e.template && delete e.hash, await Xe(n, t.destCreate), e.decompressedFonts && e.decompressedFonts.length > 1 ? (await Qe(e.decompressedFonts, t, n), e) : (await Promise.all(Ge.filter((t) => e[t] !== void 0).map(async (n) => {
606
+ let i = e[n];
607
+ if (i === void 0) return;
608
+ let o = Je(n, e, t, r);
609
+ await a.promises.writeFile(o, i);
610
+ })), e);
611
+ }, et = (e) => typeof e == "object" && e && "code" in e && typeof e.code == "number" ? e.code : 1, tt = (e) => {
612
+ nt(e).catch((e) => {
613
+ console.log(e.stack), process.exit(et(e));
614
+ });
615
+ }, nt = async (e) => {
616
+ e.flags.help && e.showHelp(), e.flags.version && e.showVersion();
617
+ let t = {
618
+ ...Q(e),
619
+ files: e.input
620
+ };
621
+ t.files.length === 0 && e.showHelp();
622
+ let n = await Ue(t);
623
+ return Ke(n, t), $e(n);
624
+ };
625
+ //#endregion
626
+ //#region src/cli/index.ts
627
+ tt(k);
628
+ //#endregion