@turntrout/subfont 1.6.0 → 1.7.1
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 +43 -43
- package/lib/FontTracerPool.d.ts +37 -0
- package/lib/FontTracerPool.d.ts.map +1 -0
- package/lib/FontTracerPool.js +212 -173
- package/lib/FontTracerPool.js.map +1 -0
- package/lib/HeadlessBrowser.js +11 -3
- package/lib/cli.d.ts +3 -0
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +15 -12
- package/lib/cli.js.map +1 -0
- package/lib/collectTextsByPage.js +425 -352
- package/lib/escapeJsStringLiteral.js +13 -0
- package/lib/extractVisibleText.js +6 -2
- package/lib/fontConverter.js +25 -0
- package/lib/fontConverterWorker.js +16 -0
- package/lib/fontFaceHelpers.js +16 -4
- package/lib/gatherStylesheetsWithPredicates.js +4 -5
- package/lib/normalizeFontPropertyValue.js +1 -1
- package/lib/sfntCache.js +10 -7
- package/lib/subfont.d.ts +33 -0
- package/lib/subfont.d.ts.map +1 -0
- package/lib/subfont.js +533 -591
- package/lib/subfont.js.map +1 -0
- package/lib/subsetFontWithGlyphs.d.ts +17 -0
- package/lib/subsetFontWithGlyphs.d.ts.map +1 -0
- package/lib/subsetFontWithGlyphs.js +231 -253
- package/lib/subsetFontWithGlyphs.js.map +1 -0
- package/lib/subsetFonts.d.ts +59 -0
- package/lib/subsetFonts.d.ts.map +1 -0
- package/lib/subsetFonts.js +921 -1180
- package/lib/subsetFonts.js.map +1 -0
- package/lib/subsetGeneration.d.ts +39 -0
- package/lib/subsetGeneration.d.ts.map +1 -0
- package/lib/subsetGeneration.js +294 -324
- package/lib/subsetGeneration.js.map +1 -0
- package/lib/unquote.js +9 -4
- package/lib/warnAboutMissingGlyphs.js +36 -25
- package/lib/wasmQueue.js +6 -2
- package/package.json +11 -3
package/README.md
CHANGED
|
@@ -55,27 +55,27 @@ subfont path/to/index.html -i --cache
|
|
|
55
55
|
|
|
56
56
|
## Options
|
|
57
57
|
|
|
58
|
-
| Flag | Default | Description
|
|
59
|
-
| -----------------: | :-----: |
|
|
60
|
-
| `-i, --in-place` | off | Modify files in-place
|
|
61
|
-
| `-o, --output` | | Output directory
|
|
62
|
-
| `--root` | | Path to web root (deduced from input files if not specified)
|
|
63
|
-
| `--canonical-root` | | URI root where the site will be deployed
|
|
64
|
-
| `-r, --recursive` | off | Crawl linked pages
|
|
65
|
-
| `--dynamic` | off | Trace with headless browser
|
|
66
|
-
| `--dry-run` | off | Preview without writing
|
|
67
|
-
| `--fallbacks` | on |
|
|
68
|
-
| `--font-display` | `swap` | `auto`/`block`/`swap`/`fallback`/`optional`
|
|
69
|
-
| `--text` | | Extra characters for every subset
|
|
70
|
-
| `--cache [dir]` | off | Cache subset results to disk between runs
|
|
71
|
-
| `--concurrency N` |
|
|
72
|
-
| `--chrome-flags` | | Custom Chrome flags for `--dynamic`
|
|
73
|
-
| `--source-maps` | off | Preserve CSS source maps (slower)
|
|
74
|
-
| `--strict` | off | Exit non-zero if any warnings are emitted
|
|
75
|
-
| `-s, --silent` | off | Suppress all console output
|
|
76
|
-
| `-d, --debug` | off | Verbose timing and font glyph detection info
|
|
77
|
-
| `--relative-urls` | off | Emit relative URLs instead of root-relative
|
|
78
|
-
| `--inline-css` | off | Inline the subset @font-face CSS into HTML
|
|
58
|
+
| Flag | Default | Description |
|
|
59
|
+
| -----------------: | :-----: | :------------------------------------------------------------------------------------ |
|
|
60
|
+
| `-i, --in-place` | off | Modify files in-place |
|
|
61
|
+
| `-o, --output` | | Output directory |
|
|
62
|
+
| `--root` | | Path to web root (deduced from input files if not specified) |
|
|
63
|
+
| `--canonical-root` | | URI root where the site will be deployed |
|
|
64
|
+
| `-r, --recursive` | off | Crawl linked pages |
|
|
65
|
+
| `--dynamic` | off | Trace with headless browser |
|
|
66
|
+
| `--dry-run` | off | Preview without writing |
|
|
67
|
+
| `--fallbacks` | on | Async-load the full original font as a fallback for dynamic content |
|
|
68
|
+
| `--font-display` | `swap` | `auto`/`block`/`swap`/`fallback`/`optional` |
|
|
69
|
+
| `--text` | | Extra characters for every subset |
|
|
70
|
+
| `--cache [dir]` | off | Cache subset results to disk between runs |
|
|
71
|
+
| `--concurrency N` | auto | Max worker threads (defaults to CPU count, capped by available memory at ~50 MB each) |
|
|
72
|
+
| `--chrome-flags` | | Custom Chrome flags for `--dynamic` (comma-separated) |
|
|
73
|
+
| `--source-maps` | off | Preserve CSS source maps (slower) |
|
|
74
|
+
| `--strict` | off | Exit non-zero if any warnings are emitted |
|
|
75
|
+
| `-s, --silent` | off | Suppress all console output |
|
|
76
|
+
| `-d, --debug` | off | Verbose timing and font glyph detection info |
|
|
77
|
+
| `--relative-urls` | off | Emit relative URLs instead of root-relative |
|
|
78
|
+
| `--inline-css` | off | Inline the subset @font-face CSS into HTML |
|
|
79
79
|
|
|
80
80
|
Run `subfont --help` for the full list.
|
|
81
81
|
|
|
@@ -113,28 +113,28 @@ with `log`, `warn`, and `error` methods — e.g. the global `console`). Pass
|
|
|
113
113
|
|
|
114
114
|
The `options` object accepts the following keys:
|
|
115
115
|
|
|
116
|
-
| Option | Type | Default | Description
|
|
117
|
-
| --------------- | ------------------- | -------- |
|
|
118
|
-
| `inputFiles` | `string[]` | `[]` | HTML entry points (file paths or URLs). At least one is required unless `root` is given.
|
|
119
|
-
| `root` | `string` | deduced | Path or URL to the web root. Deduced from `inputFiles` if omitted.
|
|
120
|
-
| `canonicalRoot` | `string` | — | URI root where the site will be deployed (used to rewrite absolute URLs).
|
|
121
|
-
| `output` | `string` | — | Output directory. Mutually exclusive with `inPlace`.
|
|
122
|
-
| `inPlace` | `boolean` | `false` | Modify input files in place.
|
|
123
|
-
| `dryRun` | `boolean` | `false` | Trace and compute subsets but do not write any files.
|
|
124
|
-
| `recursive` | `boolean` | `false` | Crawl linked pages starting from `inputFiles`.
|
|
125
|
-
| `dynamic` | `boolean` | `false` | Trace JS-rendered content in headless Chrome (via puppeteer).
|
|
126
|
-
| `fallbacks` | `boolean` | `true` |
|
|
127
|
-
| `fontDisplay` | `string` | `'swap'` | `font-display` CSS value: `auto`, `block`, `swap`, `fallback`, or `optional`.
|
|
128
|
-
| `text` | `string` | — | Extra characters to include in every subset.
|
|
129
|
-
| `inlineCss` | `boolean` | `false` | Inline the subset `@font-face` CSS into the HTML document.
|
|
130
|
-
| `relativeUrls` | `boolean` | `false` | Emit relative URLs instead of root-relative URLs.
|
|
131
|
-
| `sourceMaps` | `boolean` | `false` | Preserve CSS source maps (slower).
|
|
132
|
-
| `concurrency` | `number` | auto | Max parallel tracing workers.
|
|
133
|
-
| `chromeFlags` | `string[]` | `[]` | Extra Chrome flags forwarded to puppeteer when `dynamic` is set.
|
|
134
|
-
| `cache` | `boolean \| string` | `false` | Cache subset results between runs. Pass a path to customize the cache directory; `true` uses the
|
|
135
|
-
| `strict` | `boolean` | `false` | Resolve with a non-zero exit (via the CLI) if any warnings are emitted.
|
|
136
|
-
| `silent` | `boolean` | `false` | Suppress all log output to `console`.
|
|
137
|
-
| `debug` | `boolean` | `false` | Emit verbose timing and glyph-detection info.
|
|
116
|
+
| Option | Type | Default | Description |
|
|
117
|
+
| --------------- | ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
118
|
+
| `inputFiles` | `string[]` | `[]` | HTML entry points (file paths or URLs). At least one is required unless `root` is given. |
|
|
119
|
+
| `root` | `string` | deduced | Path or URL to the web root. Deduced from `inputFiles` if omitted. |
|
|
120
|
+
| `canonicalRoot` | `string` | — | URI root where the site will be deployed (used to rewrite absolute URLs). |
|
|
121
|
+
| `output` | `string` | — | Output directory. Mutually exclusive with `inPlace`. |
|
|
122
|
+
| `inPlace` | `boolean` | `false` | Modify input files in place. |
|
|
123
|
+
| `dryRun` | `boolean` | `false` | Trace and compute subsets but do not write any files. |
|
|
124
|
+
| `recursive` | `boolean` | `false` | Crawl linked pages starting from `inputFiles`. |
|
|
125
|
+
| `dynamic` | `boolean` | `false` | Trace JS-rendered content in headless Chrome (via puppeteer). |
|
|
126
|
+
| `fallbacks` | `boolean` | `true` | Async-load the full original font as a fallback for dynamic content. |
|
|
127
|
+
| `fontDisplay` | `string` | `'swap'` | `font-display` CSS value: `auto`, `block`, `swap`, `fallback`, or `optional`. |
|
|
128
|
+
| `text` | `string` | — | Extra characters to include in every subset. |
|
|
129
|
+
| `inlineCss` | `boolean` | `false` | Inline the subset `@font-face` CSS into the HTML document. |
|
|
130
|
+
| `relativeUrls` | `boolean` | `false` | Emit relative URLs instead of root-relative URLs. |
|
|
131
|
+
| `sourceMaps` | `boolean` | `false` | Preserve CSS source maps (slower). |
|
|
132
|
+
| `concurrency` | `number` | auto | Max parallel tracing workers. Defaults to CPU count, capped by available memory (~50 MB per worker). |
|
|
133
|
+
| `chromeFlags` | `string[]` | `[]` | Extra Chrome flags forwarded to puppeteer when `dynamic` is set. |
|
|
134
|
+
| `cache` | `boolean \| string` | `false` | Cache subset results between runs. Pass a path to customize the cache directory; `true` uses `.subfont-cache` inside the `root` directory. |
|
|
135
|
+
| `strict` | `boolean` | `false` | Resolve with a non-zero exit (via the CLI) if any warnings are emitted. |
|
|
136
|
+
| `silent` | `boolean` | `false` | Suppress all log output to `console`. |
|
|
137
|
+
| `debug` | `boolean` | `false` | Emit verbose timing and glyph-detection info. |
|
|
138
138
|
|
|
139
139
|
## License
|
|
140
140
|
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
interface StylesheetWithPredicates {
|
|
2
|
+
text?: string;
|
|
3
|
+
asset?: {
|
|
4
|
+
text?: string;
|
|
5
|
+
};
|
|
6
|
+
predicates?: Record<string, unknown>;
|
|
7
|
+
}
|
|
8
|
+
interface FontTracerPoolOptions {
|
|
9
|
+
taskTimeoutMs?: number;
|
|
10
|
+
}
|
|
11
|
+
declare class FontTracerPool {
|
|
12
|
+
private _workerPath;
|
|
13
|
+
private _numWorkers;
|
|
14
|
+
private _taskTimeoutMs;
|
|
15
|
+
private _workers;
|
|
16
|
+
private _idle;
|
|
17
|
+
private _pendingTasks;
|
|
18
|
+
private _taskCallbacks;
|
|
19
|
+
private _taskTimers;
|
|
20
|
+
private _taskByWorker;
|
|
21
|
+
private _nextTaskId;
|
|
22
|
+
constructor(numWorkers: number, { taskTimeoutMs }?: FontTracerPoolOptions);
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
private _clearTaskTimer;
|
|
25
|
+
private _onWorkerMessage;
|
|
26
|
+
private _onWorkerExit;
|
|
27
|
+
private _startTaskTimer;
|
|
28
|
+
private _dispatchPending;
|
|
29
|
+
/**
|
|
30
|
+
* Run fontTracer on the given HTML text + stylesheets in a worker.
|
|
31
|
+
* Returns a promise that resolves to textByProps.
|
|
32
|
+
*/
|
|
33
|
+
trace(htmlText: string, stylesheetsWithPredicates: StylesheetWithPredicates[]): Promise<unknown>;
|
|
34
|
+
destroy(): Promise<void>;
|
|
35
|
+
}
|
|
36
|
+
export = FontTracerPool;
|
|
37
|
+
//# sourceMappingURL=FontTracerPool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FontTracerPool.d.ts","sourceRoot":"","sources":["../src/FontTracerPool.ts"],"names":[],"mappings":"AAkBA,UAAU,wBAAwB;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAI1B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACtC;AAqCD,UAAU,qBAAqB;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,cAAM,cAAc;IAClB,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,aAAa,CAAmC;IACxD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,WAAW,CAA8B;IACjD,OAAO,CAAC,aAAa,CAAsB;IAC3C,OAAO,CAAC,WAAW,CAAS;gBAG1B,UAAU,EAAE,MAAM,EAClB,EAAE,aAAuC,EAAE,GAAE,qBAA0B;IAcnE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC3B,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,gBAAgB;IAkBxB,OAAO,CAAC,aAAa;IAwCrB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,gBAAgB;IAsBxB;;;OAGG;IAGH,KAAK,CACH,QAAQ,EAAE,MAAM,EAChB,yBAAyB,EAAE,wBAAwB,EAAE,GAEpD,OAAO,CAAC,OAAO,CAAC;IAsBb,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CA4C/B;AAED,SAAS,cAAc,CAAC"}
|
package/lib/FontTracerPool.js
CHANGED
|
@@ -1,191 +1,230 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
const pathModule = require("path");
|
|
3
|
+
const worker_threads_1 = require("worker_threads");
|
|
4
4
|
/**
|
|
5
5
|
* Worker pool for running fontTracer in parallel across pages.
|
|
6
6
|
* Each worker re-parses HTML with jsdom and runs fontTracer independently.
|
|
7
7
|
*/
|
|
8
|
+
const DEFAULT_TASK_TIMEOUT_MS = 60_000;
|
|
8
9
|
class FontTracerPool {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
worker.off('message', onMessage);
|
|
31
|
-
worker.off('error', onError);
|
|
32
|
-
worker.on('message', (msg) => this._onWorkerMessage(worker, msg));
|
|
33
|
-
worker.on('exit', (code) => this._onWorkerExit(worker, code));
|
|
34
|
-
this._idle.push(worker);
|
|
35
|
-
resolve();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
worker.on('message', onMessage);
|
|
39
|
-
worker.on('error', onError);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
worker.postMessage({ type: 'init' });
|
|
43
|
-
|
|
44
|
-
initPromises.push(initPromise);
|
|
45
|
-
}
|
|
46
|
-
await Promise.all(initPromises);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
_onWorkerMessage(worker, msg) {
|
|
50
|
-
this._taskByWorker.delete(worker);
|
|
51
|
-
const cb = this._taskCallbacks.get(msg.taskId);
|
|
52
|
-
if (cb) {
|
|
53
|
-
this._taskCallbacks.delete(msg.taskId);
|
|
54
|
-
if (msg.type === 'result') {
|
|
55
|
-
cb.resolve(msg.textByProps);
|
|
56
|
-
} else if (msg.type === 'error') {
|
|
57
|
-
cb.reject(new Error(`Worker error: ${msg.error}\n${msg.stack}`));
|
|
58
|
-
}
|
|
10
|
+
_workerPath;
|
|
11
|
+
_numWorkers;
|
|
12
|
+
_taskTimeoutMs;
|
|
13
|
+
_workers;
|
|
14
|
+
_idle;
|
|
15
|
+
_pendingTasks;
|
|
16
|
+
_taskCallbacks;
|
|
17
|
+
_taskTimers;
|
|
18
|
+
_taskByWorker;
|
|
19
|
+
_nextTaskId;
|
|
20
|
+
constructor(numWorkers, { taskTimeoutMs = DEFAULT_TASK_TIMEOUT_MS } = {}) {
|
|
21
|
+
this._workerPath = pathModule.join(__dirname, 'fontTracerWorker.js');
|
|
22
|
+
this._numWorkers = numWorkers;
|
|
23
|
+
this._taskTimeoutMs = taskTimeoutMs;
|
|
24
|
+
this._workers = [];
|
|
25
|
+
this._idle = [];
|
|
26
|
+
this._pendingTasks = [];
|
|
27
|
+
this._taskCallbacks = new Map();
|
|
28
|
+
this._taskTimers = new Map();
|
|
29
|
+
this._taskByWorker = new Map();
|
|
30
|
+
this._nextTaskId = 0;
|
|
59
31
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
32
|
+
async init() {
|
|
33
|
+
const initPromises = [];
|
|
34
|
+
for (let i = 0; i < this._numWorkers; i++) {
|
|
35
|
+
const worker = new worker_threads_1.Worker(this._workerPath);
|
|
36
|
+
this._workers.push(worker);
|
|
37
|
+
const initPromise = new Promise((resolve, reject) => {
|
|
38
|
+
const onError = reject;
|
|
39
|
+
const onMessage = (msg) => {
|
|
40
|
+
if (msg.type === 'ready') {
|
|
41
|
+
worker.off('message', onMessage);
|
|
42
|
+
worker.off('error', onError);
|
|
43
|
+
worker.on('message', (msg) => this._onWorkerMessage(worker, msg));
|
|
44
|
+
worker.on('exit', (code) => this._onWorkerExit(worker, code));
|
|
45
|
+
this._idle.push(worker);
|
|
46
|
+
resolve();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
worker.on('message', onMessage);
|
|
50
|
+
worker.on('error', onError);
|
|
51
|
+
});
|
|
52
|
+
worker.postMessage({ type: 'init' });
|
|
53
|
+
initPromises.push(initPromise);
|
|
54
|
+
}
|
|
55
|
+
await Promise.all(initPromises);
|
|
70
56
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
57
|
+
_clearTaskTimer(taskId) {
|
|
58
|
+
const timer = this._taskTimers.get(taskId);
|
|
59
|
+
if (timer) {
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
this._taskTimers.delete(taskId);
|
|
62
|
+
}
|
|
74
63
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const cb = this._taskCallbacks.get(taskId);
|
|
64
|
+
_onWorkerMessage(worker, msg) {
|
|
65
|
+
if (msg.type === 'ready')
|
|
66
|
+
return;
|
|
67
|
+
this._taskByWorker.delete(worker);
|
|
68
|
+
this._clearTaskTimer(msg.taskId);
|
|
69
|
+
const cb = this._taskCallbacks.get(msg.taskId);
|
|
82
70
|
if (cb) {
|
|
83
|
-
|
|
84
|
-
|
|
71
|
+
this._taskCallbacks.delete(msg.taskId);
|
|
72
|
+
if (msg.type === 'result') {
|
|
73
|
+
cb.resolve(msg.textByProps);
|
|
74
|
+
}
|
|
75
|
+
else if (msg.type === 'error') {
|
|
76
|
+
cb.reject(new Error(`Worker error: ${msg.error}\n${msg.stack}`));
|
|
77
|
+
}
|
|
85
78
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
79
|
+
// Worker is now idle, check for pending tasks
|
|
80
|
+
this._idle.push(worker);
|
|
81
|
+
this._dispatchPending();
|
|
82
|
+
}
|
|
83
|
+
_onWorkerExit(worker, code) {
|
|
84
|
+
// Remove crashed worker from tracking
|
|
85
|
+
const workerIdx = this._workers.indexOf(worker);
|
|
86
|
+
if (workerIdx !== -1) {
|
|
87
|
+
this._workers.splice(workerIdx, 1);
|
|
88
|
+
}
|
|
89
|
+
const idleIdx = this._idle.indexOf(worker);
|
|
90
|
+
if (idleIdx !== -1) {
|
|
91
|
+
this._idle.splice(idleIdx, 1);
|
|
92
|
+
}
|
|
93
|
+
if (code !== 0) {
|
|
94
|
+
// Reject the task that was in-flight on this worker
|
|
95
|
+
const taskId = this._taskByWorker.get(worker);
|
|
96
|
+
this._taskByWorker.delete(worker);
|
|
97
|
+
if (taskId !== undefined) {
|
|
98
|
+
this._clearTaskTimer(taskId);
|
|
99
|
+
const cb = this._taskCallbacks.get(taskId);
|
|
100
|
+
if (cb) {
|
|
101
|
+
this._taskCallbacks.delete(taskId);
|
|
102
|
+
cb.reject(new Error(`Worker exited with code ${code}`));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// If no workers remain, reject all pending tasks
|
|
106
|
+
if (this._workers.length === 0) {
|
|
107
|
+
for (const task of this._pendingTasks) {
|
|
108
|
+
const cb = this._taskCallbacks.get(task.message.taskId);
|
|
109
|
+
if (cb) {
|
|
110
|
+
this._taskCallbacks.delete(task.message.taskId);
|
|
111
|
+
cb.reject(new Error('All workers have crashed, no workers available'));
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this._pendingTasks = [];
|
|
115
|
+
}
|
|
98
116
|
}
|
|
99
|
-
this._pendingTasks = [];
|
|
100
|
-
}
|
|
101
117
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
_startTaskTimer(taskId) {
|
|
119
|
+
if (this._taskTimeoutMs <= 0)
|
|
120
|
+
return;
|
|
121
|
+
const timer = setTimeout(() => {
|
|
122
|
+
this._taskTimers.delete(taskId);
|
|
123
|
+
const cb = this._taskCallbacks.get(taskId);
|
|
124
|
+
if (cb) {
|
|
125
|
+
this._taskCallbacks.delete(taskId);
|
|
126
|
+
cb.reject(new Error(`Font tracing task ${taskId} timed out after ${this._taskTimeoutMs}ms`));
|
|
127
|
+
}
|
|
128
|
+
// Terminate the hung worker so it doesn't permanently consume a pool
|
|
129
|
+
// slot. _onWorkerExit will remove it from _workers and _idle.
|
|
130
|
+
for (const [worker, tid] of this._taskByWorker) {
|
|
131
|
+
if (tid === taskId) {
|
|
132
|
+
this._taskByWorker.delete(worker);
|
|
133
|
+
worker.terminate();
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}, this._taskTimeoutMs);
|
|
138
|
+
timer.unref();
|
|
139
|
+
this._taskTimers.set(taskId, timer);
|
|
140
|
+
}
|
|
141
|
+
_dispatchPending() {
|
|
142
|
+
while (this._idle.length > 0 && this._pendingTasks.length > 0) {
|
|
143
|
+
const worker = this._idle.pop();
|
|
144
|
+
const task = this._pendingTasks.shift();
|
|
145
|
+
this._taskByWorker.set(worker, task.message.taskId);
|
|
146
|
+
try {
|
|
147
|
+
worker.postMessage(task.message);
|
|
148
|
+
this._startTaskTimer(task.message.taskId);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
// postMessage can fail synchronously (e.g. structured clone error).
|
|
152
|
+
// Return the worker to the idle pool and reject the task.
|
|
153
|
+
this._taskByWorker.delete(worker);
|
|
154
|
+
this._idle.push(worker);
|
|
155
|
+
const cb = this._taskCallbacks.get(task.message.taskId);
|
|
156
|
+
if (cb) {
|
|
157
|
+
this._taskCallbacks.delete(task.message.taskId);
|
|
158
|
+
cb.reject(err);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
120
161
|
}
|
|
121
|
-
}
|
|
122
162
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
async destroy() {
|
|
152
|
-
// Reject any tasks still waiting in the queue
|
|
153
|
-
for (const task of this._pendingTasks) {
|
|
154
|
-
const cb = this._taskCallbacks.get(task.message.taskId);
|
|
155
|
-
if (cb) {
|
|
156
|
-
this._taskCallbacks.delete(task.message.taskId);
|
|
157
|
-
cb.reject(new Error('Worker pool destroyed'));
|
|
158
|
-
}
|
|
163
|
+
/**
|
|
164
|
+
* Run fontTracer on the given HTML text + stylesheets in a worker.
|
|
165
|
+
* Returns a promise that resolves to textByProps.
|
|
166
|
+
*/
|
|
167
|
+
// The pool is payload-agnostic; callers (subsetFonts.ts) interpret the
|
|
168
|
+
// returned textByProps according to font-tracer's contract.
|
|
169
|
+
trace(htmlText, stylesheetsWithPredicates
|
|
170
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
171
|
+
) {
|
|
172
|
+
const taskId = this._nextTaskId++;
|
|
173
|
+
// Serialize stylesheets to plain data — asset objects contain DOM/PostCSS
|
|
174
|
+
// trees that cannot be transferred via structured clone.
|
|
175
|
+
const serializedStylesheets = stylesheetsWithPredicates.map((entry) => ({
|
|
176
|
+
text: entry.text || (entry.asset && entry.asset.text) || '',
|
|
177
|
+
predicates: entry.predicates || {},
|
|
178
|
+
}));
|
|
179
|
+
const message = {
|
|
180
|
+
type: 'trace',
|
|
181
|
+
taskId,
|
|
182
|
+
htmlText,
|
|
183
|
+
stylesheetsWithPredicates: serializedStylesheets,
|
|
184
|
+
};
|
|
185
|
+
return new Promise((resolve, reject) => {
|
|
186
|
+
this._taskCallbacks.set(taskId, { resolve, reject });
|
|
187
|
+
this._pendingTasks.push({ message });
|
|
188
|
+
this._dispatchPending();
|
|
189
|
+
});
|
|
159
190
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.
|
|
168
|
-
|
|
169
|
-
|
|
191
|
+
async destroy() {
|
|
192
|
+
// Clear all task timers
|
|
193
|
+
for (const timer of this._taskTimers.values()) {
|
|
194
|
+
clearTimeout(timer);
|
|
195
|
+
}
|
|
196
|
+
this._taskTimers.clear();
|
|
197
|
+
// Reject any tasks still waiting in the queue
|
|
198
|
+
for (const task of this._pendingTasks) {
|
|
199
|
+
const cb = this._taskCallbacks.get(task.message.taskId);
|
|
200
|
+
if (cb) {
|
|
201
|
+
this._taskCallbacks.delete(task.message.taskId);
|
|
202
|
+
cb.reject(new Error('Worker pool destroyed'));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
this._pendingTasks = [];
|
|
206
|
+
// Reject any in-flight tasks still assigned to workers.
|
|
207
|
+
// Clear _taskByWorker before terminate() so _onWorkerExit won't double-reject.
|
|
208
|
+
for (const [, taskId] of this._taskByWorker) {
|
|
209
|
+
const cb = this._taskCallbacks.get(taskId);
|
|
210
|
+
if (cb) {
|
|
211
|
+
this._taskCallbacks.delete(taskId);
|
|
212
|
+
cb.reject(new Error('Worker pool destroyed'));
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
this._taskByWorker.clear();
|
|
216
|
+
// Terminate workers with a 5-second timeout to prevent hanging
|
|
217
|
+
const TERMINATE_TIMEOUT_MS = 5000;
|
|
218
|
+
await Promise.all(this._workers.map((w) => Promise.race([
|
|
219
|
+
w.terminate(),
|
|
220
|
+
new Promise((resolve) => {
|
|
221
|
+
const timer = setTimeout(resolve, TERMINATE_TIMEOUT_MS);
|
|
222
|
+
timer.unref();
|
|
223
|
+
}),
|
|
224
|
+
])));
|
|
225
|
+
this._workers = [];
|
|
226
|
+
this._idle = [];
|
|
170
227
|
}
|
|
171
|
-
this._taskByWorker.clear();
|
|
172
|
-
|
|
173
|
-
// Terminate workers with a 5-second timeout to prevent hanging
|
|
174
|
-
const TERMINATE_TIMEOUT_MS = 5000;
|
|
175
|
-
await Promise.all(
|
|
176
|
-
this._workers.map((w) =>
|
|
177
|
-
Promise.race([
|
|
178
|
-
w.terminate(),
|
|
179
|
-
new Promise((resolve) => {
|
|
180
|
-
const timer = setTimeout(resolve, TERMINATE_TIMEOUT_MS);
|
|
181
|
-
timer.unref();
|
|
182
|
-
}),
|
|
183
|
-
])
|
|
184
|
-
)
|
|
185
|
-
);
|
|
186
|
-
this._workers = [];
|
|
187
|
-
this._idle = [];
|
|
188
|
-
}
|
|
189
228
|
}
|
|
190
|
-
|
|
191
229
|
module.exports = FontTracerPool;
|
|
230
|
+
//# sourceMappingURL=FontTracerPool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FontTracerPool.js","sourceRoot":"","sources":["../src/FontTracerPool.ts"],"names":[],"mappings":"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"}
|
package/lib/HeadlessBrowser.js
CHANGED
|
@@ -13,8 +13,12 @@ async function transferResults(jsHandle) {
|
|
|
13
13
|
const results = await jsHandle.jsonValue();
|
|
14
14
|
for (const [i, result] of results.entries()) {
|
|
15
15
|
const resultHandle = await jsHandle.getProperty(String(i));
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
try {
|
|
17
|
+
const elementHandle = await resultHandle.getProperty('node');
|
|
18
|
+
result.node = elementHandle;
|
|
19
|
+
} finally {
|
|
20
|
+
await resultHandle.dispose();
|
|
21
|
+
}
|
|
18
22
|
}
|
|
19
23
|
return results;
|
|
20
24
|
}
|
|
@@ -193,7 +197,11 @@ class HeadlessBrowser {
|
|
|
193
197
|
/* istanbul ignore next */
|
|
194
198
|
() => fontTracer(document)
|
|
195
199
|
);
|
|
196
|
-
|
|
200
|
+
try {
|
|
201
|
+
return await transferResults(jsHandle);
|
|
202
|
+
} finally {
|
|
203
|
+
await jsHandle.dispose();
|
|
204
|
+
}
|
|
197
205
|
} finally {
|
|
198
206
|
await page.close();
|
|
199
207
|
}
|
package/lib/cli.d.ts
ADDED
package/lib/cli.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|