64 lines
2.1 KiB
JavaScript
64 lines
2.1 KiB
JavaScript
import { execFileSync } from "node:child_process";
|
|
import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const fontsDir = join(__dirname, "..", "public", "fonts");
|
|
const outputWoff2 = join(fontsDir, "lxgwwenkaimono-medium.woff2");
|
|
|
|
const sourceCandidates = [
|
|
join(fontsDir, "LXGWWenKaiMono-Medium.ttf"),
|
|
join(__dirname, "..", "assets", "fonts", "LXGWWenKaiMono-Medium.ttf"),
|
|
];
|
|
|
|
const sourceTtf = sourceCandidates.find((path) => existsSync(path));
|
|
const MIN_WOFF2_BYTES = 5_000_000;
|
|
|
|
if (!sourceTtf) {
|
|
console.warn("[prepare-font] LXGWWenKaiMono-Medium.ttf not found, skipping");
|
|
process.exit(0);
|
|
}
|
|
|
|
mkdirSync(fontsDir, { recursive: true });
|
|
|
|
function woff2LooksValid() {
|
|
if (!existsSync(outputWoff2)) return false;
|
|
return readFileSync(outputWoff2).length >= MIN_WOFF2_BYTES;
|
|
}
|
|
|
|
if (woff2LooksValid()) {
|
|
const sourceMtime = statSync(sourceTtf).mtimeMs;
|
|
const outputMtime = statSync(outputWoff2).mtimeMs;
|
|
if (outputMtime >= sourceMtime) {
|
|
const sizeMb = (readFileSync(outputWoff2).length / (1024 * 1024)).toFixed(2);
|
|
console.log(`[prepare-font] up to date ${outputWoff2} (${sizeMb} MB)`);
|
|
process.exit(0);
|
|
}
|
|
}
|
|
|
|
if (existsSync(outputWoff2) && !woff2LooksValid()) {
|
|
console.warn("[prepare-font] removing invalid woff2 (< 5 MB, likely subset or corrupt)");
|
|
unlinkSync(outputWoff2);
|
|
}
|
|
|
|
console.log("[prepare-font] converting full font to woff2 (no glyph subsetting, may take a few minutes)...");
|
|
|
|
const py = [
|
|
"from fontTools.ttLib.woff2 import compress",
|
|
"import sys",
|
|
"compress(sys.argv[1], sys.argv[2])",
|
|
].join("\n");
|
|
|
|
execFileSync("python", ["-c", py, sourceTtf, outputWoff2], { stdio: "inherit" });
|
|
|
|
const sizeBytes = readFileSync(outputWoff2).length;
|
|
if (sizeBytes < MIN_WOFF2_BYTES) {
|
|
throw new Error(
|
|
`[prepare-font] woff2 output too small (${sizeBytes} bytes); conversion likely failed`,
|
|
);
|
|
}
|
|
|
|
const sizeMb = (sizeBytes / (1024 * 1024)).toFixed(2);
|
|
console.log(`[prepare-font] wrote ${outputWoff2} (${sizeMb} MB, full glyph set)`);
|