Skip to content

Commit db94b50

Browse files
committed
feat(capture): identify hashed fonts via OpenType name table
Modern frameworks (Next.js, Webpack) hash font filenames like `f9b8e1e8d4c3f0a7-s.woff2`, so the capture pipeline can't tell which file belongs to which family by reading the filename. Sub-agents authoring DESIGN.md were guessing or falling back to system fonts. This adds `fontMetadataExtractor.ts`: reads the binary OpenType `name` table via `fontkit`, identifies each downloaded font by its real family name, and writes `capture/extracted/fonts-manifest.json` with per-file metadata + per-family aggregates (weights, variable-font axes, file counts). - Canonicalizes static-weight family-name packaging: "Inter Medium" resolves to family "Inter" with weight 500, "Semi Bold" normalizes to "SemiBold", etc. Width modifiers ("Tight", "Condensed") are NOT stripped — they denote separate typographic families. - Reads variable-font axes from `fvar` so a single .woff2 carrying a full weight range is identified as variable (e.g. "Inter (100-900 variable)"). - Uses `@types/fontkit` properly (no `unknown` cast), with a Font/FontCollection type guard. fontkit API drift surfaces as a compile error rather than silent undefined. - Wired into `capture/index.ts` after `downloadAndRewriteFonts` so it runs after fonts are already on disk. Non-fatal try/catch — capture succeeds even if extraction fails. Tested against 9 captures: 132/132 fonts identified by real family name, including hashed Next.js builds.
1 parent da38de1 commit db94b50

4 files changed

Lines changed: 372 additions & 10 deletions

File tree

bun.lock

Lines changed: 33 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@
3030
"citty": "^0.2.1",
3131
"compare-versions": "^6.1.1",
3232
"esbuild": "^0.25.12",
33+
"fontkit": "^2.0.4",
3334
"giget": "^3.2.0",
3435
"hono": "^4.0.0",
3536
"onnxruntime-node": "^1.20.0",
3637
"open": "^10.0.0",
3738
"postcss": "^8.5.8",
3839
"prettier": "^3.8.1",
3940
"puppeteer-core": "^24.39.1",
40-
"sharp": "^0.34.0"
41+
"sharp": "^0.34.5"
4142
},
4243
"devDependencies": {
4344
"@clack/prompts": "^1.1.0",
@@ -47,6 +48,7 @@
4748
"@hyperframes/producer": "workspace:*",
4849
"@hyperframes/studio": "workspace:*",
4950
"@types/adm-zip": "^0.5.7",
51+
"@types/fontkit": "^2.0.9",
5052
"@types/mime-types": "^3.0.1",
5153
"@types/node": "^25.0.10",
5254
"linkedom": "^0.18.12",

0 commit comments

Comments
 (0)