@fontmin-rs/wasm 0.1.0-beta.1 → 0.1.0-beta.3
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/dist/fontmin_wasm_core_bg.wasm +0 -0
- package/dist/index.d.mts +25 -6
- package/dist/index.mjs +91 -21
- package/package.json +2 -2
|
Binary file
|
package/dist/index.d.mts
CHANGED
|
@@ -5,10 +5,31 @@ type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Modul
|
|
|
5
5
|
declare function isWasmInitialized(): boolean;
|
|
6
6
|
declare function initWasm(input?: InitInput): Promise<void>;
|
|
7
7
|
//#endregion
|
|
8
|
+
//#region src/diagnostics.d.ts
|
|
9
|
+
type FontminDiagnosticCode = 'fontmin::config' | 'fontmin::convert_failed' | 'fontmin::invalid_font' | 'fontmin::io' | 'fontmin::missing_glyph' | 'fontmin::napi_bridge_failed' | 'fontmin::plugin_failed' | 'fontmin::unsupported_format';
|
|
10
|
+
declare class FontminDiagnosticError extends Error {
|
|
11
|
+
readonly name = "FontminDiagnosticError";
|
|
12
|
+
readonly code: FontminDiagnosticCode;
|
|
13
|
+
constructor(code: FontminDiagnosticCode, message: string, options?: ErrorOptions);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
8
16
|
//#region types.d.ts
|
|
9
17
|
type FontFormat = 'ttf' | 'otf' | 'woff' | 'woff2' | 'eot' | 'svg' | 'css' | 'unknown';
|
|
10
18
|
type OutputFormat = 'ttf' | 'woff' | 'woff2' | 'eot' | 'svg' | 'css';
|
|
11
19
|
type LayoutSubsetMode = 'drop' | 'conservative' | 'preserve';
|
|
20
|
+
type MissingGlyphPolicy = 'ignore' | 'warn' | 'error';
|
|
21
|
+
interface CoverageOptions {
|
|
22
|
+
basicText?: boolean;
|
|
23
|
+
text?: string;
|
|
24
|
+
unicodeRanges?: string[];
|
|
25
|
+
unicodes?: number[];
|
|
26
|
+
}
|
|
27
|
+
interface CoverageReport {
|
|
28
|
+
coveragePercent: number;
|
|
29
|
+
missing: number[];
|
|
30
|
+
requested: number[];
|
|
31
|
+
supported: number[];
|
|
32
|
+
}
|
|
12
33
|
interface FontMetadata {
|
|
13
34
|
ascender: number;
|
|
14
35
|
descender: number;
|
|
@@ -25,15 +46,12 @@ interface FontInfo {
|
|
|
25
46
|
metadata: FontMetadata;
|
|
26
47
|
size: number;
|
|
27
48
|
}
|
|
28
|
-
interface SubsetOptions {
|
|
29
|
-
basicText?: boolean;
|
|
49
|
+
interface SubsetOptions extends CoverageOptions {
|
|
30
50
|
keepNotdef?: boolean;
|
|
31
51
|
layout?: LayoutSubsetMode;
|
|
52
|
+
missingGlyphs?: MissingGlyphPolicy;
|
|
32
53
|
preserveHinting?: boolean;
|
|
33
|
-
text?: string;
|
|
34
54
|
trim?: boolean;
|
|
35
|
-
unicodeRanges?: string[];
|
|
36
|
-
unicodes?: number[];
|
|
37
55
|
}
|
|
38
56
|
interface WoffOptions {
|
|
39
57
|
compressionLevel?: number;
|
|
@@ -96,6 +114,7 @@ interface CssOptions {
|
|
|
96
114
|
//#endregion
|
|
97
115
|
//#region src/native.d.ts
|
|
98
116
|
declare function subsetTtf(input: Uint8Array, options?: SubsetOptions): Promise<Uint8Array>;
|
|
117
|
+
declare function analyzeCoverage(input: Uint8Array, options?: CoverageOptions): Promise<CoverageReport>;
|
|
99
118
|
declare function ttfToWoff(input: Uint8Array, options?: WoffOptions): Promise<Uint8Array>;
|
|
100
119
|
declare function woffToTtf(input: Uint8Array): Promise<Uint8Array>;
|
|
101
120
|
declare function ttfToWoff2(input: Uint8Array, options?: Ttf2Woff2Options): Promise<Uint8Array>;
|
|
@@ -193,4 +212,4 @@ interface BrowserOptimizeConfig {
|
|
|
193
212
|
}
|
|
194
213
|
declare function optimizeBrowser(config: BrowserOptimizeConfig): Promise<BrowserAsset[]>;
|
|
195
214
|
//#endregion
|
|
196
|
-
export { type BrowserAsset, type BrowserOptimizeConfig, type BrowserPlugin, type BrowserPluginContext, type CssFontSource, type CssGlyph, type CssOptions, type DeliverySlice, type DeliverySlicesOptions, type FontFormat, type FontInfo, type FontMetadata, type FontminCompatPresetOptions, type GlyphOptions, type LayoutSubsetMode, type MaybePromise, type ModernWebOptions, type Otf2TtfOptions, type Otf2TtfPluginOptions, type OutputFormat, type SubsetOptions, type Svg2TtfOptions, type Svg2TtfPluginOptions, type SvgIcon, type Svgs2TtfOptions, type Svgs2TtfPluginOptions, type Ttf2EotOptions, type Ttf2EotPluginOptions, type Ttf2SvgOptions, type Ttf2SvgPluginOptions, type Ttf2Woff2Options, type Ttf2Woff2PluginOptions, type Ttf2WoffPluginOptions, type WoffOptions, css, deliverySlices, eotToTtf, fontminCompatPreset, generateFontFaceCss, glyph, initWasm, inspect, isWasmInitialized, modernWeb, optimizeBrowser, otf2ttf, otfToTtf, subsetTtf, svg2ttf, svgFontToTtf, svgs2ttf, svgsToTtf, ttf2eot, ttf2svg, ttf2woff, ttf2woff2, ttfToEot, ttfToSvg, ttfToWoff, ttfToWoff2, validateWoff2, woff2ToTtf, woffToTtf };
|
|
215
|
+
export { type BrowserAsset, type BrowserOptimizeConfig, type BrowserPlugin, type BrowserPluginContext, type CoverageOptions, type CoverageReport, type CssFontSource, type CssGlyph, type CssOptions, type DeliverySlice, type DeliverySlicesOptions, type FontFormat, type FontInfo, type FontMetadata, type FontminCompatPresetOptions, type FontminDiagnosticCode, FontminDiagnosticError, type GlyphOptions, type LayoutSubsetMode, type MaybePromise, type MissingGlyphPolicy, type ModernWebOptions, type Otf2TtfOptions, type Otf2TtfPluginOptions, type OutputFormat, type SubsetOptions, type Svg2TtfOptions, type Svg2TtfPluginOptions, type SvgIcon, type Svgs2TtfOptions, type Svgs2TtfPluginOptions, type Ttf2EotOptions, type Ttf2EotPluginOptions, type Ttf2SvgOptions, type Ttf2SvgPluginOptions, type Ttf2Woff2Options, type Ttf2Woff2PluginOptions, type Ttf2WoffPluginOptions, type WoffOptions, analyzeCoverage, css, deliverySlices, eotToTtf, fontminCompatPreset, generateFontFaceCss, glyph, initWasm, inspect, isWasmInitialized, modernWeb, optimizeBrowser, otf2ttf, otfToTtf, subsetTtf, svg2ttf, svgFontToTtf, svgs2ttf, svgsToTtf, ttf2eot, ttf2svg, ttf2woff, ttf2woff2, ttfToEot, ttfToSvg, ttfToWoff, ttfToWoff2, validateWoff2, woff2ToTtf, woffToTtf };
|
package/dist/index.mjs
CHANGED
|
@@ -9,28 +9,74 @@ function assertWasmInitialized() {
|
|
|
9
9
|
}
|
|
10
10
|
async function getWasmModule() {
|
|
11
11
|
assertWasmInitialized();
|
|
12
|
-
|
|
12
|
+
const module = initialization;
|
|
13
|
+
if (module === void 0) throw new Error("fontmin-rs WASM runtime initialization is unavailable");
|
|
14
|
+
return module;
|
|
13
15
|
}
|
|
14
16
|
async function initWasm(input) {
|
|
15
|
-
initialization ??=
|
|
16
|
-
await module.default(input === void 0 ? void 0 : { module_or_path: input });
|
|
17
|
-
if (module.runtime_name() !== "fontmin-rs") throw new Error("fontmin-rs WASM runtime did not initialize correctly");
|
|
18
|
-
initialized = true;
|
|
19
|
-
return module;
|
|
20
|
-
});
|
|
17
|
+
initialization ??= initializeWasm(input);
|
|
21
18
|
await initialization;
|
|
22
19
|
}
|
|
20
|
+
async function initializeWasm(input) {
|
|
21
|
+
const module = await import("./fontmin_wasm_core-Cn_EVAE9.mjs");
|
|
22
|
+
await module.default(input === void 0 ? void 0 : { module_or_path: input });
|
|
23
|
+
if (module.runtime_name() !== "fontmin-rs") throw new Error("fontmin-rs WASM runtime did not initialize correctly");
|
|
24
|
+
initialized = true;
|
|
25
|
+
return module;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/diagnostics.ts
|
|
29
|
+
const bridgeDiagnosticPattern = /^\[(?<code>fontmin::[a-z_]+)\] (?<message>[\s\S]+)$/u;
|
|
30
|
+
var FontminDiagnosticError = class extends Error {
|
|
31
|
+
name = "FontminDiagnosticError";
|
|
32
|
+
code;
|
|
33
|
+
constructor(code, message, options) {
|
|
34
|
+
super(message, options);
|
|
35
|
+
this.code = code;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
function normalizeFontminDiagnostic(error) {
|
|
39
|
+
let message;
|
|
40
|
+
if (error instanceof Error) message = error.message;
|
|
41
|
+
else if (typeof error === "string") message = error;
|
|
42
|
+
const match = message?.match(bridgeDiagnosticPattern);
|
|
43
|
+
if (match === null || match === void 0) {
|
|
44
|
+
if (error instanceof Error) return error;
|
|
45
|
+
if (typeof error === "string") return new Error(error, { cause: error });
|
|
46
|
+
return new Error("fontmin-rs WASM operation failed", { cause: error });
|
|
47
|
+
}
|
|
48
|
+
const code = match.groups?.["code"];
|
|
49
|
+
const diagnosticMessage = match.groups?.["message"];
|
|
50
|
+
if (code === void 0 || diagnosticMessage === void 0) return new Error("fontmin-rs WASM operation returned an invalid diagnostic", { cause: error });
|
|
51
|
+
return new FontminDiagnosticError(code, diagnosticMessage, { cause: error });
|
|
52
|
+
}
|
|
53
|
+
function withFontminDiagnostics(operation) {
|
|
54
|
+
try {
|
|
55
|
+
return operation();
|
|
56
|
+
} catch (error) {
|
|
57
|
+
throw normalizeFontminDiagnostic(error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
23
60
|
//#endregion
|
|
24
61
|
//#region src/native.ts
|
|
25
62
|
function bytes(value) {
|
|
26
63
|
return new Uint8Array(value);
|
|
27
64
|
}
|
|
28
65
|
async function binary(operation, input, options = {}) {
|
|
29
|
-
|
|
66
|
+
const wasm = await getWasmModule();
|
|
67
|
+
return withFontminDiagnostics(() => bytes(wasm.transform(operation, input, options)));
|
|
30
68
|
}
|
|
31
69
|
async function subsetTtf(input, options = {}) {
|
|
70
|
+
if ((options.missingGlyphs ?? "warn") === "warn") {
|
|
71
|
+
const warning = missingGlyphWarning(await analyzeCoverage(input, coverageOptions(options)));
|
|
72
|
+
if (warning !== void 0) console.warn(warning);
|
|
73
|
+
}
|
|
32
74
|
return binary("subsetTtf", input, options);
|
|
33
75
|
}
|
|
76
|
+
async function analyzeCoverage(input, options = {}) {
|
|
77
|
+
const wasm = await getWasmModule();
|
|
78
|
+
return withFontminDiagnostics(() => wasm.transform("analyzeCoverage", input, options));
|
|
79
|
+
}
|
|
34
80
|
async function ttfToWoff(input, options = {}) {
|
|
35
81
|
return binary("ttfToWoff", input, options);
|
|
36
82
|
}
|
|
@@ -44,7 +90,8 @@ async function woff2ToTtf(input) {
|
|
|
44
90
|
return binary("woff2ToTtf", input);
|
|
45
91
|
}
|
|
46
92
|
async function validateWoff2(input) {
|
|
47
|
-
|
|
93
|
+
const wasm = await getWasmModule();
|
|
94
|
+
withFontminDiagnostics(() => wasm.transform("validateWoff2", input, {}));
|
|
48
95
|
}
|
|
49
96
|
async function ttfToEot(input, options = {}) {
|
|
50
97
|
return binary("ttfToEot", input, options);
|
|
@@ -53,22 +100,41 @@ async function eotToTtf(input) {
|
|
|
53
100
|
return binary("eotToTtf", input);
|
|
54
101
|
}
|
|
55
102
|
async function ttfToSvg(input, options = {}) {
|
|
56
|
-
|
|
103
|
+
const wasm = await getWasmModule();
|
|
104
|
+
return withFontminDiagnostics(() => wasm.transform("ttfToSvg", input, options));
|
|
57
105
|
}
|
|
58
106
|
async function svgFontToTtf(input, options = {}) {
|
|
59
|
-
|
|
107
|
+
const wasm = await getWasmModule();
|
|
108
|
+
return withFontminDiagnostics(() => bytes(wasm.transform_text("svgFontToTtf", input, options)));
|
|
60
109
|
}
|
|
61
110
|
async function svgsToTtf(inputs, options = {}) {
|
|
62
|
-
|
|
111
|
+
const wasm = await getWasmModule();
|
|
112
|
+
return withFontminDiagnostics(() => bytes(wasm.transform_icons(inputs, options)));
|
|
63
113
|
}
|
|
64
114
|
async function otfToTtf(input, options = {}) {
|
|
65
115
|
return binary("otfToTtf", input, options);
|
|
66
116
|
}
|
|
67
117
|
async function inspect(input) {
|
|
68
|
-
|
|
118
|
+
const wasm = await getWasmModule();
|
|
119
|
+
return withFontminDiagnostics(() => wasm.transform("inspect", input, {}));
|
|
69
120
|
}
|
|
70
121
|
async function generateFontFaceCss(sources, options = {}) {
|
|
71
|
-
|
|
122
|
+
const wasm = await getWasmModule();
|
|
123
|
+
return withFontminDiagnostics(() => wasm.generate_css(sources, options));
|
|
124
|
+
}
|
|
125
|
+
function coverageOptions(options) {
|
|
126
|
+
const coverage = {};
|
|
127
|
+
if (options.basicText !== void 0) coverage.basicText = options.basicText;
|
|
128
|
+
if (options.text !== void 0) coverage.text = options.text;
|
|
129
|
+
if (options.unicodeRanges !== void 0) coverage.unicodeRanges = options.unicodeRanges;
|
|
130
|
+
if (options.unicodes !== void 0) coverage.unicodes = options.unicodes;
|
|
131
|
+
return coverage;
|
|
132
|
+
}
|
|
133
|
+
function missingGlyphWarning(report) {
|
|
134
|
+
if (report.missing.length === 0) return;
|
|
135
|
+
const visible = report.missing.slice(0, 16).map((codepoint) => `U+${codepoint.toString(16).toUpperCase().padStart(4, "0")}`).join(", ");
|
|
136
|
+
const remaining = report.missing.length - 16;
|
|
137
|
+
return `missing glyphs for requested Unicode code points: ${visible}${remaining > 0 ? `, and ${remaining} more` : ""}`;
|
|
72
138
|
}
|
|
73
139
|
//#endregion
|
|
74
140
|
//#region src/plugins.ts
|
|
@@ -83,6 +149,7 @@ function glyph(options = {}) {
|
|
|
83
149
|
basicText: false,
|
|
84
150
|
keepNotdef: true,
|
|
85
151
|
layout: "conservative",
|
|
152
|
+
missingGlyphs: "warn",
|
|
86
153
|
preserveHinting: false,
|
|
87
154
|
trim: true,
|
|
88
155
|
unicodes: [],
|
|
@@ -204,7 +271,10 @@ async function optimizeBrowser(config) {
|
|
|
204
271
|
}
|
|
205
272
|
for (const slice of slices) slicedAssets.push({
|
|
206
273
|
...asset,
|
|
207
|
-
contents: await subsetTtf(asset.contents, {
|
|
274
|
+
contents: await subsetTtf(asset.contents, {
|
|
275
|
+
missingGlyphs: "ignore",
|
|
276
|
+
unicodeRanges: slice.unicodeRanges
|
|
277
|
+
}),
|
|
208
278
|
fileName: appendFileNameSuffix(asset.fileName, slice.name),
|
|
209
279
|
unicodeRanges: slice.unicodeRanges
|
|
210
280
|
});
|
|
@@ -273,9 +343,9 @@ async function optimizeBrowser(config) {
|
|
|
273
343
|
const result = await plugin.transform(asset, context);
|
|
274
344
|
if (result === null) continue;
|
|
275
345
|
if (result === void 0) transformed.push(asset);
|
|
276
|
-
else transformed.push(...(Array.isArray(result) ? result : [result]).map(formatAsset));
|
|
346
|
+
else transformed.push(...(Array.isArray(result) ? result : [result]).map((asset) => formatAsset(asset)));
|
|
277
347
|
}
|
|
278
|
-
assets = transformed
|
|
348
|
+
assets = [...transformed, ...emitted];
|
|
279
349
|
continue;
|
|
280
350
|
}
|
|
281
351
|
if (plugin.name === "otf2ttf" && optionsOf(plugin).clone === false) {
|
|
@@ -287,7 +357,7 @@ async function optimizeBrowser(config) {
|
|
|
287
357
|
const converted = await convert(asset, plugin);
|
|
288
358
|
if (converted !== void 0) additions.push(converted);
|
|
289
359
|
}
|
|
290
|
-
assets = assets
|
|
360
|
+
assets = [...assets, ...additions];
|
|
291
361
|
}
|
|
292
362
|
return assets;
|
|
293
363
|
}
|
|
@@ -323,11 +393,11 @@ function replaceExtension(fileName, extension) {
|
|
|
323
393
|
return `${fileName.replace(/\.[^.]+$/u, "")}.${extension}`;
|
|
324
394
|
}
|
|
325
395
|
function appendFileNameSuffix(fileName, suffix) {
|
|
326
|
-
const extension = fileName.match(/(
|
|
396
|
+
const extension = fileName.match(/(?<extension>\.[^.]+)$/u)?.groups?.["extension"] ?? "";
|
|
327
397
|
return `${extension === "" ? fileName : fileName.slice(0, -extension.length)}-${suffix}${extension}`;
|
|
328
398
|
}
|
|
329
399
|
function toKebabCase(value) {
|
|
330
|
-
return value.trim().replaceAll(/([a-z])([A-Z])/gu, "
|
|
400
|
+
return value.trim().replaceAll(/(?<lower>[a-z])(?<upper>[A-Z])/gu, "$<lower>-$<upper>").replaceAll(/\s+/gu, "-").toLowerCase();
|
|
331
401
|
}
|
|
332
402
|
//#endregion
|
|
333
|
-
export { css, deliverySlices, eotToTtf, fontminCompatPreset, generateFontFaceCss, glyph, initWasm, inspect, isWasmInitialized, modernWeb, optimizeBrowser, otf2ttf, otfToTtf, subsetTtf, svg2ttf, svgFontToTtf, svgs2ttf, svgsToTtf, ttf2eot, ttf2svg, ttf2woff, ttf2woff2, ttfToEot, ttfToSvg, ttfToWoff, ttfToWoff2, validateWoff2, woff2ToTtf, woffToTtf };
|
|
403
|
+
export { FontminDiagnosticError, analyzeCoverage, css, deliverySlices, eotToTtf, fontminCompatPreset, generateFontFaceCss, glyph, initWasm, inspect, isWasmInitialized, modernWeb, optimizeBrowser, otf2ttf, otfToTtf, subsetTtf, svg2ttf, svgFontToTtf, svgs2ttf, svgsToTtf, ttf2eot, ttf2svg, ttf2woff, ttf2woff2, ttfToEot, ttfToSvg, ttfToWoff, ttfToWoff2, validateWoff2, woff2ToTtf, woffToTtf };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fontmin-rs/wasm",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "Browser WASM runtime for fontmin-rs.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@ntnyq/tsconfig": "^3.1.0",
|
|
28
28
|
"playwright": "^1.61.1",
|
|
29
|
-
"tsdown": "^0.22.
|
|
29
|
+
"tsdown": "^0.22.12",
|
|
30
30
|
"typescript": "^7.0.2",
|
|
31
31
|
"vitest": "^4.1.10"
|
|
32
32
|
},
|