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", "navlinks.tpl", "content.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
}