@xingwangzhe/stalux 1.5.2 → 1.5.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/package.json +1 -1
- package/src/internal/font-subset.ts +61 -61
package/package.json
CHANGED
|
@@ -204,6 +204,21 @@ function collectCommonChars(projectRoot: string): string {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
// Also scan post frontmatter for tags, categories so those pages' chars are covered
|
|
208
|
+
const postsDir = resolve(projectRoot, CONTENT_ROOT, "posts");
|
|
209
|
+
if (existsSync(postsDir)) {
|
|
210
|
+
for (const f of readdirSync(postsDir)) {
|
|
211
|
+
if (!f.endsWith(".md") && !f.endsWith(".mdx")) continue;
|
|
212
|
+
if (f.startsWith("_")) continue;
|
|
213
|
+
try {
|
|
214
|
+
const content = readFileSync(join(postsDir, f), "utf-8");
|
|
215
|
+
for (const ch of content) chars.add(ch);
|
|
216
|
+
} catch {
|
|
217
|
+
/* skip */
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
207
222
|
return [...chars].sort().join("");
|
|
208
223
|
}
|
|
209
224
|
|
|
@@ -342,79 +357,64 @@ export async function runFontSubsetting(
|
|
|
342
357
|
const postMap: Record<string, string> = {};
|
|
343
358
|
|
|
344
359
|
let subsetCount = 0;
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
360
|
+
|
|
361
|
+
if (!skipPerRoute) {
|
|
362
|
+
for (const [hash, routes] of groups) {
|
|
363
|
+
const filename = `subset-${hash}.ttf`;
|
|
364
|
+
const outPath = join(outDir, filename);
|
|
365
|
+
if (!existsSync(outPath)) {
|
|
366
|
+
const route = routeSets.find((r) => r.hash === hash);
|
|
367
|
+
const chars = route?.chars ?? "";
|
|
368
|
+
const uniqueChars = chars
|
|
369
|
+
.split("")
|
|
370
|
+
.filter((ch) => !commonChars.includes(ch))
|
|
371
|
+
.join("");
|
|
372
|
+
if (uniqueChars.length > 0) {
|
|
373
|
+
const glyphs = get_glyph_ids(uniqueChars, "stalux", "normal", 400);
|
|
374
|
+
if (glyphs.length > 0) {
|
|
375
|
+
const result = subset_font_full("stalux", "normal", 400, 0, glyphs);
|
|
376
|
+
writeFileSync(outPath, result.fontBytes);
|
|
377
|
+
subsetCount++;
|
|
378
|
+
logger.info(
|
|
379
|
+
` subset ${subsetCount}: ${(result.fontBytes.length / 1024).toFixed(1)} KB → ${filename}`,
|
|
380
|
+
);
|
|
381
|
+
}
|
|
367
382
|
}
|
|
368
383
|
}
|
|
369
|
-
}
|
|
370
384
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
385
|
+
// Generate per-route CSS (each route gets its own CSS file)
|
|
386
|
+
// If no unique chars, reference the common TTF as fallback
|
|
387
|
+
const refTtf = existsSync(outPath) ? filename : commonFilename;
|
|
374
388
|
for (const route of routes) {
|
|
375
389
|
const cssContent = `/* Auto-generated font subset for route: ${route} */
|
|
376
390
|
@font-face {
|
|
377
391
|
font-family: "LXGW WenKai Subset";
|
|
378
|
-
src: url("/fonts/${
|
|
392
|
+
src: url("/fonts/${refTtf}") format("truetype");
|
|
379
393
|
font-display: swap;
|
|
380
394
|
}
|
|
381
395
|
`;
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
postMap[abbrlink] = cssFilename;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
} else {
|
|
394
|
-
// CSS already generated, just map
|
|
395
|
-
for (const route of routes) {
|
|
396
|
-
const cssFilename =
|
|
397
|
-
routes.length === 1
|
|
398
|
-
? `subset-${route.replace("/", "-")}.css`
|
|
399
|
-
: `subset-group-${hash}.css`;
|
|
400
|
-
routeMap[route] = cssFilename;
|
|
401
|
-
if (route.startsWith("posts/")) {
|
|
402
|
-
postMap[route.replace("posts/", "")] = cssFilename;
|
|
403
|
-
}
|
|
396
|
+
const cssName = route.replace("/", "-");
|
|
397
|
+
const cssFilename = `subset-${cssName}.css`;
|
|
398
|
+
writeFileSync(join(outDir, cssFilename), cssContent);
|
|
399
|
+
routeMap[route] = cssFilename;
|
|
400
|
+
|
|
401
|
+
if (route.startsWith("posts/")) {
|
|
402
|
+
const abbrlink = route.replace("posts/", "");
|
|
403
|
+
postMap[abbrlink] = cssFilename;
|
|
404
404
|
}
|
|
405
405
|
}
|
|
406
406
|
}
|
|
407
|
-
}
|
|
408
407
|
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
408
|
+
// 6. Generate manifest
|
|
409
|
+
const manifest: FontManifest = {
|
|
410
|
+
common: commonFilename,
|
|
411
|
+
routes: routeMap,
|
|
412
|
+
posts: postMap,
|
|
413
|
+
};
|
|
414
|
+
writeFileSync(join(outDir, "manifest.json"), JSON.stringify(manifest, null, 2));
|
|
415
|
+
|
|
416
|
+
logger.info(
|
|
417
|
+
`Font subsetting done: ${subsetCount} route subsets + common (${(fontBuffer.length / 1024 / 1024).toFixed(1)} MB → variable)`,
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
420
|
}
|