hyperframes 0.8.84 → 0.8.86
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/backgroundChecksWorker.js +1 -1
- package/dist/cli.js +243 -88
- package/dist/fontLocalizeCli.js +259 -88
- package/dist/hyperframe-runtime.js +48 -48
- package/dist/hyperframe.manifest.json +1 -1
- package/dist/hyperframe.runtime.iife.js +48 -48
- package/dist/hyperframes-player.global.js +12 -3
- package/dist/studio/assets/hyperframes-player-Dx-2Gpsu.js +473 -0
- package/dist/studio/assets/{index-D9dmtDap.js → index-8Fgryj7q.js} +1 -1
- package/dist/studio/assets/{index-DFcIBFM8.js → index-Cz3E_ZSj.js} +1 -1
- package/dist/studio/assets/{index-gjbSm-vt.js → index-d5DKK15Q.js} +175 -175
- package/dist/studio/assets/{index-BWJqxeaH.css → index-mzZCha_N.css} +1 -1
- package/dist/studio/{chunk-7VDQIGOU.js → chunk-7PLTC6SV.js} +8 -2
- package/dist/studio/chunk-7PLTC6SV.js.map +1 -0
- package/dist/studio/index.d.ts +25 -2
- package/dist/studio/index.html +2 -2
- package/dist/studio/index.js +151 -111
- package/dist/studio/index.js.map +1 -1
- package/dist/studio/player.js +1 -1
- package/dist/studio/styles.css +1 -1
- package/package.json +1 -1
- package/dist/studio/assets/hyperframes-player-Dd74fv7B.js +0 -464
- package/dist/studio/chunk-7VDQIGOU.js.map +0 -1
package/dist/fontLocalizeCli.js
CHANGED
|
@@ -94979,96 +94979,234 @@ function partitionWeightRuns(faces, coveredWeights) {
|
|
|
94979
94979
|
for (const face of unsortable) runs.push([face]);
|
|
94980
94980
|
return runs;
|
|
94981
94981
|
}
|
|
94982
|
-
async function
|
|
94982
|
+
async function bundledFamilyFaceRules(canonical, normalizedFamily, emitFamily, optional, options, fontText) {
|
|
94983
|
+
const rules = [];
|
|
94984
|
+
const coveredWeights = /* @__PURE__ */ new Set();
|
|
94985
|
+
const bundledRules = [];
|
|
94986
|
+
for (const face of canonical.faces) {
|
|
94987
|
+
const style = face.style || "normal";
|
|
94988
|
+
const src = fontDataUri(canonical.packageName, face.weight, style);
|
|
94989
|
+
bundledRules.push(
|
|
94990
|
+
buildFontFaceRule(emitFamily, src, face.weight, style, BUNDLED_SUBSET_UNICODE_RANGE)
|
|
94991
|
+
);
|
|
94992
|
+
coveredWeights.add(coverageKey(face.weight, style));
|
|
94993
|
+
}
|
|
94994
|
+
const canonicalFamily = resolveAliasDisplayName(normalizedFamily);
|
|
94995
|
+
const googleFaces = canonicalFamily ? await fetchFamilyFaces(canonicalFamily, optional, options, fontText) : [];
|
|
94996
|
+
const supplementary = googleFaces.filter(
|
|
94997
|
+
(face) => !coveredWeights.has(coverageKey(face.weight, face.style)) || !isBundledSubsetRange(face.unicodeRange)
|
|
94998
|
+
);
|
|
94999
|
+
const runs = groupFacesBySource(supplementary).flatMap(
|
|
95000
|
+
(group) => partitionWeightRuns(group, coveredWeights)
|
|
95001
|
+
);
|
|
95002
|
+
const firstAppearance = (run) => Math.min(...run.map((face) => supplementary.indexOf(face)));
|
|
95003
|
+
for (const run of [...runs].sort((a, b) => firstAppearance(a) - firstAppearance(b))) {
|
|
95004
|
+
const first = run[0];
|
|
95005
|
+
const last = run[run.length - 1];
|
|
95006
|
+
if (!first || !last) continue;
|
|
95007
|
+
const weight = run.length > 1 ? `${first.weight} ${last.weight}` : first.weight;
|
|
95008
|
+
rules.push(
|
|
95009
|
+
buildFontFaceRule(emitFamily, first.dataUri, weight, first.style, first.unicodeRange)
|
|
95010
|
+
);
|
|
95011
|
+
}
|
|
95012
|
+
rules.push(...bundledRules);
|
|
95013
|
+
return rules;
|
|
95014
|
+
}
|
|
95015
|
+
async function googleFamilyFaceRules(lookupFamily, emitFamily, optional, options, fontText) {
|
|
95016
|
+
const googleFaces = await fetchFamilyFaces(lookupFamily, optional, options, fontText);
|
|
95017
|
+
if (googleFaces.length === 0) return null;
|
|
95018
|
+
return googleFaces.map(
|
|
95019
|
+
(face) => buildFontFaceRule(emitFamily, face.dataUri, face.weight, face.style, face.unicodeRange)
|
|
95020
|
+
);
|
|
95021
|
+
}
|
|
95022
|
+
async function systemFamilyFaceRules(lookupFamily, emitFamily) {
|
|
95023
|
+
const variants = locateSystemFontVariants(lookupFamily);
|
|
95024
|
+
if (variants.length === 0) return null;
|
|
95025
|
+
const rules = [];
|
|
95026
|
+
let totalBytes = 0;
|
|
95027
|
+
for (const variant of variants) {
|
|
95028
|
+
const fontBuffer = readFileSync12(variant.path);
|
|
95029
|
+
totalBytes += fontBuffer.length;
|
|
95030
|
+
const dataUri = await fontToDataUri(fontBuffer, variant.format);
|
|
95031
|
+
rules.push(buildFontFaceRule(emitFamily, dataUri, variant.weight, variant.style));
|
|
95032
|
+
}
|
|
95033
|
+
if (totalBytes > SYSTEM_FONT_SIZE_LIMIT) {
|
|
95034
|
+
defaultLogger.warn(
|
|
95035
|
+
`[Compiler] System font "${lookupFamily}" is large (${(totalBytes / 1024 / 1024).toFixed(1)} MB total across ${variants.length} variant(s)) \u2014 embedding anyway. Consider font subsetting for production.`
|
|
95036
|
+
);
|
|
95037
|
+
}
|
|
95038
|
+
defaultLogger.info(
|
|
95039
|
+
`[Compiler] Embedded system font "${lookupFamily}" \u2014 ${variants.length} variant(s), ${(totalBytes / 1024).toFixed(0)} KB total`
|
|
95040
|
+
);
|
|
95041
|
+
return rules;
|
|
95042
|
+
}
|
|
95043
|
+
async function resolveFamilyFaceRules(normalizedFamily, lookupFamily, emitFamily, optional, options, fontText) {
|
|
95044
|
+
const canonicalKey = FONT_ALIASES[normalizedFamily];
|
|
95045
|
+
if (canonicalKey) {
|
|
95046
|
+
const canonical = CANONICAL_FONTS[canonicalKey];
|
|
95047
|
+
if (!canonical) return [];
|
|
95048
|
+
return bundledFamilyFaceRules(
|
|
95049
|
+
canonical,
|
|
95050
|
+
normalizedFamily,
|
|
95051
|
+
emitFamily,
|
|
95052
|
+
optional,
|
|
95053
|
+
options,
|
|
95054
|
+
fontText
|
|
95055
|
+
);
|
|
95056
|
+
}
|
|
95057
|
+
return await googleFamilyFaceRules(lookupFamily, emitFamily, optional, options, fontText) ?? (options.allowSystemFontCapture && !pageNamedThisFile(lookupFamily, options) ? await systemFamilyFaceRules(lookupFamily, emitFamily) : null);
|
|
95058
|
+
}
|
|
95059
|
+
function googleFontsUrlFamilies(rawUrl) {
|
|
95060
|
+
let url;
|
|
95061
|
+
try {
|
|
95062
|
+
url = new URL(rawUrl.trim(), "https://document.invalid/");
|
|
95063
|
+
} catch {
|
|
95064
|
+
return [];
|
|
95065
|
+
}
|
|
95066
|
+
if (url.hostname !== "fonts.googleapis.com") return [];
|
|
95067
|
+
if (url.pathname !== "/css" && url.pathname !== "/css2") return [];
|
|
95068
|
+
return url.searchParams.getAll("family").flatMap((value) => value.split("|")).map((entry) => (entry.split(":", 1)[0] ?? "").trim()).filter((family) => family.length > 0);
|
|
95069
|
+
}
|
|
95070
|
+
function importRuleUrl(params) {
|
|
95071
|
+
const trimmed = params.trim();
|
|
95072
|
+
if (trimmed.toLowerCase().startsWith("url(")) {
|
|
95073
|
+
const close = trimmed.indexOf(")");
|
|
95074
|
+
if (close < 0 || !isUnconditionalMedia(trimmed.slice(close + 1))) return null;
|
|
95075
|
+
return trimmed.slice(4, close).trim().replace(/^['"]/, "").replace(/['"]$/, "");
|
|
95076
|
+
}
|
|
95077
|
+
const quote = trimmed[0];
|
|
95078
|
+
if (quote !== '"' && quote !== "'") return null;
|
|
95079
|
+
const end = trimmed.indexOf(quote, 1);
|
|
95080
|
+
return end > 0 && isUnconditionalMedia(trimmed.slice(end + 1)) ? trimmed.slice(1, end) : null;
|
|
95081
|
+
}
|
|
95082
|
+
function fontFaceRuleFamily(rule) {
|
|
95083
|
+
let family;
|
|
95084
|
+
rule.walkDecls((decl) => {
|
|
95085
|
+
if (decl.prop.toLowerCase() === "font-family") family = parseFontFamilyValue(decl.value)[0];
|
|
95086
|
+
});
|
|
95087
|
+
return family;
|
|
95088
|
+
}
|
|
95089
|
+
function isUnconditionalMedia(media) {
|
|
95090
|
+
const normalized2 = (media ?? "").trim().toLowerCase();
|
|
95091
|
+
return normalized2 === "" || normalized2 === "all";
|
|
95092
|
+
}
|
|
95093
|
+
function isUnconditionalStylesheet(element) {
|
|
95094
|
+
const type = (element.getAttribute("type") ?? "").trim().toLowerCase();
|
|
95095
|
+
return isUnconditionalMedia(element.getAttribute("media")) && (type === "" || type === "text/css") && !(element.getAttribute("title") ?? "").trim() && !element.hasAttribute("disabled");
|
|
95096
|
+
}
|
|
95097
|
+
function declareStyleFontFamilies(styleEl, register) {
|
|
95098
|
+
if (!isUnconditionalStylesheet(styleEl)) return;
|
|
95099
|
+
const root = parseCssRoot(styleEl.textContent ?? "");
|
|
95100
|
+
if (!root) return;
|
|
95101
|
+
root.walkAtRules((atRule) => {
|
|
95102
|
+
if (atRule.parent?.type !== "root") return;
|
|
95103
|
+
const name = atRule.name.toLowerCase();
|
|
95104
|
+
if (name === "import") {
|
|
95105
|
+
const url = importRuleUrl(atRule.params);
|
|
95106
|
+
if (url) for (const family2 of googleFontsUrlFamilies(url)) register(family2);
|
|
95107
|
+
return;
|
|
95108
|
+
}
|
|
95109
|
+
if (name !== "font-face") return;
|
|
95110
|
+
const family = fontFaceRuleFamily(atRule);
|
|
95111
|
+
if (family) register(family, atRule);
|
|
95112
|
+
});
|
|
95113
|
+
}
|
|
95114
|
+
function declareLinkedFontFamilies(link, register) {
|
|
95115
|
+
const rel = (link.getAttribute("rel") ?? "").toLowerCase().split(/\s+/);
|
|
95116
|
+
if (!rel.includes("stylesheet") || rel.includes("alternate") || !isUnconditionalStylesheet(link))
|
|
95117
|
+
return;
|
|
95118
|
+
for (const family of googleFontsUrlFamilies(link.getAttribute("href") ?? "")) register(family);
|
|
95119
|
+
}
|
|
95120
|
+
function collectDeclaredFontFamilies(html) {
|
|
95121
|
+
const { document: document2 } = parseHTML(html);
|
|
95122
|
+
const declared = /* @__PURE__ */ new Map();
|
|
95123
|
+
const register = (family, fontFaceRule) => {
|
|
95124
|
+
const key2 = normalizeFamilyName(family);
|
|
95125
|
+
if (!key2 || GENERIC_FAMILIES2.has(key2)) return;
|
|
95126
|
+
let entry = declared.get(key2);
|
|
95127
|
+
if (!entry) {
|
|
95128
|
+
entry = { family, fontFaceRules: [] };
|
|
95129
|
+
declared.set(key2, entry);
|
|
95130
|
+
}
|
|
95131
|
+
if (fontFaceRule) entry.fontFaceRules.push(fontFaceRule);
|
|
95132
|
+
};
|
|
95133
|
+
for (const styleEl of Array.from(document2.querySelectorAll("style"))) {
|
|
95134
|
+
declareStyleFontFamilies(styleEl, register);
|
|
95135
|
+
}
|
|
95136
|
+
for (const link of Array.from(document2.querySelectorAll("link[href]"))) {
|
|
95137
|
+
declareLinkedFontFamilies(link, register);
|
|
95138
|
+
}
|
|
95139
|
+
return declared;
|
|
95140
|
+
}
|
|
95141
|
+
function familySpellingKey(family) {
|
|
95142
|
+
return family.toLowerCase().replace(/[\s_+-]+/g, "");
|
|
95143
|
+
}
|
|
95144
|
+
function findDeclaredFamilyAlias(authoredFamily, declaredFamilies) {
|
|
95145
|
+
if (declaredFamilies.has(normalizeFamilyName(authoredFamily))) return null;
|
|
95146
|
+
const key2 = familySpellingKey(authoredFamily);
|
|
95147
|
+
if (!key2) return null;
|
|
95148
|
+
let match = null;
|
|
95149
|
+
for (const entry of declaredFamilies.values()) {
|
|
95150
|
+
if (familySpellingKey(entry.family) !== key2) continue;
|
|
95151
|
+
if (match) return null;
|
|
95152
|
+
match = entry;
|
|
95153
|
+
}
|
|
95154
|
+
return match;
|
|
95155
|
+
}
|
|
95156
|
+
async function resolveDeclaredFamilyAlias(authoredFamily, declaredFamilies, optional, options, fontText) {
|
|
95157
|
+
const declared = findDeclaredFamilyAlias(authoredFamily, declaredFamilies);
|
|
95158
|
+
if (!declared) return null;
|
|
95159
|
+
let rules;
|
|
95160
|
+
if (declared.fontFaceRules.length > 0) {
|
|
95161
|
+
rules = declared.fontFaceRules.map((rule) => {
|
|
95162
|
+
const renamed = rule.clone();
|
|
95163
|
+
renamed.walkDecls((decl) => {
|
|
95164
|
+
if (decl.prop.toLowerCase() === "font-family") decl.value = `"${authoredFamily}"`;
|
|
95165
|
+
});
|
|
95166
|
+
return renamed.toString();
|
|
95167
|
+
});
|
|
95168
|
+
} else {
|
|
95169
|
+
rules = await resolveFamilyFaceRules(
|
|
95170
|
+
normalizeFamilyName(declared.family),
|
|
95171
|
+
declared.family,
|
|
95172
|
+
authoredFamily,
|
|
95173
|
+
optional,
|
|
95174
|
+
options,
|
|
95175
|
+
fontText
|
|
95176
|
+
);
|
|
95177
|
+
}
|
|
95178
|
+
if (!rules) return null;
|
|
95179
|
+
defaultLogger.warn(
|
|
95180
|
+
`[Compiler] font-family "${authoredFamily}" is not a known family; resolved it to "${declared.family}", which this document declares. Correct the authored font-family to "${declared.family}".`
|
|
95181
|
+
);
|
|
95182
|
+
return rules;
|
|
95183
|
+
}
|
|
95184
|
+
async function buildFontFaceCss(requestedFamilies, options, declaredFamilies, fontText) {
|
|
94983
95185
|
const rules = [];
|
|
94984
95186
|
const unresolved = [];
|
|
94985
95187
|
const requiredFirst = [...requestedFamilies].sort(
|
|
94986
95188
|
([, a], [, b]) => Number(a.optional) - Number(b.optional)
|
|
94987
95189
|
);
|
|
94988
95190
|
for (const [normalizedFamily, { family: originalCaseFamily, optional }] of requiredFirst) {
|
|
94989
|
-
const
|
|
94990
|
-
|
|
94991
|
-
|
|
94992
|
-
|
|
94993
|
-
|
|
94994
|
-
|
|
94995
|
-
|
|
94996
|
-
|
|
94997
|
-
|
|
94998
|
-
|
|
94999
|
-
|
|
95000
|
-
|
|
95001
|
-
|
|
95002
|
-
|
|
95003
|
-
|
|
95004
|
-
|
|
95005
|
-
|
|
95006
|
-
);
|
|
95007
|
-
coveredWeights.add(coverageKey(face.weight, style));
|
|
95008
|
-
}
|
|
95009
|
-
const canonicalFamily = resolveAliasDisplayName(normalizedFamily);
|
|
95010
|
-
const googleFaces2 = canonicalFamily ? await fetchFamilyFaces(canonicalFamily, optional, options, fontText) : [];
|
|
95011
|
-
const supplementary = googleFaces2.filter(
|
|
95012
|
-
(face) => !coveredWeights.has(coverageKey(face.weight, face.style)) || !isBundledSubsetRange(face.unicodeRange)
|
|
95013
|
-
);
|
|
95014
|
-
const runs = groupFacesBySource(supplementary).flatMap(
|
|
95015
|
-
(group) => partitionWeightRuns(group, coveredWeights)
|
|
95016
|
-
);
|
|
95017
|
-
const firstAppearance = (run) => Math.min(...run.map((face) => supplementary.indexOf(face)));
|
|
95018
|
-
for (const run of [...runs].sort((a, b) => firstAppearance(a) - firstAppearance(b))) {
|
|
95019
|
-
const first = run[0];
|
|
95020
|
-
const last = run[run.length - 1];
|
|
95021
|
-
if (!first || !last) continue;
|
|
95022
|
-
const weight = run.length > 1 ? `${first.weight} ${last.weight}` : first.weight;
|
|
95023
|
-
rules.push(
|
|
95024
|
-
buildFontFaceRule(
|
|
95025
|
-
originalCaseFamily,
|
|
95026
|
-
first.dataUri,
|
|
95027
|
-
weight,
|
|
95028
|
-
first.style,
|
|
95029
|
-
first.unicodeRange
|
|
95030
|
-
)
|
|
95031
|
-
);
|
|
95032
|
-
}
|
|
95033
|
-
rules.push(...bundledRules);
|
|
95034
|
-
continue;
|
|
95035
|
-
}
|
|
95036
|
-
const googleFaces = await fetchFamilyFaces(originalCaseFamily, optional, options, fontText);
|
|
95037
|
-
if (googleFaces.length > 0) {
|
|
95038
|
-
for (const face of googleFaces) {
|
|
95039
|
-
rules.push(
|
|
95040
|
-
buildFontFaceRule(
|
|
95041
|
-
originalCaseFamily,
|
|
95042
|
-
face.dataUri,
|
|
95043
|
-
face.weight,
|
|
95044
|
-
face.style,
|
|
95045
|
-
face.unicodeRange
|
|
95046
|
-
)
|
|
95047
|
-
);
|
|
95048
|
-
}
|
|
95191
|
+
const familyRules = await resolveFamilyFaceRules(
|
|
95192
|
+
normalizedFamily,
|
|
95193
|
+
originalCaseFamily,
|
|
95194
|
+
originalCaseFamily,
|
|
95195
|
+
optional,
|
|
95196
|
+
options,
|
|
95197
|
+
fontText
|
|
95198
|
+
) ?? // Last, so a family that already resolves keeps exactly the faces it had.
|
|
95199
|
+
await resolveDeclaredFamilyAlias(
|
|
95200
|
+
originalCaseFamily,
|
|
95201
|
+
declaredFamilies(),
|
|
95202
|
+
optional,
|
|
95203
|
+
options,
|
|
95204
|
+
fontText
|
|
95205
|
+
);
|
|
95206
|
+
if (familyRules) {
|
|
95207
|
+
rules.push(...familyRules);
|
|
95049
95208
|
continue;
|
|
95050
95209
|
}
|
|
95051
|
-
if (options.allowSystemFontCapture && !pageNamedThisFile(originalCaseFamily, options)) {
|
|
95052
|
-
const variants = locateSystemFontVariants(originalCaseFamily);
|
|
95053
|
-
if (variants.length > 0) {
|
|
95054
|
-
let totalBytes = 0;
|
|
95055
|
-
for (const variant of variants) {
|
|
95056
|
-
const fontBuffer = readFileSync12(variant.path);
|
|
95057
|
-
totalBytes += fontBuffer.length;
|
|
95058
|
-
const dataUri = await fontToDataUri(fontBuffer, variant.format);
|
|
95059
|
-
rules.push(buildFontFaceRule(originalCaseFamily, dataUri, variant.weight, variant.style));
|
|
95060
|
-
}
|
|
95061
|
-
if (totalBytes > SYSTEM_FONT_SIZE_LIMIT) {
|
|
95062
|
-
defaultLogger.warn(
|
|
95063
|
-
`[Compiler] System font "${originalCaseFamily}" is large (${(totalBytes / 1024 / 1024).toFixed(1)} MB total across ${variants.length} variant(s)) \u2014 embedding anyway. Consider font subsetting for production.`
|
|
95064
|
-
);
|
|
95065
|
-
}
|
|
95066
|
-
defaultLogger.info(
|
|
95067
|
-
`[Compiler] Embedded system font "${originalCaseFamily}" \u2014 ${variants.length} variant(s), ${(totalBytes / 1024).toFixed(0)} KB total`
|
|
95068
|
-
);
|
|
95069
|
-
continue;
|
|
95070
|
-
}
|
|
95071
|
-
}
|
|
95072
95210
|
unresolved.push(originalCaseFamily);
|
|
95073
95211
|
}
|
|
95074
95212
|
return {
|
|
@@ -95142,13 +95280,16 @@ var FontFetchError = class extends Error {
|
|
|
95142
95280
|
familyName;
|
|
95143
95281
|
url;
|
|
95144
95282
|
cause;
|
|
95145
|
-
|
|
95283
|
+
/** Unlike `message`, holds no URLs: safe for callers that must not echo resolver output. */
|
|
95284
|
+
unresolvedFamilies;
|
|
95285
|
+
constructor(familyName, url, message, cause, code = FONT_FETCH_FAILED, unresolvedFamilies = []) {
|
|
95146
95286
|
super(message);
|
|
95147
95287
|
this.name = "FontFetchError";
|
|
95148
95288
|
this.code = code;
|
|
95149
95289
|
this.familyName = familyName;
|
|
95150
95290
|
this.url = url;
|
|
95151
95291
|
this.cause = cause;
|
|
95292
|
+
this.unresolvedFamilies = unresolvedFamilies;
|
|
95152
95293
|
}
|
|
95153
95294
|
};
|
|
95154
95295
|
var FontFetchUnavailableError = class extends FontFetchError {
|
|
@@ -95571,9 +95712,11 @@ async function injectDeterministicFontFaces(html, options = {}) {
|
|
|
95571
95712
|
if (pendingFamilies.size === 0) {
|
|
95572
95713
|
return html;
|
|
95573
95714
|
}
|
|
95715
|
+
let declaredFamilies;
|
|
95574
95716
|
const { css, unresolved } = await buildFontFaceCss(
|
|
95575
95717
|
pendingFamilies,
|
|
95576
95718
|
fetchOptions,
|
|
95719
|
+
() => declaredFamilies ??= collectDeclaredFontFamilies(html),
|
|
95577
95720
|
extractGoogleFontsText(html)
|
|
95578
95721
|
);
|
|
95579
95722
|
const required = unresolved.filter(
|
|
@@ -95583,7 +95726,10 @@ async function injectDeterministicFontFaces(html, options = {}) {
|
|
|
95583
95726
|
throw new FontFetchError(
|
|
95584
95727
|
required.join(", "),
|
|
95585
95728
|
"",
|
|
95586
|
-
`[Compiler] Unresolved fonts in fail-closed mode: ${required.join(", ")}. Distributed renders require all fonts to be resolvable
|
|
95729
|
+
`[Compiler] Unresolved fonts in fail-closed mode: ${required.join(", ")}. Distributed renders require all fonts to be resolvable.`,
|
|
95730
|
+
void 0,
|
|
95731
|
+
FONT_FETCH_FAILED,
|
|
95732
|
+
unresolved
|
|
95587
95733
|
);
|
|
95588
95734
|
}
|
|
95589
95735
|
if (!css) {
|
|
@@ -105085,6 +105231,29 @@ function safeErrorName(error) {
|
|
|
105085
105231
|
const name = error instanceof Error ? error.name : "UnknownError";
|
|
105086
105232
|
return /^[A-Za-z][A-Za-z0-9]*$/.test(name) ? name : "Error";
|
|
105087
105233
|
}
|
|
105234
|
+
var MAX_REPORTED_FAMILIES = 8;
|
|
105235
|
+
var MAX_FAMILY_NAME_LENGTH = 64;
|
|
105236
|
+
function unresolvedFamilyList(error) {
|
|
105237
|
+
if (!(error instanceof Error) || !("unresolvedFamilies" in error)) return [];
|
|
105238
|
+
const families = error.unresolvedFamilies;
|
|
105239
|
+
return Array.isArray(families) ? families : [];
|
|
105240
|
+
}
|
|
105241
|
+
function safeFamilyName(family) {
|
|
105242
|
+
if (typeof family !== "string" || /[:/?#&=%@\\]/.test(family)) return null;
|
|
105243
|
+
const safe = family.replace(/[^A-Za-z0-9 _-]+/g, " ").replace(/\s+/g, " ").trim().slice(0, MAX_FAMILY_NAME_LENGTH).trim();
|
|
105244
|
+
return safe || null;
|
|
105245
|
+
}
|
|
105246
|
+
function unresolvedFamiliesSuffix(error) {
|
|
105247
|
+
const families = unresolvedFamilyList(error);
|
|
105248
|
+
if (families.length === 0) return "";
|
|
105249
|
+
const printable = families.map(safeFamilyName).filter((name) => name !== null);
|
|
105250
|
+
const distinct = [...new Set(printable)];
|
|
105251
|
+
const shown = distinct.slice(0, MAX_REPORTED_FAMILIES);
|
|
105252
|
+
const hidden = families.length - printable.length + (distinct.length - shown.length);
|
|
105253
|
+
const listed = shown.map((name) => `"${name}"`).join(", ");
|
|
105254
|
+
const more = hidden > 0 ? `${listed ? " " : ""}(+${hidden} more)` : "";
|
|
105255
|
+
return `: unresolved font families: ${listed}${more}`;
|
|
105256
|
+
}
|
|
105088
105257
|
async function runFontLocalize(io, localize) {
|
|
105089
105258
|
const html = await io.readInput();
|
|
105090
105259
|
if (!html.trim()) {
|
|
@@ -105100,15 +105269,17 @@ async function runFontLocalize(io, localize) {
|
|
|
105100
105269
|
io.writeOutput(localized);
|
|
105101
105270
|
return 0;
|
|
105102
105271
|
} catch (error) {
|
|
105103
|
-
io.writeError(
|
|
105104
|
-
`)
|
|
105272
|
+
io.writeError(
|
|
105273
|
+
`font localization failed (${safeErrorName(error)})${unresolvedFamiliesSuffix(error)}
|
|
105274
|
+
`
|
|
105275
|
+
);
|
|
105105
105276
|
return 1;
|
|
105106
105277
|
}
|
|
105107
105278
|
}
|
|
105108
105279
|
|
|
105109
105280
|
// src/version.ts
|
|
105110
|
-
var VERSION = true ? "0.8.
|
|
105111
|
-
var PRODUCER_VERSION = true ? "0.8.
|
|
105281
|
+
var VERSION = true ? "0.8.86" : "0.0.0-dev";
|
|
105282
|
+
var PRODUCER_VERSION = true ? "0.8.86" : "0.0.0-dev";
|
|
105112
105283
|
|
|
105113
105284
|
// src/fontLocalizeCli.ts
|
|
105114
105285
|
async function readStdin() {
|