Add HyperFrames skills
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011h6NB8JQtfPc6eRCefEzBB
This commit is contained in:
964 files changed
+142321
No files matched your search
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
* build-fonts-css.cjs — bundle the template fonts into ONE self-contained
|
||||
* fonts.css with base64 data-URI @font-face (no sub-resources, no CDN, no
|
||||
* system-font dependency). This is what makes Standard/Cinematic renders
|
||||
* deterministic on ANY machine: hyperframes' renderer only auto-supplies its
|
||||
* ~18 CANONICAL_FONTS; every other family falls back to a generic font unless
|
||||
* the HTML ships a local @font-face. (hyperframes' own font linter says exactly
|
||||
* this: "Use local @font-face declarations with captured .woff2 files.")
|
||||
*
|
||||
* Source woff2 live in ./files/<slug>-latin-<weight>-normal.woff2 (latin subset
|
||||
* from @fontsource via jsdelivr). Re-run after adding/removing a font:
|
||||
* node build-fonts-css.cjs
|
||||
*/
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const FILES = path.join(__dirname, "files");
|
||||
const OUT = path.join(__dirname, "fonts.css");
|
||||
|
||||
// slug → exact CSS family name (must match what templates declare in font-family).
|
||||
const FAMILY = {
|
||||
anton: "Anton",
|
||||
audiowide: "Audiowide",
|
||||
inter: "Inter",
|
||||
"baloo-2": "Baloo 2",
|
||||
bangers: "Bangers",
|
||||
"bodoni-moda": "Bodoni Moda",
|
||||
caveat: "Caveat",
|
||||
cinzel: "Cinzel",
|
||||
"cormorant-garamond": "Cormorant Garamond",
|
||||
creepster: "Creepster",
|
||||
fredoka: "Fredoka",
|
||||
monoton: "Monoton",
|
||||
orbitron: "Orbitron",
|
||||
"permanent-marker": "Permanent Marker",
|
||||
"press-start-2p": "Press Start 2P",
|
||||
"saira-stencil-one": "Saira Stencil One",
|
||||
"shippori-mincho": "Shippori Mincho",
|
||||
rajdhani: "Rajdhani",
|
||||
"chakra-petch": "Chakra Petch",
|
||||
sora: "Sora",
|
||||
"space-grotesk": "Space Grotesk",
|
||||
"special-elite": "Special Elite",
|
||||
teko: "Teko",
|
||||
vt323: "VT323",
|
||||
};
|
||||
|
||||
const files = fs
|
||||
.readdirSync(FILES)
|
||||
.filter((f) => f.endsWith(".woff2"))
|
||||
.sort();
|
||||
const faces = [];
|
||||
let raw = 0;
|
||||
const seenFamilies = new Set();
|
||||
for (const f of files) {
|
||||
const m = f.match(/^(.*)-latin-(\d+)-(normal|italic)\.woff2$/);
|
||||
if (!m) {
|
||||
console.error(`[fonts] skip unrecognized filename: ${f}`);
|
||||
continue;
|
||||
}
|
||||
const slug = m[1],
|
||||
weight = m[2],
|
||||
style = m[3];
|
||||
const family = FAMILY[slug];
|
||||
if (!family) {
|
||||
console.error(`[fonts] no family mapping for slug "${slug}" (${f}) — add it to FAMILY`);
|
||||
process.exit(1);
|
||||
}
|
||||
const buf = fs.readFileSync(path.join(FILES, f));
|
||||
raw += buf.length;
|
||||
seenFamilies.add(family);
|
||||
faces.push(
|
||||
`@font-face {\n` +
|
||||
` font-family: '${family}';\n` +
|
||||
` font-style: ${style};\n` +
|
||||
` font-weight: ${weight};\n` +
|
||||
` font-display: block;\n` + // block (not swap): render text only once the real face is ready — measure-layout + capture see the true glyphs, never a fallback flash
|
||||
` src: url(data:font/woff2;base64,${buf.toString("base64")}) format('woff2');\n` +
|
||||
`}`,
|
||||
);
|
||||
}
|
||||
|
||||
const header =
|
||||
`/* AUTO-GENERATED by build-fonts-css.cjs — do not edit by hand.\n` +
|
||||
` ${faces.length} faces / ${seenFamilies.size} families, ${Math.round(raw / 1024)}KB raw woff2 (latin subset, base64-inlined).\n` +
|
||||
` Families: ${[...seenFamilies].sort().join(", ")}.\n` +
|
||||
` These are the template fonts NOT in hyperframes' auto-resolved set; inlining\n` +
|
||||
` them makes every render deterministic regardless of installed system fonts. */\n`;
|
||||
|
||||
fs.writeFileSync(OUT, header + "\n" + faces.join("\n\n") + "\n");
|
||||
const outKb = Math.round(fs.statSync(OUT).size / 1024);
|
||||
console.log(`[fonts] wrote ${OUT}`);
|
||||
console.log(
|
||||
`[fonts] ${faces.length} faces, ${seenFamilies.size} families, ${outKb}KB css (${Math.round(raw / 1024)}KB raw)`,
|
||||
);
|
||||
console.log(`[fonts] families: ${[...seenFamilies].sort().join(", ")}`);
|
||||
Reference in new issue
Block a user