-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtemplate.go
57 lines (48 loc) · 1.36 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package torque
import (
"net/http"
"reflect"
"text/template/parse"
"github.com/tylermmorton/tmpl"
)
type templateRenderer[T ViewModel] struct {
hasOutlet bool
template tmpl.Template[tmpl.TemplateProvider]
}
func (t templateRenderer[T]) Render(wr http.ResponseWriter, req *http.Request, vm T) error {
opts := make([]tmpl.RenderOption, 0)
if target := UseTarget(req); len(target) != 0 {
opts = append(opts, tmpl.WithTarget(target))
}
return t.template.Render(wr, any(vm).(tmpl.TemplateProvider), opts...)
}
func createTemplateRenderer[T ViewModel](tp tmpl.TemplateProvider) (*templateRenderer[T], bool, error) {
var (
r = &templateRenderer[T]{}
err error
)
r.template, err = tmpl.Compile(
tp,
tmpl.UseAnalyzers(outletAnalyzer(r)),
)
if err != nil {
return nil, false, err
}
return r, r.hasOutlet, nil
}
const outletIdent = "outlet"
func outletAnalyzer[T ViewModel](t *templateRenderer[T]) tmpl.Analyzer {
return func(h *tmpl.AnalysisHelper) tmpl.AnalyzerFunc {
return func(val reflect.Value, node parse.Node) {
switch node := node.(type) {
case *parse.IdentifierNode:
if node.Ident == outletIdent && t.hasOutlet == true {
h.AddError(node, "outlet can only be defined once per template")
} else if node.Ident == outletIdent {
t.hasOutlet = true
h.AddFunc(outletIdent, func() string { return "{{ . }}" })
}
}
}
}
}