@turntrout/subfont 1.10.7 → 1.11.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/CHANGELOG.md +1 -1
- package/README.md +21 -21
- package/lib/FontTracerPool.d.ts +22 -27
- package/lib/FontTracerPool.d.ts.map +1 -1
- package/lib/FontTracerPool.js +51 -277
- package/lib/FontTracerPool.js.map +1 -1
- package/lib/HeadlessBrowser.d.ts.map +1 -1
- package/lib/HeadlessBrowser.js +44 -28
- package/lib/HeadlessBrowser.js.map +1 -1
- package/lib/cli.js +14 -10
- package/lib/cli.js.map +1 -1
- package/lib/codepointMaps.d.ts.map +1 -1
- package/lib/codepointMaps.js +0 -3
- package/lib/codepointMaps.js.map +1 -1
- package/lib/collectTextsByPage.d.ts +2 -1
- package/lib/collectTextsByPage.d.ts.map +1 -1
- package/lib/collectTextsByPage.js +15 -4
- package/lib/collectTextsByPage.js.map +1 -1
- package/lib/escapeJsStringLiteral.d.ts.map +1 -1
- package/lib/escapeJsStringLiteral.js +12 -5
- package/lib/escapeJsStringLiteral.js.map +1 -1
- package/lib/extractVisibleText.d.ts.map +1 -1
- package/lib/extractVisibleText.js +68 -147
- package/lib/extractVisibleText.js.map +1 -1
- package/lib/fontConverter.d.ts +5 -1
- package/lib/fontConverter.d.ts.map +1 -1
- package/lib/fontConverter.js +47 -122
- package/lib/fontConverter.js.map +1 -1
- package/lib/fontConverterWorker.d.ts +14 -1
- package/lib/fontConverterWorker.d.ts.map +1 -1
- package/lib/fontConverterWorker.js +16 -16
- package/lib/fontConverterWorker.js.map +1 -1
- package/lib/fontFaceHelpers.d.ts +3 -2
- package/lib/fontFaceHelpers.d.ts.map +1 -1
- package/lib/fontFaceHelpers.js +18 -17
- package/lib/fontFaceHelpers.js.map +1 -1
- package/lib/fontFeatureHelpers.d.ts.map +1 -1
- package/lib/fontFeatureHelpers.js +5 -1
- package/lib/fontFeatureHelpers.js.map +1 -1
- package/lib/fontTracerWorker.d.ts +17 -4
- package/lib/fontTracerWorker.d.ts.map +1 -1
- package/lib/fontTracerWorker.js +31 -60
- package/lib/fontTracerWorker.js.map +1 -1
- package/lib/getCssRulesByProperty.d.ts.map +1 -1
- package/lib/getCssRulesByProperty.js +11 -2
- package/lib/getCssRulesByProperty.js.map +1 -1
- package/lib/parseCommandLineOptions.d.ts.map +1 -1
- package/lib/parseCommandLineOptions.js +12 -7
- package/lib/parseCommandLineOptions.js.map +1 -1
- package/lib/piscinaRunWithTimeout.d.ts +18 -0
- package/lib/piscinaRunWithTimeout.d.ts.map +1 -0
- package/lib/piscinaRunWithTimeout.js +78 -0
- package/lib/piscinaRunWithTimeout.js.map +1 -0
- package/lib/subfont.js.map +1 -1
- package/lib/subsetFontWithGlyphs.d.ts +1 -0
- package/lib/subsetFontWithGlyphs.d.ts.map +1 -1
- package/lib/subsetFontWithGlyphs.js +4 -2
- package/lib/subsetFontWithGlyphs.js.map +1 -1
- package/lib/subsetFonts.d.ts +4 -3
- package/lib/subsetFonts.d.ts.map +1 -1
- package/lib/subsetFonts.js +19 -11
- package/lib/subsetFonts.js.map +1 -1
- package/lib/subsetGeneration.d.ts +1 -1
- package/lib/subsetGeneration.d.ts.map +1 -1
- package/lib/subsetGeneration.js +7 -7
- package/lib/subsetGeneration.js.map +1 -1
- package/lib/types/shared.d.ts +1 -0
- package/lib/types/shared.d.ts.map +1 -1
- package/lib/types/shared.js.map +1 -1
- package/lib/unquote.d.ts +17 -0
- package/lib/unquote.d.ts.map +1 -1
- package/lib/unquote.js +63 -9
- package/lib/unquote.js.map +1 -1
- package/package.json +2 -2
|
@@ -1,179 +1,100 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
const parse5_1 = require("parse5");
|
|
3
|
+
// Tags whose textual contents (and attribute text) must NOT contribute to
|
|
4
|
+
// the rendered character set we trace for font subsetting. `title` lives in
|
|
5
|
+
// `<head>` for valid documents and is already skipped via the head subtree,
|
|
6
|
+
// but parse5 auto-promotes a stray top-level `<title>` from fragment input
|
|
7
|
+
// into the synthetic head — listing it explicitly makes the intent
|
|
8
|
+
// (browser tab titles aren't rendered with web fonts) match either parse
|
|
9
|
+
// outcome.
|
|
2
10
|
const INVISIBLE_ELEMENTS = new Set([
|
|
3
11
|
'script',
|
|
4
12
|
'style',
|
|
5
13
|
'svg',
|
|
6
14
|
'template',
|
|
7
15
|
'head',
|
|
16
|
+
'title',
|
|
8
17
|
'noscript',
|
|
9
18
|
'iframe',
|
|
10
19
|
'object',
|
|
11
20
|
'embed',
|
|
12
21
|
'datalist',
|
|
13
22
|
]);
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// Named and numeric HTML entity decoder. Covers the XML built-ins plus
|
|
30
|
-
// typographic entities commonly found in blog/article content. Rare
|
|
31
|
-
// entities are left as-is (their literal characters still enter the
|
|
32
|
-
// subset, so glyphs are never lost — just slightly overcounted).
|
|
33
|
-
const namedEntities = {
|
|
34
|
-
amp: '&',
|
|
35
|
-
lt: '<',
|
|
36
|
-
gt: '>',
|
|
37
|
-
quot: '"',
|
|
38
|
-
apos: "'",
|
|
39
|
-
nbsp: ' ',
|
|
40
|
-
// Typographic quotes & dashes
|
|
41
|
-
ldquo: '“',
|
|
42
|
-
rdquo: '”',
|
|
43
|
-
lsquo: '‘',
|
|
44
|
-
rsquo: '’',
|
|
45
|
-
mdash: '—',
|
|
46
|
-
ndash: '–',
|
|
47
|
-
hellip: '…',
|
|
48
|
-
laquo: '«',
|
|
49
|
-
raquo: '»',
|
|
50
|
-
// Common symbols
|
|
51
|
-
bull: '•',
|
|
52
|
-
middot: '·',
|
|
53
|
-
copy: '©',
|
|
54
|
-
reg: '®',
|
|
55
|
-
trade: '™',
|
|
56
|
-
times: '×',
|
|
57
|
-
divide: '÷',
|
|
58
|
-
minus: '−',
|
|
59
|
-
plusmn: '±',
|
|
60
|
-
deg: '°',
|
|
61
|
-
micro: 'µ',
|
|
62
|
-
para: '¶',
|
|
63
|
-
sect: '§',
|
|
64
|
-
// Currency
|
|
65
|
-
euro: '€',
|
|
66
|
-
pound: '£',
|
|
67
|
-
yen: '¥',
|
|
68
|
-
cent: '¢',
|
|
69
|
-
// Arrows
|
|
70
|
-
larr: '←',
|
|
71
|
-
rarr: '→',
|
|
72
|
-
uarr: '↑',
|
|
73
|
-
darr: '↓',
|
|
74
|
-
};
|
|
75
|
-
const entityRe = /&(?:#x([0-9a-fA-F]+)|#(\d+)|([a-zA-Z]+));/g;
|
|
76
|
-
// Numeric character references may name surrogate halves (U+D800–U+DFFF) or
|
|
77
|
-
// values past U+10FFFF; both produce invalid scalar values that break
|
|
78
|
-
// downstream iterators (harfbuzz, unicode-range emitter). Skip them.
|
|
79
|
-
function codePointToScalar(cp, match) {
|
|
80
|
-
if (cp > 0x10ffff || (cp >= 0xd800 && cp <= 0xdfff)) {
|
|
81
|
-
return match;
|
|
82
|
-
}
|
|
83
|
-
return String.fromCodePoint(cp);
|
|
84
|
-
}
|
|
85
|
-
function decodeEntities(str) {
|
|
86
|
-
return str.replace(entityRe, (match, hex, dec, name) => {
|
|
87
|
-
if (hex) {
|
|
88
|
-
const cp = parseInt(hex, 16);
|
|
89
|
-
return Number.isNaN(cp) ? match : codePointToScalar(cp, match);
|
|
90
|
-
}
|
|
91
|
-
if (dec) {
|
|
92
|
-
const cp = parseInt(dec, 10);
|
|
93
|
-
return Number.isNaN(cp) ? match : codePointToScalar(cp, match);
|
|
94
|
-
}
|
|
95
|
-
if (name && namedEntities[name.toLowerCase()] !== undefined) {
|
|
96
|
-
return namedEntities[name.toLowerCase()];
|
|
23
|
+
// Attributes whose values render as visible text in the page (typically
|
|
24
|
+
// surfaced as tooltips, alternative text, or input value labels).
|
|
25
|
+
const EXTRACTABLE_ATTRS = new Set([
|
|
26
|
+
'alt',
|
|
27
|
+
'title',
|
|
28
|
+
'placeholder',
|
|
29
|
+
'value',
|
|
30
|
+
'aria-label',
|
|
31
|
+
]);
|
|
32
|
+
function isHiddenInput(node) {
|
|
33
|
+
if (node.tagName !== 'input' || !node.attrs)
|
|
34
|
+
return false;
|
|
35
|
+
for (const attr of node.attrs) {
|
|
36
|
+
if (attr.name === 'type') {
|
|
37
|
+
return attr.value.toLowerCase() === 'hidden';
|
|
97
38
|
}
|
|
98
|
-
|
|
99
|
-
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
100
41
|
}
|
|
101
|
-
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
|
|
106
|
-
function
|
|
107
|
-
|
|
108
|
-
hiddenInputRe.lastIndex = 0;
|
|
109
|
-
attrRe.lastIndex = 0;
|
|
42
|
+
// parse5 maps invalid numeric character references to U+FFFD per spec, so
|
|
43
|
+
// lone surrogates should never appear. This is a belt-and-suspenders pass:
|
|
44
|
+
// downstream code (harfbuzz, unicode-range emitter) breaks on lone surrogates,
|
|
45
|
+
// so any that slip through here must not propagate.
|
|
46
|
+
const LONE_SURROGATE_RE = /[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?<![\uD800-\uDBFF])[\uDC00-\uDFFF]/g;
|
|
47
|
+
function stripLoneSurrogates(text) {
|
|
48
|
+
return text.replace(LONE_SURROGATE_RE, '');
|
|
110
49
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
50
|
+
function walk(node, parts) {
|
|
51
|
+
if (node.nodeName === '#text') {
|
|
52
|
+
if (node.value)
|
|
53
|
+
parts.push(node.value);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (node.nodeName === '#comment' || node.nodeName === '#documentType') {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (node.tagName && INVISIBLE_ELEMENTS.has(node.tagName)) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
if (node.attrs && node.attrs.length > 0) {
|
|
63
|
+
const hidden = isHiddenInput(node);
|
|
64
|
+
for (const attr of node.attrs) {
|
|
65
|
+
if (!EXTRACTABLE_ATTRS.has(attr.name))
|
|
66
|
+
continue;
|
|
67
|
+
if (hidden && attr.name === 'value')
|
|
68
|
+
continue;
|
|
69
|
+
if (attr.value)
|
|
70
|
+
parts.push(attr.value);
|
|
123
71
|
}
|
|
124
72
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
let text = html.replace(invisibleBlockRe, ' ');
|
|
130
|
-
text = text.replace(commentRe, ' ');
|
|
131
|
-
return text;
|
|
132
|
-
}
|
|
133
|
-
function extractAttributes(cleanedHtml, hiddenInputValues) {
|
|
134
|
-
attrRe.lastIndex = 0;
|
|
135
|
-
const parts = [];
|
|
136
|
-
let match;
|
|
137
|
-
while ((match = attrRe.exec(cleanedHtml)) !== null) {
|
|
138
|
-
const attrName = match[1].toLowerCase();
|
|
139
|
-
const val = match[2] ?? match[3] ?? match[4];
|
|
140
|
-
if (!val)
|
|
141
|
-
continue;
|
|
142
|
-
if (attrName === 'value' && hiddenInputValues.has(val))
|
|
143
|
-
continue;
|
|
144
|
-
parts.push(decodeEntities(val));
|
|
73
|
+
if (node.childNodes) {
|
|
74
|
+
for (const child of node.childNodes) {
|
|
75
|
+
walk(child, parts);
|
|
76
|
+
}
|
|
145
77
|
}
|
|
146
|
-
return parts;
|
|
147
|
-
}
|
|
148
|
-
function stripTagsAndDecode(cleanedHtml) {
|
|
149
|
-
const text = cleanedHtml.replace(tagRe, ' ');
|
|
150
|
-
return decodeEntities(text);
|
|
151
78
|
}
|
|
152
79
|
/**
|
|
153
80
|
* Fast extraction of visible text content from HTML source.
|
|
154
81
|
* Used as a lightweight alternative to full font-tracer for pages
|
|
155
82
|
* that share the same CSS configuration as an already-traced page.
|
|
156
83
|
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
84
|
+
* Uses parse5 (the WHATWG-spec HTML parser used by jsdom) to:
|
|
85
|
+
* - skip invisible subtrees (script, style, svg, etc.) regardless of
|
|
86
|
+
* attribute contents or nesting peculiarities
|
|
87
|
+
* - decode every named or numeric HTML entity (~2200 entities incl.
|
|
88
|
+
* accented Latin like é / ö that hand-rolled tables miss)
|
|
89
|
+
* - lowercase tag/attribute names so case variations don't leak text
|
|
162
90
|
*/
|
|
163
91
|
function extractVisibleText(html) {
|
|
164
92
|
if (!html)
|
|
165
93
|
return '';
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
// Stage 2: remove invisible content
|
|
171
|
-
const cleaned = stripInvisible(html);
|
|
172
|
-
// Stage 3: extract attributes from cleaned HTML (not original!)
|
|
173
|
-
const attrTexts = extractAttributes(cleaned, hiddenInputValues);
|
|
174
|
-
// Stage 4: strip tags and decode remaining text content
|
|
175
|
-
const bodyText = stripTagsAndDecode(cleaned);
|
|
176
|
-
return [...attrTexts, bodyText].join(' ');
|
|
94
|
+
const doc = (0, parse5_1.parse)(html);
|
|
95
|
+
const parts = [];
|
|
96
|
+
walk(doc, parts);
|
|
97
|
+
return stripLoneSurrogates(parts.join(' '));
|
|
177
98
|
}
|
|
178
99
|
extractVisibleText.INVISIBLE_ELEMENTS =
|
|
179
100
|
INVISIBLE_ELEMENTS;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractVisibleText.js","sourceRoot":"","sources":["../src/extractVisibleText.ts"],"names":[],"mappings":";AAAA,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAS;IACzC,QAAQ;IACR,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,UAAU;CACX,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"extractVisibleText.js","sourceRoot":"","sources":["../src/extractVisibleText.ts"],"names":[],"mappings":";AAAA,mCAA+B;AAE/B,0EAA0E;AAC1E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,mEAAmE;AACnE,yEAAyE;AACzE,WAAW;AACX,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAS;IACzC,QAAQ;IACR,OAAO;IACP,KAAK;IACL,UAAU;IACV,MAAM;IACN,OAAO;IACP,UAAU;IACV,QAAQ;IACR,QAAQ;IACR,OAAO;IACP,UAAU;CACX,CAAC,CAAC;AAEH,wEAAwE;AACxE,kEAAkE;AAClE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAS;IACxC,KAAK;IACL,OAAO;IACP,aAAa;IACb,OAAO;IACP,YAAY;CACb,CAAC,CAAC;AAYH,SAAS,aAAa,CAAC,IAAgB;IACrC,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAC1D,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,QAAQ,CAAC;QAC/C,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,+EAA+E;AAC/E,oDAAoD;AACpD,MAAM,iBAAiB,GACrB,yEAAyE,CAAC;AAC5E,SAAS,mBAAmB,CAAC,IAAY;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,IAAI,CAAC,IAAgB,EAAE,KAAe;IAC7C,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC9B,IAAI,IAAI,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvC,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,QAAQ,KAAK,UAAU,IAAI,IAAI,CAAC,QAAQ,KAAK,eAAe,EAAE,CAAC;QACtE,OAAO;IACT,CAAC;IACD,IAAI,IAAI,CAAC,OAAO,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACzD,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YAC9B,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,SAAS;YAChD,IAAI,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,OAAO;gBAAE,SAAS;YAC9C,IAAI,IAAI,CAAC,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACpB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,kBAAkB,CAAC,IAAY;IACtC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,GAAG,GAAG,IAAA,cAAK,EAAC,IAAI,CAAC,CAAC;IACxB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,GAAiB,EAAE,KAAK,CAAC,CAAC;IAC/B,OAAO,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC9C,CAAC;AAOA,kBAAyC,CAAC,kBAAkB;IAC3D,kBAAkB,CAAC;AAErB,iBAAS,kBAAwC,CAAC"}
|
package/lib/fontConverter.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
interface ConvertOptions {
|
|
2
|
+
signal?: AbortSignal;
|
|
3
|
+
}
|
|
4
|
+
export declare function convert(buffer: Buffer | Uint8Array, targetFormat: string, sourceFormat?: string, { signal }?: ConvertOptions): Promise<Buffer>;
|
|
2
5
|
export declare function destroy(): Promise<void>;
|
|
6
|
+
export {};
|
|
3
7
|
//# sourceMappingURL=fontConverter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontConverter.d.ts","sourceRoot":"","sources":["../src/fontConverter.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fontConverter.d.ts","sourceRoot":"","sources":["../src/fontConverter.ts"],"names":[],"mappings":"AAiBA,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAiCD,wBAAsB,OAAO,CAC3B,MAAM,EAAE,MAAM,GAAG,UAAU,EAC3B,YAAY,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,EACrB,EAAE,MAAM,EAAE,GAAE,cAAmB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ7C"}
|
package/lib/fontConverter.js
CHANGED
|
@@ -4,136 +4,61 @@ exports.convert = convert;
|
|
|
4
4
|
exports.destroy = destroy;
|
|
5
5
|
const pathModule = require("path");
|
|
6
6
|
const os = require("os");
|
|
7
|
-
const
|
|
7
|
+
const piscina_1 = require("piscina");
|
|
8
8
|
const concurrencyLimit_1 = require("./concurrencyLimit");
|
|
9
|
+
const piscinaRunWithTimeout_1 = require("./piscinaRunWithTimeout");
|
|
10
|
+
/**
|
|
11
|
+
* Font format conversion routed through a piscina worker pool. Each
|
|
12
|
+
* worker thread loads its own wawoff2 WASM instance, enabling safe
|
|
13
|
+
* parallel woff2 compression — wawoff2's shared WASM instance corrupts
|
|
14
|
+
* memory under concurrent main-thread calls.
|
|
15
|
+
*/
|
|
9
16
|
const workerPath = pathModule.join(__dirname, 'fontConverterWorker.js');
|
|
10
17
|
const CONVERT_TIMEOUT_MS = 120_000;
|
|
11
18
|
const POOL_SIZE = Math.max(1, Math.min(os.cpus().length, concurrencyLimit_1.MAX_POOL_SIZE));
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
19
|
+
let _pool = null;
|
|
20
|
+
// Held while `destroy()` is awaiting the underlying piscina teardown.
|
|
21
|
+
// Concurrent `convert()` calls await this before constructing a fresh
|
|
22
|
+
// pool — otherwise a `convert()` that lands between `_pool = null` and
|
|
23
|
+
// `pool.destroy()` would spin up a second pool alongside the dying one.
|
|
24
|
+
let _destroyPromise = null;
|
|
25
|
+
function getPool() {
|
|
26
|
+
if (_pool === null) {
|
|
27
|
+
_pool = new piscina_1.Piscina({
|
|
28
|
+
filename: workerPath,
|
|
29
|
+
// Cap concurrency at MAX_POOL_SIZE (shared with the tracer pool).
|
|
30
|
+
// Spin workers up lazily so a process that never converts woff2 pays
|
|
31
|
+
// nothing.
|
|
32
|
+
minThreads: 0,
|
|
33
|
+
maxThreads: POOL_SIZE,
|
|
34
|
+
concurrentTasksPerWorker: 1,
|
|
35
|
+
// Reclaim WASM-bearing workers after a short idle period; long-lived
|
|
36
|
+
// wawoff2 instances accrete memory over the run.
|
|
37
|
+
idleTimeout: 30_000,
|
|
29
38
|
});
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
function releaseSlot() {
|
|
33
|
-
_activeCount--;
|
|
34
|
-
const next = _queue.shift();
|
|
35
|
-
if (next)
|
|
36
|
-
next();
|
|
37
|
-
}
|
|
38
|
-
function createWorker() {
|
|
39
|
-
const worker = new worker_threads_1.Worker(workerPath);
|
|
40
|
-
worker.unref();
|
|
41
|
-
_alive.add(worker);
|
|
42
|
-
worker.on('exit', () => {
|
|
43
|
-
_alive.delete(worker);
|
|
44
|
-
const idx = _idle.indexOf(worker);
|
|
45
|
-
if (idx !== -1)
|
|
46
|
-
_idle.splice(idx, 1);
|
|
47
|
-
});
|
|
48
|
-
return worker;
|
|
49
|
-
}
|
|
50
|
-
function returnToIdle(worker) {
|
|
51
|
-
_idle.push(worker);
|
|
52
|
-
}
|
|
53
|
-
function discard(worker) {
|
|
54
|
-
_alive.delete(worker);
|
|
55
|
-
const idx = _idle.indexOf(worker);
|
|
56
|
-
if (idx !== -1)
|
|
57
|
-
_idle.splice(idx, 1);
|
|
58
|
-
worker.terminate().catch(() => { });
|
|
59
|
-
}
|
|
60
|
-
function doConvert(worker, buffer, targetFormat, sourceFormat) {
|
|
61
|
-
return new Promise((resolve, reject) => {
|
|
62
|
-
let settled = false;
|
|
63
|
-
const timer = setTimeout(() => {
|
|
64
|
-
if (settled)
|
|
65
|
-
return;
|
|
66
|
-
settled = true;
|
|
67
|
-
cleanup();
|
|
68
|
-
discard(worker);
|
|
69
|
-
reject(new Error(`Font conversion to ${targetFormat} timed out after ${CONVERT_TIMEOUT_MS}ms`));
|
|
70
|
-
}, CONVERT_TIMEOUT_MS);
|
|
71
|
-
timer.unref();
|
|
72
|
-
const cleanup = () => {
|
|
73
|
-
clearTimeout(timer);
|
|
74
|
-
worker.off('message', onMessage);
|
|
75
|
-
worker.off('error', onError);
|
|
76
|
-
worker.off('exit', onExit);
|
|
77
|
-
};
|
|
78
|
-
const onMessage = (msg) => {
|
|
79
|
-
if (settled)
|
|
80
|
-
return;
|
|
81
|
-
settled = true;
|
|
82
|
-
cleanup();
|
|
83
|
-
if (msg.type === 'result' && msg.buffer) {
|
|
84
|
-
returnToIdle(worker);
|
|
85
|
-
resolve(Buffer.from(msg.buffer));
|
|
86
|
-
}
|
|
87
|
-
else {
|
|
88
|
-
discard(worker);
|
|
89
|
-
reject(new Error(msg.error || `Font conversion to ${targetFormat} failed`));
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
const onError = (err) => {
|
|
93
|
-
if (settled)
|
|
94
|
-
return;
|
|
95
|
-
settled = true;
|
|
96
|
-
cleanup();
|
|
97
|
-
discard(worker);
|
|
98
|
-
reject(err);
|
|
99
|
-
};
|
|
100
|
-
const onExit = (code) => {
|
|
101
|
-
if (settled)
|
|
102
|
-
return;
|
|
103
|
-
settled = true;
|
|
104
|
-
cleanup();
|
|
105
|
-
discard(worker);
|
|
106
|
-
reject(new Error(`Font converter worker exited unexpectedly with code ${code}`));
|
|
107
|
-
};
|
|
108
|
-
worker.on('message', onMessage);
|
|
109
|
-
worker.on('error', onError);
|
|
110
|
-
worker.on('exit', onExit);
|
|
111
|
-
try {
|
|
112
|
-
worker.postMessage({ buffer, targetFormat, sourceFormat });
|
|
113
|
-
}
|
|
114
|
-
catch (err) {
|
|
115
|
-
settled = true;
|
|
116
|
-
cleanup();
|
|
117
|
-
discard(worker);
|
|
118
|
-
reject(err);
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
async function convert(buffer, targetFormat, sourceFormat) {
|
|
123
|
-
await acquireSlot();
|
|
124
|
-
try {
|
|
125
|
-
const worker = _idle.pop() ?? createWorker();
|
|
126
|
-
return await doConvert(worker, buffer, targetFormat, sourceFormat);
|
|
127
39
|
}
|
|
128
|
-
|
|
129
|
-
|
|
40
|
+
return _pool;
|
|
41
|
+
}
|
|
42
|
+
async function convert(buffer, targetFormat, sourceFormat, { signal } = {}) {
|
|
43
|
+
// If a destroy is in flight, wait it out so we don't spawn a new pool
|
|
44
|
+
// alongside the dying one.
|
|
45
|
+
if (_destroyPromise) {
|
|
46
|
+
await _destroyPromise;
|
|
130
47
|
}
|
|
48
|
+
const task = { buffer, targetFormat, sourceFormat };
|
|
49
|
+
const result = await (0, piscinaRunWithTimeout_1.runWithTimeoutAndSignal)(getPool(), task, signal, CONVERT_TIMEOUT_MS, (ms) => `Font conversion to ${targetFormat} timed out after ${ms}ms`);
|
|
50
|
+
// Structured clone strips the Buffer prototype on its way back; wrap so
|
|
51
|
+
// callers (subsetFonts, sfntCache) receive a Buffer as advertised.
|
|
52
|
+
return Buffer.from(result);
|
|
131
53
|
}
|
|
132
54
|
async function destroy() {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
55
|
+
if (_pool === null)
|
|
56
|
+
return;
|
|
57
|
+
const pool = _pool;
|
|
58
|
+
_pool = null;
|
|
59
|
+
_destroyPromise = pool.destroy().finally(() => {
|
|
60
|
+
_destroyPromise = null;
|
|
61
|
+
});
|
|
62
|
+
await _destroyPromise;
|
|
138
63
|
}
|
|
139
64
|
//# sourceMappingURL=fontConverter.js.map
|
package/lib/fontConverter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontConverter.js","sourceRoot":"","sources":["../src/fontConverter.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"fontConverter.js","sourceRoot":"","sources":["../src/fontConverter.ts"],"names":[],"mappings":";;AAoDA,0BAsBC;AAED,0BAQC;AApFD,mCAAoC;AACpC,yBAA0B;AAC1B,qCAAkC;AAClC,yDAAmD;AACnD,mEAAkE;AAElE;;;;;GAKG;AAEH,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;AACxE,MAAM,kBAAkB,GAAG,OAAO,CAAC;AACnC,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,gCAAa,CAAC,CAAC,CAAC;AAYzE,IAAI,KAAK,GAAmB,IAAI,CAAC;AACjC,sEAAsE;AACtE,sEAAsE;AACtE,uEAAuE;AACvE,wEAAwE;AACxE,IAAI,eAAe,GAAyB,IAAI,CAAC;AAEjD,SAAS,OAAO;IACd,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,KAAK,GAAG,IAAI,iBAAO,CAAC;YAClB,QAAQ,EAAE,UAAU;YACpB,kEAAkE;YAClE,qEAAqE;YACrE,WAAW;YACX,UAAU,EAAE,CAAC;YACb,UAAU,EAAE,SAAS;YACrB,wBAAwB,EAAE,CAAC;YAC3B,qEAAqE;YACrE,iDAAiD;YACjD,WAAW,EAAE,MAAM;SACpB,CAAC,CAAC;IACL,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAEM,KAAK,UAAU,OAAO,CAC3B,MAA2B,EAC3B,YAAoB,EACpB,YAAqB,EACrB,EAAE,MAAM,KAAqB,EAAE;IAE/B,sEAAsE;IACtE,2BAA2B;IAC3B,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,eAAe,CAAC;IACxB,CAAC;IACD,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;IACjE,MAAM,MAAM,GAAG,MAAM,IAAA,+CAAuB,EAC1C,OAAO,EAAE,EACT,IAAI,EACJ,MAAM,EACN,kBAAkB,EAClB,CAAC,EAAE,EAAE,EAAE,CAAC,sBAAsB,YAAY,oBAAoB,EAAE,IAAI,CACrE,CAAC;IACF,wEAAwE;IACxE,mEAAmE;IACnE,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAC7B,CAAC;AAEM,KAAK,UAAU,OAAO;IAC3B,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO;IAC3B,MAAM,IAAI,GAAG,KAAK,CAAC;IACnB,KAAK,GAAG,IAAI,CAAC;IACb,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;QAC5C,eAAe,GAAG,IAAI,CAAC;IACzB,CAAC,CAAC,CAAC;IACH,MAAM,eAAe,CAAC;AACxB,CAAC"}
|
|
@@ -1,2 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Piscina worker handler for font format conversion.
|
|
3
|
+
*
|
|
4
|
+
* Each worker thread loads its own wawoff2 WASM instance via fontverter,
|
|
5
|
+
* enabling safe parallel woff2 compression — wawoff2's shared WASM
|
|
6
|
+
* instance corrupts memory under concurrent use within a single thread.
|
|
7
|
+
*/
|
|
8
|
+
interface ConvertTask {
|
|
9
|
+
buffer: Uint8Array | Buffer;
|
|
10
|
+
targetFormat: string;
|
|
11
|
+
sourceFormat?: string;
|
|
12
|
+
}
|
|
13
|
+
declare function convertTask(task: ConvertTask): Promise<Uint8Array>;
|
|
14
|
+
export = convertTask;
|
|
2
15
|
//# sourceMappingURL=fontConverterWorker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontConverterWorker.d.ts","sourceRoot":"","sources":["../src/fontConverterWorker.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"fontConverterWorker.d.ts","sourceRoot":"","sources":["../src/fontConverterWorker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,UAAU,WAAW;IACnB,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,iBAAe,WAAW,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAQjE;AAED,SAAS,WAAW,CAAC"}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Piscina worker handler for font format conversion.
|
|
4
|
+
*
|
|
5
|
+
* Each worker thread loads its own wawoff2 WASM instance via fontverter,
|
|
6
|
+
* enabling safe parallel woff2 compression — wawoff2's shared WASM
|
|
7
|
+
* instance corrupts memory under concurrent use within a single thread.
|
|
8
|
+
*/
|
|
2
9
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
10
|
if (k2 === undefined) k2 = k;
|
|
4
11
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -32,22 +39,15 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
39
|
return result;
|
|
33
40
|
};
|
|
34
41
|
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
const worker_threads_1 = require("worker_threads");
|
|
37
42
|
const fontverter = __importStar(require("fontverter"));
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
async function convertTask(task) {
|
|
44
|
+
// Structured clone delivers Uint8Array on the worker side; wrap so
|
|
45
|
+
// fontverter sees the Buffer it expects. The host wraps the response
|
|
46
|
+
// in Buffer.from on its end — wrapping here would duplicate work
|
|
47
|
+
// since structured clone copies bytes and strips the Buffer prototype
|
|
48
|
+
// on every transfer.
|
|
49
|
+
const buffer = Buffer.from(task.buffer);
|
|
50
|
+
return await fontverter.convert(buffer, task.targetFormat, task.sourceFormat);
|
|
40
51
|
}
|
|
41
|
-
|
|
42
|
-
port.on('message', async (msg) => {
|
|
43
|
-
try {
|
|
44
|
-
const buffer = Buffer.from(msg.buffer);
|
|
45
|
-
const result = await fontverter.convert(buffer, msg.targetFormat, msg.sourceFormat);
|
|
46
|
-
port.postMessage({ type: 'result', buffer: result });
|
|
47
|
-
}
|
|
48
|
-
catch (rawErr) {
|
|
49
|
-
const err = rawErr;
|
|
50
|
-
port.postMessage({ type: 'error', error: err.message });
|
|
51
|
-
}
|
|
52
|
-
});
|
|
52
|
+
module.exports = convertTask;
|
|
53
53
|
//# sourceMappingURL=fontConverterWorker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontConverterWorker.js","sourceRoot":"","sources":["../src/fontConverterWorker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fontConverterWorker.js","sourceRoot":"","sources":["../src/fontConverterWorker.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEH,uDAAyC;AAQzC,KAAK,UAAU,WAAW,CAAC,IAAiB;IAC1C,mEAAmE;IACnE,qEAAqE;IACrE,iEAAiE;IACjE,sEAAsE;IACtE,qBAAqB;IACrB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxC,OAAO,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;AAChF,CAAC;AAED,iBAAS,WAAW,CAAC"}
|
package/lib/fontFaceHelpers.d.ts
CHANGED
|
@@ -56,8 +56,9 @@ export declare function cssAssetIsEmpty(cssAsset: {
|
|
|
56
56
|
}>;
|
|
57
57
|
};
|
|
58
58
|
}): boolean;
|
|
59
|
-
export
|
|
60
|
-
export declare function
|
|
59
|
+
export type RangeWarnFn = (err: Error) => void;
|
|
60
|
+
export declare function parseFontWeightRange(str: string | undefined, warn?: RangeWarnFn): [number, number];
|
|
61
|
+
export declare function parseFontStretchRange(str: string | undefined, warn?: RangeWarnFn): [number, number];
|
|
61
62
|
export declare function uniqueChars(text: string): string;
|
|
62
63
|
export declare function uniqueCharsFromArray(texts: string[]): string;
|
|
63
64
|
export declare function hashHexPrefix(stringOrBuffer: string | Buffer | Uint8Array): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fontFaceHelpers.d.ts","sourceRoot":"","sources":["../src/fontFaceHelpers.ts"],"names":[],"mappings":"AAaA,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,GAAG,GAAG,GAAG,GACf,MAAM,CAKR;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQnD;AAED,UAAU,mBAAmB;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CACjC,uBAAuB,GAAE,mBAAmB,EAAO,GAClD,MAAM,GAAG,SAAS,CAkCpB;AAED,UAAU,oBAAoB;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,QAAQ,IAAI,MAAM,CAAC;CACpB;AAID,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,eAAe,EACrB,SAAS,EAAE,oBAAoB,EAAE,GAChC,MAAM,CAoBR;AAiCD,UAAU,aAAa;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC;IACvC,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IACpD,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC3B;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM,CAgDxE;AAED,UAAU,iBAAiB;IAIzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;QACf,EAAE,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAC;QACpB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAI7B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,aAAa,EAAE,EAC3B,+BAA+B,EAAE,iBAAiB,EAAE,GACnD,MAAM,CAmDR;AAED,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,aAAa,EAAE,GAAG,MAAM,CAK1E;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAapD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE;IACxC,SAAS,EAAE;QAAE,KAAK,CAAC,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;CAC/D,GAAG,OAAO,CAMV;AAED,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"fontFaceHelpers.d.ts","sourceRoot":"","sources":["../src/fontFaceHelpers.ts"],"names":[],"mappings":"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"}
|