summaryrefslogtreecommitdiffhomepage
path: root/tpl
diff options
context:
space:
mode:
authorCameron Moore <[email protected]>2020-08-27 21:59:20 -0500
committerBjørn Erik Pedersen <[email protected]>2020-08-28 08:55:58 +0200
commitf9ebaaed1be1e4a26eef2aebd2c7554c979f29fa (patch)
treee9d4e39da776a1cf1bd2b577893904a113177d05 /tpl
parentd39636a5fc6bb82b3e0bd013858c7d116faa0c6b (diff)
downloadhugo-f9ebaaed1be1e4a26eef2aebd2c7554c979f29fa.tar.gz
hugo-f9ebaaed1be1e4a26eef2aebd2c7554c979f29fa.zip
tpl: Add limit option to replace template function
Updates #7586
Diffstat (limited to 'tpl')
-rw-r--r--tpl/strings/init.go11
-rw-r--r--tpl/strings/strings.go54
-rw-r--r--tpl/strings/strings_test.go30
3 files changed, 59 insertions, 36 deletions
diff --git a/tpl/strings/init.go b/tpl/strings/init.go
index fe0cff83b..09419a51f 100644
--- a/tpl/strings/init.go
+++ b/tpl/strings/init.go
@@ -63,7 +63,8 @@ func init() {
[][2]string{
{
`{{ findRE "[G|g]o" "Hugo is a static side generator written in Go." "1" }}`,
- `[go]`},
+ `[go]`,
+ },
},
)
@@ -87,7 +88,12 @@ func init() {
[][2]string{
{
`{{ replace "Batman and Robin" "Robin" "Catwoman" }}`,
- `Batman and Catwoman`},
+ `Batman and Catwoman`,
+ },
+ {
+ `{{ replace "aabbaabb" "a" "z" 2 }}`,
+ `zzbbaabb`,
+ },
},
)
@@ -192,7 +198,6 @@ func init() {
)
return ns
-
}
internal.AddTemplateFuncsNamespace(f)
diff --git a/tpl/strings/strings.go b/tpl/strings/strings.go
index d78234e41..c87b532d3 100644
--- a/tpl/strings/strings.go
+++ b/tpl/strings/strings.go
@@ -19,14 +19,12 @@ import (
"fmt"
"html/template"
"strings"
-
- _strings "strings"
"unicode/utf8"
- _errors "github.com/pkg/errors"
-
"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/helpers"
+
+ _errors "github.com/pkg/errors"
"github.com/spf13/cast"
)
@@ -79,7 +77,7 @@ func (ns *Namespace) CountWords(s interface{}) (int, error) {
}
counter := 0
- for _, word := range _strings.Fields(helpers.StripHTML(ss)) {
+ for _, word := range strings.Fields(helpers.StripHTML(ss)) {
runeCount := utf8.RuneCountInString(word)
if len(word) == runeCount {
counter++
@@ -112,14 +110,13 @@ func (ns *Namespace) Chomp(s interface{}) (interface{}, error) {
return "", err
}
- res := _strings.TrimRight(ss, "\r\n")
+ res := strings.TrimRight(ss, "\r\n")
switch s.(type) {
case template.HTML:
return template.HTML(res), nil
default:
return res, nil
}
-
}
// Contains reports whether substr is in s.
@@ -134,7 +131,7 @@ func (ns *Namespace) Contains(s, substr interface{}) (bool, error) {
return false, err
}
- return _strings.Contains(ss, su), nil
+ return strings.Contains(ss, su), nil
}
// ContainsAny reports whether any Unicode code points in chars are within s.
@@ -149,7 +146,7 @@ func (ns *Namespace) ContainsAny(s, chars interface{}) (bool, error) {
return false, err
}
- return _strings.ContainsAny(ss, sc), nil
+ return strings.ContainsAny(ss, sc), nil
}
// HasPrefix tests whether the input s begins with prefix.
@@ -164,7 +161,7 @@ func (ns *Namespace) HasPrefix(s, prefix interface{}) (bool, error) {
return false, err
}
- return _strings.HasPrefix(ss, sx), nil
+ return strings.HasPrefix(ss, sx), nil
}
// HasSuffix tests whether the input s begins with suffix.
@@ -179,12 +176,13 @@ func (ns *Namespace) HasSuffix(s, suffix interface{}) (bool, error) {
return false, err
}
- return _strings.HasSuffix(ss, sx), nil
+ return strings.HasSuffix(ss, sx), nil
}
// Replace returns a copy of the string s with all occurrences of old replaced
-// with new.
-func (ns *Namespace) Replace(s, old, new interface{}) (string, error) {
+// with new. The number of replacements can be limited with an optional fourth
+// parameter.
+func (ns *Namespace) Replace(s, old, new interface{}, limit ...interface{}) (string, error) {
ss, err := cast.ToStringE(s)
if err != nil {
return "", err
@@ -200,7 +198,16 @@ func (ns *Namespace) Replace(s, old, new interface{}) (string, error) {
return "", err
}
- return _strings.Replace(ss, so, sn, -1), nil
+ if len(limit) == 0 {
+ return strings.ReplaceAll(ss, so, sn), nil
+ }
+
+ lim, err := cast.ToIntE(limit[0])
+ if err != nil {
+ return "", err
+ }
+
+ return strings.Replace(ss, so, sn, lim), nil
}
// SliceString slices a string by specifying a half-open range with
@@ -247,7 +254,6 @@ func (ns *Namespace) SliceString(a interface{}, startEnd ...interface{}) (string
} else {
return string(asRunes[:]), nil
}
-
}
// Split slices an input string into all substrings separated by delimiter.
@@ -257,7 +263,7 @@ func (ns *Namespace) Split(a interface{}, delimiter string) ([]string, error) {
return []string{}, err
}
- return _strings.Split(aStr, delimiter), nil
+ return strings.Split(aStr, delimiter), nil
}
// Substr extracts parts of a string, beginning at the character at the specified
@@ -362,7 +368,7 @@ func (ns *Namespace) ToLower(s interface{}) (string, error) {
return "", err
}
- return _strings.ToLower(ss), nil
+ return strings.ToLower(ss), nil
}
// ToUpper returns a copy of the input s with all Unicode letters mapped to their
@@ -373,7 +379,7 @@ func (ns *Namespace) ToUpper(s interface{}) (string, error) {
return "", err
}
- return _strings.ToUpper(ss), nil
+ return strings.ToUpper(ss), nil
}
// Trim returns a string with all leading and trailing characters defined
@@ -389,7 +395,7 @@ func (ns *Namespace) Trim(s, cutset interface{}) (string, error) {
return "", err
}
- return _strings.Trim(ss, sc), nil
+ return strings.Trim(ss, sc), nil
}
// TrimLeft returns a slice of the string s with all leading characters
@@ -405,7 +411,7 @@ func (ns *Namespace) TrimLeft(cutset, s interface{}) (string, error) {
return "", err
}
- return _strings.TrimLeft(ss, sc), nil
+ return strings.TrimLeft(ss, sc), nil
}
// TrimPrefix returns s without the provided leading prefix string. If s doesn't
@@ -421,7 +427,7 @@ func (ns *Namespace) TrimPrefix(prefix, s interface{}) (string, error) {
return "", err
}
- return _strings.TrimPrefix(ss, sx), nil
+ return strings.TrimPrefix(ss, sx), nil
}
// TrimRight returns a slice of the string s with all trailing characters
@@ -437,7 +443,7 @@ func (ns *Namespace) TrimRight(cutset, s interface{}) (string, error) {
return "", err
}
- return _strings.TrimRight(ss, sc), nil
+ return strings.TrimRight(ss, sc), nil
}
// TrimSuffix returns s without the provided trailing suffix string. If s
@@ -453,7 +459,7 @@ func (ns *Namespace) TrimSuffix(suffix, s interface{}) (string, error) {
return "", err
}
- return _strings.TrimSuffix(ss, sx), nil
+ return strings.TrimSuffix(ss, sx), nil
}
// Repeat returns a new string consisting of count copies of the string s.
@@ -472,5 +478,5 @@ func (ns *Namespace) Repeat(n, s interface{}) (string, error) {
return "", errors.New("strings: negative Repeat count")
}
- return _strings.Repeat(ss, sn), nil
+ return strings.Repeat(ss, sn), nil
}
diff --git a/tpl/strings/strings_test.go b/tpl/strings/strings_test.go
index 2fc3dc028..6a14acd78 100644
--- a/tpl/strings/strings_test.go
+++ b/tpl/strings/strings_test.go
@@ -15,11 +15,11 @@ package strings
import (
"html/template"
-
"testing"
- qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/deps"
+
+ qt "github.com/frankban/quicktest"
"github.com/spf13/cast"
"github.com/spf13/viper"
)
@@ -302,18 +302,30 @@ func TestReplace(t *testing.T) {
s interface{}
old interface{}
new interface{}
+ limit interface{}
expect interface{}
}{
- {"aab", "a", "b", "bbb"},
- {"11a11", 1, 2, "22a22"},
- {12345, 1, 2, "22345"},
+ {"aab", "a", "b", nil, "bbb"},
+ {"11a11", 1, 2, nil, "22a22"},
+ {12345, 1, 2, nil, "22345"},
+ {"aab", "a", "b", 1, "bab"},
+ {"11a11", 1, 2, 2, "22a11"},
// errors
- {tstNoStringer{}, "a", "b", false},
- {"a", tstNoStringer{}, "b", false},
- {"a", "b", tstNoStringer{}, false},
+ {tstNoStringer{}, "a", "b", nil, false},
+ {"a", tstNoStringer{}, "b", nil, false},
+ {"a", "b", tstNoStringer{}, nil, false},
} {
- result, err := ns.Replace(test.s, test.old, test.new)
+ var (
+ result string
+ err error
+ )
+
+ if test.limit != nil {
+ result, err = ns.Replace(test.s, test.old, test.new, test.limit)
+ } else {
+ result, err = ns.Replace(test.s, test.old, test.new)
+ }
if b, ok := test.expect.(bool); ok && !b {
c.Assert(err, qt.Not(qt.IsNil))