-
Notifications
You must be signed in to change notification settings - Fork 181
/
var_replacer.go
81 lines (68 loc) · 2.04 KB
/
var_replacer.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
package textutil
import (
"reflect"
"regexp"
"strings"
"github.com/gookit/goutil/maputil"
"github.com/gookit/goutil/strutil"
)
const defaultVarFormat = "{{,}}"
// VarReplacer struct
type VarReplacer struct {
init bool
Left, Right string
lLen, rLen int
varReg *regexp.Regexp
}
// NewVarReplacer instance
func NewVarReplacer(format string) *VarReplacer {
return (&VarReplacer{}).WithFormat(format)
}
// WithFormat custom var template
func (r *VarReplacer) WithFormat(format string) *VarReplacer {
r.Left, r.Right = strutil.MustCut(strutil.OrElse(format, defaultVarFormat), ",")
r.Init()
return r
}
// Init var matcher
func (r *VarReplacer) Init() *VarReplacer {
if !r.init {
r.lLen, r.rLen = len(r.Left), len(r.Right)
if r.Right != "" {
r.varReg = regexp.MustCompile(regexp.QuoteMeta(r.Left) + `([\w\s.-]+)` + regexp.QuoteMeta(r.Right))
} else {
// no right tag. eg: $name, $user.age
// r.varReg = regexp.MustCompile(regexp.QuoteMeta(r.Left) + `([\w.-]+)`)
r.varReg = regexp.MustCompile(regexp.QuoteMeta(r.Left) + `(\w[\w-]*(?:\.[\w-]+)*)`)
}
}
return r
}
// Replace any-map vars in the text contents
func (r *VarReplacer) Replace(s string, tplVars map[string]any) string {
if len(tplVars) == 0 || !strings.Contains(s, r.Left) {
return s
}
varMap := make(map[string]string, len(tplVars)*2)
maputil.FlatWithFunc(tplVars, func(path string, val reflect.Value) {
varMap[path] = strutil.QuietString(val.Interface())
})
return r.Init().doReplace(s, varMap)
}
// RenderSimple string-map vars in the text contents
func (r *VarReplacer) RenderSimple(s string, varMap map[string]string) string {
if len(varMap) == 0 || !strings.Contains(s, r.Left) {
return s
}
return r.Init().doReplace(s, varMap)
}
// Replace string-map vars in the text contents
func (r *VarReplacer) doReplace(s string, varMap map[string]string) string {
return r.varReg.ReplaceAllStringFunc(s, func(sub string) string {
varName := strings.TrimSpace(sub[r.lLen : len(sub)-r.rLen])
if val, ok := varMap[varName]; ok {
return val
}
return sub
})
}