/
funcs.go
149 lines (144 loc) · 3.58 KB
/
funcs.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package multitemplate
import "html/template"
func generateFuncs(t *Template) template.FuncMap {
return template.FuncMap{
"yield": func(vals ...interface{}) (string, error) {
var e error
switch len(vals) {
case 0:
t.ctx.output.Immediate(t.ctx.mainContent)
return "<\"'.", nil
case 1:
if name, ok := vals[0].(string); ok {
if t.ctx.Yields[name] != "" {
rb, e := t.ctx.exec(t.ctx.Yields[name], t.ctx.Dot)
t.ctx.output.Immediate(rb)
if e != nil {
return "<\"'.", e
}
}
if rb, ok := t.ctx.Blocks[name]; ok {
t.ctx.output.Immediate(rb)
return "<\"'.", nil
}
}
rb, e := t.ctx.exec(t.ctx.Main, vals[0])
t.ctx.output.Immediate(rb)
return "<\"'.", e
case 2:
if name, ok := vals[0].(string); ok {
// Use provided fallback if necessary
if f, ok := vals[0].(fallback); ok {
t.ctx.output.next, e = t.ctx.execWithFallback(name, f, t.ctx.Dot)
return "<\"'.", e
// Provided data to run
} else {
if t.ctx.Yields[name] != "" {
t.ctx.output.next, e = t.ctx.exec(t.ctx.Yields[name], vals[0])
return "<\"'.", e
}
if rb, ok := t.ctx.Blocks[name]; ok {
t.ctx.output.next = rb
return "<\"'.", nil
}
return "", nil
}
}
default:
if name, ok := vals[0].(string); ok {
var d interface{}
for _, v := range vals {
if f, ok := v.(fallback); ok {
if d == nil {
t.ctx.execWithFallback(name, f, vals[1])
} else {
t.ctx.execWithFallback(name, f, d)
}
} else {
if d == nil {
d = v
}
}
}
t.ctx.output.next, e = t.ctx.exec(name, d)
return "<\"'.", e
}
}
return "", nil
},
"content_for": func(name string, templateName string) string {
if t.ctx.Yields[name] == "" {
if _, ok := t.ctx.Blocks[name]; !ok {
t.ctx.Yields[name] = templateName
}
}
return ""
},
"root_dot": func() interface{} {
return t.ctx.Dot
},
"exec": func(templateName string, dot interface{}) (string, error) {
rb, e := t.ctx.exec(templateName, dot)
t.ctx.output.next = rb
return "<\"'.", e
},
"block": func(name string) (string, error) {
if t.ctx.openableScope() {
t.ctx.output.Open(name)
} else {
if _, ok := t.ctx.Yields[name]; ok {
rb, e := t.ctx.exec(t.ctx.Yields[name], t.ctx.Dot)
t.ctx.output.Nop(rb)
return "", e
} else if rb, ok := t.ctx.Blocks[name]; ok {
t.ctx.output.Nop(rb)
} else {
return "", nil
}
}
return "<\"'.", nil
},
"exec_block": func(name string) (string, error) {
if _, ok := t.ctx.Yields[name]; ok {
rb, e := t.ctx.exec(t.ctx.Yields[name], t.ctx.Dot)
t.ctx.output.Nop(rb)
return "<\"'.", e
} else if rb, ok := t.ctx.Blocks[name]; ok {
t.ctx.output.Nop(rb)
return "<\"'.", nil
} else {
return "", nil
}
},
"define_block": func(name string) string {
t.ctx.output.Open(name)
return "<\"'."
},
"end_block": func() string {
n, rb := t.ctx.output.Close()
if n == "" {
return ""
}
if _, ok := t.ctx.Blocks[n]; !ok {
if t.ctx.Yields[n] == "" {
t.ctx.Blocks[n] = rb
}
}
return ""
},
"extend": func(parent string) string {
t.ctx.output.NoRoot()
t.ctx.parent = parent
return ""
},
}
}
// Functions that are not tied to a context, but are part of the core
// multitemplate system
var StaticFuncs = template.FuncMap{
"fallback": func(s string) fallback {
return fallback(s)
},
}
// LoadedFuncs is the place to load functions to be loaded.
var LoadedFuncs = template.FuncMap{}