From 8e5abb8bb4ce221d2db149b588e47132a1570d24 Mon Sep 17 00:00:00 2001 From: early Date: Tue, 22 Oct 2024 22:59:53 -0600 Subject: [PATCH] Fix issues with function namespacing --- internal/compile/compile.go | 12 +++++++----- internal/compile/template.go | 33 +++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/internal/compile/compile.go b/internal/compile/compile.go index 2cbcc70..9b88807 100644 --- a/internal/compile/compile.go +++ b/internal/compile/compile.go @@ -4,7 +4,6 @@ package compile import ( "errors" "html/template" - "maps" "regexp" "strings" @@ -53,10 +52,10 @@ func Compile(root TemplateSource, transform ...func(root *html.Node)) (Result, e return result, err } - fullDependencies := make(Sources) + fullDependencies := Sources{root.Name(): root} mapSources(fullDependencies, root.Includes()) computeRoot := &computeNode{ - name: "root", + name: root.Name(), compute: root.OnLoad(), } // Insert an assignment to $compute so we can always raise scope, even @@ -67,8 +66,8 @@ func Compile(root TemplateSource, transform ...func(root *html.Node)) (Result, e }, document.FirstChild) // Replace template functions in the root before we add any subsources + // fmt.Println(root.TemplateFuncs()) htmltree.Walk(document, func(n *html.Node) (bool, error) { - // Replace template functions with namespaced functions. replaceTemplateFuncs(root, n) return false, nil }) @@ -90,7 +89,10 @@ func Compile(root TemplateSource, transform ...func(root *html.Node)) (Result, e // gather global template funcs // Start with the root's template, then add template funcs for all subsource // with a namespace - templateFuncs := maps.Clone(root.TemplateFuncs()) + templateFuncs := make(template.FuncMap) + for fname, f := range root.TemplateFuncs() { + templateFuncs[snakeCase(root.Name())+"_"+fname] = f + } var process func(n *html.Node, c *computeNode) error process = func(n *html.Node, c *computeNode) error { diff --git a/internal/compile/template.go b/internal/compile/template.go index a1e0e2b..1fd6f5b 100644 --- a/internal/compile/template.go +++ b/internal/compile/template.go @@ -17,13 +17,18 @@ const ( tokenCloseTemplate = "}}" ) -var funcRegexp = regexp.MustCompile(`^[a-zA-Z]\w*$`) +var funcRegexp = regexp.MustCompile(`^\(?([a-zA-Z]\w*)\)?$`) var fieldRegexp = regexp.MustCompile(`^(?:\.[a-zA-Z]\w*)+$`) +var scopesDownRegexp = regexp.MustCompile(`[\{\s]end[\}\s]`) var setsDotRegexp = regexp.MustCompile(`^\{\{-?\s*(?:with|range).*?\}\}$`) var templateRegexp = regexp.MustCompile(`\{\{.*\}\}`) -func isFunc(token string) bool { - return funcRegexp.MatchString(token) +func funcFrom(token string) string { + submatches := funcRegexp.FindStringSubmatch(token) + if len(submatches) > 1 { + return submatches[1] + } + return "" } func isField(token string) bool { @@ -41,7 +46,7 @@ func scopesUp(token string) bool { } func scopesDown(token string) bool { - return strings.Contains(token, "end") + return scopesDownRegexp.MatchString(token) } func setsDot(token string) bool { @@ -85,6 +90,7 @@ func splitTemplateNodes(n *html.Node) { if depth == 0 { // If we're just starting a pipeline, set the "template" // cursor to the template open position + splitNodes = append(splitNodes, n.Data[t:i+open]) t += open } depth++ @@ -100,6 +106,7 @@ func splitTemplateNodes(n *html.Node) { } i += close + 2 } else { + splitNodes = append(splitNodes, n.Data[i:]) break } } @@ -195,11 +202,12 @@ func replaceTemplateFuncs(source TemplateSource, n *html.Node) { var done, inTemplate bool var output []string for { - endToken := strings.Index(data, " ") + endToken := strings.IndexAny(data, " ") if endToken == -1 { endToken = len(data) done = true } + token := data[:endToken] // Track when we're in a template using open/close brackets if token == tokenOpenTemplate { @@ -210,13 +218,22 @@ func replaceTemplateFuncs(source TemplateSource, n *html.Node) { } // If we're in a template and found a function identifier, replace it // with a namespaced version - if inTemplate && isFunc(token) { + if inTemplate { + funcName := funcFrom(token) + if funcName == "" { + goto done + } + // fmt.Println("func", token) + // fmt.Println(source.TemplateFuncs()) // Skip anything that the target source doesn't have as a templatefunc - if _, ok := source.TemplateFuncs()[token]; ok { - token = snakeCase(source.Name()) + "_" + token + if _, ok := source.TemplateFuncs()[funcName]; ok { + // fmt.Println("found", token) + namespaced := snakeCase(source.Name()) + "_" + funcName + token = strings.Replace(token, funcName, namespaced, -1) } } + done: output = append(output, token) if done { break -- 2.39.5