// clone clones a template Node. func clone(n parse.Node) parse.Node { switch t := n.(type) { case *parse.ActionNode: return cloneAction(t) case *parse.IfNode: b := new(parse.IfNode) copyBranch(&b.BranchNode, &t.BranchNode) return b case *parse.ListNode: return cloneList(t) case *parse.RangeNode: b := new(parse.RangeNode) copyBranch(&b.BranchNode, &t.BranchNode) return b case *parse.TemplateNode: return cloneTemplate(t) case *parse.TextNode: return cloneText(t) case *parse.WithNode: b := new(parse.WithNode) copyBranch(&b.BranchNode, &t.BranchNode) return b } panic("cloning " + n.String() + " is unimplemented") }
// Walk functions step through the major pieces of the template structure, // generating output as they go. func (s *state) walk(dot reflect.Value, node parse.Node) { s.at(node) switch node := node.(type) { case *parse.ActionNode: // Do not pop variables so they persist until next end. // Also, if the action declares variables, don't print the result. val := s.evalPipeline(dot, node.Pipe) if len(node.Pipe.Decl) == 0 { s.visitValue(node, val) } case *parse.IfNode: s.walkIfOrWith(parse.NodeIf, dot, node.Pipe, node.List, node.ElseList) case *parse.ListNode: for _, node := range node.Nodes { s.walk(dot, node) } case *parse.RangeNode: s.walkRange(dot, node) case *parse.TemplateNode: s.walkTemplate(dot, node) case *parse.TextNode: s.v.Visit(node.String()) case *parse.WithNode: s.walkIfOrWith(parse.NodeWith, dot, node.Pipe, node.List, node.ElseList) default: s.errorf("unknown node: %s", node) } }
// escape escapes a template node. func (e *escaper) escape(c context, n parse.Node) context { switch n := n.(type) { case *parse.ActionNode: return e.escapeAction(c, n) case *parse.IfNode: return e.escapeBranch(c, &n.BranchNode, "if") case *parse.ListNode: return e.escapeList(c, n) case *parse.RangeNode: return e.escapeBranch(c, &n.BranchNode, "range") case *parse.TemplateNode: return e.escapeTemplate(c, n) case *parse.TextNode: return e.escapeText(c, n) case *parse.WithNode: return e.escapeBranch(c, &n.BranchNode, "with") } panic("escaping " + n.String() + " is unimplemented") }
// IsPseudoFunction returns true iff n is a *parse.ActionNode // consisting solely of a fn call without any arguments. func IsPseudoFunction(n parse.Node, fn string) bool { return n.Type() == parse.NodeAction && n.String() == leftDelim+fn+rightDelim }