109 lines
2.6 KiB
Go
109 lines
2.6 KiB
Go
|
package templates
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"html/template"
|
||
|
"log"
|
||
|
"net/http"
|
||
|
"path"
|
||
|
"path/filepath"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/shurcooL/httpfs/html/vfstemplate"
|
||
|
"github.com/shurcooL/httpfs/path/vfspath"
|
||
|
)
|
||
|
|
||
|
// Templates contains a map of filenames to parsed and prepared templates
|
||
|
type Templates map[string]*template.Template
|
||
|
|
||
|
// LoadTemplatesFS takes a filesystem and a location, and returns a Templates
|
||
|
// map
|
||
|
func LoadTemplatesFS(fs http.FileSystem, dir string) Templates {
|
||
|
var templates = make(map[string]*template.Template)
|
||
|
|
||
|
layouts, err := vfspath.Glob(fs, dir+"/layouts/*.tmpl")
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
|
||
|
//log.Printf("Loaded %d layouts", len(layouts))
|
||
|
|
||
|
includes, err := vfspath.Glob(fs, dir+"/includes/*.tmpl")
|
||
|
if err != nil {
|
||
|
log.Fatal(err)
|
||
|
}
|
||
|
|
||
|
//log.Printf("Loaded %d includes", len(includes))
|
||
|
|
||
|
funcs := getFuncMap() // generate function map
|
||
|
|
||
|
// Generate our templates map from our layouts/ and includes/ directories
|
||
|
for _, layout := range layouts {
|
||
|
files := append(includes, layout)
|
||
|
t := template.New(filepath.Base(layout)).Funcs(funcs)
|
||
|
t, err := vfstemplate.ParseFiles(fs, t, files...)
|
||
|
if err != nil {
|
||
|
log.Fatalf("Error parsing template %s: %s",
|
||
|
filepath.Base(layout), err)
|
||
|
}
|
||
|
templates[filepath.Base(layout)] = t
|
||
|
}
|
||
|
|
||
|
return templates
|
||
|
}
|
||
|
|
||
|
func (templates Templates) Get(name string) *template.Template {
|
||
|
t, ok := templates[name]
|
||
|
if !ok {
|
||
|
log.Printf("Error loading template %s", name)
|
||
|
return template.Must(template.New("empty").Parse("ERROR: Template missing"))
|
||
|
}
|
||
|
return t
|
||
|
}
|
||
|
|
||
|
func getFuncMap() template.FuncMap {
|
||
|
return template.FuncMap{
|
||
|
"istrue": func(value bool) bool {
|
||
|
return value
|
||
|
},
|
||
|
"join": func(sep string, a []string) string {
|
||
|
return strings.Join(a, sep)
|
||
|
},
|
||
|
"dict": func(values ...interface{}) (map[string]interface{}, error) {
|
||
|
if len(values)%2 != 0 {
|
||
|
return nil, errors.New("invalid dict call")
|
||
|
}
|
||
|
dict := make(map[string]interface{}, len(values)/2)
|
||
|
for i := 0; i < len(values); i += 2 {
|
||
|
key, ok := values[i].(string)
|
||
|
if !ok {
|
||
|
return nil, errors.New("dict keys must be strings")
|
||
|
}
|
||
|
dict[key] = values[i+1]
|
||
|
}
|
||
|
return dict, nil
|
||
|
},
|
||
|
"url": func(rel ...string) string {
|
||
|
params := []string{"/"}
|
||
|
params = append(params, rel...)
|
||
|
return path.Join(params...)
|
||
|
},
|
||
|
"static": func(rel ...string) string {
|
||
|
params := []string{"/static"}
|
||
|
params = append(params, rel...)
|
||
|
return path.Join(params...)
|
||
|
},
|
||
|
"i18n": func(locale, key string) string {
|
||
|
switch locale {
|
||
|
case "de":
|
||
|
return "Hallo Welt!"
|
||
|
case "en":
|
||
|
return "Hello World!"
|
||
|
default:
|
||
|
log.Printf("I18n: '%s' has no key '%s'", locale, key)
|
||
|
return key
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
}
|