1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package template 6 7 import ( 8 "fmt" 9 "reflect" 10 "sync" 11 "text/template/parse" 12 ) 13 14 // common holds the information shared by related templates. 15 type common struct { 16 tmpl map[string]*Template // Map from name to defined templates. 17 option option 18 // We use two maps, one for parsing and one for execution. 19 // This separation makes the API cleaner since it doesn't 20 // expose reflection to the client. 21 muFuncs sync.RWMutex // protects parseFuncs and execFuncs 22 parseFuncs FuncMap 23 execFuncs map[string]reflect.Value 24 } 25 26 // Template is the representation of a parsed template. The *parse.Tree 27 // field is exported only for use by html/template and should be treated 28 // as unexported by all other clients. 29 type Template struct { 30 name string 31 *parse.Tree 32 *common 33 leftDelim string 34 rightDelim string 35 } 36 37 // New allocates a new, undefined template with the given name. 38 func New(name string) *Template { 39 t := &Template{ 40 name: name, 41 } 42 t.init() 43 return t 44 } 45 46 // Name returns the name of the template. 47 func (t *Template) Name() string { 48 return t.name 49 } 50 51 // New allocates a new, undefined template associated with the given one and with the same 52 // delimiters. The association, which is transitive, allows one template to 53 // invoke another with a {{template}} action. 54 func (t *Template) New(name string) *Template { 55 t.init() 56 nt := &Template{ 57 name: name, 58 common: t.common, 59 leftDelim: t.leftDelim, 60 rightDelim: t.rightDelim, 61 } 62 return nt 63 } 64 65 // init guarantees that t has a valid common structure. 66 func (t *Template) init() { 67 if t.common == nil { 68 c := new(common) 69 c.tmpl = make(map[string]*Template) 70 c.parseFuncs = make(FuncMap) 71 c.execFuncs = make(map[string]reflect.Value) 72 t.common = c 73 } 74 } 75 76 // Clone returns a duplicate of the template, including all associated 77 // templates. The actual representation is not copied, but the name space of 78 // associated templates is, so further calls to Parse in the copy will add 79 // templates to the copy but not to the original. Clone can be used to prepare 80 // common templates and use them with variant definitions for other templates 81 // by adding the variants after the clone is made. 82 func (t *Template) Clone() (*Template, error) { 83 nt := t.copy(nil) 84 nt.init() 85 if t.common == nil { 86 return nt, nil 87 } 88 for k, v := range t.tmpl { 89 if k == t.name { 90 nt.tmpl[t.name] = nt 91 continue 92 } 93 // The associated templates share nt's common structure. 94 tmpl := v.copy(nt.common) 95 nt.tmpl[k] = tmpl 96 } 97 t.muFuncs.RLock() 98 defer t.muFuncs.RUnlock() 99 for k, v := range t.parseFuncs { 100 nt.parseFuncs[k] = v 101 } 102 for k, v := range t.execFuncs { 103 nt.execFuncs[k] = v 104 } 105 return nt, nil 106 } 107 108 // copy returns a shallow copy of t, with common set to the argument. 109 func (t *Template) copy(c *common) *Template { 110 nt := New(t.name) 111 nt.Tree = t.Tree 112 nt.common = c 113 nt.leftDelim = t.leftDelim 114 nt.rightDelim = t.rightDelim 115 return nt 116 } 117 118 // AddParseTree adds parse tree for template with given name and associates it with t. 119 // If the template does not already exist, it will create a new one. 120 // It is an error to reuse a name except to overwrite an empty template. 121 func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { 122 t.init() 123 // If the name is the name of this template, overwrite this template. 124 // The associate method checks it's not a redefinition. 125 nt := t 126 if name != t.name { 127 nt = t.New(name) 128 } 129 // Even if nt == t, we need to install it in the common.tmpl map. 130 if replace, err := t.associate(nt, tree); err != nil { 131 return nil, err 132 } else if replace { 133 nt.Tree = tree 134 } 135 return nt, nil 136 } 137 138 // Templates returns a slice of defined templates associated with t. 139 func (t *Template) Templates() []*Template { 140 if t.common == nil { 141 return nil 142 } 143 // Return a slice so we don't expose the map. 144 m := make([]*Template, 0, len(t.tmpl)) 145 for _, v := range t.tmpl { 146 m = append(m, v) 147 } 148 return m 149 } 150 151 // Delims sets the action delimiters to the specified strings, to be used in 152 // subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template 153 // definitions will inherit the settings. An empty delimiter stands for the 154 // corresponding default: {{ or }}. 155 // The return value is the template, so calls can be chained. 156 func (t *Template) Delims(left, right string) *Template { 157 t.init() 158 t.leftDelim = left 159 t.rightDelim = right 160 return t 161 } 162 163 // Funcs adds the elements of the argument map to the template's function map. 164 // It panics if a value in the map is not a function with appropriate return 165 // type. However, it is legal to overwrite elements of the map. The return 166 // value is the template, so calls can be chained. 167 func (t *Template) Funcs(funcMap FuncMap) *Template { 168 t.init() 169 t.muFuncs.Lock() 170 defer t.muFuncs.Unlock() 171 addValueFuncs(t.execFuncs, funcMap) 172 addFuncs(t.parseFuncs, funcMap) 173 return t 174 } 175 176 // Lookup returns the template with the given name that is associated with t. 177 // It returns nil if there is no such template or the template has no definition. 178 func (t *Template) Lookup(name string) *Template { 179 if t.common == nil { 180 return nil 181 } 182 return t.tmpl[name] 183 } 184 185 // Parse defines the template by parsing the text. Nested template definitions will be 186 // associated with the top-level template t. Parse may be called multiple times 187 // to parse definitions of templates to associate with t. It is an error if a 188 // resulting template is non-empty (contains content other than template 189 // definitions) and would replace a non-empty template with the same name. 190 // (In multiple calls to Parse with the same receiver template, only one call 191 // can contain text other than space, comments, and template definitions.) 192 func (t *Template) Parse(text string) (*Template, error) { 193 t.init() 194 t.muFuncs.RLock() 195 trees, err := parse.Parse(t.name, text, t.leftDelim, t.rightDelim, t.parseFuncs, builtins) 196 t.muFuncs.RUnlock() 197 if err != nil { 198 return nil, err 199 } 200 // Add the newly parsed trees, including the one for t, into our common structure. 201 for name, tree := range trees { 202 if _, err := t.AddParseTree(name, tree); err != nil { 203 return nil, err 204 } 205 } 206 return t, nil 207 } 208 209 // associate installs the new template into the group of templates associated 210 // with t. It is an error to reuse a name except to overwrite an empty 211 // template. The two are already known to share the common structure. 212 // The boolean return value reports wither to store this tree as t.Tree. 213 func (t *Template) associate(new *Template, tree *parse.Tree) (bool, error) { 214 if new.common != t.common { 215 panic("internal error: associate not common") 216 } 217 name := new.name 218 if old := t.tmpl[name]; old != nil { 219 oldIsEmpty := parse.IsEmptyTree(old.Root) 220 newIsEmpty := parse.IsEmptyTree(tree.Root) 221 if newIsEmpty { 222 // Whether old is empty or not, new is empty; no reason to replace old. 223 return false, nil 224 } 225 if !oldIsEmpty { 226 return false, fmt.Errorf("template: redefinition of template %q", name) 227 } 228 } 229 t.tmpl[name] = new 230 return true, nil 231 } 232