Add typecheck + CI checks, light theme with self-hosted Inter, fix real-model test
- Typecheck: typescript 7 devDependency, `bun run typecheck`; CI gains a `check` stage (install, typecheck, fast tests) gating image builds (D-038). - Light theme: every colour is a token; prefers-color-scheme: light overrides them. Inter Variable self-hosted from @fontsource-variable/inter, kept out of Bun's CSS inlining and precached (scripts/fonts.ts, D-037). Backend select no longer overflows on narrow phones. - tests/live-real-model.test.ts: time budget scales with clip length and en_alien gets a measured WER bar; it had failed since July (D-039). - Delete the temporary isolate_wer2.ts; fix icon "not checked in" comments and the README's model-weights location. - Agent docs: branch naming, typecheck, CI, Bun CSS gotcha, permissions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
0ece4b3a2a
commit
4942461f79
21 files changed
+477
-113
No files matched your search
+17
-4
@@ -15,6 +15,7 @@
|
||||
import { cp, readdir, rm } from "node:fs/promises";
|
||||
import { join, relative } from "node:path";
|
||||
import { injectPrecacheManifest, precachePathsFromOutputs } from "../src/pwa/precache.ts";
|
||||
import { ensureFonts, FONTS_DIR } from "./fonts.ts";
|
||||
import { ensureIcons, ICON_SIZES, ICONS_DIR } from "./generate-icons.ts";
|
||||
|
||||
const ROOT = join(import.meta.dir, "..");
|
||||
@@ -23,8 +24,11 @@ const DIST = join(ROOT, "dist");
|
||||
await rm(DIST, { recursive: true, force: true });
|
||||
|
||||
// Icons before the shell build — index.html references src/pwa/icons/ (the
|
||||
// HTML loader resolves the file at bundle time) and they aren't checked in.
|
||||
// HTML loader resolves the file at bundle time). They are checked in, but
|
||||
// regenerate any that are missing.
|
||||
await ensureIcons(ICONS_DIR);
|
||||
// Self-hosted Inter must exist for index.css to resolve (scripts/fonts.ts).
|
||||
const fontFiles = await ensureFonts();
|
||||
|
||||
// 1. App shell (hashed assets).
|
||||
const shellBuild = await Bun.build({
|
||||
@@ -35,6 +39,8 @@ const shellBuild = await Bun.build({
|
||||
sourcemap: "linked",
|
||||
define: { "process.env.NODE_ENV": '"production"' },
|
||||
env: "BUN_PUBLIC_*",
|
||||
// Self-hosted fonts stay as plain url(fonts/...) files — see scripts/fonts.ts.
|
||||
external: ["*.woff2"],
|
||||
});
|
||||
|
||||
// 2. Inference worker at its stable URL (Bun does not follow `new Worker`
|
||||
@@ -63,10 +69,13 @@ const ortFiles = (await readdir(ortDist)).filter((name) =>
|
||||
for (const name of ortFiles) {
|
||||
await cp(join(ortDist, name), join(DIST, "ort", name));
|
||||
}
|
||||
for (const name of fontFiles) {
|
||||
await cp(join(FONTS_DIR, name), join(DIST, "fonts", name));
|
||||
}
|
||||
|
||||
// 4. Service worker with the injected precache manifest (D-007). Icons,
|
||||
// manifest, and the worker are unhashed, so the cache version hashes their
|
||||
// contents (the hashed shell assets are covered by their names).
|
||||
// manifest, the worker, and fonts are unhashed, so the cache version hashes
|
||||
// their contents (the hashed shell assets are covered by their names).
|
||||
const swBuild = await Bun.build({
|
||||
entrypoints: [join(ROOT, "src/pwa/sw.ts")],
|
||||
target: "browser",
|
||||
@@ -82,10 +91,14 @@ const precachePaths = precachePathsFromOutputs(
|
||||
"inference.worker.js",
|
||||
"manifest.webmanifest",
|
||||
...ICON_SIZES.map((size) => `icons/icon-${size}.png`),
|
||||
...fontFiles.map((name) => `fonts/${name}`),
|
||||
],
|
||||
);
|
||||
const fontBytes = await Promise.all(
|
||||
fontFiles.map((name) => Bun.file(join(FONTS_DIR, name)).bytes()),
|
||||
);
|
||||
const version = Bun.hash(
|
||||
JSON.stringify(precachePaths) + swSource + workerScript,
|
||||
JSON.stringify(precachePaths) + swSource + workerScript + fontBytes.map((b) => Bun.hash(b)).join(),
|
||||
).toString(36);
|
||||
await Bun.write(join(DIST, "sw.js"), injectPrecacheManifest(swSource, precachePaths, version));
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* Self-hosted Inter (variable, upright) from @fontsource-variable/inter.
|
||||
*
|
||||
* src/index.css declares one @font-face per unicode-range subset with a
|
||||
* relative `url(fonts/<file>)`, which resolves to src/fonts/ — a generated,
|
||||
* gitignored copy of the package's files (`ensureFonts()`; Bun's CSS bundler
|
||||
* must be able to resolve every url()).
|
||||
*
|
||||
* - Dev (`bun dev`): the HTML-import bundler inlines them as base64. Fine
|
||||
* locally.
|
||||
* - Production (scripts/build.ts): `external: ["*.woff2"]` keeps them out of
|
||||
* the bundle — Bun inlines every resolvable CSS url() asset, which would put
|
||||
* ~220 KB into the render-blocking stylesheet and defeat unicode-range lazy
|
||||
* loading. The build copies them to dist/fonts/ and precaches them instead.
|
||||
*
|
||||
* Same-origin either way, so COEP `require-corp` (D-023) allows them.
|
||||
*/
|
||||
|
||||
import { copyFile, mkdir } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
|
||||
const PACKAGE_FILES = join(import.meta.dir, "../node_modules/@fontsource-variable/inter/files");
|
||||
const CSS_PATH = join(import.meta.dir, "../src/index.css");
|
||||
export const FONTS_DIR = join(import.meta.dir, "../src/fonts");
|
||||
|
||||
/** The font files a stylesheet references via `url(fonts/<file>)`. */
|
||||
export function fontFilesInCss(css: string): string[] {
|
||||
const files = [...css.matchAll(/url\(["']?fonts\/([^"')]+)["']?\)/g)].map((match) => match[1]!);
|
||||
return [...new Set(files)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy every font src/index.css references into src/fonts/ (idempotent).
|
||||
* Always overwrites (~220 KB), so a package upgrade can't leave stale copies.
|
||||
*/
|
||||
export async function ensureFonts(): Promise<string[]> {
|
||||
const files = fontFilesInCss(await Bun.file(CSS_PATH).text());
|
||||
await mkdir(FONTS_DIR, { recursive: true });
|
||||
for (const name of files) {
|
||||
await copyFile(join(PACKAGE_FILES, name), join(FONTS_DIR, name));
|
||||
}
|
||||
return files;
|
||||
}
|
||||
Reference in new issue
Block a user