-
Notifications
You must be signed in to change notification settings - Fork 0
/
collection.go
135 lines (115 loc) · 2.85 KB
/
collection.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
133
134
135
package xtpl
import (
"crypto/md5"
"fmt"
"io"
"io/fs"
"sync"
)
var (
m sync.RWMutex
collection map[string]*xtpl
viewsPath string
viewExtension string
cyclesLimit uint
debug bool
embeddedFS fs.FS
serialID *serial
)
func init() {
collection = make(map[string]*xtpl)
cyclesLimit = 10000
viewsPath = "."
viewExtension = "tpl"
serialID = &serial{}
}
// ViewsPath Путь к корневой директории с шаблонами
func ViewsPath(path string) {
m.Lock()
viewsPath = path
for fileName := range collection {
collection[fileName] = xtplInit(fileName)
}
m.Unlock()
}
func EmbeddedFs(fs fs.FS) {
embeddedFS = fs
}
// ViewExtension Расширение файлов шаблона
func ViewExtension(extension string) {
m.Lock()
viewExtension = extension
for fileName := range collection {
collection[fileName] = xtplInit(fileName)
}
m.Unlock()
}
// Functions Загрузка пользовательских функций в шаблонизатор.
func Functions(functions map[string]interface{}) {
m.Lock()
for name, function := range functions {
xtplFunctions[name] = function
}
for fileName := range collection {
collection[fileName] = xtplInit(fileName)
}
m.Unlock()
}
// CycleLimit Установка ограничения, на максимальное количество итераций в циклах. По умолчанию 10000
func CycleLimit(limit uint) {
m.Lock()
cyclesLimit = limit
m.Unlock()
}
// Debug Переключение в режим отладки.
// В этом режиме, все изменения в шаблонах подхватываются налету, однако обработка шаблона занимет больше времени
func Debug(on bool) {
debug = on
}
// View Обработка шаблона
func View(tplPath string, data map[string]interface{}, writer io.Writer) error {
var xTpl *xtpl
if debug {
xTpl = xtplInit(tplPath)
xTpl.run(data, writer)
} else {
var ok bool
m.RLock()
xTpl, ok = collection[tplPath]
m.RUnlock()
if !ok {
m.Lock()
xTpl = xtplInit(tplPath)
collection[tplPath] = xTpl
m.Unlock()
}
xTpl.run(data, writer)
}
return xTpl.errors.Error()
}
// String Обработает строку как шаблон
func String(source string, data map[string]interface{}, writer io.Writer) error {
var xTpl *xtpl
if debug {
xTpl = xtplInitFromSource(source)
xTpl.run(data, writer)
} else {
var h = md5.New()
if _, err := h.Write([]byte(source)); err != nil {
return err
}
var tplKey = "xtpl_" + fmt.Sprintf("%x", h.Sum(nil))
var ok bool
m.RLock()
xTpl, ok = collection[tplKey]
m.RUnlock()
if !ok {
m.Lock()
xTpl = xtplInitFromSource(source)
collection[tplKey] = xTpl
m.Unlock()
}
xTpl.run(data, writer)
}
return xTpl.errors.Error()
}