forked from gotuna/gotuna
/
templating.go
117 lines (101 loc) · 2.9 KB
/
templating.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
110
111
112
113
114
115
116
117
package gotuna
import (
"fmt"
"html/template"
"net/http"
)
// ContentTypeHTML is a standard Content-Type header for HTML response.
const ContentTypeHTML = "text/html; charset=utf-8"
// ViewHelperFunc is a view helper that can be used in any template file.
type ViewHelperFunc func(w http.ResponseWriter, r *http.Request) (string, interface{})
// TemplatingEngine used for rendering response.
type TemplatingEngine interface {
Render(w http.ResponseWriter, r *http.Request, patterns ...string)
Set(key string, data interface{}) TemplatingEngine
SetError(errorKey, description string) TemplatingEngine
GetErrors() map[string]string
}
// NewTemplatingEngine is a constructor that returns a native HTML templating engine.
func (app App) NewTemplatingEngine() TemplatingEngine {
return &nativeHTML{
app: app,
Data: make(map[string]interface{}),
Errors: make(map[string]string),
}
}
type nativeHTML struct {
app App
Data map[string]interface{}
Errors map[string]string
Flashes []FlashMessage
}
func (t *nativeHTML) Set(key string, data interface{}) TemplatingEngine {
t.Data[key] = data
return t
}
func (t *nativeHTML) SetError(errorKey, description string) TemplatingEngine {
t.Errors[errorKey] = description
return t
}
func (t nativeHTML) GetErrors() map[string]string {
return t.Errors
}
func (t *nativeHTML) Render(w http.ResponseWriter, r *http.Request, patterns ...string) {
if t.app.ViewFiles == nil {
panic("view filesystem not configured")
}
if t.app.Session != nil {
t.Flashes = t.app.Session.Flashes(w, r)
}
tmpl := template.Must(
template.New("app").
Funcs(t.getHelpers(w, r)).
ParseFS(t.app.ViewFiles, patterns...))
w.Header().Set("Content-type", ContentTypeHTML)
err := tmpl.Execute(w, t)
if err != nil {
panic(fmt.Errorf("error rendering %v", err))
}
}
func (t nativeHTML) getHelpers(w http.ResponseWriter, r *http.Request, patterns ...string) template.FuncMap {
// default helpers
fmap := template.FuncMap{
"request": func() *http.Request {
return r
},
"t": func(s string) string {
locale := t.app.Session.GetLocale(r)
return t.app.Locale.T(locale, s)
},
"tp": func(s string, n int) string {
locale := t.app.Session.GetLocale(r)
return t.app.Locale.TP(locale, s, n)
},
"static": func(file string) string {
hash := "123" // TODO:
return fmt.Sprintf("%s%s?%s", t.app.StaticPrefix, file, hash)
},
"currentUser": func() (User, error) {
user, err := GetUserFromContext(r.Context())
return user, err
},
"currentLocale": func() string {
return t.app.Session.GetLocale(r)
},
"isGuest": func() bool {
return t.app.Session.IsGuest(r)
},
"currentName": func() string {
return t.app.Session.GetName(r)
},
"currentEnvironment": func() string {
return t.app.Session.GetEnvironment(r)
},
}
// add custom, user-defined helpers
for _, v := range t.app.ViewHelpers {
n, f := v(w, r)
fmap[n] = f
}
return fmap
}