♻️ Refactored template utils map setup

This commit is contained in:
Maxim Lebedev 2023-11-09 05:04:18 +06:00
parent 6012945d06
commit a475dacd60
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
4 changed files with 133 additions and 2 deletions

View File

@ -0,0 +1,42 @@
package partial
import (
"bytes"
"fmt"
"html/template"
"io/fs"
"path/filepath"
"strings"
)
type Namespace struct {
dir fs.FS
funcMap template.FuncMap
}
func New(dir fs.FS, funcMap template.FuncMap) *Namespace {
return &Namespace{
dir: dir,
funcMap: funcMap,
}
}
func (ns *Namespace) Include(name string, data any) (template.HTML, error) {
name = strings.TrimPrefix(filepath.Clean(name), "partials/")
if filepath.Ext(name) == "" {
name += ".html"
}
tpl, err := template.New(name).Funcs(ns.funcMap).ParseFS(ns.dir, name)
if err != nil {
return "", fmt.Errorf("cannot parse partial: %w", err)
}
buf := bytes.NewBuffer(nil)
if err = tpl.Execute(buf, data); err != nil {
return "", fmt.Errorf("cannot execute partial: %w", err)
}
return template.HTML(buf.String()), nil
}

View File

@ -1,4 +1,4 @@
package templateutil
package safe
import (
"errors"
@ -6,13 +6,23 @@ import (
"reflect"
)
type Namespace struct{}
var ErrSafeHTML error = errors.New("unsupported input type for SafeHTML")
func SafeHTML(v reflect.Value) (template.HTML, error) {
func New() *Namespace {
return &Namespace{}
}
func (Namespace) HTML(v reflect.Value) (template.HTML, error) {
switch v.Kind() {
default:
return "", ErrSafeHTML
case reflect.Slice:
if v.Elem().Kind() != reflect.Uint8 {
return "", ErrSafeHTML
}
return template.HTML(v.Bytes()), nil
case reflect.String:
return template.HTML(v.String()), nil

View File

@ -0,0 +1,17 @@
package string
import "strings"
type Namespace struct{}
func New() *Namespace {
return &Namespace{}
}
func (ns *Namespace) HasPrefix(s, prefix string) bool {
return strings.HasPrefix(s, prefix)
}
func (ns *Namespace) HasSuffix(s, suffix string) bool {
return strings.HasSuffix(s, suffix)
}

View File

@ -0,0 +1,62 @@
package templateutil
import (
"fmt"
"html/template"
"io/fs"
"source.toby3d.me/toby3d/home/internal/templateutil/partial"
"source.toby3d.me/toby3d/home/internal/templateutil/safe"
strings "source.toby3d.me/toby3d/home/internal/templateutil/string"
)
type Function struct {
Handler func(v ...any) any
Methods template.FuncMap
Name string
}
func New(dir fs.FS) (template.FuncMap, error) {
partials, err := fs.Sub(dir, "partials")
if err != nil {
return nil, fmt.Errorf("cannot substitute into partials subdirectory: %w", err)
}
funcMap := make(template.FuncMap)
funcs := make([]Function, 0)
stringsNamespace := strings.New()
funcs = append(funcs, Function{
Name: "strings",
Handler: func(v ...any) any { return stringsNamespace },
Methods: template.FuncMap{
"hasPrefix": stringsNamespace.HasPrefix,
"hasSuffix": stringsNamespace.HasSuffix,
},
})
safeNamespace := safe.New()
funcs = append(funcs, Function{
Name: "safe",
Handler: func(v ...any) any { return safeNamespace },
Methods: template.FuncMap{
"safeHTML": safeNamespace.HTML,
},
})
partialNamespace := partial.New(partials, funcMap)
funcs = append(funcs, Function{
Name: "partials",
Handler: func(v ...any) any { return partialNamespace },
Methods: template.FuncMap{
"partial": partialNamespace.Include,
},
})
for _, f := range funcs {
funcMap[f.Name] = f.Handler
for name, m := range f.Methods {
funcMap[name] = m
}
}
return funcMap, nil
}