Files
sproutclaw-web/frontend/scripts/prepare-font.mjs
shumengya 767a776a3e feat: align chat rendering with CLI and trim frontend load weight
- Merge thinking and assistant text into one assistant bubble with ordered blocks

- Restyle tool execution blocks to match CLI layout and status

- Remove startup splash screen and ship woff2-only fonts in public

- Add default avatars when agent or user image is unset

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-21 20:42:48 +08:00

94 lines
3.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { execFileSync } from "node:child_process";
import { existsSync, mkdirSync, readFileSync, readdirSync, 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 sourceTtf = join(__dirname, "..", "assets", "fonts", "LXGWWenKaiMono-Medium.ttf");
/** Full CJK font woff2 is typically 710 MB; reject obvious subset/corrupt output. */
const MIN_WOFF2_BYTES = 5_000_000;
if (!existsSync(sourceTtf)) {
console.warn(`[prepare-font] source not found: ${sourceTtf}`);
process.exit(0);
}
mkdirSync(fontsDir, { recursive: true });
function removePublicTtfCopies() {
for (const name of readdirSync(fontsDir)) {
if (name.toLowerCase().endsWith(".ttf")) {
const path = join(fontsDir, name);
unlinkSync(path);
console.log(`[prepare-font] removed public TTF copy (woff2 only): ${path}`);
}
}
}
function woff2LooksValid() {
if (!existsSync(outputWoff2)) return false;
return readFileSync(outputWoff2).length >= MIN_WOFF2_BYTES;
}
function verifyGlyphCount() {
const py = [
"from fontTools.ttLib import TTFont",
"import sys",
"src, out = sys.argv[1], sys.argv[2]",
"source_glyphs = len(TTFont(src).getGlyphOrder())",
"output_glyphs = len(TTFont(out).getGlyphOrder())",
"if source_glyphs != output_glyphs:",
"\traise SystemExit(f'glyph count mismatch: source={source_glyphs}, output={output_glyphs}')",
"print(output_glyphs)",
].join("\n");
const count = execFileSync("python", ["-c", py, sourceTtf, outputWoff2], {
encoding: "utf8",
}).trim();
console.log(`[prepare-font] verified full glyph set (${count} glyphs)`);
}
removePublicTtfCopies();
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, woff2 only)`);
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, glyf/loca/hmtx transforms)...",
);
const py = [
"from fontTools.ttLib.woff2 import compress",
"import sys",
"compress(sys.argv[1], sys.argv[2], transform_tables={'glyf', 'loca', 'hmtx'})",
].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`,
);
}
verifyGlyphCount();
removePublicTtfCopies();
const sizeMb = (sizeBytes / (1024 * 1024)).toFixed(2);
console.log(`[prepare-font] wrote ${outputWoff2} (${sizeMb} MB, full glyph set, woff2 only)`);