From ad0cc92e16aa98ee10bead846c0ff4c74c5244d6 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Mon, 27 Apr 2026 08:40:32 +0300 Subject: generator: lazy-init themeSet and navDefs with sync.Once --- internal/generator/doc.go | 2 +- internal/generator/generator.go | 2 +- internal/generator/generator_test.go | 12 +++++------ internal/generator/shared.go | 23 +++++++++++++------- internal/generator/templates.go | 2 +- internal/generator/themes.go | 42 +++++++++++++++++++++--------------- 6 files changed, 49 insertions(+), 34 deletions(-) diff --git a/internal/generator/doc.go b/internal/generator/doc.go index be82bdc..8eaf4db 100644 --- a/internal/generator/doc.go +++ b/internal/generator/doc.go @@ -8,7 +8,7 @@ // shared.css/shared.js and per-theme assets, then call atom.Generate. // - themes.go — ListThemes / validThemeName helpers backed by the embedded FS. // - shared.go — navDefs: shared {{define}} blocks (splashGate, navhints, -// navmodal) merged at parse time with shell.tmpl so a single html/template +// navSharedCSS) merged at parse time with shell.tmpl so a single html/template // parse sees every name. // - theme_sounds.go — Per-theme Web Audio parameters; one file is written per // theme to dist/themes//sounds.json and the default theme's preset is diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 0b51edd..db9531b 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -99,7 +99,7 @@ func Run(cfg *config.Config) error { if err != nil { return fmt.Errorf("load shell template: %w", err) } - combined := shellSrc + "\n" + navDefs + combined := shellSrc + "\n" + getNavDefs() tmpl, err := template.New("page").Parse(combined) if err != nil { return fmt.Errorf("parse page template: %w", err) diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go index 0e3708b..56542a3 100644 --- a/internal/generator/generator_test.go +++ b/internal/generator/generator_test.go @@ -93,7 +93,7 @@ func TestJSONStringOrNull(t *testing.T) { func TestThemeSoundPresetsMatchRegistry(t *testing.T) { t.Parallel() - for name := range themeSet { + for name := range getThemeSet() { if _, ok := themeSoundPresets[name]; !ok { t.Errorf("theme %q has no sound preset in themeSoundPresets", name) } @@ -112,7 +112,7 @@ func TestThemeSoundsJSON_ambientSchema(t *testing.T) { t.Parallel() // Verify the ambient schema is present and valid for every registered theme. - for name := range themeSet { + for name := range getThemeSet() { j := themeSoundsJSON(name) if len(j) < 50 { t.Fatalf("themeSoundsJSON(%q) too short: %q", name, j) @@ -148,7 +148,7 @@ func TestThemeSoundsJSON_ambientSchema(t *testing.T) { func TestThemeSoundPresetsAmbientPopulated(t *testing.T) { t.Parallel() - for name := range themeSet { + for name := range getThemeSet() { preset, ok := themeSoundPresets[name] if !ok { t.Errorf("theme %q missing from themeSoundPresets", name) @@ -170,7 +170,7 @@ func TestThemeSoundPresetsAmbientPopulated(t *testing.T) { func TestThemeSoundPresetsAmbientValuesBounded(t *testing.T) { t.Parallel() - for name := range themeSet { + for name := range getThemeSet() { preset, ok := themeSoundPresets[name] if !ok { continue @@ -384,8 +384,8 @@ func TestLoadThemeMeta_neonHasFields(t *testing.T) { func TestListThemes_sortedAndComplete(t *testing.T) { t.Parallel() names := ListThemes() - if len(names) != len(themeSet) { - t.Fatalf("len=%d, want %d", len(names), len(themeSet)) + if len(names) != len(getThemeSet()) { + t.Fatalf("len=%d, want %d", len(names), len(getThemeSet())) } for i := 1; i < len(names); i++ { if names[i] <= names[i-1] { diff --git a/internal/generator/shared.go b/internal/generator/shared.go index d0badb8..378a01f 100644 --- a/internal/generator/shared.go +++ b/internal/generator/shared.go @@ -2,6 +2,7 @@ package generator import ( "log" + "sync" "codeberg.org/snonux/snonux/internal/generator/templates" ) @@ -18,13 +19,19 @@ import ( // Each theme ends its