forked from andeya/lessgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrender.go
99 lines (86 loc) · 2.18 KB
/
render.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
package lessgo
import (
"encoding/json"
"errors"
"github.com/lessgo/lessgo/pongo2"
"io"
"sync"
"time"
)
type (
Tpl struct {
template *pongo2.Template
modTime time.Time
}
// Pongo2Render is a custom lessgo template renderer using Pongo2.
Pongo2Render struct {
set *pongo2.TemplateSet
caching bool // false=disable caching, true=enable caching
tplCache map[string]*Tpl
sync.RWMutex
}
)
// New creates a new Pongo2Render instance with custom Options.
func NewPongo2Render(caching bool) *Pongo2Render {
return &Pongo2Render{
set: pongo2.NewSet("lessgo", pongo2.DefaultLoader),
caching: caching,
tplCache: make(map[string]*Tpl),
}
}
// Render should render the template to the io.Writer.
func (p *Pongo2Render) Render(w io.Writer, filename string, data interface{}, c *Context) error {
var (
template *pongo2.Template
data2 = pongo2.Context{}
)
switch d := data.(type) {
case pongo2.Context:
data2 = d
case map[string]interface{}:
data2 = pongo2.Context(d)
default:
b, _ := json.Marshal(data)
json.Unmarshal(b, &data2)
}
if p.caching {
template = pongo2.Must(p.FromCache(filename))
} else {
template = pongo2.Must(p.set.FromFile(filename))
}
return template.ExecuteWriter(data2, w)
}
func (p *Pongo2Render) FromCache(fname string) (*pongo2.Template, error) {
//从文件系统缓存中获取文件信息
fbytes, finfo, exist := lessgo.App.MemoryCache().GetCacheFile(fname)
// 文件已不存在
if !exist {
// 移除模板中缓存
p.Lock()
_, has := p.tplCache[fname]
if has {
delete(p.tplCache, fname)
}
p.Unlock()
// 返回错误
return nil, errors.New(fname + "is not found.")
}
// 查看模板缓存
p.RLock()
tpl, has := p.tplCache[fname]
p.RUnlock()
// 存在模板缓存且文件未更新时,直接读模板缓存
if has && p.tplCache[fname].modTime.Equal(finfo.ModTime()) {
return tpl.template, nil
}
// 缓存模板不存在或文件已更新时,均新建缓存模板
p.Lock()
defer p.Unlock()
// 创建新模板并缓存
newtpl, err := p.set.FromBytes(fname, fbytes)
if err != nil {
return nil, err
}
p.tplCache[fname] = &Tpl{template: newtpl, modTime: finfo.ModTime()}
return newtpl, nil
}