summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid E. Wheeler <david@justatheory.com>2018-06-03 02:55:37 -0400
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2018-06-03 09:55:37 +0300
commit13435a6f608306c5094fdcd72a1d9538727f91b2 (patch)
treef452078c55bfe6d326d866f9aaaebf338d560cec
parent07b96d16e8679c40e289c9076ef4414ed6eb7f81 (diff)
tpl: Add strings.Repeat
-rw-r--r--docs/content/en/functions/strings.Repeat.md31
-rw-r--r--docs/data/docs.json14
-rw-r--r--tpl/strings/init.go7
-rw-r--r--tpl/strings/strings.go21
-rw-r--r--tpl/strings/strings_test.go36
5 files changed, 109 insertions, 0 deletions
diff --git a/docs/content/en/functions/strings.Repeat.md b/docs/content/en/functions/strings.Repeat.md
new file mode 100644
index 000000000..8dcb8eaa2
--- /dev/null
+++ b/docs/content/en/functions/strings.Repeat.md
@@ -0,0 +1,31 @@
+---
+title: strings.Repeat
+# linktitle:
+description: Returns a string consisting of count copies of the string s.
+godocref:
+date: 2018-05-31
+publishdate: 2018-05-31
+lastmod: 2018-05-31
+categories: [functions]
+menu:
+ docs:
+ parent: "functions"
+keywords: [strings]
+signature: ["strings.Repeat INPUT COUNT"]
+workson: []
+hugoversion:
+relatedfuncs: []
+deprecated: false
+---
+
+`strings.Repeat` provides the Go [`strings.Repeat`](https://golang.org/pkg/strings/#Repeat) function for Hugo templates. It takes a string and a count, and returns a string with consisting of count copies of the string argument.
+
+```
+{{ strings.Repeat "yo" 3 }} → "yoyoyo"
+```
+
+`strings.Repeat` *requires* the second argument, which tells the function how many times to repeat the first argument; there is no default. However, it can be used as a pipeline:
+
+```
+{{ "yo" | strings.Repeat 3 }} → "yoyoyo"
+```
diff --git a/docs/data/docs.json b/docs/data/docs.json
index 2a7f727b7..4eddf8eae 100644
--- a/docs/data/docs.json
+++ b/docs/data/docs.json
@@ -3410,6 +3410,20 @@
]
]
},
+ "Repeat": {
+ "Description": "Repeat returns a new string consisting of count copies of the string s.",
+ "Args": [
+ "s",
+ "n"
+ ],
+ "Aliases": null,
+ "Examples": [
+ [
+ "{{ \"yo\" | strings.Repeat 4 }}",
+ "yoyoyoyo"
+ ]
+ ]
+ },
"Truncate": {
"Description": "Truncate truncates a given string to the specified length.",
"Args": [
diff --git a/tpl/strings/init.go b/tpl/strings/init.go
index 54009b897..883ce76d1 100644
--- a/tpl/strings/init.go
+++ b/tpl/strings/init.go
@@ -158,6 +158,13 @@ func init() {
},
)
+ ns.AddMethodMapping(ctx.Repeat,
+ nil,
+ [][2]string{
+ {`{{ "yo" | strings.Repeat 4 }}`, `yoyoyoyo`},
+ },
+ )
+
ns.AddMethodMapping(ctx.ToUpper,
[]string{"upper"},
[][2]string{
diff --git a/tpl/strings/strings.go b/tpl/strings/strings.go
index 6d423391f..796b8ff62 100644
--- a/tpl/strings/strings.go
+++ b/tpl/strings/strings.go
@@ -17,6 +17,7 @@ import (
"errors"
"fmt"
"html/template"
+ "math"
_strings "strings"
"unicode/utf8"
@@ -417,3 +418,23 @@ func (ns *Namespace) TrimSuffix(suffix, s interface{}) (string, error) {
return _strings.TrimSuffix(ss, sx), nil
}
+
+// Repeat returns a new string consisting of count copies of the string s.
+// The count is limited to an in16 value (up to 32767).
+func (ns *Namespace) Repeat(n, s interface{}) (string, error) {
+ ss, err := cast.ToStringE(s)
+ if err != nil {
+ return "", err
+ }
+
+ sn, err := cast.ToIntE(n)
+ if err != nil {
+ return "", err
+ }
+
+ if sn > math.MaxInt16 {
+ return "", fmt.Errorf("Cannot repeat string more than %d times", math.MaxInt16)
+ }
+
+ return _strings.Repeat(ss, sn), nil
+}
diff --git a/tpl/strings/strings_test.go b/tpl/strings/strings_test.go
index 91e71fd01..bf19ad562 100644
--- a/tpl/strings/strings_test.go
+++ b/tpl/strings/strings_test.go
@@ -16,6 +16,7 @@ package strings
import (
"fmt"
"html/template"
+ "math"
"testing"
"github.com/gohugoio/hugo/deps"
@@ -709,3 +710,38 @@ func TestTrimSuffix(t *testing.T) {
assert.Equal(t, test.expect, result, errMsg)
}
}
+
+func TestRepeat(t *testing.T) {
+ t.Parallel()
+
+ for i, test := range []struct {
+ s interface{}
+ n interface{}
+ expect interface{}
+ }{
+ {"yo", "2", "yoyo"},
+ {"~", "16", "~~~~~~~~~~~~~~~~"},
+ {"<tag>", "0", ""},
+ {"yay", "1", "yay"},
+ {1221, "1", "1221"},
+ {1221, 2, "12211221"},
+ {template.HTML("<tag>"), "2", "<tag><tag>"},
+ {[]byte("<tag>"), 2, "<tag><tag>"},
+ // errors
+ {"", tstNoStringer{}, false},
+ {tstNoStringer{}, "", false},
+ {"hi", math.MaxInt16 + 1, false},
+ } {
+ errMsg := fmt.Sprintf("[%d] %v", i, test)
+
+ result, err := ns.Repeat(test.n, test.s)
+
+ if b, ok := test.expect.(bool); ok && !b {
+ require.Error(t, err, errMsg)
+ continue
+ }
+
+ require.NoError(t, err, errMsg)
+ assert.Equal(t, test.expect, result, errMsg)
+ }
+}