// escapeTree escapes the named template starting in the given context as // necessary and returns its output context. func (e *escaper) escapeTree(c context, node parse.Node, name string, line int) (context, string) { // Mangle the template name with the input context to produce a reliable // identifier. dname := c.mangle(name) e.called[dname] = true if out, ok := e.output[dname]; ok { // Already escaped. return out, dname } t := e.template(name) if t == nil { // Two cases: The template exists but is empty, or has never been mentioned at // all. Distinguish the cases in the error messages. if e.tmpl.set[name] != nil { return context{ state: stateError, err: errorf(ErrNoSuchTemplate, node, line, "%q is an incomplete or empty template", name), }, dname } return context{}, dname } if dname != name { // Use any template derived during an earlier call to escapeTemplate // with different top level templates, or clone if necessary. dt := e.template(dname) if dt == nil { dt = template.New(dname) dt.Tree = &parse.Tree{Name: dname, Root: t.Root.CopyList()} e.derived[dname] = dt } t = dt } return e.computeOutCtx(c, t), dname }
func ExampleTemplate() { // Define a template. const letter = ` Dear {{.Name}}, {{if .Attended}} It was a pleasure to see you at the wedding.{{else}} It is a shame you couldn't make it to the wedding.{{end}} {{with .Gift}}Thank you for the lovely {{.}}. {{end}} Best wishes, Josie ` // Prepare some data to insert into the template. type Recipient struct { Name, Gift string Attended bool } var recipients = []Recipient{ {"Aunt Mildred", "bone china tea set", true}, {"Uncle John", "moleskin pants", false}, {"Cousin Rodney", "", false}, } // Create a new template and parse the letter into it. t := template.Must(template.New("letter").Parse(letter)) // Execute the template for each recipient. for _, r := range recipients { err := t.Execute(os.Stdout, r) if err != nil { log.Println("executing template:", err) } } // Output: // Dear Aunt Mildred, // // It was a pleasure to see you at the wedding. // Thank you for the lovely bone china tea set. // // Best wishes, // Josie // // Dear Uncle John, // // It is a shame you couldn't make it to the wedding. // Thank you for the lovely moleskin pants. // // Best wishes, // Josie // // Dear Cousin Rodney, // // It is a shame you couldn't make it to the wedding. // // Best wishes, // Josie }
// 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 }
// This example demonstrates a custom function to process template text. // It installs the strings.Title function and uses it to // Make Title Text Look Good In Our Template's Output. func ExampleTemplate_func() { // First we create a FuncMap with which to register the function. funcMap := template.FuncMap{ // The name "title" is what the function will be called in the template text. "title": strings.Title, } // A simple template definition to test our function. // We print the input text several ways: // - the original // - title-cased // - title-cased and then printed with %q // - printed with %q and then title-cased. const templateText = ` Input: {{printf "%q" .}} Output 0: {{title .}} Output 1: {{title . | printf "%q"}} Output 2: {{printf "%q" . | title}} ` // Create a template, add the function map, and parse the text. tmpl, err := template.New("titleTest").Funcs(funcMap).Parse(templateText) if err != nil { log.Fatalf("parsing: %s", err) } // Run the template to verify the output. err = tmpl.Execute(os.Stdout, "the go programming language") if err != nil { log.Fatalf("execution: %s", err) } // Output: // Input: "the go programming language" // Output 0: The Go Programming Language // Output 1: "The Go Programming Language" // Output 2: "The Go Programming Language" }
func TestEnsurePipelineContains(t *testing.T) { tests := []struct { input, output string ids []string }{ { "{{.X}}", ".X", []string{}, }, { "{{.X | html}}", ".X | html", []string{}, }, { "{{.X}}", ".X | html", []string{"html"}, }, { "{{.X | html}}", ".X | html | urlquery", []string{"urlquery"}, }, { "{{.X | html | urlquery}}", ".X | html | urlquery", []string{"urlquery"}, }, { "{{.X | html | urlquery}}", ".X | html | urlquery", []string{"html", "urlquery"}, }, { "{{.X | html | urlquery}}", ".X | html | urlquery", []string{"html"}, }, { "{{.X | urlquery}}", ".X | html | urlquery", []string{"html", "urlquery"}, }, { "{{.X | html | print}}", ".X | urlquery | html | print", []string{"urlquery", "html"}, }, { "{{($).X | html | print}}", "($).X | urlquery | html | print", []string{"urlquery", "html"}, }, { "{{.X | print 2 | .f 3}}", ".X | print 2 | .f 3 | urlquery | html", []string{"urlquery", "html"}, }, { "{{.X | html | print 2 | .f 3}}", ".X | urlquery | html | print 2 | .f 3", []string{"urlquery", "html"}, }, { // covering issue 10801 "{{.X | js.x }}", ".X | js.x | urlquery | html", []string{"urlquery", "html"}, }, { // covering issue 10801 "{{.X | (print 12 | js).x }}", ".X | (print 12 | js).x | urlquery | html", []string{"urlquery", "html"}, }, } for i, test := range tests { tmpl := template.Must(template.New("test").Parse(test.input)) action, ok := (tmpl.Tree.Root.Nodes[0].(*parse.ActionNode)) if !ok { t.Errorf("#%d: First node is not an action: %s", i, test.input) continue } pipe := action.Pipe ensurePipelineContains(pipe, test.ids) got := pipe.String() if got != test.output { t.Errorf("#%d: %s, %v: want\n\t%s\ngot\n\t%s", i, test.input, test.ids, test.output, got) } } }