3.3 KiB
3.3 KiB
Tasks: enterprise-react-font-decompress
Change ID: enterprise-react-font-decompress
Package: @suaveplan/react-font-decompress
Target path: react/media/react-font-decompress
Prerequisite packages on Verdaccio: @suaveplan/error, @suaveplan/font-decompress
0. Pre-flight (non-negotiable)
- 0.1 Confirm clean working tree (
git statusreports nothing) and no in-flight worktrees with uncommitted work (git worktree listthengit statusin each) - 0.2 If any worktrees exist under
.claude/worktrees/, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (git worktree remove) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - 0.3 Confirm the package set in
MANIFEST.mdmatchesfind packages -maxdepth 3 -name package.jsoncount. Drift here means a prior change archived without regenerating the manifest.
1. Scaffold
- Create directory tree. Write
package.jsonat0.1.0,tsconfig.json,vitest.config.ts, scripts. - Dependencies:
@suaveplan/error workspace:^,@suaveplan/font-decompress workspace:^,zod catalog:forms,tslib catalog:build.
2. Error codes
- Define
FontError; codes:FONT_LOAD_FAILED,FONT_DECODE_FAILED.
3. BinaryFontLoader
- Module-level cache:
Map<url, Promise<TypefaceFont>>. BinaryFontLoader.load(url: string, fetchFn?: typeof fetch): Promise<TypefaceFont>:- Returns cached promise if URL already in map.
- Fetches ArrayBuffer, delegates decode to
@suaveplan/font-decompress. - Throws
FontError(FONT_LOAD_FAILED)on fetch error;FontError(FONT_DECODE_FAILED)on decode error. - Removes from cache on rejection so retry is possible.
- Write
binary-font-loader.test.ts(≤500 lines): load, cache dedup (same URL returns same promise), fetch error, decode error, retry after error. DI injectedfetchFn.{ timeout: 10000 }. - Write
binary-font-loader.md.
4. createBrowserLoader
- Returns an inline-script string (self-contained, no imports) that can be injected as
<script>for zero-dep browser font loading. - Write
browser-loader.test.ts: returned string is valid JS (eval in sandbox), loads a font given an ArrayBuffer.{ timeout: 5000 }. - Write
browser-loader.md.
5. Hooks
useFont
useFont(url: string, fetchFn?): callsBinaryFontLoader.load; returns{ font, loading, error }.- Write
use-font.test.ts(≤500 lines): loading state, success state, error state, cache reuse on re-render.{ timeout: 10000 }. - Write
use-font.stories.tsx: playground (URL input → show font name). - Write
use-font.md.
useFonts
useFonts(urls: string[], fetchFn?): loads all in parallel; returns{ fonts, loading, error }.- Write
use-fonts.test.ts: all loaded, partial error, empty array.{ timeout: 10000 }. - Write
use-fonts.stories.tsx: playground (multiple URLs). - Write
use-fonts.md.
6. Verify and publish
bunx turbo lint typecheck test --filter=@suaveplan/react-font-decompress— green.bunx turbo test:coverage --filter=@suaveplan/react-font-decompress— 100%.bun scripts/publish.ts --package @suaveplan/react-font-decompress.- Archive change folder.