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
5package template
6
7import (
8	"fmt"
9	"io"
10	"io/ioutil"
11	"path/filepath"
12	"sync"
13	"text/template"
14	"text/template/parse"
15)
16
17// Template is a specialized Template from "text/template" that produces a safe
18// HTML document fragment.
19type Template struct {
20	// Sticky error if escaping fails, or escapeOK if succeeded.
21	escapeErr error
22	// We could embed the text/template field, but it's safer not to because
23	// we need to keep our version of the name space and the underlying
24	// template's in sync.
25	text *template.Template
26	// The underlying template's parse tree, updated to be HTML-safe.
27	Tree       *parse.Tree
28	*nameSpace // common to all associated templates
29}
30
31// escapeOK is a sentinel value used to indicate valid escaping.
32var escapeOK = fmt.Errorf("template escaped correctly")
33
34// nameSpace is the data structure shared by all templates in an association.
35type nameSpace struct {
36	mu      sync.Mutex
37	set     map[string]*Template
38	escaped bool
39	esc     escaper
40}
41
42// Templates returns a slice of the templates associated with t, including t
43// itself.
44func (t *Template) Templates() []*Template {
45	ns := t.nameSpace
46	ns.mu.Lock()
47	defer ns.mu.Unlock()
48	// Return a slice so we don't expose the map.
49	m := make([]*Template, 0, len(ns.set))
50	for _, v := range ns.set {
51		m = append(m, v)
52	}
53	return m
54}
55
56// Option sets options for the template. Options are described by
57// strings, either a simple string or "key=value". There can be at
58// most one equals sign in an option string. If the option string
59// is unrecognized or otherwise invalid, Option panics.
60//
61// Known options:
62//
63// missingkey: Control the behavior during execution if a map is
64// indexed with a key that is not present in the map.
65//	"missingkey=default" or "missingkey=invalid"
66//		The default behavior: Do nothing and continue execution.
67//		If printed, the result of the index operation is the string
68//		"<no value>".
69//	"missingkey=zero"
70//		The operation returns the zero value for the map type's element.
71//	"missingkey=error"
72//		Execution stops immediately with an error.
73//
74func (t *Template) Option(opt ...string) *Template {
75	t.text.Option(opt...)
76	return t
77}
78
79// checkCanParse checks whether it is OK to parse templates.
80// If not, it returns an error.
81func (t *Template) checkCanParse() error {
82	if t == nil {
83		return nil
84	}
85	t.nameSpace.mu.Lock()
86	defer t.nameSpace.mu.Unlock()
87	if t.nameSpace.escaped {
88		return fmt.Errorf("html/template: cannot Parse after Execute")
89	}
90	return nil
91}
92
93// escape escapes all associated templates.
94func (t *Template) escape() error {
95	t.nameSpace.mu.Lock()
96	defer t.nameSpace.mu.Unlock()
97	t.nameSpace.escaped = true
98	if t.escapeErr == nil {
99		if t.Tree == nil {
100			return fmt.Errorf("template: %q is an incomplete or empty template", t.Name())
101		}
102		if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil {
103			return err
104		}
105	} else if t.escapeErr != escapeOK {
106		return t.escapeErr
107	}
108	return nil
109}
110
111// Execute applies a parsed template to the specified data object,
112// writing the output to wr.
113// If an error occurs executing the template or writing its output,
114// execution stops, but partial results may already have been written to
115// the output writer.
116// A template may be executed safely in parallel, although if parallel
117// executions share a Writer the output may be interleaved.
118func (t *Template) Execute(wr io.Writer, data interface{}) error {
119	if err := t.escape(); err != nil {
120		return err
121	}
122	return t.text.Execute(wr, data)
123}
124
125// ExecuteTemplate applies the template associated with t that has the given
126// name to the specified data object and writes the output to wr.
127// If an error occurs executing the template or writing its output,
128// execution stops, but partial results may already have been written to
129// the output writer.
130// A template may be executed safely in parallel, although if parallel
131// executions share a Writer the output may be interleaved.
132func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error {
133	tmpl, err := t.lookupAndEscapeTemplate(name)
134	if err != nil {
135		return err
136	}
137	return tmpl.text.Execute(wr, data)
138}
139
140// lookupAndEscapeTemplate guarantees that the template with the given name
141// is escaped, or returns an error if it cannot be. It returns the named
142// template.
143func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) {
144	t.nameSpace.mu.Lock()
145	defer t.nameSpace.mu.Unlock()
146	t.nameSpace.escaped = true
147	tmpl = t.set[name]
148	if tmpl == nil {
149		return nil, fmt.Errorf("html/template: %q is undefined", name)
150	}
151	if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK {
152		return nil, tmpl.escapeErr
153	}
154	if tmpl.text.Tree == nil || tmpl.text.Root == nil {
155		return nil, fmt.Errorf("html/template: %q is an incomplete template", name)
156	}
157	if t.text.Lookup(name) == nil {
158		panic("html/template internal error: template escaping out of sync")
159	}
160	if tmpl.escapeErr == nil {
161		err = escapeTemplate(tmpl, tmpl.text.Root, name)
162	}
163	return tmpl, err
164}
165
166// DefinedTemplates returns a string listing the defined templates,
167// prefixed by the string "; defined templates are: ". If there are none,
168// it returns the empty string. Used to generate an error message.
169func (t *Template) DefinedTemplates() string {
170	return t.text.DefinedTemplates()
171}
172
173// Parse parses text as a template body for t.
174// Named template definitions ({{define ...}} or {{block ...}} statements) in text
175// define additional templates associated with t and are removed from the
176// definition of t itself.
177//
178// Templates can be redefined in successive calls to Parse,
179// before the first use of Execute on t or any associated template.
180// A template definition with a body containing only white space and comments
181// is considered empty and will not replace an existing template's body.
182// This allows using Parse to add new named template definitions without
183// overwriting the main template body.
184func (t *Template) Parse(text string) (*Template, error) {
185	if err := t.checkCanParse(); err != nil {
186		return nil, err
187	}
188
189	ret, err := t.text.Parse(text)
190	if err != nil {
191		return nil, err
192	}
193
194	// In general, all the named templates might have changed underfoot.
195	// Regardless, some new ones may have been defined.
196	// The template.Template set has been updated; update ours.
197	t.nameSpace.mu.Lock()
198	defer t.nameSpace.mu.Unlock()
199	for _, v := range ret.Templates() {
200		name := v.Name()
201		tmpl := t.set[name]
202		if tmpl == nil {
203			tmpl = t.new(name)
204		}
205		tmpl.text = v
206		tmpl.Tree = v.Tree
207	}
208	return t, nil
209}
210
211// AddParseTree creates a new template with the name and parse tree
212// and associates it with t.
213//
214// It returns an error if t or any associated template has already been executed.
215func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
216	if err := t.checkCanParse(); err != nil {
217		return nil, err
218	}
219
220	t.nameSpace.mu.Lock()
221	defer t.nameSpace.mu.Unlock()
222	text, err := t.text.AddParseTree(name, tree)
223	if err != nil {
224		return nil, err
225	}
226	ret := &Template{
227		nil,
228		text,
229		text.Tree,
230		t.nameSpace,
231	}
232	t.set[name] = ret
233	return ret, nil
234}
235
236// Clone returns a duplicate of the template, including all associated
237// templates. The actual representation is not copied, but the name space of
238// associated templates is, so further calls to Parse in the copy will add
239// templates to the copy but not to the original. Clone can be used to prepare
240// common templates and use them with variant definitions for other templates
241// by adding the variants after the clone is made.
242//
243// It returns an error if t has already been executed.
244func (t *Template) Clone() (*Template, error) {
245	t.nameSpace.mu.Lock()
246	defer t.nameSpace.mu.Unlock()
247	if t.escapeErr != nil {
248		return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
249	}
250	textClone, err := t.text.Clone()
251	if err != nil {
252		return nil, err
253	}
254	ns := &nameSpace{set: make(map[string]*Template)}
255	ns.esc = makeEscaper(ns)
256	ret := &Template{
257		nil,
258		textClone,
259		textClone.Tree,
260		ns,
261	}
262	ret.set[ret.Name()] = ret
263	for _, x := range textClone.Templates() {
264		name := x.Name()
265		src := t.set[name]
266		if src == nil || src.escapeErr != nil {
267			return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name())
268		}
269		x.Tree = x.Tree.Copy()
270		ret.set[name] = &Template{
271			nil,
272			x,
273			x.Tree,
274			ret.nameSpace,
275		}
276	}
277	// Return the template associated with the name of this template.
278	return ret.set[ret.Name()], nil
279}
280
281// New allocates a new HTML template with the given name.
282func New(name string) *Template {
283	ns := &nameSpace{set: make(map[string]*Template)}
284	ns.esc = makeEscaper(ns)
285	tmpl := &Template{
286		nil,
287		template.New(name),
288		nil,
289		ns,
290	}
291	tmpl.set[name] = tmpl
292	return tmpl
293}
294
295// New allocates a new HTML template associated with the given one
296// and with the same delimiters. The association, which is transitive,
297// allows one template to invoke another with a {{template}} action.
298//
299// If a template with the given name already exists, the new HTML template
300// will replace it. The existing template will be reset and disassociated with
301// t.
302func (t *Template) New(name string) *Template {
303	t.nameSpace.mu.Lock()
304	defer t.nameSpace.mu.Unlock()
305	return t.new(name)
306}
307
308// new is the implementation of New, without the lock.
309func (t *Template) new(name string) *Template {
310	tmpl := &Template{
311		nil,
312		t.text.New(name),
313		nil,
314		t.nameSpace,
315	}
316	if existing, ok := tmpl.set[name]; ok {
317		emptyTmpl := New(existing.Name())
318		*existing = *emptyTmpl
319	}
320	tmpl.set[name] = tmpl
321	return tmpl
322}
323
324// Name returns the name of the template.
325func (t *Template) Name() string {
326	return t.text.Name()
327}
328
329// FuncMap is the type of the map defining the mapping from names to
330// functions. Each function must have either a single return value, or two
331// return values of which the second has type error. In that case, if the
332// second (error) argument evaluates to non-nil during execution, execution
333// terminates and Execute returns that error. FuncMap has the same base type
334// as FuncMap in "text/template", copied here so clients need not import
335// "text/template".
336type FuncMap map[string]interface{}
337
338// Funcs adds the elements of the argument map to the template's function map.
339// It must be called before the template is parsed.
340// It panics if a value in the map is not a function with appropriate return
341// type. However, it is legal to overwrite elements of the map. The return
342// value is the template, so calls can be chained.
343func (t *Template) Funcs(funcMap FuncMap) *Template {
344	t.text.Funcs(template.FuncMap(funcMap))
345	return t
346}
347
348// Delims sets the action delimiters to the specified strings, to be used in
349// subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template
350// definitions will inherit the settings. An empty delimiter stands for the
351// corresponding default: {{ or }}.
352// The return value is the template, so calls can be chained.
353func (t *Template) Delims(left, right string) *Template {
354	t.text.Delims(left, right)
355	return t
356}
357
358// Lookup returns the template with the given name that is associated with t,
359// or nil if there is no such template.
360func (t *Template) Lookup(name string) *Template {
361	t.nameSpace.mu.Lock()
362	defer t.nameSpace.mu.Unlock()
363	return t.set[name]
364}
365
366// Must is a helper that wraps a call to a function returning (*Template, error)
367// and panics if the error is non-nil. It is intended for use in variable initializations
368// such as
369//	var t = template.Must(template.New("name").Parse("html"))
370func Must(t *Template, err error) *Template {
371	if err != nil {
372		panic(err)
373	}
374	return t
375}
376
377// ParseFiles creates a new Template and parses the template definitions from
378// the named files. The returned template's name will have the (base) name and
379// (parsed) contents of the first file. There must be at least one file.
380// If an error occurs, parsing stops and the returned *Template is nil.
381//
382// When parsing multiple files with the same name in different directories,
383// the last one mentioned will be the one that results.
384// For instance, ParseFiles("a/foo", "b/foo") stores "b/foo" as the template
385// named "foo", while "a/foo" is unavailable.
386func ParseFiles(filenames ...string) (*Template, error) {
387	return parseFiles(nil, filenames...)
388}
389
390// ParseFiles parses the named files and associates the resulting templates with
391// t. If an error occurs, parsing stops and the returned template is nil;
392// otherwise it is t. There must be at least one file.
393//
394// When parsing multiple files with the same name in different directories,
395// the last one mentioned will be the one that results.
396//
397// ParseFiles returns an error if t or any associated template has already been executed.
398func (t *Template) ParseFiles(filenames ...string) (*Template, error) {
399	return parseFiles(t, filenames...)
400}
401
402// parseFiles is the helper for the method and function. If the argument
403// template is nil, it is created from the first file.
404func parseFiles(t *Template, filenames ...string) (*Template, error) {
405	if err := t.checkCanParse(); err != nil {
406		return nil, err
407	}
408
409	if len(filenames) == 0 {
410		// Not really a problem, but be consistent.
411		return nil, fmt.Errorf("html/template: no files named in call to ParseFiles")
412	}
413	for _, filename := range filenames {
414		b, err := ioutil.ReadFile(filename)
415		if err != nil {
416			return nil, err
417		}
418		s := string(b)
419		name := filepath.Base(filename)
420		// First template becomes return value if not already defined,
421		// and we use that one for subsequent New calls to associate
422		// all the templates together. Also, if this file has the same name
423		// as t, this file becomes the contents of t, so
424		//  t, err := New(name).Funcs(xxx).ParseFiles(name)
425		// works. Otherwise we create a new template associated with t.
426		var tmpl *Template
427		if t == nil {
428			t = New(name)
429		}
430		if name == t.Name() {
431			tmpl = t
432		} else {
433			tmpl = t.New(name)
434		}
435		_, err = tmpl.Parse(s)
436		if err != nil {
437			return nil, err
438		}
439	}
440	return t, nil
441}
442
443// ParseGlob creates a new Template and parses the template definitions from the
444// files identified by the pattern, which must match at least one file. The
445// returned template will have the (base) name and (parsed) contents of the
446// first file matched by the pattern. ParseGlob is equivalent to calling
447// ParseFiles with the list of files matched by the pattern.
448//
449// When parsing multiple files with the same name in different directories,
450// the last one mentioned will be the one that results.
451func ParseGlob(pattern string) (*Template, error) {
452	return parseGlob(nil, pattern)
453}
454
455// ParseGlob parses the template definitions in the files identified by the
456// pattern and associates the resulting templates with t. The pattern is
457// processed by filepath.Glob and must match at least one file. ParseGlob is
458// equivalent to calling t.ParseFiles with the list of files matched by the
459// pattern.
460//
461// When parsing multiple files with the same name in different directories,
462// the last one mentioned will be the one that results.
463//
464// ParseGlob returns an error if t or any associated template has already been executed.
465func (t *Template) ParseGlob(pattern string) (*Template, error) {
466	return parseGlob(t, pattern)
467}
468
469// parseGlob is the implementation of the function and method ParseGlob.
470func parseGlob(t *Template, pattern string) (*Template, error) {
471	if err := t.checkCanParse(); err != nil {
472		return nil, err
473	}
474	filenames, err := filepath.Glob(pattern)
475	if err != nil {
476		return nil, err
477	}
478	if len(filenames) == 0 {
479		return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern)
480	}
481	return parseFiles(t, filenames...)
482}
483
484// IsTrue reports whether the value is 'true', in the sense of not the zero of its type,
485// and whether the value has a meaningful truth value. This is the definition of
486// truth used by if and other such actions.
487func IsTrue(val interface{}) (truth, ok bool) {
488	return template.IsTrue(val)
489}
490