package templ import ( "embed" "html/template" "io/fs" "os" "sync" "gosten/form" ) //go:embed *.tpl var fsEmbed embed.FS var templates = make(map[string]*template.Template) var muTpl sync.RWMutex var baseTpl *template.Template var isLive = sync.OnceValue(checkLive) func init() { loadBase(fsEmbed) } func checkLive() bool { return os.Getenv("GOSTEN_LIVE") != "" } func loadBase(fs fs.FS) { baseTpl = template.Must(template.New("base.tpl"). Funcs(form.ParsingFuncMap()). ParseFS(fs, "base.tpl", "form.tpl", "navlinks.tpl", "content.tpl")) baseTpl.Funcs(form.FuncMap(baseTpl.Lookup("formItem"))) } func Lookup(name string) *template.Template { if isLive() { fs := os.DirFS("templ/") loadBase(fs) return getTemplate(name, fs) } muTpl.RLock() tpl := templates[name] muTpl.RUnlock() if tpl == nil { return parse(name) } return tpl } func parse(name string) *template.Template { muTpl.Lock() defer muTpl.Unlock() if tpl := templates[name]; tpl != nil { // might've been created by another goroutine return tpl } t := getTemplate(name, fsEmbed) templates[name] = t return t } func getTemplate(name string, fs fs.FS) *template.Template { b := template.Must(baseTpl.Clone()) t := template.Must(b.ParseFS(fs, name+".tpl")) return t }