utils/gin/tmpls/tmpls.go

88 lines
1.8 KiB
Go

package tmpls
import (
"errors"
"html/template"
"io/fs"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/gin-gonic/gin/render"
)
var ErrNoTmpl = errors.New("no such template in map")
// TmplMap is a map of templates that implements
// the render.HTMLRender interface
type Map map[string]*template.Template
// Instance returns a Tmpl instance for the given template
func (m Map) Instance(name string, data interface{}) render.Render {
tmpl, ok := m[name]
if !ok {
return nil
}
return Tmpl{
Template: tmpl,
data: data,
}
}
// Tmpl implements the render.Render interface
type Tmpl struct {
*template.Template
data interface{}
}
// Render renders the template to response writer
func (t Tmpl) Render(res http.ResponseWriter) error {
if t.Template == nil {
return ErrNoTmpl
}
return t.Execute(res, t.data)
}
// WriteContentType sets content type to HTML
func (t Tmpl) WriteContentType(res http.ResponseWriter) {
res.Header().Set("Content-Type", "text/html; charset=utf-8")
}
func FromFS(f fs.FS, root, ext string, fm template.FuncMap) (Map, error) {
tmpls := Map{}
err := fs.WalkDir(f, root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() || path == filepath.Join(root, "base"+ext) {
return nil
}
tmplName := strings.TrimPrefix(path, root+"/")
tmplName = strings.TrimSuffix(tmplName, ext)
tmpl := template.New(filepath.Base(path))
if fm != nil {
tmpl = tmpl.Funcs(fm)
}
tmpl, err = tmpl.ParseFS(f, path, filepath.Join(root, "base"+ext))
if err != nil {
return err
}
tmpls[tmplName] = tmpl
return nil
})
return tmpls, err
}
func FromDir(baseDir, ext string, fm template.FuncMap) (Map, error) {
dir := filepath.Dir(baseDir)
root := filepath.Base(baseDir)
return FromFS(os.DirFS(dir), root, ext, fm)
}