package main import ( "html/template" "io/fs" "os" "sync" ) var devMode bool // assetFS defaults to the embedded FS so package-level initializers (e.g. icon // vars in render.go) can read assets before main() runs. initAssets() swaps it // for os.DirFS when -dev is set. var assetFS fs.FS = assets func initAssets(dev bool) { devMode = dev if dev { assetFS = os.DirFS(".") } } // readAsset reads a file from the asset FS (embedded in prod, live disk in dev). func readAsset(path string) ([]byte, error) { return fs.ReadFile(assetFS, path) } // tmplLoader holds a lazily-parsed template. In dev mode it re-parses on every // get() call so HTML changes are visible without recompiling. type tmplLoader struct { name string patterns []string once sync.Once t *template.Template } // newTemplate creates a tmplLoader. name is the root template name passed to // template.New; patterns are the glob/path arguments forwarded to ParseFS. func newTemplate(name string, patterns ...string) *tmplLoader { return &tmplLoader{name: name, patterns: patterns} } func (l *tmplLoader) get() *template.Template { if devMode { return template.Must(template.New(l.name).ParseFS(assetFS, l.patterns...)) } l.once.Do(func() { l.t = template.Must(template.New(l.name).ParseFS(assetFS, l.patterns...)) }) return l.t }