101 lines
2.3 KiB
Go
101 lines
2.3 KiB
Go
package webutil
|
|
|
|
import (
|
|
"embed"
|
|
"html/template"
|
|
"io/fs"
|
|
"log"
|
|
"path"
|
|
"strings"
|
|
)
|
|
|
|
// ParseTemplateSet parses sets of templates from an embed.FS.
|
|
//
|
|
// Each directory constitutes a set of templates that are parsed together.
|
|
//
|
|
// Structure (within a directory):
|
|
// - share/* are always parsed.
|
|
// - base.html will be parsed with each other file in same dir
|
|
//
|
|
// Call a template with m[path].Execute(w, data) (root dir name is excluded).
|
|
//
|
|
// For example, if you have
|
|
// - /user/share/*
|
|
// - /user/base.html
|
|
// - /user/home.html
|
|
//
|
|
// Then you call m["/user/home.html"].Execute(w, data).
|
|
func ParseTemplateSet(funcs template.FuncMap, fs embed.FS) map[string]*template.Template {
|
|
m := map[string]*template.Template{}
|
|
rootDir := readDir(fs, ".")[0].Name()
|
|
loadTemplateDir(fs, funcs, m, rootDir, rootDir)
|
|
return m
|
|
}
|
|
|
|
func loadTemplateDir(
|
|
fs embed.FS,
|
|
funcs template.FuncMap,
|
|
m map[string]*template.Template,
|
|
dirPath string,
|
|
rootDir string,
|
|
) map[string]*template.Template {
|
|
t := template.New("")
|
|
if funcs != nil {
|
|
t = t.Funcs(funcs)
|
|
}
|
|
|
|
shareDir := path.Join(dirPath, "share")
|
|
if _, err := fs.ReadDir(shareDir); err == nil {
|
|
log.Printf("Parsing %s...", path.Join(shareDir, "*"))
|
|
t = template.Must(t.ParseFS(fs, path.Join(shareDir, "*")))
|
|
}
|
|
|
|
if data, _ := fs.ReadFile(path.Join(dirPath, "base.html")); data != nil {
|
|
log.Printf("Parsing %s...", path.Join(dirPath, "base.html"))
|
|
t = template.Must(t.Parse(string(data)))
|
|
}
|
|
|
|
for _, ent := range readDir(fs, dirPath) {
|
|
if ent.Type().IsDir() {
|
|
if ent.Name() != "share" {
|
|
m = loadTemplateDir(fs, funcs, m, path.Join(dirPath, ent.Name()), rootDir)
|
|
}
|
|
continue
|
|
}
|
|
|
|
if !ent.Type().IsRegular() {
|
|
continue
|
|
}
|
|
|
|
if ent.Name() == "base.html" {
|
|
continue
|
|
}
|
|
|
|
filePath := path.Join(dirPath, ent.Name())
|
|
log.Printf("Parsing %s...", filePath)
|
|
|
|
key := strings.TrimPrefix(path.Join(dirPath, ent.Name()), rootDir)
|
|
tt := template.Must(t.Clone())
|
|
tt = template.Must(tt.Parse(readFile(fs, filePath)))
|
|
m[key] = tt
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
func readDir(fs embed.FS, dirPath string) []fs.DirEntry {
|
|
ents, err := fs.ReadDir(dirPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return ents
|
|
}
|
|
|
|
func readFile(fs embed.FS, path string) string {
|
|
data, err := fs.ReadFile(path)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return string(data)
|
|
}
|