-
Notifications
You must be signed in to change notification settings - Fork 22
/
environment.go
112 lines (93 loc) · 3 KB
/
environment.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
package gonja
import (
"io/ioutil"
"sync"
"github.com/goph/emperror"
"github.com/noirbizarre/gonja/builtins"
"github.com/noirbizarre/gonja/config"
"github.com/noirbizarre/gonja/exec"
"github.com/noirbizarre/gonja/loaders"
)
type Environment struct {
*exec.EvalConfig
Loader loaders.Loader
Cache map[string]*exec.Template
CacheMutex sync.Mutex
}
func NewEnvironment(cfg *config.Config, loader loaders.Loader) *Environment {
env := &Environment{
EvalConfig: exec.NewEvalConfig(cfg),
Loader: loader,
Cache: map[string]*exec.Template{},
}
env.EvalConfig.Loader = env
env.Filters.Update(builtins.Filters)
env.Statements.Update(builtins.Statements)
env.Tests.Update(builtins.Tests)
env.Globals.Merge(builtins.Globals)
env.Globals.Set("gonja", map[string]interface{}{
"version": VERSION,
})
return env
}
// CleanCache cleans the template cache. If filenames is not empty,
// it will remove the template caches of those filenames.
// Or it will empty the whole template cache. It is thread-safe.
func (env *Environment) CleanCache(filenames ...string) {
env.CacheMutex.Lock()
defer env.CacheMutex.Unlock()
if len(filenames) == 0 {
env.Cache = map[string]*exec.Template{}
}
for _, filename := range filenames {
delete(env.Cache, filename)
}
}
// FromCache is a convenient method to cache templates. It is thread-safe
// and will only compile the template associated with a filename once.
// If Environment.Debug is true (for example during development phase),
// FromCache() will not cache the template and instead recompile it on any
// call (to make changes to a template live instantaneously).
func (env *Environment) FromCache(filename string) (*exec.Template, error) {
if env.Config.Debug {
// Recompile on any request
return env.FromFile(filename)
}
env.CacheMutex.Lock()
defer env.CacheMutex.Unlock()
tpl, has := env.Cache[filename]
// Cache miss
if !has {
tpl, err := env.FromFile(filename)
if err != nil {
return nil, err
}
env.Cache[filename] = tpl
return tpl, nil
}
// Cache hit
return tpl, nil
}
// FromString loads a template from string and returns a Template instance.
func (env *Environment) FromString(tpl string) (*exec.Template, error) {
return exec.NewTemplate("string", tpl, env.EvalConfig)
}
// FromBytes loads a template from bytes and returns a Template instance.
func (env *Environment) FromBytes(tpl []byte) (*exec.Template, error) {
return exec.NewTemplate("bytes", string(tpl), env.EvalConfig)
}
// FromFile loads a template from a filename and returns a Template instance.
func (env *Environment) FromFile(filename string) (*exec.Template, error) {
fd, err := env.Loader.Get(filename)
if err != nil {
return nil, emperror.With(err, "filename", filename)
}
buf, err := ioutil.ReadAll(fd)
if err != nil {
return nil, emperror.With(err, "filename", filename)
}
return exec.NewTemplate(filename, string(buf), env.EvalConfig)
}
func (env *Environment) GetTemplate(filename string) (*exec.Template, error) {
return env.FromFile(filename)
}