2017-01-26 19:44:31 -08:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
2017-01-26 19:52:34 -08:00
|
|
|
"fmt"
|
2017-01-26 19:44:31 -08:00
|
|
|
"html/template"
|
|
|
|
"path/filepath"
|
2017-01-26 19:52:34 -08:00
|
|
|
"sync"
|
2017-01-26 19:44:31 -08:00
|
|
|
)
|
|
|
|
|
|
|
|
// TemplateGetter defines what needs to be implemented to be able to fetch
|
|
|
|
// templates for use by a Site.
|
|
|
|
type TemplateGetter interface {
|
|
|
|
Get(name string) (*template.Template, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Disk keeps track of the location of the root directory of the template
|
|
|
|
// directory.
|
|
|
|
type Disk struct {
|
|
|
|
Root string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get attempts to merge the requested name+.html with base.html found at root.
|
|
|
|
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"))
|
|
|
|
}
|
2017-01-26 19:52:34 -08:00
|
|
|
|
|
|
|
// 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
|
|
|
|
}
|