Commit d38cc47c authored by Rob Pike's avatar Rob Pike

text/template: replace Add with AddParseTree

Makes it clear we're adding exactly one tree and creating a
new template for it.

R=rsc
CC=golang-dev
https://golang.org/cl/5448077
parent 6bee4e55
...@@ -720,7 +720,9 @@ func (e *escaper) commit() { ...@@ -720,7 +720,9 @@ func (e *escaper) commit() {
e.template(name).Funcs(funcMap) e.template(name).Funcs(funcMap)
} }
for _, t := range e.derived { for _, t := range e.derived {
e.tmpl.text.Add(t) if _, err := e.tmpl.text.AddParseTree(t.Name(), t.Tree); err != nil {
panic("error adding derived template")
}
} }
for n, s := range e.actionNodeEdits { for n, s := range e.actionNodeEdits {
ensurePipelineContains(n.Pipe, s) ensurePipelineContains(n.Pipe, s)
......
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"text/template" "text/template"
"text/template/parse"
) )
// Template is a specialized template.Template that produces a safe HTML // Template is a specialized template.Template that produces a safe HTML
...@@ -65,10 +66,14 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) ...@@ -65,10 +66,14 @@ func (t *Template) ExecuteTemplate(wr io.Writer, name string, data interface{})
return tmpl.text.ExecuteTemplate(wr, name, data) return tmpl.text.ExecuteTemplate(wr, name, data)
} }
// Parse parses a string into a set of named templates. Parse may be called // Parse parses a string into a template. Nested template definitions
// multiple times for a given set, adding the templates defined in the string // will be associated with the top-level template t. Parse may be
// to the set. If a template is redefined, the element in the set is // called multiple times to parse definitions of templates to associate
// overwritten with the new definition. // 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) { func (t *Template) Parse(src string) (*Template, error) {
t.nameSpace.mu.Lock() t.nameSpace.mu.Lock()
t.escaped = false t.escaped = false
...@@ -94,9 +99,9 @@ func (t *Template) Parse(src string) (*Template, error) { ...@@ -94,9 +99,9 @@ func (t *Template) Parse(src string) (*Template, error) {
return t, nil return t, nil
} }
// Add is unimplemented. // AddParseTree is unimplemented.
func (t *Template) Add(*Template) error { func (t *Template) AddParseTree(name string, tree *parse.Tree) error {
return fmt.Errorf("html/template: Add unimplemented") return fmt.Errorf("html/template: AddParseTree unimplemented")
} }
// Clone is unimplemented. // Clone is unimplemented.
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"testing" "testing"
"text/template/parse"
) )
type isEmptyTest struct { type isEmptyTest struct {
...@@ -258,3 +259,30 @@ func TestClone(t *testing.T) { ...@@ -258,3 +259,30 @@ func TestClone(t *testing.T) {
t.Errorf("expected %q got %q", "bclone", b.String()) t.Errorf("expected %q got %q", "bclone", b.String())
} }
} }
func TestAddParseTree(t *testing.T) {
// Create some templates.
root, err := New("root").Parse(cloneText1)
if err != nil {
t.Fatal(err)
}
_, err = root.Parse(cloneText2)
if err != nil {
t.Fatal(err)
}
// Add a new parse tree.
tree, err := parse.Parse("cloneText3", cloneText3, "", "", nil, builtins)
if err != nil {
t.Fatal(err)
}
added, err := root.AddParseTree("c", tree["c"])
// Execute.
var b bytes.Buffer
err = added.ExecuteTemplate(&b, "a", 0)
if err != nil {
t.Fatal(err)
}
if b.String() != "broot" {
t.Errorf("expected %q got %q", "broot", b.String())
}
}
...@@ -103,21 +103,16 @@ func (t *Template) copy(c *common) *Template { ...@@ -103,21 +103,16 @@ func (t *Template) copy(c *common) *Template {
return nt return nt
} }
// Add associates the argument template, arg, with t, and vice versa, // AddParseTree creates a new template with the name and parse tree
// so they may invoke each other. To do this, it also removes any // and associates it with t.
// prior associations arg may have. Except for losing the link to func (t *Template) AddParseTree(name string, tree *parse.Tree) (*Template, error) {
// arg, templates associated with arg are otherwise unaffected. It if t.tmpl[name] != nil {
// is an error if the argument template's name is already associated return nil, fmt.Errorf("template: redefinition of template %q", name)
// with t. Add is here to support html/template and is not intended }
// for other uses. nt := t.New(name)
// TODO: make this take a parse.Tree argument instead of a template. nt.Tree = tree
func (t *Template) Add(arg *Template) error { t.tmpl[name] = nt
if t.tmpl[arg.name] != nil { return nt, nil
return fmt.Errorf("template: redefinition of template %q", arg.name)
}
arg.common = t.common
t.tmpl[arg.name] = arg
return nil
} }
// Templates returns a slice of the templates associated with t, including t // Templates returns a slice of the templates associated with t, including t
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment