diff --git a/tmpl.go b/tmpl.go index 5e9987b..b54cdd0 100644 --- a/tmpl.go +++ b/tmpl.go @@ -1,8 +1,10 @@ package web import ( + "fmt" "html/template" "path/filepath" + "sync" ) // TemplateGetter defines what needs to be implemented to be able to fetch @@ -22,3 +24,53 @@ func (d Disk) Get(name string) (*template.Template, error) { p := filepath.Join(d.Root, name+".html") return template.New("").ParseFiles(p, filepath.Join(d.Root, "base.html")) } + +// AssetTemplate pulls templates from an assetfs. +type AssetTemplate struct { + sync.RWMutex + Asset func(name string) ([]byte, error) + + cache map[string]*template.Template +} + +// NewAssetTemplate returns a ready-to-use AssetTemplate. +func NewAssetTemplate(asset func(string) ([]byte, error)) *AssetTemplate { + return &AssetTemplate{ + Asset: asset, + cache: map[string]*template.Template{}, + } +} + +// Get attempts to merge the requested name+.html with base.html found at root. +func (at *AssetTemplate) Get(name string) (*template.Template, error) { + at.RLock() + if t, ok := at.cache[name]; ok { + at.RUnlock() + return t, nil + } + at.RUnlock() + + base, err := at.Asset("templates/base.html") + if err != nil { + return nil, fmt.Errorf("could not get base contents: %v", err) + } + page, err := at.Asset(fmt.Sprintf("templates/%s.html", name)) + if err != nil { + return nil, fmt.Errorf("could not get base contents: %v", err) + } + + t, err := template.New(name).Parse(string(base)) + if err != nil { + return t, fmt.Errorf("parsing base: %v", err) + } + t, err = t.Parse(string(page)) + if err != nil { + return t, fmt.Errorf("parsing specific page %s: %v", name, err) + } + + at.Lock() + at.cache[name] = t + at.Unlock() + + return t, nil +} diff --git a/web.go b/web.go index 983b2ec..6ae2a01 100644 --- a/web.go +++ b/web.go @@ -33,6 +33,7 @@ func NewSite(sm *http.ServeMux, static, templates string) *Site { } } + s.tmpl = NewAssetTemplate(Asset) if templates != "" { s.tmpl = Disk{templates} }