hull/pkg/tpl/parse/node_wrapper.go

81 lines
2.3 KiB
Go

package parse
import (
"fmt"
"text/template/parse"
)
type Node struct {
node parse.Node
parent *Node
// fieldContext is the root context to use when adding fields
// For example, in a range or with block, anything that is parsed within it
// will need to append the fieldContext before adding the field
//
// If fieldContext is an empty string, that implies that it was impossible to identify
// what the root context of this node is, so it's impossible to figure out what
// a field parsed from within this node is
//
// i.e. If you have the following template:
// {{ range (toYaml .Values.namespaces | fromYaml) }}
// {{ .data }}
// {{ end }}
//
// (toYaml .Values.namespaces | fromYaml) is considered ambiguous since we don't have
// a direct reference to a field in the built-in object, so the only thing that
// should be collected here is .Values.namespace, not .Values.namespace.data, since the
// only way you could know that (toYaml .Values.namespaces | fromYaml) is equivalent to
// .Values.namespaces is by understanding how toYaml and fromYaml manipulate the data. This
// is something that is not capable for Hull to do today.
fieldContext string
}
func (n *Node) isAmbiguous() bool {
return len(n.fieldContext) == 0
}
func (n *Node) getFieldContext(fieldContext string) string {
if n.parent == nil {
return fieldContext
}
if n.parent.isAmbiguous() {
// ambiguous parent implies ambiguous child; ignore fieldContext provided
return ""
}
if len(fieldContext) == 0 {
// ambiguous values provided
return fieldContext
}
if fieldContext == "." {
// use parent fieldContext
return n.parent.fieldContext
}
if n.parent.fieldContext == "." {
// use child fieldContext
return fieldContext
}
// parent has fieldContext and provided fieldContext is not ambiguous or ., so prepend it
return n.parent.fieldContext + fieldContext
}
func toNode(node parse.Node, parent *Node, fieldContext string) *Node {
if node == nil {
panic(fmt.Errorf("cannot convert nil node toNode"))
}
n := &Node{
node: node,
parent: parent,
}
n.fieldContext = n.getFieldContext(fieldContext)
return n
}
func toNodes(parseNodes []parse.Node, parent *Node, fieldContext string) []*Node {
nodes := make([]*Node, len(parseNodes))
for i, parseNode := range parseNodes {
nodes[i] = toNode(parseNode, parent, fieldContext)
}
return nodes
}