mirror of
https://github.com/gohugoio/hugo.git
synced 2025-04-07 16:04:45 +00:00
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
This commit is contained in:
parent
047af7cfe5
commit
cdfd1c99ba
3 changed files with 49 additions and 14 deletions
|
@ -99,7 +99,16 @@ func init() {
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.ReplaceRE,
|
ns.AddMethodMapping(ctx.ReplaceRE,
|
||||||
[]string{"replaceRE"},
|
[]string{"replaceRE"},
|
||||||
[][2]string{},
|
[][2]string{
|
||||||
|
{
|
||||||
|
`{{ replaceRE "a+b" "X" "aabbaabbab" }}`,
|
||||||
|
`XbXbX`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
`{{ replaceRE "a+b" "X" "aabbaabbab" 1 }}`,
|
||||||
|
`Xbaabbab`,
|
||||||
|
},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
ns.AddMethodMapping(ctx.SliceString,
|
ns.AddMethodMapping(ctx.SliceString,
|
||||||
|
|
|
@ -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
|
// ReplaceRE returns a copy of s, replacing all matches of the regular
|
||||||
// expression pattern with the replacement text repl.
|
// expression pattern with the replacement text repl. The number of replacements
|
||||||
func (ns *Namespace) ReplaceRE(pattern, repl, s interface{}) (_ string, err error) {
|
// 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)
|
sp, err := cast.ToStringE(pattern)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
@ -63,12 +64,27 @@ func (ns *Namespace) ReplaceRE(pattern, repl, s interface{}) (_ string, err erro
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nn := -1
|
||||||
|
if len(n) > 0 {
|
||||||
|
nn, err = cast.ToIntE(n[0])
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
re, err := reCache.Get(sp)
|
re, err := reCache.Get(sp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
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.
|
// regexpCache represents a cache of regexp objects protected by a mutex.
|
||||||
|
|
|
@ -46,7 +46,7 @@ func TestFindRE(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Assert(err, qt.IsNil)
|
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{}
|
pattern interface{}
|
||||||
repl interface{}
|
repl interface{}
|
||||||
s interface{}
|
s interface{}
|
||||||
|
n []interface{}
|
||||||
expect interface{}
|
expect interface{}
|
||||||
}{
|
}{
|
||||||
{"^https?://([^/]+).*", "$1", "http://gohugo.io/docs", "gohugo.io"},
|
{"^https?://([^/]+).*", "$1", "http://gohugo.io/docs", nil, "gohugo.io"},
|
||||||
{"^https?://([^/]+).*", "$2", "http://gohugo.io/docs", ""},
|
{"^https?://([^/]+).*", "$2", "http://gohugo.io/docs", nil, ""},
|
||||||
{"(ab)", "AB", "aabbaab", "aABbaAB"},
|
{"(ab)", "AB", "aabbaab", nil, "aABbaAB"},
|
||||||
|
{"(ab)", "AB", "aabbaab", []interface{}{1}, "aABbaab"},
|
||||||
// errors
|
// errors
|
||||||
{"(ab", "AB", "aabb", false}, // invalid re
|
{"(ab", "AB", "aabb", nil, false}, // invalid re
|
||||||
{tstNoStringer{}, "$2", "http://gohugo.io/docs", false},
|
{tstNoStringer{}, "$2", "http://gohugo.io/docs", nil, false},
|
||||||
{"^https?://([^/]+).*", tstNoStringer{}, "http://gohugo.io/docs", false},
|
{"^https?://([^/]+).*", tstNoStringer{}, "http://gohugo.io/docs", nil, false},
|
||||||
{"^https?://([^/]+).*", "$2", tstNoStringer{}, 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 {
|
if b, ok := test.expect.(bool); ok && !b {
|
||||||
c.Assert(err, qt.Not(qt.IsNil))
|
c.Assert(err, qt.Not(qt.IsNil))
|
||||||
|
@ -78,6 +88,6 @@ func TestReplaceRE(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Assert(err, qt.IsNil)
|
c.Assert(err, qt.IsNil)
|
||||||
c.Assert(result, qt.Equals, test.expect)
|
c.Check(result, qt.Equals, test.expect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue