@turntrout/subfont 1.10.2 → 1.10.4
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 +21 -21
- package/lib/HeadlessBrowser.d.ts +2 -0
- package/lib/HeadlessBrowser.d.ts.map +1 -1
- package/lib/HeadlessBrowser.js +64 -58
- package/lib/HeadlessBrowser.js.map +1 -1
- package/lib/collectTextsByPage.d.ts.map +1 -1
- package/lib/collectTextsByPage.js +145 -136
- package/lib/collectTextsByPage.js.map +1 -1
- package/lib/concurrencyLimit.d.ts +1 -0
- package/lib/concurrencyLimit.d.ts.map +1 -1
- package/lib/concurrencyLimit.js +5 -1
- package/lib/concurrencyLimit.js.map +1 -1
- package/lib/findCustomPropertyDefinitions.js.map +1 -1
- package/lib/fontConverter.d.ts.map +1 -1
- package/lib/fontConverter.js +2 -1
- package/lib/fontConverter.js.map +1 -1
- package/lib/getCssRulesByProperty.d.ts.map +1 -1
- package/lib/getCssRulesByProperty.js +234 -207
- package/lib/getCssRulesByProperty.js.map +1 -1
- package/lib/normalizeFontPropertyValue.js +1 -1
- package/lib/normalizeFontPropertyValue.js.map +1 -1
- package/lib/parseCommandLineOptions.d.ts.map +1 -1
- package/lib/parseCommandLineOptions.js +30 -19
- package/lib/parseCommandLineOptions.js.map +1 -1
- package/lib/sfntCache.d.ts.map +1 -1
- package/lib/sfntCache.js +2 -0
- package/lib/sfntCache.js.map +1 -1
- package/lib/subfont.d.ts.map +1 -1
- package/lib/subfont.js +347 -311
- package/lib/subfont.js.map +1 -1
- package/lib/subsetFontWithGlyphs.d.ts.map +1 -1
- package/lib/subsetFontWithGlyphs.js +62 -49
- package/lib/subsetFontWithGlyphs.js.map +1 -1
- package/lib/subsetFonts.d.ts.map +1 -1
- package/lib/subsetFonts.js +345 -283
- package/lib/subsetFonts.js.map +1 -1
- package/lib/subsetGeneration.d.ts.map +1 -1
- package/lib/subsetGeneration.js +152 -127
- package/lib/subsetGeneration.js.map +1 -1
- package/lib/unquote.js +2 -2
- package/lib/unquote.js.map +1 -1
- package/lib/warnAboutMissingGlyphs.d.ts.map +1 -1
- package/lib/warnAboutMissingGlyphs.js +132 -112
- package/lib/warnAboutMissingGlyphs.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,27 +59,27 @@ subfont path/to/index.html -i --cache
|
|
|
59
59
|
|
|
60
60
|
## Options
|
|
61
61
|
|
|
62
|
-
| Flag | Default | Description
|
|
63
|
-
| -----------------: | :-----: |
|
|
64
|
-
| `-i, --in-place` | off | Modify files in-place
|
|
65
|
-
| `-o, --output` | | Output directory
|
|
66
|
-
| `--root` | | Path to web root (deduced from input files if not specified)
|
|
67
|
-
| `--canonical-root` | | URI root where the site will be deployed
|
|
68
|
-
| `-r, --recursive` | off | Crawl linked pages
|
|
69
|
-
| `--dynamic` | off | Trace with headless browser
|
|
70
|
-
| `--dry-run` | off | Preview without writing
|
|
71
|
-
| `--fallbacks` | on | Async-load the full original font as a fallback for dynamic content
|
|
72
|
-
| `--font-display` | `swap` | `auto`/`block`/`swap`/`fallback`/`optional`
|
|
73
|
-
| `--text` | | Extra characters for every subset
|
|
74
|
-
| `--cache [dir]` | off | Cache subset results to disk between runs
|
|
75
|
-
| `--concurrency N` | auto | Max worker threads (defaults to CPU count,
|
|
76
|
-
| `--chrome-flags` | | Custom Chrome flags for `--dynamic` (comma-separated)
|
|
77
|
-
| `--source-maps` | off | Preserve CSS source maps (slower)
|
|
78
|
-
| `--strict` | off | Exit non-zero if any warnings are emitted
|
|
79
|
-
| `-s, --silent` | off | Suppress all console output
|
|
80
|
-
| `-d, --debug` | off | Verbose timing and font glyph detection info
|
|
81
|
-
| `--relative-urls` | off | Emit relative URLs instead of root-relative
|
|
82
|
-
| `--inline-css` | off | Inline the subset @font-face CSS into HTML
|
|
62
|
+
| Flag | Default | Description |
|
|
63
|
+
| -----------------: | :-----: | :---------------------------------------------------------------------------------------------------------------- |
|
|
64
|
+
| `-i, --in-place` | off | Modify files in-place |
|
|
65
|
+
| `-o, --output` | | Output directory |
|
|
66
|
+
| `--root` | | Path to web root (deduced from input files if not specified) |
|
|
67
|
+
| `--canonical-root` | | URI root where the site will be deployed |
|
|
68
|
+
| `-r, --recursive` | off | Crawl linked pages |
|
|
69
|
+
| `--dynamic` | off | Trace with headless browser |
|
|
70
|
+
| `--dry-run` | off | Preview without writing |
|
|
71
|
+
| `--fallbacks` | on | Async-load the full original font as a fallback for dynamic content |
|
|
72
|
+
| `--font-display` | `swap` | `auto`/`block`/`swap`/`fallback`/`optional` |
|
|
73
|
+
| `--text` | | Extra characters for every subset |
|
|
74
|
+
| `--cache [dir]` | off | Cache subset results to disk between runs |
|
|
75
|
+
| `--concurrency N` | auto | Max worker threads (defaults to CPU count, max 8). Warns when exceeding memory-based estimate (~50 MB per worker) |
|
|
76
|
+
| `--chrome-flags` | | Custom Chrome flags for `--dynamic` (comma-separated) |
|
|
77
|
+
| `--source-maps` | off | Preserve CSS source maps (slower) |
|
|
78
|
+
| `--strict` | off | Exit non-zero if any warnings are emitted |
|
|
79
|
+
| `-s, --silent` | off | Suppress all console output |
|
|
80
|
+
| `-d, --debug` | off | Verbose timing and font glyph detection info |
|
|
81
|
+
| `--relative-urls` | off | Emit relative URLs instead of root-relative |
|
|
82
|
+
| `--inline-css` | off | Inline the subset @font-face CSS into HTML |
|
|
83
83
|
|
|
84
84
|
Run `subfont --help` for the full list.
|
|
85
85
|
|
package/lib/HeadlessBrowser.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ declare class HeadlessBrowser {
|
|
|
11
11
|
private _closed;
|
|
12
12
|
constructor({ console, chromeArgs }: HeadlessBrowserOptions);
|
|
13
13
|
private _launchBrowserMemoized;
|
|
14
|
+
private _attachRequestInterceptor;
|
|
15
|
+
private _attachErrorListeners;
|
|
14
16
|
tracePage(htmlAsset: Asset): Promise<TraceResult[]>;
|
|
15
17
|
close(): Promise<void>;
|
|
16
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadlessBrowser.d.ts","sourceRoot":"","sources":["../src/HeadlessBrowser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"HeadlessBrowser.d.ts","sourceRoot":"","sources":["../src/HeadlessBrowser.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAc,KAAK,EAAE,MAAM,YAAY,CAAC;AAKpD,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA2E3C,UAAU,sBAAsB;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,cAAM,eAAe;IACnB,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,WAAW,CAAW;IAC9B,OAAO,CAAC,cAAc,CAAC,CAA4B;IACnD,OAAO,CAAC,OAAO,CAAkB;gBAErB,EAAE,OAAO,EAAE,UAAe,EAAE,EAAE,sBAAsB;IAKhE,OAAO,CAAC,sBAAsB;IAgB9B,OAAO,CAAC,yBAAyB;IAwCjC,OAAO,CAAC,qBAAqB;IA2BvB,SAAS,CAAC,SAAS,EAAE,KAAK,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IAwDnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAkB7B;AAED,SAAS,eAAe,CAAC"}
|
package/lib/HeadlessBrowser.js
CHANGED
|
@@ -113,6 +113,65 @@ class HeadlessBrowser {
|
|
|
113
113
|
}
|
|
114
114
|
return this._launchPromise;
|
|
115
115
|
}
|
|
116
|
+
_attachRequestInterceptor(page, assetGraph, baseUrl) {
|
|
117
|
+
page.on('request', (request) => {
|
|
118
|
+
const url = request.url();
|
|
119
|
+
try {
|
|
120
|
+
if (url.startsWith(baseUrl)) {
|
|
121
|
+
let agUrl = url.replace(baseUrl, assetGraph.root);
|
|
122
|
+
if (/\/$/.test(agUrl)) {
|
|
123
|
+
agUrl += 'index.html';
|
|
124
|
+
}
|
|
125
|
+
const asset = assetGraph.findAssets({
|
|
126
|
+
isLoaded: true,
|
|
127
|
+
url: agUrl,
|
|
128
|
+
})[0];
|
|
129
|
+
if (asset) {
|
|
130
|
+
request.respond({
|
|
131
|
+
status: 200,
|
|
132
|
+
contentType: asset.contentType,
|
|
133
|
+
body: asset.rawSrc,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
request.respond({ status: 404, body: '' });
|
|
138
|
+
}
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
if (url.startsWith('file:')) {
|
|
142
|
+
request.continue();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
// External request — abort to avoid hanging on DNS/network.
|
|
146
|
+
request.abort('failed');
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
// Request may already be handled or page may be closing — ignore.
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
_attachErrorListeners(page) {
|
|
154
|
+
page.on('requestfailed', (request) => {
|
|
155
|
+
const failure = request.failure();
|
|
156
|
+
const reason = failure ? failure.errorText : 'unknown error';
|
|
157
|
+
this.console.error(`${request.method()} ${request.url()} failed: ${reason}`);
|
|
158
|
+
});
|
|
159
|
+
page.on('pageerror', (err) => {
|
|
160
|
+
// Puppeteer v24+ passes Error objects; format stack to match v19 style
|
|
161
|
+
if (err instanceof Error && err.stack) {
|
|
162
|
+
// Normalize "at <anonymous> (url:line:col)" to "at url:line:col"
|
|
163
|
+
const normalized = err.stack.replace(/at <anonymous> \((.+)\)/g, 'at $1');
|
|
164
|
+
this.console.error(normalized);
|
|
165
|
+
}
|
|
166
|
+
else if (err instanceof Error) {
|
|
167
|
+
this.console.error(`${err.name}: ${err.message}`);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
this.console.error(err);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
page.on('error', this.console.error);
|
|
174
|
+
}
|
|
116
175
|
async tracePage(htmlAsset) {
|
|
117
176
|
const assetGraph = htmlAsset.assetGraph;
|
|
118
177
|
const browser = await this._launchBrowserMemoized();
|
|
@@ -122,65 +181,12 @@ class HeadlessBrowser {
|
|
|
122
181
|
const baseUrl = assetGraph.canonicalRoot
|
|
123
182
|
? assetGraph.canonicalRoot.replace(/\/?$/, '/')
|
|
124
183
|
: 'https://example.com/';
|
|
125
|
-
// Intercept all requests made by the headless browser, and
|
|
126
|
-
//
|
|
127
|
-
//
|
|
184
|
+
// Intercept all requests made by the headless browser, and fake a
|
|
185
|
+
// response from the assetgraph instance if the corresponding asset
|
|
186
|
+
// is found there.
|
|
128
187
|
await page.setRequestInterception(true);
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
try {
|
|
132
|
-
if (url.startsWith(baseUrl)) {
|
|
133
|
-
let agUrl = url.replace(baseUrl, assetGraph.root);
|
|
134
|
-
if (/\/$/.test(agUrl)) {
|
|
135
|
-
agUrl += 'index.html';
|
|
136
|
-
}
|
|
137
|
-
const asset = assetGraph.findAssets({
|
|
138
|
-
isLoaded: true,
|
|
139
|
-
url: agUrl,
|
|
140
|
-
})[0];
|
|
141
|
-
if (asset) {
|
|
142
|
-
request.respond({
|
|
143
|
-
status: 200,
|
|
144
|
-
contentType: asset.contentType,
|
|
145
|
-
body: asset.rawSrc,
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
request.respond({ status: 404, body: '' });
|
|
150
|
-
}
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
if (url.startsWith('file:')) {
|
|
154
|
-
request.continue();
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
// External request — abort to avoid hanging on DNS/network.
|
|
158
|
-
request.abort('failed');
|
|
159
|
-
}
|
|
160
|
-
catch {
|
|
161
|
-
// Request may already be handled or page may be closing — ignore.
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
page.on('requestfailed', (request) => {
|
|
165
|
-
const failure = request.failure();
|
|
166
|
-
const reason = failure ? failure.errorText : 'unknown error';
|
|
167
|
-
this.console.error(`${request.method()} ${request.url()} failed: ${reason}`);
|
|
168
|
-
});
|
|
169
|
-
page.on('pageerror', (err) => {
|
|
170
|
-
// Puppeteer v24+ passes Error objects; format stack to match v19 style
|
|
171
|
-
if (err instanceof Error && err.stack) {
|
|
172
|
-
// Normalize "at <anonymous> (url:line:col)" to "at url:line:col"
|
|
173
|
-
const normalized = err.stack.replace(/at <anonymous> \((.+)\)/g, 'at $1');
|
|
174
|
-
this.console.error(normalized);
|
|
175
|
-
}
|
|
176
|
-
else if (err instanceof Error) {
|
|
177
|
-
this.console.error(`${err.name}: ${err.message}`);
|
|
178
|
-
}
|
|
179
|
-
else {
|
|
180
|
-
this.console.error(err);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
page.on('error', this.console.error);
|
|
188
|
+
this._attachRequestInterceptor(page, assetGraph, baseUrl);
|
|
189
|
+
this._attachErrorListeners(page);
|
|
184
190
|
// Prevent the CSP of the page from rejecting our injection of font-tracer
|
|
185
191
|
await page.setBypassCSP(true);
|
|
186
192
|
await page.goto(urlTools.resolveUrl(baseUrl, urlTools.buildRelativeUrl(assetGraph.root, htmlAsset.url)), { timeout: 30000 });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadlessBrowser.js","sourceRoot":"","sources":["../src/HeadlessBrowser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mDAAqC;AACrC,0DAA4C;
|
|
1
|
+
{"version":3,"file":"HeadlessBrowser.js","sourceRoot":"","sources":["../src/HeadlessBrowser.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collectTextsByPage.d.ts","sourceRoot":"","sources":["../src/collectTextsByPage.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collectTextsByPage.d.ts","sourceRoot":"","sources":["../src/collectTextsByPage.ts"],"names":[],"mappings":"AA2BA,OAAO,EACL,mCAAmC,EAEpC,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,KAAK,EAAE,UAAU,EAAyB,MAAM,YAAY,CAAC;AAC3E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAwCtD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE9B,cAAc,CAAC,EAAE,KAAK,CAAC;CACxB;AAg5BD,UAAU,uBAAuB;IAC/B,cAAc,EAAE,KAAK,CAAC;IACtB,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,+BAA+B,EAAE,mBAAmB,EAAE,CAAC;IACvD,+BAA+B,EAAE,UAAU,CACzC,OAAO,mCAAmC,CAC3C,CAAC;IACF,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IAK9C,UAAU,EAAE,eAAe,EAAE,CAAC;CAC/B;AA2MD,UAAU,yBAAyB;IACjC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,UAAU,wBAAwB;IAChC,4BAA4B,EAAE,uBAAuB,EAAE,CAAC;IACxD,oCAAoC,EAAE,GAAG,CAAC,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACxE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAChD;AAED,iBAAe,kBAAkB,CAC/B,UAAU,EAAE,UAAU,EACtB,eAAe,EAAE,KAAK,EAAE,EACxB,EACE,IAAI,EACJ,OAAO,EACP,OAAe,EACf,KAAa,EACb,WAAW,EACX,UAAe,GAChB,GAAE,yBAA8B,GAChC,OAAO,CAAC,wBAAwB,CAAC,CA8InC;AAED,SAAS,kBAAkB,CAAC"}
|
|
@@ -40,6 +40,7 @@ const fontSnapper = require("font-snapper");
|
|
|
40
40
|
const HeadlessBrowser = require("./HeadlessBrowser");
|
|
41
41
|
const FontTracerPool = require("./FontTracerPool");
|
|
42
42
|
const gatherStylesheetsWithPredicates = require("./gatherStylesheetsWithPredicates");
|
|
43
|
+
const concurrencyLimit_1 = require("./concurrencyLimit");
|
|
43
44
|
const cssFontParser = __importStar(require("css-font-parser"));
|
|
44
45
|
const unquote = require("./unquote");
|
|
45
46
|
const normalizeFontPropertyValue = require("./normalizeFontPropertyValue");
|
|
@@ -154,14 +155,7 @@ function computeSnappedGlobalEntries(declarations, globalTextByProps) {
|
|
|
154
155
|
}
|
|
155
156
|
return entries;
|
|
156
157
|
}
|
|
157
|
-
|
|
158
|
-
// declarations entry. No-op on repeat calls — results are shared across
|
|
159
|
-
// pages that resolve to the same @font-face set.
|
|
160
|
-
function populateGlobalFontUsages(cached, accumulatedFontFaceDeclarations, text) {
|
|
161
|
-
if (cached.fontUsageTemplates) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
const snappedGlobalEntries = cached.snappedEntries;
|
|
158
|
+
function indexSnappedEntries(snappedGlobalEntries) {
|
|
165
159
|
const pageTextIndex = new Map();
|
|
166
160
|
const entriesByFontUrl = new Map();
|
|
167
161
|
const textAndPropsToFontUrl = new Map();
|
|
@@ -190,6 +184,9 @@ function populateGlobalFontUsages(cached, accumulatedFontFaceDeclarations, text)
|
|
|
190
184
|
arr.push(entry);
|
|
191
185
|
textAndPropsToFontUrl.set(entry.textAndProps, entry.fontUrl);
|
|
192
186
|
}
|
|
187
|
+
return { pageTextIndex, entriesByFontUrl, textAndPropsToFontUrl };
|
|
188
|
+
}
|
|
189
|
+
function collectExtraTextsByFontUrl(accumulatedFontFaceDeclarations, text) {
|
|
193
190
|
const extraTextsByFontUrl = new Map();
|
|
194
191
|
for (const fontFaceDeclaration of accumulatedFontFaceDeclarations) {
|
|
195
192
|
const { relations, '-subfont-text': subfontText, ...props } = fontFaceDeclaration;
|
|
@@ -197,84 +194,89 @@ function populateGlobalFontUsages(cached, accumulatedFontFaceDeclarations, text)
|
|
|
197
194
|
if (!fontUrl)
|
|
198
195
|
continue;
|
|
199
196
|
const extras = [];
|
|
200
|
-
if (subfontText !== undefined)
|
|
197
|
+
if (subfontText !== undefined)
|
|
201
198
|
extras.push(unquote(subfontText));
|
|
202
|
-
|
|
203
|
-
if (text !== undefined) {
|
|
199
|
+
if (text !== undefined)
|
|
204
200
|
extras.push(text);
|
|
201
|
+
if (extras.length === 0)
|
|
202
|
+
continue;
|
|
203
|
+
let arr = extraTextsByFontUrl.get(fontUrl);
|
|
204
|
+
if (!arr) {
|
|
205
|
+
// After destructuring out `relations` and `-subfont-text`, the
|
|
206
|
+
// remaining spread props are CSS descriptor strings.
|
|
207
|
+
arr = {
|
|
208
|
+
texts: [],
|
|
209
|
+
props: props,
|
|
210
|
+
fontRelations: relations,
|
|
211
|
+
};
|
|
212
|
+
extraTextsByFontUrl.set(fontUrl, arr);
|
|
205
213
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
214
|
+
arr.texts.push(...extras);
|
|
215
|
+
}
|
|
216
|
+
return extraTextsByFontUrl;
|
|
217
|
+
}
|
|
218
|
+
function buildFontUsageTemplate(fontUrl, fontEntries, extra) {
|
|
219
|
+
const allTexts = [];
|
|
220
|
+
if (extra)
|
|
221
|
+
allTexts.push(...extra.texts);
|
|
222
|
+
for (const e of fontEntries)
|
|
223
|
+
allTexts.push(e.textAndProps.text);
|
|
224
|
+
const fontFamilies = new Set(fontEntries.map((e) => e.props['font-family']));
|
|
225
|
+
const fontStyles = new Set(fontEntries.map((e) => e.fontStyle));
|
|
226
|
+
const fontWeights = new Set(fontEntries.map((e) => e.fontWeight));
|
|
227
|
+
const fontStretches = new Set(fontEntries.map((e) => e.fontStretch));
|
|
228
|
+
const fontVariationSettings = new Set(fontEntries
|
|
229
|
+
.map((e) => e.fontVariationSettings)
|
|
230
|
+
.filter((fvs) => typeof fvs === 'string' && fvs.toLowerCase() !== 'normal'));
|
|
231
|
+
// Use first entry's relations for size computation, or extra's if no entries
|
|
232
|
+
const fontRelations = fontEntries.length > 0
|
|
233
|
+
? fontEntries[0].fontRelations
|
|
234
|
+
: extra.fontRelations;
|
|
235
|
+
let smallestOriginalSize = 0;
|
|
236
|
+
let smallestOriginalFormat;
|
|
237
|
+
for (const relation of fontRelations) {
|
|
238
|
+
if (relation.to.isLoaded) {
|
|
239
|
+
const size = relation.to.rawSrc.length;
|
|
240
|
+
if (smallestOriginalSize === 0 || size < smallestOriginalSize) {
|
|
241
|
+
smallestOriginalSize = size;
|
|
242
|
+
smallestOriginalFormat = relation.to.type?.toLowerCase();
|
|
217
243
|
}
|
|
218
|
-
arr.texts.push(...extras);
|
|
219
244
|
}
|
|
220
245
|
}
|
|
221
|
-
|
|
222
|
-
|
|
246
|
+
const props = fontEntries.length > 0
|
|
247
|
+
? { ...fontEntries[0].props }
|
|
248
|
+
: { ...extra.props };
|
|
249
|
+
const extraTextsStr = extra ? extra.texts.join('') : '';
|
|
250
|
+
return {
|
|
251
|
+
smallestOriginalSize,
|
|
252
|
+
smallestOriginalFormat,
|
|
253
|
+
texts: allTexts,
|
|
254
|
+
text: (0, fontFaceHelpers_1.uniqueCharsFromArray)(allTexts),
|
|
255
|
+
extraTextsStr,
|
|
256
|
+
props,
|
|
257
|
+
fontUrl,
|
|
258
|
+
fontFamilies,
|
|
259
|
+
fontStyles,
|
|
260
|
+
fontStretches,
|
|
261
|
+
fontWeights,
|
|
262
|
+
fontVariationSettings,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
// Fill in fontUsageTemplates/pageTextIndex/preloadIndex on the cached
|
|
266
|
+
// declarations entry. No-op on repeat calls — results are shared across
|
|
267
|
+
// pages that resolve to the same @font-face set.
|
|
268
|
+
function populateGlobalFontUsages(cached, accumulatedFontFaceDeclarations, text) {
|
|
269
|
+
if (cached.fontUsageTemplates)
|
|
270
|
+
return;
|
|
271
|
+
const { pageTextIndex, entriesByFontUrl, textAndPropsToFontUrl } = indexSnappedEntries(cached.snappedEntries);
|
|
272
|
+
const extraTextsByFontUrl = collectExtraTextsByFontUrl(accumulatedFontFaceDeclarations, text);
|
|
223
273
|
const allFontUrls = new Set([
|
|
224
274
|
...entriesByFontUrl.keys(),
|
|
225
275
|
...extraTextsByFontUrl.keys(),
|
|
226
276
|
]);
|
|
277
|
+
const fontUsageTemplates = [];
|
|
227
278
|
for (const fontUrl of allFontUrls) {
|
|
228
|
-
|
|
229
|
-
const extra = extraTextsByFontUrl.get(fontUrl);
|
|
230
|
-
// Collect all texts (extras first, then global entries)
|
|
231
|
-
const allTexts = [];
|
|
232
|
-
if (extra) {
|
|
233
|
-
allTexts.push(...extra.texts);
|
|
234
|
-
}
|
|
235
|
-
for (const e of fontEntries) {
|
|
236
|
-
allTexts.push(e.textAndProps.text);
|
|
237
|
-
}
|
|
238
|
-
const fontFamilies = new Set(fontEntries.map((e) => e.props['font-family']));
|
|
239
|
-
const fontStyles = new Set(fontEntries.map((e) => e.fontStyle));
|
|
240
|
-
const fontWeights = new Set(fontEntries.map((e) => e.fontWeight));
|
|
241
|
-
const fontStretches = new Set(fontEntries.map((e) => e.fontStretch));
|
|
242
|
-
const fontVariationSettings = new Set(fontEntries
|
|
243
|
-
.map((e) => e.fontVariationSettings)
|
|
244
|
-
.filter((fvs) => typeof fvs === 'string' && fvs.toLowerCase() !== 'normal'));
|
|
245
|
-
// Use first entry's relations for size computation, or extra's if no entries
|
|
246
|
-
const fontRelations = fontEntries.length > 0
|
|
247
|
-
? fontEntries[0].fontRelations
|
|
248
|
-
: extra.fontRelations;
|
|
249
|
-
let smallestOriginalSize = 0;
|
|
250
|
-
let smallestOriginalFormat;
|
|
251
|
-
for (const relation of fontRelations) {
|
|
252
|
-
if (relation.to.isLoaded) {
|
|
253
|
-
const size = relation.to.rawSrc.length;
|
|
254
|
-
if (smallestOriginalSize === 0 || size < smallestOriginalSize) {
|
|
255
|
-
smallestOriginalSize = size;
|
|
256
|
-
smallestOriginalFormat = relation.to.type?.toLowerCase();
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
const props = fontEntries.length > 0
|
|
261
|
-
? { ...fontEntries[0].props }
|
|
262
|
-
: { ...extra.props };
|
|
263
|
-
const extraTextsStr = extra ? extra.texts.join('') : '';
|
|
264
|
-
fontUsageTemplates.push({
|
|
265
|
-
smallestOriginalSize,
|
|
266
|
-
smallestOriginalFormat,
|
|
267
|
-
texts: allTexts,
|
|
268
|
-
text: (0, fontFaceHelpers_1.uniqueCharsFromArray)(allTexts),
|
|
269
|
-
extraTextsStr,
|
|
270
|
-
props,
|
|
271
|
-
fontUrl,
|
|
272
|
-
fontFamilies,
|
|
273
|
-
fontStyles,
|
|
274
|
-
fontStretches,
|
|
275
|
-
fontWeights,
|
|
276
|
-
fontVariationSettings,
|
|
277
|
-
});
|
|
279
|
+
fontUsageTemplates.push(buildFontUsageTemplate(fontUrl, entriesByFontUrl.get(fontUrl) || [], extraTextsByFontUrl.get(fontUrl)));
|
|
278
280
|
}
|
|
279
281
|
cached.fontUsageTemplates = fontUsageTemplates;
|
|
280
282
|
cached.pageTextIndex = pageTextIndex;
|
|
@@ -294,9 +296,11 @@ async function tracePages(pagesNeedingFullTrace, { headlessBrowser, concurrency,
|
|
|
294
296
|
label: 'Tracing fonts',
|
|
295
297
|
});
|
|
296
298
|
if (useWorkerPool) {
|
|
299
|
+
// Explicit --concurrency overrides the default cap (subfont.ts warns
|
|
300
|
+
// when it exceeds the memory-based estimate).
|
|
297
301
|
const maxWorkers = concurrency && concurrency > 0
|
|
298
302
|
? concurrency
|
|
299
|
-
: Math.min(os.cpus().length,
|
|
303
|
+
: Math.min(os.cpus().length, concurrencyLimit_1.MAX_POOL_SIZE);
|
|
300
304
|
const numWorkers = Math.min(maxWorkers, totalPages);
|
|
301
305
|
const pool = new FontTracerPool(numWorkers);
|
|
302
306
|
await pool.init();
|
|
@@ -381,11 +385,13 @@ function planFastPathPages(fastPathPages) {
|
|
|
381
385
|
for (const entry of repTextByProps) {
|
|
382
386
|
const family = entry.props['font-family'] || '';
|
|
383
387
|
const propsKey = fontPropsKey(family, entry.props['font-weight'] || '', entry.props['font-style'] || '', entry.props['font-stretch'] || '');
|
|
384
|
-
|
|
388
|
+
let texts = textPerPropsKey.get(propsKey);
|
|
389
|
+
if (!texts) {
|
|
385
390
|
uniquePropsMap.set(propsKey, entry.props);
|
|
386
|
-
|
|
391
|
+
texts = [];
|
|
392
|
+
textPerPropsKey.set(propsKey, texts);
|
|
387
393
|
}
|
|
388
|
-
|
|
394
|
+
texts.push(entry.text);
|
|
389
395
|
if (family) {
|
|
390
396
|
const weight = entry.props['font-weight'] || 'normal';
|
|
391
397
|
const style = entry.props['font-style'] || 'normal';
|
|
@@ -656,6 +662,62 @@ function planTracing(pageData, hasHeadlessBrowser) {
|
|
|
656
662
|
uniqueGroupCount: pagesByStylesheetKey.size,
|
|
657
663
|
};
|
|
658
664
|
}
|
|
665
|
+
function getOrSnapDeclCacheEntry(declCache, accumulatedFontFaceDeclarations, globalTextByProps) {
|
|
666
|
+
const declKey = getDeclarationsKey(accumulatedFontFaceDeclarations);
|
|
667
|
+
let elapsedSnap = 0;
|
|
668
|
+
if (!declCache.has(declKey)) {
|
|
669
|
+
const snapStart = Date.now();
|
|
670
|
+
declCache.set(declKey, {
|
|
671
|
+
snappedEntries: computeSnappedGlobalEntries(accumulatedFontFaceDeclarations, globalTextByProps),
|
|
672
|
+
fontUsageTemplates: null,
|
|
673
|
+
pageTextIndex: null,
|
|
674
|
+
preloadIndex: null,
|
|
675
|
+
});
|
|
676
|
+
elapsedSnap = Date.now() - snapStart;
|
|
677
|
+
}
|
|
678
|
+
return { entry: declCache.get(declKey), elapsedSnap };
|
|
679
|
+
}
|
|
680
|
+
function instantiateFontUsagesForPage(entry, declCacheEntry, uniqueCharsCache) {
|
|
681
|
+
const fontUsageTemplates = declCacheEntry.fontUsageTemplates;
|
|
682
|
+
const pageTextIndex = declCacheEntry.pageTextIndex;
|
|
683
|
+
const textAndPropsToFontUrl = declCacheEntry.preloadIndex;
|
|
684
|
+
const preloadFontUrls = new Set();
|
|
685
|
+
for (const textByPropsEntry of entry.textByProps) {
|
|
686
|
+
const fontUrl = textAndPropsToFontUrl.get(textByPropsEntry);
|
|
687
|
+
if (fontUrl)
|
|
688
|
+
preloadFontUrls.add(fontUrl);
|
|
689
|
+
}
|
|
690
|
+
const assetTexts = pageTextIndex.get(entry.htmlOrSvgAsset);
|
|
691
|
+
entry.fontUsages = fontUsageTemplates.map((template) => {
|
|
692
|
+
const pageTexts = assetTexts ? assetTexts.get(template.fontUrl) : undefined;
|
|
693
|
+
let pageTextStr = pageTexts ? pageTexts.join('') : '';
|
|
694
|
+
if (template.extraTextsStr)
|
|
695
|
+
pageTextStr += template.extraTextsStr;
|
|
696
|
+
let pageTextUnique = uniqueCharsCache.get(pageTextStr);
|
|
697
|
+
if (pageTextUnique === undefined) {
|
|
698
|
+
pageTextUnique = (0, fontFaceHelpers_1.uniqueChars)(pageTextStr);
|
|
699
|
+
uniqueCharsCache.set(pageTextStr, pageTextUnique);
|
|
700
|
+
}
|
|
701
|
+
const { hasFontFeatureSettings, fontFeatureTags } = (0, fontFeatureHelpers_1.resolveFeatureSettings)(template.fontFamilies, entry.fontFamiliesWithFeatureSettings, entry.featureTagsByFamily);
|
|
702
|
+
return {
|
|
703
|
+
smallestOriginalSize: template.smallestOriginalSize,
|
|
704
|
+
smallestOriginalFormat: template.smallestOriginalFormat,
|
|
705
|
+
texts: template.texts,
|
|
706
|
+
pageText: pageTextUnique,
|
|
707
|
+
text: template.text,
|
|
708
|
+
props: { ...template.props },
|
|
709
|
+
fontUrl: template.fontUrl,
|
|
710
|
+
fontFamilies: template.fontFamilies,
|
|
711
|
+
fontStyles: template.fontStyles,
|
|
712
|
+
fontStretches: template.fontStretches,
|
|
713
|
+
fontWeights: template.fontWeights,
|
|
714
|
+
fontVariationSettings: template.fontVariationSettings,
|
|
715
|
+
preload: preloadFontUrls.has(template.fontUrl),
|
|
716
|
+
hasFontFeatureSettings,
|
|
717
|
+
fontFeatureTags,
|
|
718
|
+
};
|
|
719
|
+
});
|
|
720
|
+
}
|
|
659
721
|
// Iterate every traced page, snap its text against the @font-face set, and
|
|
660
722
|
// emit fully-formed per-page fontUsages (one entry per font URL + props).
|
|
661
723
|
function buildPerPageFontUsages(htmlOrSvgAssetTextsWithProps, globalTextByProps, text) {
|
|
@@ -665,66 +727,13 @@ function buildPerPageFontUsages(htmlOrSvgAssetTextsWithProps, globalTextByProps,
|
|
|
665
727
|
let globalUsageTime = 0;
|
|
666
728
|
let cloningTime = 0;
|
|
667
729
|
for (const entry of htmlOrSvgAssetTextsWithProps) {
|
|
668
|
-
const {
|
|
669
|
-
|
|
670
|
-
if (!declCache.has(declKey)) {
|
|
671
|
-
const snapStart = Date.now();
|
|
672
|
-
declCache.set(declKey, {
|
|
673
|
-
snappedEntries: computeSnappedGlobalEntries(accumulatedFontFaceDeclarations, globalTextByProps),
|
|
674
|
-
fontUsageTemplates: null,
|
|
675
|
-
pageTextIndex: null,
|
|
676
|
-
preloadIndex: null,
|
|
677
|
-
});
|
|
678
|
-
snappingTime += Date.now() - snapStart;
|
|
679
|
-
}
|
|
680
|
-
const declCacheEntry = declCache.get(declKey);
|
|
730
|
+
const { entry: declCacheEntry, elapsedSnap } = getOrSnapDeclCacheEntry(declCache, entry.accumulatedFontFaceDeclarations, globalTextByProps);
|
|
731
|
+
snappingTime += elapsedSnap;
|
|
681
732
|
const globalUsageStart = Date.now();
|
|
682
|
-
populateGlobalFontUsages(declCacheEntry, accumulatedFontFaceDeclarations, text);
|
|
733
|
+
populateGlobalFontUsages(declCacheEntry, entry.accumulatedFontFaceDeclarations, text);
|
|
683
734
|
globalUsageTime += Date.now() - globalUsageStart;
|
|
684
|
-
const fontUsageTemplates = declCacheEntry.fontUsageTemplates;
|
|
685
|
-
const pageTextIndex = declCacheEntry.pageTextIndex;
|
|
686
|
-
const textAndPropsToFontUrl = declCacheEntry.preloadIndex;
|
|
687
|
-
const preloadFontUrls = new Set();
|
|
688
|
-
for (const textByPropsEntry of textByProps) {
|
|
689
|
-
const fontUrl = textAndPropsToFontUrl.get(textByPropsEntry);
|
|
690
|
-
if (fontUrl) {
|
|
691
|
-
preloadFontUrls.add(fontUrl);
|
|
692
|
-
}
|
|
693
|
-
}
|
|
694
735
|
const cloneStart = Date.now();
|
|
695
|
-
|
|
696
|
-
entry.fontUsages = fontUsageTemplates.map((template) => {
|
|
697
|
-
const pageTexts = assetTexts
|
|
698
|
-
? assetTexts.get(template.fontUrl)
|
|
699
|
-
: undefined;
|
|
700
|
-
let pageTextStr = pageTexts ? pageTexts.join('') : '';
|
|
701
|
-
if (template.extraTextsStr) {
|
|
702
|
-
pageTextStr += template.extraTextsStr;
|
|
703
|
-
}
|
|
704
|
-
let pageTextUnique = uniqueCharsCache.get(pageTextStr);
|
|
705
|
-
if (pageTextUnique === undefined) {
|
|
706
|
-
pageTextUnique = (0, fontFaceHelpers_1.uniqueChars)(pageTextStr);
|
|
707
|
-
uniqueCharsCache.set(pageTextStr, pageTextUnique);
|
|
708
|
-
}
|
|
709
|
-
const { hasFontFeatureSettings, fontFeatureTags } = (0, fontFeatureHelpers_1.resolveFeatureSettings)(template.fontFamilies, fontFamiliesWithFeatureSettings, featureTagsByFamily);
|
|
710
|
-
return {
|
|
711
|
-
smallestOriginalSize: template.smallestOriginalSize,
|
|
712
|
-
smallestOriginalFormat: template.smallestOriginalFormat,
|
|
713
|
-
texts: template.texts,
|
|
714
|
-
pageText: pageTextUnique,
|
|
715
|
-
text: template.text,
|
|
716
|
-
props: { ...template.props },
|
|
717
|
-
fontUrl: template.fontUrl,
|
|
718
|
-
fontFamilies: template.fontFamilies,
|
|
719
|
-
fontStyles: template.fontStyles,
|
|
720
|
-
fontStretches: template.fontStretches,
|
|
721
|
-
fontWeights: template.fontWeights,
|
|
722
|
-
fontVariationSettings: template.fontVariationSettings,
|
|
723
|
-
preload: preloadFontUrls.has(template.fontUrl),
|
|
724
|
-
hasFontFeatureSettings,
|
|
725
|
-
fontFeatureTags,
|
|
726
|
-
};
|
|
727
|
-
});
|
|
736
|
+
instantiateFontUsagesForPage(entry, declCacheEntry, uniqueCharsCache);
|
|
728
737
|
cloningTime += Date.now() - cloneStart;
|
|
729
738
|
}
|
|
730
739
|
return { snappingTime, globalUsageTime, cloningTime };
|