Repository navigation
feat(core): the renderer's font pipeline is importable from @hyperframes/core/fonts/embed - #5041
Conversation
…mes/core/fonts/embed
…sts pass on Windows
Edit accuracy: accurate 2040 (base branch 2040), smooth 1542 of thoseThe gate passes. Quarantined, measured but not gated (0) |
jrusso1020
left a comment
There was a problem hiding this comment.
Approving at aa731214.
The move keeps behavior the same
fontData.generated.tsis the same blob as before the move (d9a3789).authoredGoogleFonts.tsis unchanged, andfontCompression.tschanges only a comment.deterministicFonts.tschanges four things:- relative imports in place of the two
@hyperframes/core/...ones; - a
fontToDataUrire-export forhtmlCompiler; - a
fallow-ignorecomment; defaultLoggerreplaced byoptions.log. That is the caller'slogger, or a stderr default with the same[WARN]/[INFO]format. The producer passes its owndefaultLogger, so its output is unchanged.
- relative imports in place of the two
- The export set only grows (
FontLogger,fontToDataUri).producer/src/index.tskeeps its export list identical, and producer'sexportsfield is unchanged. The@fontsource/*dependencies it drops were never imported at runtime.
Packed core: I packed core and its workspace deps and installed them clean in a temp dir: 76 MB, matching the body. Both @hyperframes/core/fonts/embed functions import and run on an Inter page, and the output carries the marker, an Inter @font-face, and the "Injected…" message routed to logger. fonts/embedded-data loads 42 entries. Core's root entry doesn't expose the pipeline, and nothing in core's browser entry, studio/src, player or sdk imports the new subpaths. check:package-subpaths passes.
Images and stale paths: Dockerfile.test and the Cloud Run Dockerfile build core, which runs build:fonts (a skip, since the generated file is committed), before producer. So dropping producer's generator step is safe. No code still points at the old producer font paths.
Tests:
- Core
src/fonts: 217 pass (16 files). - Producer bun unit lane: 644/644.
- Producer vitest: 861/862. The one failure is the
audioPadTrimloudness integration test locally, unrelated to fonts and green in CI. - Typechecks are clean in core, producer, cli and studio.
- It merges into current main with no conflicts. CI: 89 pass, 5 skipped.
Reuse / simplicity: these are pure renames with no copy left behind in producer, and core had no logger type to reuse. One option: fonts/embedded-data exists so the planner can hash the font map, and exporting a fingerprint from fonts/embed would avoid a second public subpath. Not blocking.
Nits (non-blocking)
deterministicFonts.ts:1649-1651: theOptions for {@link injectDeterministicFontFaces}doc comment now sits aboveFontLogger, and the newlogger?field has no doc.deterministicFonts.ts:1110: the unwritable-cache-dir warning still goes straight to stderr rather than the caller'slogger.fontCompression.test.tsreads its TTF from a docs catalog item, so renaming that item would break core's tests. A copy under core's own fixtures would decouple them..github/workflows/windows-render.yml:195,466comments still namepackages/producer/node_modules/@fontsource/*.
— Rames
What changes for a person
A preview that wants to show exactly the fonts a render will use can now call the renderer's own font pipeline, from
@hyperframes/core, without installing the producer:That is the same pair, in the same order, the producer runs when it compiles a render (
htmlCompiler.ts,compileForRender). Until now it lived only in@hyperframes/producer, so the HyperFrames desktop app's preview had to install the whole renderer to match it.Install footprint
Clean installs on Linux from the release tarball (
pnpm pack),du -sm node_modules:@hyperframes/[email protected](today's only home of the pipeline)@hyperframes/[email protected](published)@hyperframes/corewith this PRThe desktop app already depends on
@hyperframes/core, so the pipeline costs it about 2 MB (wawoff2and its one dependency, plus the embedded font data) instead of 203 MB.The move
One owner, no copy left behind:
packages/producer/src/services/{deterministicFonts,fontCompression,authoredGoogleFonts,fontData.generated}.tsand their 15 test files move topackages/core/src/fonts/(git renames).packages/core/scripts/; core'sbuildrunsbuild:fontsthe way the producer's did.wawoff2and the@fontsource/*packages move with them. The@fontsource/*packages are only read by the generator, so they become core devDependencies; 11 of them were runtime dependencies of the producer.package-subpaths.jsonwithenvironments: ["bun", "node"]:@hyperframes/core/fonts/embed(the pipeline) and@hyperframes/core/fonts/embedded-data(the font data the distributed planner hashes). Core's root entry does not pull in either; the pipeline reads the disk cache and usesnode:fs,node:osandnode:crypto.@hyperframes/producer, so its public API is unchanged. Its own bundle still contains the pipeline.Behaviour
Unchanged. The one new option is
loggeroninjectDeterministicFontFaces: core has no logger of its own, so the messages the pipeline used to send to the producer's logger go to the caller'sloggerwhen given, and otherwise to stderr in the same[WARN]/[INFO]format the producer's console logger writes (never stdout). The producer passes its own logger, so its output is the same as before.Tests
bun testin the producer; core runs vitest. They now import fromvitestand run in a Node environment (@vitest-environment node; core's default is jsdom). Two bun-only matchers became vitest ones (toBeString,toStartWith). The fail-closed test now captures the default logger'sconsole.warn.Date.now()let a second attempt start. It now runs withDateandsetTimeoutfaked, so the budget is read from the test's clock. 16 files, 216 tests pass in 5 of 5 full runs on this code.verify:packed-manifestsafter a full workspace build: 157 packed exports resolved, clean consumer install and Node execution pass.@hyperframes/core/fonts/embed, runs both functions on a page that asks for Inter, and embeds Inter's face; theloggeroption receives the pipeline's message..fallowrc.jsonc: the moved files bring their existing duplication and one inherited complexity finding with them, which fallow reads as new because the paths changed. They are listed underduplicates.ignoreandhealth.ignorewith a "moved from" note, as the earlier parsers move did;parseFontFamilyValuekeeps its complexity with an inline ignore.No visible change
The only Studio change is two lines in
packages/studio/vite.adapter.ts: the dev server loads the same font function from its new home in core. Preview and render output are unchanged.