forked from gravityblast/traffic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
132 lines (104 loc) · 2.87 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
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package traffic
import (
"fmt"
"html/template"
"io/ioutil"
"os"
"path/filepath"
)
const TemplateExtension = ".tpl"
type RenderFunc func(w ResponseWriter, template string, data interface{})
var templateManager *TemplateManager
type TemplateManager struct {
viewsBasePath string
templates *template.Template
renderFunc RenderFunc
templatesReadError error
templatesParseError error
}
var templateFuncs = make(map[string]interface{})
func TemplateFuncs(funcs map[string]interface{}) {
for name, fn := range funcs {
TemplateFunc(name, fn)
}
}
func TemplateFunc(name string, fn interface{}) {
templateFuncs[name] = fn
}
func (t *TemplateManager) loadTemplates() {
t.templates = template.New("templates")
t.templates.Funcs(templateFuncs)
if t.viewsBasePath == "" {
panic("views base path is blank")
}
filepath.Walk(t.viewsBasePath, t.WalkFunc)
}
func (t *TemplateManager) WalkFunc(path string, info os.FileInfo, err error) error {
if err != nil {
t.templatesReadError = err
t.renderFunc = t.RenderTemplateErrors
return err
}
if extension := filepath.Ext(path); !info.IsDir() && extension == TemplateExtension {
relativePath, err := filepath.Rel(t.viewsBasePath, path)
if err != nil {
t.templatesReadError = err
t.renderFunc = t.RenderTemplateErrors
return err
}
templateName := relativePath[0:(len(relativePath) - len(extension))]
t.addTemplate(templateName, path)
}
return nil
}
func (t *TemplateManager) addTemplate(name, path string) {
fileContent, err := ioutil.ReadFile(path)
if err != nil {
t.templatesReadError = err
t.renderFunc = t.RenderTemplateErrors
return
}
templateContent := fmt.Sprintf(`{{ define "%s" }}%s{{ end }}`, name, fileContent)
tmpl, err := t.templates.Parse(templateContent)
if tmpl == nil && err != nil {
t.templatesParseError = err
t.renderFunc = t.RenderTemplateErrors
}
}
func (t *TemplateManager) templatesPath() string {
if path := GetVar("views"); path != nil {
return path.(string)
}
return DefaultViewsPath
}
func (t *TemplateManager) Render(w ResponseWriter, template string, data interface{}) {
err := t.templates.ExecuteTemplate(w, template, data)
if err != nil {
panic(err)
}
}
func (t *TemplateManager) RenderTemplateErrors(w ResponseWriter, template string, data interface{}) {
if t.templatesReadError != nil {
panic(t.templatesReadError)
}
if t.templatesParseError != nil {
panic(t.templatesParseError)
}
}
func newTemplateManager() *TemplateManager {
t := &TemplateManager{}
t.viewsBasePath = ViewsPath()
t.renderFunc = t.Render
t.loadTemplates()
return t
}
func initTemplateManager() {
templateManager = newTemplateManager()
}
func RenderTemplate(w ResponseWriter, templateName string, data ...interface{}) {
if len(data) == 0 {
templateManager.renderFunc(w, templateName, nil)
} else {
templateManager.renderFunc(w, templateName, data[0])
}
}