From f2282a81fb81281f22e74d6986e08b69ee957d83 Mon Sep 17 00:00:00 2001 From: MelekTaus Date: Wed, 30 Sep 2026 21:27:46 +0200 Subject: [PATCH] Stop loading the bold face the editor never draws in (#273) The editor waits for every face in FACES before it starts. Source Sans 3 in 700 was one of them, but nothing in src/ sets a weight above 600, so it cost a download and a wait for nothing. - fonts.ts loads Source Sans 3 in 400, 500 and 600 plus Source Code Pro 400. The 700 file (15 596 bytes) is gone from src/ui/fonts. - A search for bold, font-weight and HTML headings in src/, web/*.html and the player found nothing that would fall back to 700. - fonts.test.ts now checks both ways. A loaded Sans face must be set somewhere in src/, and every .woff2 in the font folder must be in FACES, so a stray file the glyph test would still read shows up too. - The weight scan moved into usedWeights(), since two tests need it. Tests: - Gate on melektaus-atx: 197 files, 2856 tests (2855 + 1), exit 0. - e2e 1-14: all passed, 492 checks, loaded faces ["400","500","600"]. - e2e 14 alone fails its two tab width checks, as known: it needs the documents 7-13 open. The font check was green there as well. - dist/assets holds no 700 file after the build. - Counter check: loading 700 again with its file fails the new "loads no face the editor never sets". - Counter check: the file back without a FACES entry fails "... and no other" and names the file. Co-Authored-By: Claude Opus 5.5 --- src/ui/fonts.ts | 2 - .../source-sans-3-latin-700-normal.woff2 | Bin 15596 -> 0 bytes tests/ui/fonts.test.ts | 38 +++++++++++++----- 3 files changed, 28 insertions(+), 12 deletions(-) delete mode 100644 src/ui/fonts/source-sans-3-latin-700-normal.woff2 diff --git a/src/ui/fonts.ts b/src/ui/fonts.ts index c8bb7463..520c6ff2 100644 --- a/src/ui/fonts.ts +++ b/src/ui/fonts.ts @@ -2,13 +2,11 @@ import codePro400 from './fonts/source-code-pro-latin-400-normal.woff2?url'; import sans400 from './fonts/source-sans-3-latin-400-normal.woff2?url'; import sans500 from './fonts/source-sans-3-latin-500-normal.woff2?url'; import sans600 from './fonts/source-sans-3-latin-600-normal.woff2?url'; -import sans700 from './fonts/source-sans-3-latin-700-normal.woff2?url'; export const FACES: readonly [family: string, url: string, weight: string][] = [ ['Source Sans 3', sans400, '400'], ['Source Sans 3', sans500, '500'], ['Source Sans 3', sans600, '600'], - ['Source Sans 3', sans700, '700'], ['Source Code Pro', codePro400, '400'], ]; diff --git a/src/ui/fonts/source-sans-3-latin-700-normal.woff2 b/src/ui/fonts/source-sans-3-latin-700-normal.woff2 deleted file mode 100644 index 3cb944ca31199f76bc2684bcd50a0ef935b2b8f0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15596 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 G0RR9FN-o#{ diff --git a/tests/ui/fonts.test.ts b/tests/ui/fonts.test.ts index d05eede3..f863afb7 100644 --- a/tests/ui/fonts.test.ts +++ b/tests/ui/fonts.test.ts @@ -97,27 +97,45 @@ function codePoints(file: string): Set { return found; } +/** The weights `src/` sets as `fontWeight`, plus the 400 a style without one draws in. */ +function usedWeights(): Set { + const used = new Set(['400']); + for (const file of sources('src')) + for (const [, setting] of readFileSync(file, 'utf8').matchAll(/fontWeight:([^,\n}]*)/g)) + for (const [, weight] of setting!.matchAll(/'(\d{3}|bold|normal)'/g)) + used.add(weight === 'bold' ? '700' : weight === 'normal' ? '400' : weight!); + return used; +} + describe('editor fonts', () => { + const loaded = new Set( + FACES.filter(([family]) => family === 'Source Sans 3').map(([, , weight]) => weight), + ); + it('loads a face for every weight the editor sets (#214)', () => { - const loaded = new Set( - FACES.filter(([family]) => family === 'Source Sans 3').map(([, , weight]) => weight), - ); - const used = new Set(['400']); - for (const file of sources('src')) - for (const [, setting] of readFileSync(file, 'utf8').matchAll(/fontWeight:([^,\n}]*)/g)) - for (const [, weight] of setting!.matchAll(/'(\d{3}|bold|normal)'/g)) - used.add(weight === 'bold' ? '700' : weight === 'normal' ? '400' : weight!); + const used = usedWeights(); expect(used.has('500')).toBe(true); for (const weight of used) expect(loaded, `weight ${weight}`).toContain(weight); }); - it('ships a file for every face it loads', () => { - const files = readdirSync(FONT_DIR); + // Every face is waited for before the editor starts (#273). + it('loads no face the editor never sets', () => { + const used = usedWeights(); + for (const weight of loaded) expect(used, `weight ${weight}`).toContain(weight); + }); + + it('ships a file for every face it loads, and no other', () => { + const files = readdirSync(FONT_DIR).filter((f) => f.endsWith('.woff2')); for (const [, url, weight] of FACES) expect( files.some((f) => url.endsWith(f)), `${url} (${weight})`, ).toBe(true); + for (const file of files) + expect( + FACES.some(([, url]) => url.endsWith(file)), + file, + ).toBe(true); }); it('reads the Latin subset from the files themselves', () => {