feat(engine): resolve any google fonts family by name - #40
Open
heristop wants to merge 1 commit into
Open
Conversation
Deploying leclap with
|
| Latest commit: |
be83ebe
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://4819af27.leclap.pages.dev |
| Branch Preview URL: | https://worktree-google-fonts-resolv.leclap.pages.dev |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A font that could not be staged was logged and skipped. A missing font does not stop
drawtext— itdraws with a fallback face — so the only symptom was a finished video in the wrong typeface, with a
successful exit code. That silent path is now a hard failure.
Fixing it exposed why fonts kept failing to resolve in the first place: the Google Fonts lookup
rebuilt the family name from the filename, splitting on
-and..BebasNeue.ttfbecamefamily=BebasNeue, which the API rejects with a 400. Multi-word families were unreachable, and theweight in a name like
Roboto-Bold.ttfwas silently discarded.Naming a font by family
fonttakes a third form anywhere a text sugar accepts one (caption,titleCardline styles,global.overlays):It is an object rather than another string on purpose: a typo in a registry id (
"bebbas") stays alocal
unknown_fontvalidation error instead of becoming a network lookup that fails mid-render.The trade-off is that family names are not checked at validation time — there is no offline copy of
the catalogue — so a bad family surfaces during the render, naming the family.
How it resolves
Requests go to the css2 endpoint with a legacy
User-Agent, because Google keys the response formatoff it and a modern UA yields woff2, which
drawtextcannot read.css2 also matters for a subtler reason: for a variable family it returns a static instance cut at
the requested weight. Fetching the variable
.ttfdirectly — for example from thegoogle/fontsrepo — hands freetype a font it renders at its default instance, so a request for weight 700 would
quietly draw Regular. Verified against the real API:
Robotoat 900 comes back as a 124KB staticcut, not the 876KB variable file.
The ref travels beside the staged filename rather than being encoded into it. The slug
(
google-playfair-display-700-italic.ttf) is a cache key that is written and never parsed back —decoding a slug into a family name is lossy for names like
Press Start 2P, which is the same classof guess that caused the original bug.
Staging order, cheapest first: already staged → bundled → persistent cache → catalog → download →
throw.
Caching and platform support
Downloads are copied to
~/.cache/leclap/fonts(override withFVC_FONT_CACHE_DIR), which outlivesthe build directory, so a repeat render needs no network and does not re-hit the rate limit.
The browser backend declares no support and rejects the object form up front with an explanation —
it cannot override
User-Agent, so it would only ever receive woff2. Web apps ship the fonts theyneed instead. The curated 12 stay bundled and pinned everywhere.
Verification
1463/1463 engine tests pass. 31 of them are new, each written before the code and watched fail.
Engine,
@leclap/weband@leclap/creative-kittypecheck clean; lint clean.Resolution was also checked end to end against the live API: multi-word (
Playfair Display),digit-bearing (
Press Start 2P), italic, and variable-at-weight-900 all return genuine TrueType(magic
00010000); a nonexistent family 400s and raises an error naming it.Known limitations
opened and re-saved in the admin editor has its font replaced by the default. Documented at
fontIdFromFile; templates using a named family should not be round-tripped through the editoruntil the picker can carry one.
Roboto-Bold.ttfstill resolvesto Roboto at weight 400 and ignores
Bold. The object form is the replacement for it.