summaryrefslogtreecommitdiffstats
path: root/tpl
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-01-17 09:35:16 +0100
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2023-01-17 12:14:11 +0100
commit2fb40ece5df38c3d6565cfd69ae194dbe0126f53 (patch)
tree2a0472335a48b0edf540c7495d6a8fabfe889271 /tpl
parentc6b3887696162335d806ff25e9b9db27d73611de (diff)
tpl/strings: Add findRESubmatch
Fixes #10594
Diffstat (limited to 'tpl')
-rw-r--r--tpl/internal/templatefuncsRegistry.go5
-rw-r--r--tpl/strings/init.go12
-rw-r--r--tpl/strings/regexp.go25
-rw-r--r--tpl/strings/regexp_test.go33
4 files changed, 74 insertions, 1 deletions
diff --git a/tpl/internal/templatefuncsRegistry.go b/tpl/internal/templatefuncsRegistry.go
index da9aa5d29..84e0e25fa 100644
--- a/tpl/internal/templatefuncsRegistry.go
+++ b/tpl/internal/templatefuncsRegistry.go
@@ -66,6 +66,11 @@ func (t *TemplateFuncsNamespace) AddMethodMapping(m any, aliases []string, examp
name := methodToName(m)
+ // Rewrite §§ to ` in example commands.
+ for i, e := range examples {
+ examples[i][0] = strings.ReplaceAll(e[0], "§§", "`")
+ }
+
// sanity check
for _, e := range examples {
if e[0] == "" {
diff --git a/tpl/strings/init.go b/tpl/strings/init.go
index 0a4d87762..503ec6a25 100644
--- a/tpl/strings/init.go
+++ b/tpl/strings/init.go
@@ -78,12 +78,22 @@ func init() {
[]string{"findRE"},
[][2]string{
{
- `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`,
+ `{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." 1 }}`,
`[go]`,
},
},
)
+ ns.AddMethodMapping(ctx.FindRESubmatch,
+ []string{"findRESubmatch"},
+ [][2]string{
+ {
+ `{{ findRESubmatch §§<a\s*href="(.+?)">(.+?)</a>§§ §§<li><a href="#foo">Foo</a></li> <li><a href="#bar">Bar</a></li>§§ | print | safeHTML }}`,
+ "[[<a href=\"#foo\">Foo</a> #foo Foo] [<a href=\"#bar\">Bar</a> #bar Bar]]",
+ },
+ },
+ )
+
ns.AddMethodMapping(ctx.HasPrefix,
[]string{"hasPrefix"},
[][2]string{
diff --git a/tpl/strings/regexp.go b/tpl/strings/regexp.go
index 5b6a812d4..84b015ffb 100644
--- a/tpl/strings/regexp.go
+++ b/tpl/strings/regexp.go
@@ -45,6 +45,31 @@ func (ns *Namespace) FindRE(expr string, content any, limit ...any) ([]string, e
return re.FindAllString(conv, lim), nil
}
+// FindRESubmatch returns returns a slice of strings holding the text of the leftmost match of the regular expression in s and the matches, if any, of its subexpressions.
+//
+// By default all matches will be included. The number of matches can be limited with the optional limit parameter. A return value of nil indicates no match.
+func (ns *Namespace) FindRESubmatch(expr string, content any, limit ...any) ([][]string, error) {
+ re, err := reCache.Get(expr)
+ if err != nil {
+ return nil, err
+ }
+
+ conv, err := cast.ToStringE(content)
+ if err != nil {
+ return nil, err
+ }
+ n := -1
+ if len(limit) > 0 {
+ n, err = cast.ToIntE(limit[0])
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return re.FindAllStringSubmatch(conv, n), nil
+
+}
+
// ReplaceRE returns a copy of s, replacing all matches of the regular
// expression pattern with the replacement text repl. The number of replacements
// can be limited with an optional fourth parameter.
diff --git a/tpl/strings/regexp_test.go b/tpl/strings/regexp_test.go
index 9ac098c17..b6ec5cb9e 100644
--- a/tpl/strings/regexp_test.go
+++ b/tpl/strings/regexp_test.go
@@ -50,6 +50,39 @@ func TestFindRE(t *testing.T) {
}
}
+func TestFindRESubmatch(t *testing.T) {
+ t.Parallel()
+ c := qt.New(t)
+
+ for _, test := range []struct {
+ expr string
+ content any
+ limit any
+ expect any
+ }{
+ {`<a\s*href="(.+?)">(.+?)</a>`, `<li><a href="#foo">Foo</a></li><li><a href="#bar">Bar</a></li>`, -1, [][]string{
+ {"<a href=\"#foo\">Foo</a>", "#foo", "Foo"},
+ {"<a href=\"#bar\">Bar</a>", "#bar", "Bar"},
+ }},
+ // Some simple cases.
+ {"([G|g]o)", "Hugo is a static site generator written in Go.", -1, [][]string{{"go", "go"}, {"Go", "Go"}}},
+ {"([G|g]o)", "Hugo is a static site generator written in Go.", 1, [][]string{{"go", "go"}}},
+
+ // errors
+ {"([G|go", "Hugo is a static site generator written in Go.", nil, false},
+ {"([G|g]o)", t, nil, false},
+ } {
+ result, err := ns.FindRESubmatch(test.expr, test.content, test.limit)
+
+ if b, ok := test.expect.(bool); ok && !b {
+ c.Assert(err, qt.Not(qt.IsNil))
+ continue
+ }
+
+ c.Assert(err, qt.IsNil)
+ c.Check(result, qt.DeepEquals, test.expect)
+ }
+}
func TestReplaceRE(t *testing.T) {
t.Parallel()
c := qt.New(t)