From faec0641a7063f2e41a5bb5474388ffa41e34e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henrique=20Ara=C3=BAjo?= Date: Thu, 15 Oct 2026 00:14:48 -0300 Subject: [PATCH 1/3] chore: start #120 From e5fa380f5fb19b81c4e5eea789c9df390ae172c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henrique=20Ara=C3=BAjo?= Date: Thu, 15 Oct 2026 00:19:02 -0300 Subject: [PATCH 2/3] fix: generateBrand: load system fonts only for marks with text (#120) resvg loads every system font on each construction by default: ~450 ms per render on Windows, ~2.7 s per icon set at every build, and the generateBrand unit test timed out (13 s against 5 s), failing validate and the pre-push gate there. The render options now come from resvgOptions(), which turns system fonts off unless the SVG has . Closes #120 --- .changeset/brand-render-no-system-fonts.md | 5 +++++ packages/ui/src/lib/brand.ts | 14 +++++++++++++- packages/ui/tests/brand.test.ts | 13 ++++++++++++- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 .changeset/brand-render-no-system-fonts.md diff --git a/.changeset/brand-render-no-system-fonts.md b/.changeset/brand-render-no-system-fonts.md new file mode 100644 index 00000000..97490350 --- /dev/null +++ b/.changeset/brand-render-no-system-fonts.md @@ -0,0 +1,5 @@ +--- +"@codeatlasdev/ui": patch +--- + +`generateBrand` and the brand Vite plugin no longer load every system font for each PNG they render. resvg did that by default on every construction (~450 ms per render on Windows, ~2.7 s per icon set, at every build and dev start); fonts now load only when the mark has `` (#120). diff --git a/packages/ui/src/lib/brand.ts b/packages/ui/src/lib/brand.ts index 326d16f0..095a9f82 100644 --- a/packages/ui/src/lib/brand.ts +++ b/packages/ui/src/lib/brand.ts @@ -109,6 +109,18 @@ export interface GenerateBrandOptions { const SIZES = [16, 32, 48] as const; +/** + * Render options for one PNG. resvg loads every system font on each construction by default + * (~450 ms per render on Windows); a mark drawn with paths needs none, so fonts load only when the + * SVG has text (#120). + */ +export function resvgOptions(svg: string, size: number) { + return { + fitTo: { mode: "width" as const, value: size }, + font: { loadSystemFonts: /.svg`, `favicon..ico` (16/32/48), `favicon-32..png`, `apple-touch-icon..png` * (180, opaque), `icon-192/512..png`, `maskable-512..png` and `manifest..webmanifest`. @@ -146,7 +158,7 @@ export async function generateBrand(o: GenerateBrandOptions): Promise - new Resvg(svg, { fitTo: { mode: "width", value: size } }).render().asPng(); + new Resvg(svg, resvgOptions(svg, size)).render().asPng(); /** Transparent PNG of the mark alone (favicon sizes). */ const bare = (size: number) => png(light.replace(/ { expect(html).toContain("1200px"); }); }); + +describe("resvgOptions", () => { + // resvg loads every system font per render by default: ~450 ms each on Windows, so one icon set + // took ~2.7 s and the generateBrand test timed out there (#120). A mark without text needs none. + it("loads system fonts only for an SVG with text (#120)", () => { + expect(resvgOptions(MARK, 32).font?.loadSystemFonts).toBe(false); + const withText = MARK.replace("", 'A'); + expect(resvgOptions(withText, 32).font?.loadSystemFonts).toBe(true); + expect(resvgOptions(MARK, 180).fitTo).toEqual({ mode: "width", value: 180 }); + }); +}); From 74fdfa8b264ef9a6445f4e7487480c8e582069be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A1bio=20Henrique=20Ara=C3=BAjo?= Date: Thu, 15 Oct 2026 00:55:52 -0300 Subject: [PATCH 3/3] ci: run checks on final head