URI: 
       tpl: Add limit support to replaceRE - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit cdfd1c99baa22d69e865294dfcd783811f96c880
   DIR parent 047af7cfe5e9aa740b85e0f9974a2d31a0ef4c08
  HTML Author: Cameron Moore <moorereason@gmail.com>
       Date:   Fri, 28 Aug 2020 09:29:26 -0500
       
       tpl: Add limit support to replaceRE
       
       Go stdlib doesn't contain a limited replace in the regexp package, but
       we can accomplish the same thing with ReplaceAllStringFunc.
       
       Fixes #7586
       
       Diffstat:
         M tpl/strings/init.go                 |      11 ++++++++++-
         M tpl/strings/regexp.go               |      22 +++++++++++++++++++---
         M tpl/strings/regexp_test.go          |      30 ++++++++++++++++++++----------
       
       3 files changed, 49 insertions(+), 14 deletions(-)
       ---
   DIR diff --git a/tpl/strings/init.go b/tpl/strings/init.go
       @@ -99,7 +99,16 @@ func init() {
        
                        ns.AddMethodMapping(ctx.ReplaceRE,
                                []string{"replaceRE"},
       -                        [][2]string{},
       +                        [][2]string{
       +                                {
       +                                        `{{ replaceRE "a+b" "X" "aabbaabbab" }}`,
       +                                        `XbXbX`,
       +                                },
       +                                {
       +                                        `{{ replaceRE "a+b" "X" "aabbaabbab" 1 }}`,
       +                                        `Xbaabbab`,
       +                                },
       +                        },
                        )
        
                        ns.AddMethodMapping(ctx.SliceString,
   DIR diff --git a/tpl/strings/regexp.go b/tpl/strings/regexp.go
       @@ -46,8 +46,9 @@ func (ns *Namespace) FindRE(expr string, content interface{}, limit ...interface
        }
        
        // ReplaceRE returns a copy of s, replacing all matches of the regular
       -// expression pattern with the replacement text repl.
       -func (ns *Namespace) ReplaceRE(pattern, repl, s interface{}) (_ string, err error) {
       +// expression pattern with the replacement text repl. The number of replacements
       +// can be limited with an optional fourth parameter.
       +func (ns *Namespace) ReplaceRE(pattern, repl, s interface{}, n ...interface{}) (_ string, err error) {
                sp, err := cast.ToStringE(pattern)
                if err != nil {
                        return
       @@ -63,12 +64,27 @@ func (ns *Namespace) ReplaceRE(pattern, repl, s interface{}) (_ string, err erro
                        return
                }
        
       +        nn := -1
       +        if len(n) > 0 {
       +                nn, err = cast.ToIntE(n[0])
       +                if err != nil {
       +                        return
       +                }
       +        }
       +
                re, err := reCache.Get(sp)
                if err != nil {
                        return "", err
                }
        
       -        return re.ReplaceAllString(ss, sr), nil
       +        return re.ReplaceAllStringFunc(ss, func(str string) string {
       +                if nn == 0 {
       +                        return str
       +                }
       +
       +                nn -= 1
       +                return re.ReplaceAllString(str, sr)
       +        }), nil
        }
        
        // regexpCache represents a cache of regexp objects protected by a mutex.
   DIR diff --git a/tpl/strings/regexp_test.go b/tpl/strings/regexp_test.go
       @@ -46,7 +46,7 @@ func TestFindRE(t *testing.T) {
                        }
        
                        c.Assert(err, qt.IsNil)
       -                c.Assert(result, qt.DeepEquals, test.expect)
       +                c.Check(result, qt.DeepEquals, test.expect)
                }
        }
        
       @@ -58,19 +58,29 @@ func TestReplaceRE(t *testing.T) {
                        pattern interface{}
                        repl    interface{}
                        s       interface{}
       +                n       []interface{}
                        expect  interface{}
                }{
       -                {"^https?://([^/]+).*", "$1", "http://gohugo.io/docs", "gohugo.io"},
       -                {"^https?://([^/]+).*", "$2", "http://gohugo.io/docs", ""},
       -                {"(ab)", "AB", "aabbaab", "aABbaAB"},
       +                {"^https?://([^/]+).*", "$1", "http://gohugo.io/docs", nil, "gohugo.io"},
       +                {"^https?://([^/]+).*", "$2", "http://gohugo.io/docs", nil, ""},
       +                {"(ab)", "AB", "aabbaab", nil, "aABbaAB"},
       +                {"(ab)", "AB", "aabbaab", []interface{}{1}, "aABbaab"},
                        // errors
       -                {"(ab", "AB", "aabb", false}, // invalid re
       -                {tstNoStringer{}, "$2", "http://gohugo.io/docs", false},
       -                {"^https?://([^/]+).*", tstNoStringer{}, "http://gohugo.io/docs", false},
       -                {"^https?://([^/]+).*", "$2", tstNoStringer{}, false},
       +                {"(ab", "AB", "aabb", nil, false}, // invalid re
       +                {tstNoStringer{}, "$2", "http://gohugo.io/docs", nil, false},
       +                {"^https?://([^/]+).*", tstNoStringer{}, "http://gohugo.io/docs", nil, false},
       +                {"^https?://([^/]+).*", "$2", tstNoStringer{}, nil, false},
                } {
        
       -                result, err := ns.ReplaceRE(test.pattern, test.repl, test.s)
       +                var (
       +                        result string
       +                        err    error
       +                )
       +                if len(test.n) > 0 {
       +                        result, err = ns.ReplaceRE(test.pattern, test.repl, test.s, test.n...)
       +                } else {
       +                        result, err = ns.ReplaceRE(test.pattern, test.repl, test.s)
       +                }
        
                        if b, ok := test.expect.(bool); ok && !b {
                                c.Assert(err, qt.Not(qt.IsNil))
       @@ -78,6 +88,6 @@ func TestReplaceRE(t *testing.T) {
                        }
        
                        c.Assert(err, qt.IsNil)
       -                c.Assert(result, qt.Equals, test.expect)
       +                c.Check(result, qt.Equals, test.expect)
                }
        }