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 } }, } }