You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
website/templates/templates.go

102 lines
2.2 KiB
Go

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 <body>
"Name": strings.TrimSuffix(path.Base(name), ".html"),
}
newData["Config"] = config.Object()
return cachedTemplate.Template().ExecuteTemplate(w, "base", newData)
}