-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathview.go
109 lines (94 loc) · 2.27 KB
/
view.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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package views
import (
"fmt"
"github.com/flosch/pongo2/v6"
"github.com/goal-web/contracts"
"github.com/goal-web/supports/exceptions"
"github.com/goal-web/supports/logs"
"github.com/goal-web/supports/utils"
"path/filepath"
"strings"
"sync"
)
type View struct {
templates map[string]*pongo2.Template
debug bool
path string
mutex sync.Mutex
}
func (v *View) Register(name, template string) {
tpl, err := pongo2.FromString(template)
if err != nil {
logs.Default().
WithField("name", name).
WithError(err).
WithField("template", template).
Debug(fmt.Sprintf("Failed to parse template: %s", err))
panic(RegisterException{
Exception: exceptions.WithError(err),
Name: name,
Template: template,
})
}
v.mutex.Lock()
v.templates[name] = tpl
v.mutex.Unlock()
}
func NewView(path string, debug bool) contracts.Views {
return &View{
templates: make(map[string]*pongo2.Template),
path: path,
debug: debug,
}
}
func (v *View) Render(name string, data ...any) contracts.HttpResponse {
context, err := utils.ToFields(utils.DefaultValue(data, any(contracts.Fields{})))
if err != nil {
logs.Default().
WithField("name", name).
WithField("data", data).
Debug(fmt.Sprintf("Failed to parse data: %s", err.Error()))
panic(DataInvalidException{
Exception: exceptions.WithError(err),
Name: name,
Data: data,
})
}
tpl, exists := v.templates[name]
if !exists {
viewPath := name
if !strings.HasPrefix(name, "/") {
viewPath = filepath.Join(v.path, name)
}
tpl, err = pongo2.FromFile(viewPath)
if err != nil {
logs.Default().
WithField("name", name).
WithField("data", data).
Debug(fmt.Sprintf("template %s not found", name))
panic(ViewNotFoundException{
Exception: exceptions.WithError(err),
Name: name,
Data: data,
})
}
if !v.debug {
v.mutex.Lock()
v.templates[name] = tpl
v.mutex.Unlock()
}
}
output, err := tpl.Execute(pongo2.Context(context))
if err != nil {
logs.Default().
WithField("name", name).
WithField("data", data).
Debug(fmt.Sprintf("Failed to render view: %s", err.Error()))
panic(ViewRenderException{
Exception: exceptions.WithError(err),
Name: name,
Data: data,
})
}
return NewResponse([]byte(output))
}