package templ import ( "embed" "html/template" "io/fs" "os" "sync" "github.com/Necoro/form" ) //go:embed *.tpl var fsEmbed embed.FS var templates = make(map[string]*template.Template) var muTpl sync.RWMutex var baseTpl *template.Template var formBuilder form.Builder 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.FuncMap()). ParseFS(fs, "base.tpl", "form.tpl")) formBuilder = form.Builder{InputTemplate: baseTpl.Lookup("formItem")} baseTpl.Funcs(formBuilder.FuncMap()) } 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 }