]> git.maquefel.me Git - brevno-suite/hugo/commitdiff
tpl/strings: Add findRESubmatch
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 17 Jan 2023 08:35:16 +0000 (09:35 +0100)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 17 Jan 2023 11:14:11 +0000 (12:14 +0100)
Fixes #10594

tpl/internal/templatefuncsRegistry.go
tpl/strings/init.go
tpl/strings/regexp.go
tpl/strings/regexp_test.go

index da9aa5d292b4c478f2e1eba27e8e4212657e8b73..84e0e25faf4b87741fcc42b26954e7b876224cf7 100644 (file)
@@ -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] == "" {
index 0a4d8776267492dfe50c507a972b4e0871a56907..503ec6a25e254fcd7776bd1dae3e49a4d43ed1b7 100644 (file)
@@ -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{
index 5b6a812d444fac6e5b578383c64f54a341c1910f..84b015ffb31316638ce05a2a2385cedcfe043211 100644 (file)
@@ -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.
index 9ac098c171abda9caa412c2bb087d6f36d745ee9..b6ec5cb9ed5d425e1997a88bbf2a90631020354e 100644 (file)
@@ -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)