package templates import ( "html/template" "io" "path" "strings" "git.phc.dm.unipi.it/phc/website/config" "git.phc.dm.unipi.it/phc/website/util" ) type CachedTemplate struct { LoadPatterns []string cachedTmpl *template.Template } func NewCacheTemplate(loadPatterns ...string) *CachedTemplate { cachedTemplate := &CachedTemplate{ LoadPatterns: loadPatterns, cachedTmpl: nil, } template.Must(cachedTemplate.Load(template.New(""))) return cachedTemplate } func (ct *CachedTemplate) Load(t *template.Template) (*template.Template, error) { if ct.cachedTmpl != nil { return ct.cachedTmpl, nil } ct.cachedTmpl = t for _, pattern := range ct.LoadPatterns { var err error ct.cachedTmpl, err = ct.cachedTmpl.ParseGlob(pattern) if err != nil { return nil, err } } return ct.cachedTmpl, nil } func (ct *CachedTemplate) Reload() { ct.cachedTmpl = nil template.Must(ct.Load(nil)) } func (ct *CachedTemplate) Template() *template.Template { return ct.cachedTmpl } // Renderer holds cached templates for rendering type Renderer struct { rootPath string loadPatterns []string templateCache map[string]*CachedTemplate } // NewRenderer constructs a template renderer with a base file func NewRenderer(rootPath string, loadPatterns ...string) *Renderer { return &Renderer{ rootPath, loadPatterns, map[string]*CachedTemplate{}, } } func (r *Renderer) Load(name string) *CachedTemplate { cachedTemplate, present := r.templateCache[name] if !present { loaders := []string{} loaders = append(loaders, r.loadPatterns...) loaders = append(loaders, path.Join(r.rootPath, name)) cachedTemplate = NewCacheTemplate(loaders...) r.templateCache[name] = cachedTemplate } return cachedTemplate } // Render the template, also injects "Page" and "Config" values in the template func (r *Renderer) Render(w io.Writer, name string, data util.H) error { cachedTemplate := r.Load(name) if config.Mode == "development" { cachedTemplate.Reload() } newData := util.H{} newData.Apply(data) newData["Page"] = util.H{ // Used to inject a page specific class on
"Name": strings.TrimSuffix(path.Base(name), ".html"), } newData["Config"] = config.Object() return cachedTemplate.Template().ExecuteTemplate(w, "base", newData) }