@bagelink/blox 1.15.673 → 1.15.675
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/{shard-runner-C1yhyjvs.cjs → shard-runner-B6QuBu1v.cjs} +2 -2
- package/dist/{shard-runner-esdE7BT1.js → shard-runner-D9iaxpkZ.js} +2 -2
- package/dist/ssg/cli.cjs +2 -2
- package/dist/ssg/cli.mjs +2 -2
- package/dist/ssg/index.cjs +1 -1
- package/dist/ssg/index.mjs +2 -2
- package/dist/ssg/prerender.d.ts +11 -0
- package/dist/ssg/prerender.d.ts.map +1 -1
- package/dist/{validate-output-CWWWtrI-.cjs → validate-output-B1pkkoqo.cjs} +93 -6
- package/dist/{validate-output-BK5OVQ7Y.js → validate-output-xNcexUzJ.js} +93 -6
- package/package.json +1 -1
|
@@ -26,7 +26,7 @@ const node_child_process = require("node:child_process");
|
|
|
26
26
|
const os = require("node:os");
|
|
27
27
|
const path = require("node:path");
|
|
28
28
|
const process = require("node:process");
|
|
29
|
-
const llmArtifacts = require("./validate-output-
|
|
29
|
+
const llmArtifacts = require("./validate-output-B1pkkoqo.cjs");
|
|
30
30
|
const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
|
|
31
31
|
const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
|
|
32
32
|
const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
|
|
@@ -166,7 +166,7 @@ async function runSharded(opts) {
|
|
|
166
166
|
}
|
|
167
167
|
if (process.env.BLOX_SSG_LLM !== "0") {
|
|
168
168
|
try {
|
|
169
|
-
const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-
|
|
169
|
+
const { mergeLlmParts } = await Promise.resolve().then(() => require("./validate-output-B1pkkoqo.cjs")).then((n) => n.llmArtifacts);
|
|
170
170
|
const mergeWebsite = website;
|
|
171
171
|
const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
|
|
172
172
|
const { pages } = await mergeLlmParts({
|
|
@@ -2,7 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
|
-
import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-
|
|
5
|
+
import { f as fetchCmsSiteData, g as generateSitemapArtifacts } from "./validate-output-xNcexUzJ.js";
|
|
6
6
|
const AUTO_SHARD_CAP = Number(process.env.BLOX_SSG_SHARD_CAP) || 6;
|
|
7
7
|
const PREFETCH_BUDGET = Number(process.env.BLOX_SSG_PREFETCH_BUDGET) || 24;
|
|
8
8
|
const SEQUENTIAL_SHARDS = process.env.BLOX_SSG_SEQUENTIAL === "1";
|
|
@@ -142,7 +142,7 @@ async function runSharded(opts) {
|
|
|
142
142
|
}
|
|
143
143
|
if (process.env.BLOX_SSG_LLM !== "0") {
|
|
144
144
|
try {
|
|
145
|
-
const { mergeLlmParts } = await import("./validate-output-
|
|
145
|
+
const { mergeLlmParts } = await import("./validate-output-xNcexUzJ.js").then((n) => n.C);
|
|
146
146
|
const mergeWebsite = website;
|
|
147
147
|
const partFiles = Array.from({ length: total }, (_, i) => path.join(llmPartsDir, `part.${i}.json`));
|
|
148
148
|
const { pages } = await mergeLlmParts({
|
package/dist/ssg/cli.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const process = require("node:process");
|
|
4
4
|
const fs = require("node:fs/promises");
|
|
5
5
|
const ssg_buildGrant = require("./build-grant.cjs");
|
|
6
|
-
const llmArtifacts = require("../validate-output-
|
|
6
|
+
const llmArtifacts = require("../validate-output-B1pkkoqo.cjs");
|
|
7
7
|
function installFetchTimeout() {
|
|
8
8
|
const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
|
|
9
9
|
const original = globalThis.fetch;
|
|
@@ -147,7 +147,7 @@ Environment:
|
|
|
147
147
|
if (shardsOpt !== null || routesCmd) {
|
|
148
148
|
const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
|
|
149
149
|
const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
|
|
150
|
-
const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-
|
|
150
|
+
const { runSharded } = await Promise.resolve().then(() => require("../shard-runner-B6QuBu1v.cjs"));
|
|
151
151
|
const code = await runSharded({
|
|
152
152
|
shards: shardsOpt ?? "auto",
|
|
153
153
|
mode,
|
package/dist/ssg/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import fs from "node:fs/promises";
|
|
4
4
|
import { resolveBloxBuildGrant } from "./build-grant.mjs";
|
|
5
|
-
import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, b as buildCollectionResolver, a as prerender, c as validateInternalLinks } from "../validate-output-
|
|
5
|
+
import { v as validateSsgOutput, u as uploadBloxManifest, p as polyfillBloxSsgGlobals, f as fetchCmsSiteData, b as buildCollectionResolver, a as prerender, c as validateInternalLinks } from "../validate-output-xNcexUzJ.js";
|
|
6
6
|
function installFetchTimeout() {
|
|
7
7
|
const ms = Number(process.env.BLOX_SSG_FETCH_TIMEOUT_MS) || 2e4;
|
|
8
8
|
const original = globalThis.fetch;
|
|
@@ -146,7 +146,7 @@ Environment:
|
|
|
146
146
|
if (shardsOpt !== null || routesCmd) {
|
|
147
147
|
const { apiBase: apiBase2, websiteName: configWebsiteName2 } = await resolveApiBase(mode);
|
|
148
148
|
const websiteName2 = process.env.WEBSITE_NAME ?? configWebsiteName2 ?? "default";
|
|
149
|
-
const { runSharded } = await import("../shard-runner-
|
|
149
|
+
const { runSharded } = await import("../shard-runner-D9iaxpkZ.js");
|
|
150
150
|
const code = await runSharded({
|
|
151
151
|
shards: shardsOpt ?? "auto",
|
|
152
152
|
mode,
|
package/dist/ssg/index.cjs
CHANGED
|
@@ -22,7 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
mod
|
|
23
23
|
));
|
|
24
24
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
25
|
-
const llmArtifacts = require("../validate-output-
|
|
25
|
+
const llmArtifacts = require("../validate-output-B1pkkoqo.cjs");
|
|
26
26
|
const ssg_buildGrant = require("./build-grant.cjs");
|
|
27
27
|
const ssg_client = require("../client-AoDTJJXJ.cjs");
|
|
28
28
|
const vue = require("vue");
|
package/dist/ssg/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as buildPageHead, e as primaryContextEntry, h as buildJsonLd, i as extractPageText, B as BloxBuildResponseError, j as bloxBuildJson } from "../validate-output-
|
|
2
|
-
import { k, l, f, m, n, o, q, g, r, s, t, w, x, y, p, a, z, A, u, c, v } from "../validate-output-
|
|
1
|
+
import { d as buildPageHead, e as primaryContextEntry, h as buildJsonLd, i as extractPageText, B as BloxBuildResponseError, j as bloxBuildJson } from "../validate-output-xNcexUzJ.js";
|
|
2
|
+
import { k, l, f, m, n, o, q, g, r, s, t, w, x, y, p, a, z, A, u, c, v } from "../validate-output-xNcexUzJ.js";
|
|
3
3
|
import { parseBloxBuildGrantBody, resolveBloxBuildGrant } from "./build-grant.mjs";
|
|
4
4
|
import { a as BLOX_HYDRATION_WINDOW_KEY } from "../client-Ce9fRCGH.js";
|
|
5
5
|
import { createSSRApp, h, Suspense } from "vue";
|
package/dist/ssg/prerender.d.ts
CHANGED
|
@@ -99,6 +99,17 @@ export declare function prerender({ root, clientOutDir, serverEntry, paths, craw
|
|
|
99
99
|
* prefetch (render resolves inline). Default 8.
|
|
100
100
|
*/
|
|
101
101
|
resolvePrefetchConcurrency, appPaths, includeRoot, routePartsFile, mode, website, websiteId, redirects, llm, }?: PrerenderOptions): Promise<PrerenderResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Collect `<link rel="preload">` tags for the web fonts a page is likely to use.
|
|
104
|
+
*
|
|
105
|
+
* Fonts are usually split into many `@font-face` blocks — one per `unicode-range`
|
|
106
|
+
* subset (latin, latin-ext, cyrillic, greek, vietnamese…) and per weight. Only one
|
|
107
|
+
* subset per (family, weight, style) is ever needed for a given page, so preloading
|
|
108
|
+
* every URL makes the browser fetch megabytes of subsets it will never render,
|
|
109
|
+
* competing with the LCP resource. Prefer the Latin subset of each face and skip
|
|
110
|
+
* the rest; browsers still fetch any other subset on demand via `unicode-range`.
|
|
111
|
+
*/
|
|
112
|
+
export declare function discoverFontPreloads(clientOutDir: string): Promise<string>;
|
|
102
113
|
export declare function injectIntoTemplate(template: string, head: string, appHtml: string, fontPreloads: string, htmlAttrs?: string, teleports?: Record<string, string>): string;
|
|
103
114
|
export declare function injectTeleports(html: string, teleports: Record<string, string>): string;
|
|
104
115
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"prerender.d.ts","sourceRoot":"","sources":["../../src/ssg/prerender.ts"],"names":[],"mappings":"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"}
|
|
@@ -1279,7 +1279,56 @@ function makeExcludeChecker(excludePaths) {
|
|
|
1279
1279
|
return false;
|
|
1280
1280
|
};
|
|
1281
1281
|
}
|
|
1282
|
+
const FONT_FACE_RE = /@font-face\s*\{([^}]*)\}/g;
|
|
1283
|
+
const SRC_URL_RE = /url\(\s*(["']?)([^"')\s]+\.woff2)\1\s*\)/;
|
|
1284
|
+
const LATIN_CODE_POINT = 65;
|
|
1285
|
+
function rangeCoversLatin(range) {
|
|
1286
|
+
for (const part of range.split(",")) {
|
|
1287
|
+
const token = part.trim().replace(/^U\+/i, "");
|
|
1288
|
+
if (!token) continue;
|
|
1289
|
+
const [start, end] = token.split("-");
|
|
1290
|
+
const lo = Number.parseInt(start, 16);
|
|
1291
|
+
const hi = end ? Number.parseInt(end, 16) : lo;
|
|
1292
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi)) continue;
|
|
1293
|
+
if (LATIN_CODE_POINT >= lo && LATIN_CODE_POINT <= hi) return true;
|
|
1294
|
+
}
|
|
1295
|
+
return false;
|
|
1296
|
+
}
|
|
1297
|
+
const CSS_IMPORT_RE = /@import\s+(?:url\(\s*)?["']?(?:https?:)?\/\/([^"')\s]+)["']?\s*\)?/g;
|
|
1298
|
+
async function cssImportHints(cssFiles) {
|
|
1299
|
+
const origins = /* @__PURE__ */ new Set();
|
|
1300
|
+
const imported = [];
|
|
1301
|
+
for (const file of cssFiles) {
|
|
1302
|
+
let css = "";
|
|
1303
|
+
try {
|
|
1304
|
+
css = await fs.readFile(file, "utf8");
|
|
1305
|
+
} catch {
|
|
1306
|
+
continue;
|
|
1307
|
+
}
|
|
1308
|
+
for (const [, rest] of css.matchAll(CSS_IMPORT_RE)) {
|
|
1309
|
+
if (!rest) continue;
|
|
1310
|
+
const href = rest.startsWith("http") ? rest : `https://${rest}`;
|
|
1311
|
+
const isFontCss = /fonts\.googleapis\.com|font-awesome|material-symbols/i.test(href);
|
|
1312
|
+
if (!isFontCss) continue;
|
|
1313
|
+
if (imported.includes(href)) continue;
|
|
1314
|
+
imported.push(href);
|
|
1315
|
+
try {
|
|
1316
|
+
origins.add(new URL(href).origin);
|
|
1317
|
+
} catch {
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
const tags = [];
|
|
1322
|
+
for (const origin of origins) {
|
|
1323
|
+
tags.push(`<link rel="preconnect" href="${origin}">`);
|
|
1324
|
+
}
|
|
1325
|
+
for (const href of imported) {
|
|
1326
|
+
tags.push(`<link rel="preload" as="style" href="${href}">`);
|
|
1327
|
+
}
|
|
1328
|
+
return tags;
|
|
1329
|
+
}
|
|
1282
1330
|
async function discoverFontPreloads(clientOutDir) {
|
|
1331
|
+
var _a, _b, _c, _d, _e;
|
|
1283
1332
|
const assetsDir = path.join(clientOutDir, "assets");
|
|
1284
1333
|
let cssFiles = [];
|
|
1285
1334
|
try {
|
|
@@ -1288,15 +1337,42 @@ async function discoverFontPreloads(clientOutDir) {
|
|
|
1288
1337
|
} catch {
|
|
1289
1338
|
return "";
|
|
1290
1339
|
}
|
|
1291
|
-
const
|
|
1292
|
-
const woff2Re = /url\((["']?)(https?:\/\/[^"')]+\.woff2)\1\)/g;
|
|
1340
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1293
1341
|
for (const file of cssFiles) {
|
|
1294
1342
|
const css = await fs.readFile(file, "utf8");
|
|
1295
|
-
for (const [,
|
|
1296
|
-
|
|
1343
|
+
for (const [, body] of css.matchAll(FONT_FACE_RE)) {
|
|
1344
|
+
const src = SRC_URL_RE.exec(body ?? "");
|
|
1345
|
+
const url = src == null ? void 0 : src[2];
|
|
1346
|
+
if (!url) continue;
|
|
1347
|
+
if (!/^(https?:\/\/|\/)/.test(url)) continue;
|
|
1348
|
+
const family = (((_a = /font-family\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _a[1]) ?? "").trim().replace(/^["']|["']$/g, "");
|
|
1349
|
+
const style = (((_b = /font-style\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _b[1]) ?? "normal").trim();
|
|
1350
|
+
const weight = (((_c = /font-weight\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _c[1]) ?? "400").trim();
|
|
1351
|
+
const rangeRaw = (_e = (_d = /unicode-range\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _d[1]) == null ? void 0 : _e.trim();
|
|
1352
|
+
const key = `${family}|${style}|${weight}`;
|
|
1353
|
+
const list = groups.get(key) ?? [];
|
|
1354
|
+
if (list.some((candidate) => candidate.url === url)) continue;
|
|
1355
|
+
list.push({
|
|
1356
|
+
family,
|
|
1357
|
+
style,
|
|
1358
|
+
weight,
|
|
1359
|
+
url,
|
|
1360
|
+
hasRange: Boolean(rangeRaw),
|
|
1361
|
+
coversLatin: rangeRaw ? rangeCoversLatin(rangeRaw) : true
|
|
1362
|
+
});
|
|
1363
|
+
groups.set(key, list);
|
|
1297
1364
|
}
|
|
1298
1365
|
}
|
|
1299
|
-
|
|
1366
|
+
const picked = [];
|
|
1367
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1368
|
+
for (const candidates of groups.values()) {
|
|
1369
|
+
const choice = candidates.find((candidate) => candidate.coversLatin) ?? (candidates.every((candidate) => candidate.hasRange) ? void 0 : candidates[0]);
|
|
1370
|
+
if (!choice || seen.has(choice.url)) continue;
|
|
1371
|
+
seen.add(choice.url);
|
|
1372
|
+
picked.push(choice.url);
|
|
1373
|
+
}
|
|
1374
|
+
const fontTags = picked.map((href) => `<link rel="preload" as="font" type="font/woff2" crossorigin href="${href}">`);
|
|
1375
|
+
return [...await cssImportHints(cssFiles), ...fontTags].join("\n");
|
|
1300
1376
|
}
|
|
1301
1377
|
function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "", teleports = {}) {
|
|
1302
1378
|
let out = template;
|
|
@@ -1312,7 +1388,18 @@ function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "
|
|
|
1312
1388
|
}
|
|
1313
1389
|
}
|
|
1314
1390
|
if (fontPreloads) {
|
|
1315
|
-
|
|
1391
|
+
const alreadyDeclared = new Set(
|
|
1392
|
+
(template.match(/<link[^>]+href="([^"]+)"[^>]*>/g) ?? []).map((tag) => {
|
|
1393
|
+
var _a;
|
|
1394
|
+
return (_a = /href="([^"]+)"/.exec(tag)) == null ? void 0 : _a[1];
|
|
1395
|
+
}).filter((href) => Boolean(href))
|
|
1396
|
+
);
|
|
1397
|
+
const hints = fontPreloads.split("\n").filter((line) => {
|
|
1398
|
+
var _a;
|
|
1399
|
+
const href = (_a = /href="([^"]+)"/.exec(line)) == null ? void 0 : _a[1];
|
|
1400
|
+
return !href || !alreadyDeclared.has(href);
|
|
1401
|
+
}).join("\n");
|
|
1402
|
+
if (hints) out = out.replace("</head>", `${hints}
|
|
1316
1403
|
</head>`);
|
|
1317
1404
|
}
|
|
1318
1405
|
if (head) {
|
|
@@ -1256,7 +1256,56 @@ function makeExcludeChecker(excludePaths) {
|
|
|
1256
1256
|
return false;
|
|
1257
1257
|
};
|
|
1258
1258
|
}
|
|
1259
|
+
const FONT_FACE_RE = /@font-face\s*\{([^}]*)\}/g;
|
|
1260
|
+
const SRC_URL_RE = /url\(\s*(["']?)([^"')\s]+\.woff2)\1\s*\)/;
|
|
1261
|
+
const LATIN_CODE_POINT = 65;
|
|
1262
|
+
function rangeCoversLatin(range) {
|
|
1263
|
+
for (const part of range.split(",")) {
|
|
1264
|
+
const token = part.trim().replace(/^U\+/i, "");
|
|
1265
|
+
if (!token) continue;
|
|
1266
|
+
const [start, end] = token.split("-");
|
|
1267
|
+
const lo = Number.parseInt(start, 16);
|
|
1268
|
+
const hi = end ? Number.parseInt(end, 16) : lo;
|
|
1269
|
+
if (!Number.isFinite(lo) || !Number.isFinite(hi)) continue;
|
|
1270
|
+
if (LATIN_CODE_POINT >= lo && LATIN_CODE_POINT <= hi) return true;
|
|
1271
|
+
}
|
|
1272
|
+
return false;
|
|
1273
|
+
}
|
|
1274
|
+
const CSS_IMPORT_RE = /@import\s+(?:url\(\s*)?["']?(?:https?:)?\/\/([^"')\s]+)["']?\s*\)?/g;
|
|
1275
|
+
async function cssImportHints(cssFiles) {
|
|
1276
|
+
const origins = /* @__PURE__ */ new Set();
|
|
1277
|
+
const imported = [];
|
|
1278
|
+
for (const file of cssFiles) {
|
|
1279
|
+
let css = "";
|
|
1280
|
+
try {
|
|
1281
|
+
css = await fs.readFile(file, "utf8");
|
|
1282
|
+
} catch {
|
|
1283
|
+
continue;
|
|
1284
|
+
}
|
|
1285
|
+
for (const [, rest] of css.matchAll(CSS_IMPORT_RE)) {
|
|
1286
|
+
if (!rest) continue;
|
|
1287
|
+
const href = rest.startsWith("http") ? rest : `https://${rest}`;
|
|
1288
|
+
const isFontCss = /fonts\.googleapis\.com|font-awesome|material-symbols/i.test(href);
|
|
1289
|
+
if (!isFontCss) continue;
|
|
1290
|
+
if (imported.includes(href)) continue;
|
|
1291
|
+
imported.push(href);
|
|
1292
|
+
try {
|
|
1293
|
+
origins.add(new URL(href).origin);
|
|
1294
|
+
} catch {
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
}
|
|
1298
|
+
const tags = [];
|
|
1299
|
+
for (const origin of origins) {
|
|
1300
|
+
tags.push(`<link rel="preconnect" href="${origin}">`);
|
|
1301
|
+
}
|
|
1302
|
+
for (const href of imported) {
|
|
1303
|
+
tags.push(`<link rel="preload" as="style" href="${href}">`);
|
|
1304
|
+
}
|
|
1305
|
+
return tags;
|
|
1306
|
+
}
|
|
1259
1307
|
async function discoverFontPreloads(clientOutDir) {
|
|
1308
|
+
var _a, _b, _c, _d, _e;
|
|
1260
1309
|
const assetsDir = path.join(clientOutDir, "assets");
|
|
1261
1310
|
let cssFiles = [];
|
|
1262
1311
|
try {
|
|
@@ -1265,15 +1314,42 @@ async function discoverFontPreloads(clientOutDir) {
|
|
|
1265
1314
|
} catch {
|
|
1266
1315
|
return "";
|
|
1267
1316
|
}
|
|
1268
|
-
const
|
|
1269
|
-
const woff2Re = /url\((["']?)(https?:\/\/[^"')]+\.woff2)\1\)/g;
|
|
1317
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1270
1318
|
for (const file of cssFiles) {
|
|
1271
1319
|
const css = await fs.readFile(file, "utf8");
|
|
1272
|
-
for (const [,
|
|
1273
|
-
|
|
1320
|
+
for (const [, body] of css.matchAll(FONT_FACE_RE)) {
|
|
1321
|
+
const src = SRC_URL_RE.exec(body ?? "");
|
|
1322
|
+
const url = src == null ? void 0 : src[2];
|
|
1323
|
+
if (!url) continue;
|
|
1324
|
+
if (!/^(https?:\/\/|\/)/.test(url)) continue;
|
|
1325
|
+
const family = (((_a = /font-family\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _a[1]) ?? "").trim().replace(/^["']|["']$/g, "");
|
|
1326
|
+
const style = (((_b = /font-style\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _b[1]) ?? "normal").trim();
|
|
1327
|
+
const weight = (((_c = /font-weight\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _c[1]) ?? "400").trim();
|
|
1328
|
+
const rangeRaw = (_e = (_d = /unicode-range\s*:\s*([^;]+)/i.exec(body)) == null ? void 0 : _d[1]) == null ? void 0 : _e.trim();
|
|
1329
|
+
const key = `${family}|${style}|${weight}`;
|
|
1330
|
+
const list = groups.get(key) ?? [];
|
|
1331
|
+
if (list.some((candidate) => candidate.url === url)) continue;
|
|
1332
|
+
list.push({
|
|
1333
|
+
family,
|
|
1334
|
+
style,
|
|
1335
|
+
weight,
|
|
1336
|
+
url,
|
|
1337
|
+
hasRange: Boolean(rangeRaw),
|
|
1338
|
+
coversLatin: rangeRaw ? rangeCoversLatin(rangeRaw) : true
|
|
1339
|
+
});
|
|
1340
|
+
groups.set(key, list);
|
|
1274
1341
|
}
|
|
1275
1342
|
}
|
|
1276
|
-
|
|
1343
|
+
const picked = [];
|
|
1344
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1345
|
+
for (const candidates of groups.values()) {
|
|
1346
|
+
const choice = candidates.find((candidate) => candidate.coversLatin) ?? (candidates.every((candidate) => candidate.hasRange) ? void 0 : candidates[0]);
|
|
1347
|
+
if (!choice || seen.has(choice.url)) continue;
|
|
1348
|
+
seen.add(choice.url);
|
|
1349
|
+
picked.push(choice.url);
|
|
1350
|
+
}
|
|
1351
|
+
const fontTags = picked.map((href) => `<link rel="preload" as="font" type="font/woff2" crossorigin href="${href}">`);
|
|
1352
|
+
return [...await cssImportHints(cssFiles), ...fontTags].join("\n");
|
|
1277
1353
|
}
|
|
1278
1354
|
function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "", teleports = {}) {
|
|
1279
1355
|
let out = template;
|
|
@@ -1289,7 +1365,18 @@ function injectIntoTemplate(template, head, appHtml, fontPreloads, htmlAttrs = "
|
|
|
1289
1365
|
}
|
|
1290
1366
|
}
|
|
1291
1367
|
if (fontPreloads) {
|
|
1292
|
-
|
|
1368
|
+
const alreadyDeclared = new Set(
|
|
1369
|
+
(template.match(/<link[^>]+href="([^"]+)"[^>]*>/g) ?? []).map((tag) => {
|
|
1370
|
+
var _a;
|
|
1371
|
+
return (_a = /href="([^"]+)"/.exec(tag)) == null ? void 0 : _a[1];
|
|
1372
|
+
}).filter((href) => Boolean(href))
|
|
1373
|
+
);
|
|
1374
|
+
const hints = fontPreloads.split("\n").filter((line) => {
|
|
1375
|
+
var _a;
|
|
1376
|
+
const href = (_a = /href="([^"]+)"/.exec(line)) == null ? void 0 : _a[1];
|
|
1377
|
+
return !href || !alreadyDeclared.has(href);
|
|
1378
|
+
}).join("\n");
|
|
1379
|
+
if (hints) out = out.replace("</head>", `${hints}
|
|
1293
1380
|
</head>`);
|
|
1294
1381
|
}
|
|
1295
1382
|
if (head) {
|
package/package.json
CHANGED