shithub: hugo

Download patch

ref: bdc02edfa8fb3178808420f529599e5970012304
parent: 4493e8ed9f3c4dadc66689e0451bc3611e07fa6f
author: Bjørn Erik Pedersen <[email protected]>
date: Sat Feb 18 04:08:00 EST 2017

tplimpl: Fix issue with recursive templates

Fixes #2927

--- a/tpl/tplimpl/template_ast_transformers.go
+++ b/tpl/tplimpl/template_ast_transformers.go
@@ -35,12 +35,21 @@
 }
 
 type templateContext struct {
-	decl  decl
-	templ *template.Template
+	decl    decl
+	templ   *template.Template
+	visited map[string]bool
 }
 
+func (c templateContext) getIfNotVisited(name string) *template.Template {
+	if c.visited[name] {
+		return nil
+	}
+	c.visited[name] = true
+	return c.templ.Lookup(name)
+}
+
 func newTemplateContext(templ *template.Template) *templateContext {
-	return &templateContext{templ: templ, decl: make(map[string]string)}
+	return &templateContext{templ: templ, decl: make(map[string]string), visited: make(map[string]bool)}
 
 }
 
@@ -59,7 +68,6 @@
 // paramsKeysToLower is made purposely non-generic to make it not so tempting
 // to do more of these hard-to-maintain AST transformations.
 func (c *templateContext) paramsKeysToLower(n parse.Node) {
-
 	switch x := n.(type) {
 	case *parse.ListNode:
 		if x != nil {
@@ -74,7 +82,7 @@
 	case *parse.RangeNode:
 		c.paramsKeysToLowerForNodes(x.Pipe, x.List, x.ElseList)
 	case *parse.TemplateNode:
-		subTempl := c.templ.Lookup(x.Name)
+		subTempl := c.getIfNotVisited(x.Name)
 		if subTempl != nil {
 			c.paramsKeysToLowerForNodes(subTempl.Tree.Root)
 		}
--- a/tpl/tplimpl/template_ast_transformers_test.go
+++ b/tpl/tplimpl/template_ast_transformers_test.go
@@ -267,3 +267,24 @@
 	require.Contains(t, result, "P1: P1L")
 	require.Contains(t, result, "P2: P1L")
 }
+
+// Issue #2927
+func TestTransformRecursiveTemplate(t *testing.T) {
+
+	recursive := `
+{{ define "menu-nodes" }}
+{{ template "menu-node" }}
+{{ end }}
+{{ define "menu-node" }}
+{{ template "menu-node" }}
+{{ end }}
+{{ template "menu-nodes" }}
+`
+
+	templ, err := template.New("foo").Parse(recursive)
+	require.NoError(t, err)
+
+	c := newTemplateContext(templ)
+	c.paramsKeysToLower(templ.Tree.Root)
+
+}