| // Copyright 2011 The Go Authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style | 
 | // license that can be found in the LICENSE file. | 
 |  | 
 | package template | 
 |  | 
 | import ( | 
 | 	"fmt" | 
 | 	"io" | 
 | 	"io/ioutil" | 
 | 	"path/filepath" | 
 | 	"sync" | 
 | 	"text/template" | 
 | 	"text/template/parse" | 
 | ) | 
 |  | 
 | // Template is a specialized Template from "text/template" that produces a safe | 
 | // HTML document fragment. | 
 | type Template struct { | 
 | 	// Sticky error if escaping fails, or escapeOK if succeeded. | 
 | 	escapeErr error | 
 | 	// We could embed the text/template field, but it's safer not to because | 
 | 	// we need to keep our version of the name space and the underlying | 
 | 	// template's in sync. | 
 | 	text *template.Template | 
 | 	// The underlying template's parse tree, updated to be HTML-safe. | 
 | 	Tree       *parse.Tree | 
 | 	*nameSpace // common to all associated templates | 
 | } | 
 |  | 
 | // escapeOK is a sentinel value used to indicate valid escaping. | 
 | var escapeOK = fmt.Errorf("template escaped correctly") | 
 |  | 
 | // nameSpace is the data structure shared by all templates in an association. | 
 | type nameSpace struct { | 
 | 	mu  sync.Mutex | 
 | 	set map[string]*Template | 
 | } | 
 |  | 
 | // Templates returns a slice of the templates associated with t, including t | 
 | // itself. | 
 | func (t *Template) Templates() []*Template { | 
 | 	ns := t.nameSpace | 
 | 	ns.mu.Lock() | 
 | 	defer ns.mu.Unlock() | 
 | 	// Return a slice so we don't expose the map. | 
 | 	m := make([]*Template, 0, len(ns.set)) | 
 | 	for _, v := range ns.set { | 
 | 		m = append(m, v) | 
 | 	} | 
 | 	return m | 
 | } | 
 |  | 
 | // Option sets options for the template. Options are described by | 
 | // strings, either a simple string or "key=value". There can be at | 
 | // most one equals sign in an option string. If the option string | 
 | // is unrecognized or otherwise invalid, Option panics. | 
 | // | 
 | // Known options: | 
 | // | 
 | // missingkey: Control the behavior during execution if a map is | 
 | // indexed with a key that is not present in the map. | 
 | //	"missingkey=default" or "missingkey=invalid" | 
 | //		The default behavior: Do nothing and continue execution. | 
 | //		If printed, the result of the index operation is the string | 
 | //		"<no value>". | 
 | //	"missingkey=zero" | 
 | //		The operation returns the zero value for the map type's element. | 
 | //	"missingkey=error" | 
 | //		Execution stops immediately with an error. | 
 | // | 
 | func (t *Template) Option(opt ...string) *Template { | 
 | 	t.text.Option(opt...) | 
 | 	return t | 
 | } | 
 |  | 
 | // escape escapes all associated templates. | 
 | func (t *Template) escape() error { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	if t.escapeErr == nil { | 
 | 		if t.Tree == nil { | 
 | 			return fmt.Errorf("template: %q is an incomplete or empty template%s", t.Name(), t.DefinedTemplates()) | 
 | 		} | 
 | 		if err := escapeTemplate(t, t.text.Root, t.Name()); err != nil { | 
 | 			return err | 
 | 		} | 
 | 	} else if t.escapeErr != escapeOK { | 
 | 		return t.escapeErr | 
 | 	} | 
 | 	return nil | 
 | } | 
 |  | 
 | // Execute applies a parsed template to the specified data object, | 
 | // writing the output to wr. | 
 | // If an error occurs executing the template or writing its output, | 
 | // execution stops, but partial results may already have been written to | 
 | // the output writer. | 
 | // A template may be executed safely in parallel. | 
 | func (t *Template) Execute(wr io.Writer, data interface{}) error { | 
 | 	if err := t.escape(); err != nil { | 
 | 		return err | 
 | 	} | 
 | 	return t.text.Execute(wr, data) | 
 | } | 
 |  | 
 | // ExecuteTemplate applies the template associated with t that has the given | 
 | // name to the specified data object and writes the output to wr. | 
 | // If an error occurs executing the template or writing its output, | 
 | // execution stops, but partial results may already have been written to | 
 | // the output writer. | 
 | // A template may be executed safely in parallel. | 
 | func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error { | 
 | 	tmpl, err := t.lookupAndEscapeTemplate(name) | 
 | 	if err != nil { | 
 | 		return err | 
 | 	} | 
 | 	return tmpl.text.Execute(wr, data) | 
 | } | 
 |  | 
 | // lookupAndEscapeTemplate guarantees that the template with the given name | 
 | // is escaped, or returns an error if it cannot be. It returns the named | 
 | // template. | 
 | func (t *Template) lookupAndEscapeTemplate(name string) (tmpl *Template, err error) { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	tmpl = t.set[name] | 
 | 	if tmpl == nil { | 
 | 		return nil, fmt.Errorf("html/template: %q is undefined", name) | 
 | 	} | 
 | 	if tmpl.escapeErr != nil && tmpl.escapeErr != escapeOK { | 
 | 		return nil, tmpl.escapeErr | 
 | 	} | 
 | 	if tmpl.text.Tree == nil || tmpl.text.Root == nil { | 
 | 		return nil, fmt.Errorf("html/template: %q is an incomplete template", name) | 
 | 	} | 
 | 	if t.text.Lookup(name) == nil { | 
 | 		panic("html/template internal error: template escaping out of sync") | 
 | 	} | 
 | 	if tmpl.escapeErr == nil { | 
 | 		err = escapeTemplate(tmpl, tmpl.text.Root, name) | 
 | 	} | 
 | 	return tmpl, err | 
 | } | 
 |  | 
 | // DefinedTemplates returns a string listing the defined templates, | 
 | // prefixed by the string "; defined templates are: ". If there are none, | 
 | // it returns the empty string. Used to generate an error message. | 
 | func (t *Template) DefinedTemplates() string { | 
 | 	return t.text.DefinedTemplates() | 
 | } | 
 |  | 
 | // Parse parses a string into a template. Nested template definitions | 
 | // will be associated with the top-level template t. Parse may be | 
 | // called multiple times to parse definitions of templates to associate | 
 | // with t. It is an error if a resulting template is non-empty (contains | 
 | // content other than template definitions) and would replace a | 
 | // non-empty template with the same name.  (In multiple calls to Parse | 
 | // with the same receiver template, only one call can contain text | 
 | // other than space, comments, and template definitions.) | 
 | func (t *Template) Parse(src string) (*Template, error) { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	t.escapeErr = nil | 
 | 	t.nameSpace.mu.Unlock() | 
 | 	ret, err := t.text.Parse(src) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	// In general, all the named templates might have changed underfoot. | 
 | 	// Regardless, some new ones may have been defined. | 
 | 	// The template.Template set has been updated; update ours. | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	for _, v := range ret.Templates() { | 
 | 		name := v.Name() | 
 | 		tmpl := t.set[name] | 
 | 		if tmpl == nil { | 
 | 			tmpl = t.new(name) | 
 | 		} else if tmpl.escapeErr != nil { | 
 | 			return nil, fmt.Errorf("html/template: cannot redefine %q after it has executed", name) | 
 | 		} | 
 | 		// Restore our record of this text/template to its unescaped original state. | 
 | 		tmpl.escapeErr = nil | 
 | 		tmpl.text = v | 
 | 		tmpl.Tree = v.Tree | 
 | 	} | 
 | 	return t, nil | 
 | } | 
 |  | 
 | // AddParseTree creates a new template with the name and parse tree | 
 | // and associates it with t. | 
 | // | 
 | // It returns an error if t has already been executed. | 
 | func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	if t.escapeErr != nil { | 
 | 		return nil, fmt.Errorf("html/template: cannot AddParseTree to %q after it has executed", t.Name()) | 
 | 	} | 
 | 	text, err := t.text.AddParseTree(name, tree) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	ret := &Template{ | 
 | 		nil, | 
 | 		text, | 
 | 		text.Tree, | 
 | 		t.nameSpace, | 
 | 	} | 
 | 	t.set[name] = ret | 
 | 	return ret, nil | 
 | } | 
 |  | 
 | // Clone returns a duplicate of the template, including all associated | 
 | // templates. The actual representation is not copied, but the name space of | 
 | // associated templates is, so further calls to Parse in the copy will add | 
 | // templates to the copy but not to the original. Clone can be used to prepare | 
 | // common templates and use them with variant definitions for other templates | 
 | // by adding the variants after the clone is made. | 
 | // | 
 | // It returns an error if t has already been executed. | 
 | func (t *Template) Clone() (*Template, error) { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	if t.escapeErr != nil { | 
 | 		return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name()) | 
 | 	} | 
 | 	textClone, err := t.text.Clone() | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	ret := &Template{ | 
 | 		nil, | 
 | 		textClone, | 
 | 		textClone.Tree, | 
 | 		&nameSpace{ | 
 | 			set: make(map[string]*Template), | 
 | 		}, | 
 | 	} | 
 | 	ret.set[ret.Name()] = ret | 
 | 	for _, x := range textClone.Templates() { | 
 | 		name := x.Name() | 
 | 		src := t.set[name] | 
 | 		if src == nil || src.escapeErr != nil { | 
 | 			return nil, fmt.Errorf("html/template: cannot Clone %q after it has executed", t.Name()) | 
 | 		} | 
 | 		x.Tree = x.Tree.Copy() | 
 | 		ret.set[name] = &Template{ | 
 | 			nil, | 
 | 			x, | 
 | 			x.Tree, | 
 | 			ret.nameSpace, | 
 | 		} | 
 | 	} | 
 | 	return ret, nil | 
 | } | 
 |  | 
 | // New allocates a new HTML template with the given name. | 
 | func New(name string) *Template { | 
 | 	tmpl := &Template{ | 
 | 		nil, | 
 | 		template.New(name), | 
 | 		nil, | 
 | 		&nameSpace{ | 
 | 			set: make(map[string]*Template), | 
 | 		}, | 
 | 	} | 
 | 	tmpl.set[name] = tmpl | 
 | 	return tmpl | 
 | } | 
 |  | 
 | // New allocates a new HTML template associated with the given one | 
 | // and with the same delimiters. The association, which is transitive, | 
 | // allows one template to invoke another with a {{template}} action. | 
 | func (t *Template) New(name string) *Template { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	return t.new(name) | 
 | } | 
 |  | 
 | // new is the implementation of New, without the lock. | 
 | func (t *Template) new(name string) *Template { | 
 | 	tmpl := &Template{ | 
 | 		nil, | 
 | 		t.text.New(name), | 
 | 		nil, | 
 | 		t.nameSpace, | 
 | 	} | 
 | 	tmpl.set[name] = tmpl | 
 | 	return tmpl | 
 | } | 
 |  | 
 | // Name returns the name of the template. | 
 | func (t *Template) Name() string { | 
 | 	return t.text.Name() | 
 | } | 
 |  | 
 | // FuncMap is the type of the map defining the mapping from names to | 
 | // functions. Each function must have either a single return value, or two | 
 | // return values of which the second has type error. In that case, if the | 
 | // second (error) argument evaluates to non-nil during execution, execution | 
 | // terminates and Execute returns that error. FuncMap has the same base type | 
 | // as FuncMap in "text/template", copied here so clients need not import | 
 | // "text/template". | 
 | type FuncMap map[string]interface{} | 
 |  | 
 | // Funcs adds the elements of the argument map to the template's function map. | 
 | // It panics if a value in the map is not a function with appropriate return | 
 | // type. However, it is legal to overwrite elements of the map. The return | 
 | // value is the template, so calls can be chained. | 
 | func (t *Template) Funcs(funcMap FuncMap) *Template { | 
 | 	t.text.Funcs(template.FuncMap(funcMap)) | 
 | 	return t | 
 | } | 
 |  | 
 | // Delims sets the action delimiters to the specified strings, to be used in | 
 | // subsequent calls to Parse, ParseFiles, or ParseGlob. Nested template | 
 | // definitions will inherit the settings. An empty delimiter stands for the | 
 | // corresponding default: {{ or }}. | 
 | // The return value is the template, so calls can be chained. | 
 | func (t *Template) Delims(left, right string) *Template { | 
 | 	t.text.Delims(left, right) | 
 | 	return t | 
 | } | 
 |  | 
 | // Lookup returns the template with the given name that is associated with t, | 
 | // or nil if there is no such template. | 
 | func (t *Template) Lookup(name string) *Template { | 
 | 	t.nameSpace.mu.Lock() | 
 | 	defer t.nameSpace.mu.Unlock() | 
 | 	return t.set[name] | 
 | } | 
 |  | 
 | // Must is a helper that wraps a call to a function returning (*Template, error) | 
 | // and panics if the error is non-nil. It is intended for use in variable initializations | 
 | // such as | 
 | //	var t = template.Must(template.New("name").Parse("html")) | 
 | func Must(t *Template, err error) *Template { | 
 | 	if err != nil { | 
 | 		panic(err) | 
 | 	} | 
 | 	return t | 
 | } | 
 |  | 
 | // ParseFiles creates a new Template and parses the template definitions from | 
 | // the named files. The returned template's name will have the (base) name and | 
 | // (parsed) contents of the first file. There must be at least one file. | 
 | // If an error occurs, parsing stops and the returned *Template is nil. | 
 | func ParseFiles(filenames ...string) (*Template, error) { | 
 | 	return parseFiles(nil, filenames...) | 
 | } | 
 |  | 
 | // ParseFiles parses the named files and associates the resulting templates with | 
 | // t. If an error occurs, parsing stops and the returned template is nil; | 
 | // otherwise it is t. There must be at least one file. | 
 | func (t *Template) ParseFiles(filenames ...string) (*Template, error) { | 
 | 	return parseFiles(t, filenames...) | 
 | } | 
 |  | 
 | // parseFiles is the helper for the method and function. If the argument | 
 | // template is nil, it is created from the first file. | 
 | func parseFiles(t *Template, filenames ...string) (*Template, error) { | 
 | 	if len(filenames) == 0 { | 
 | 		// Not really a problem, but be consistent. | 
 | 		return nil, fmt.Errorf("html/template: no files named in call to ParseFiles") | 
 | 	} | 
 | 	for _, filename := range filenames { | 
 | 		b, err := ioutil.ReadFile(filename) | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 		s := string(b) | 
 | 		name := filepath.Base(filename) | 
 | 		// First template becomes return value if not already defined, | 
 | 		// and we use that one for subsequent New calls to associate | 
 | 		// all the templates together. Also, if this file has the same name | 
 | 		// as t, this file becomes the contents of t, so | 
 | 		//  t, err := New(name).Funcs(xxx).ParseFiles(name) | 
 | 		// works. Otherwise we create a new template associated with t. | 
 | 		var tmpl *Template | 
 | 		if t == nil { | 
 | 			t = New(name) | 
 | 		} | 
 | 		if name == t.Name() { | 
 | 			tmpl = t | 
 | 		} else { | 
 | 			tmpl = t.New(name) | 
 | 		} | 
 | 		_, err = tmpl.Parse(s) | 
 | 		if err != nil { | 
 | 			return nil, err | 
 | 		} | 
 | 	} | 
 | 	return t, nil | 
 | } | 
 |  | 
 | // ParseGlob creates a new Template and parses the template definitions from the | 
 | // files identified by the pattern, which must match at least one file. The | 
 | // returned template will have the (base) name and (parsed) contents of the | 
 | // first file matched by the pattern. ParseGlob is equivalent to calling | 
 | // ParseFiles with the list of files matched by the pattern. | 
 | func ParseGlob(pattern string) (*Template, error) { | 
 | 	return parseGlob(nil, pattern) | 
 | } | 
 |  | 
 | // ParseGlob parses the template definitions in the files identified by the | 
 | // pattern and associates the resulting templates with t. The pattern is | 
 | // processed by filepath.Glob and must match at least one file. ParseGlob is | 
 | // equivalent to calling t.ParseFiles with the list of files matched by the | 
 | // pattern. | 
 | func (t *Template) ParseGlob(pattern string) (*Template, error) { | 
 | 	return parseGlob(t, pattern) | 
 | } | 
 |  | 
 | // parseGlob is the implementation of the function and method ParseGlob. | 
 | func parseGlob(t *Template, pattern string) (*Template, error) { | 
 | 	filenames, err := filepath.Glob(pattern) | 
 | 	if err != nil { | 
 | 		return nil, err | 
 | 	} | 
 | 	if len(filenames) == 0 { | 
 | 		return nil, fmt.Errorf("html/template: pattern matches no files: %#q", pattern) | 
 | 	} | 
 | 	return parseFiles(t, filenames...) | 
 | } | 
 |  | 
 | // IsTrue reports whether the value is 'true', in the sense of not the zero of its type, | 
 | // and whether the value has a meaningful truth value. This is the definition of | 
 | // truth used by if and other such actions. | 
 | func IsTrue(val interface{}) (truth, ok bool) { | 
 | 	return template.IsTrue(val) | 
 | } |