forked from devfeel/dotweb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrender.go
More file actions
103 lines (89 loc) · 2.52 KB
/
render.go
File metadata and controls
103 lines (89 loc) · 2.52 KB
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
package dotweb
import (
"github.com/devfeel/dotweb/framework/file"
"html/template"
"io"
"path"
"sync"
)
// Renderer is the interface that wraps the render method.
type Renderer interface {
SetTemplatePath(path string)
Render(io.Writer, interface{}, Context, ...string) error
}
type innerRenderer struct {
templatePath string
// Template cache (for FromCache())
enabledCache bool
templateCache map[string]*template.Template
templateCacheMutex sync.RWMutex
}
// Render render view use http/template
func (r *innerRenderer) Render(w io.Writer, data interface{}, ctx Context, tpl ...string) error {
t, err := r.parseFiles(tpl...)
if err != nil {
return err
}
return t.Execute(w, data)
}
// SetTemplatePath set default template path
func (r *innerRenderer) SetTemplatePath(path string) {
r.templatePath = path
}
// 定义函数unescaped
func unescaped(x string) interface{} { return template.HTML(x) }
// return http/template by gived file name
func (r *innerRenderer) parseFiles(fileNames ...string) (*template.Template, error) {
var realFileNames []string
var filesCacheKey string
var err error
for _, v := range fileNames {
if !file.Exist(v) {
v = path.Join(r.templatePath, v)
}
realFileNames = append(realFileNames, v)
filesCacheKey = filesCacheKey + v
}
var t *template.Template
var exists bool
if r.enabledCache {
//check from chach
t, exists = r.parseFilesFromCache(filesCacheKey)
}
if !exists{
t, err = template.ParseFiles(realFileNames...)
if err != nil {
return nil, err
}
r.templateCacheMutex.Lock()
defer r.templateCacheMutex.Unlock()
r.templateCache[filesCacheKey] = t
}
t = registeTemplateFunc(t)
return t, nil
}
func (r *innerRenderer) parseFilesFromCache(filesCacheKey string) (*template.Template, bool){
r.templateCacheMutex.RLock()
defer r.templateCacheMutex.RUnlock()
t, exists:= r.templateCache[filesCacheKey]
return t, exists
}
// registeTemplateFunc registe default support funcs
func registeTemplateFunc(t *template.Template) *template.Template {
return t.Funcs(template.FuncMap{"unescaped": unescaped})
//TODO:add more func
}
// NewInnerRenderer create a inner renderer instance
func NewInnerRenderer() Renderer {
r := new(innerRenderer)
r.enabledCache = true
r.templateCache = make(map[string]*template.Template)
return r
}
// NewInnerRendererNoCache create a inner renderer instance with no cache mode
func NewInnerRendererNoCache() Renderer {
r := new(innerRenderer)
r.enabledCache = false
r.templateCache = make(map[string]*template.Template)
return r
}