tpl/strings: strings.RuneCount
authorDavid E. Wheeler <david@justatheory.com>
Mon, 4 Jun 2018 17:47:03 +0000 (13:47 -0400)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Mon, 4 Jun 2018 17:47:03 +0000 (20:47 +0300)
docs/content/en/functions/strings.RuneCount.md [new file with mode: 0644]
docs/data/docs.json
tpl/strings/init.go
tpl/strings/strings.go
tpl/strings/strings_test.go

diff --git a/docs/content/en/functions/strings.RuneCount.md b/docs/content/en/functions/strings.RuneCount.md
new file mode 100644 (file)
index 0000000..63012ab
--- /dev/null
@@ -0,0 +1,28 @@
+---
+title: strings.RuneCount
+description: Determines the number of runes in a string.
+godocref:
+date: 2018-06-01
+publishdate: 2018-06-01
+lastmod: 2018-06-01
+categories: [functions]
+menu:
+  docs:
+    parent: "functions"
+keywords: [counting, character count, length, rune length, rune count]
+signature: ["strings.RuneCount INPUT"]
+workson: []
+hugoversion:
+relatedfuncs: ["len", "countrunes"]
+deprecated: false
+aliases: []
+---
+
+In contrast with `strings.CountRunes` function, which strips HTML and whitespace before counting runes, `strings.RuneCount` simply counts all the runes in a string. It relies on the Go [`utf8.RuneCountInString`] function.
+
+```
+{{ "Hello, 世界" | strings.RuneCount }}
+<!-- outputs a content length of 9 runes. -->
+```
+
+[`utf8.RuneCount`]: https://golang.org/pkg/unicode/utf8/#RuneCount
\ No newline at end of file
index 4eddf8eae100da30613b07d6ce1525fb33920368..3020a21f210ee78279214d0782daee2b3fb19d9d 100644 (file)
           "Aliases": [
             "countrunes"
           ],
-          "Examples": []
+          "Examples": [
+            [
+              "{{ \"Hello, 世界\" | countrunes }}",
+              "8"
+            ]
+          ]
+        },
+        "RuneCount": {
+          "Description": "RuneCount returns the number of runes in s",
+          "Args": [
+            "s"
+          ],
+          "Aliases": [],
+          "Examples": [
+            [
+              "{{ \"Hello, 世界\" | strings.RuneCount }}",
+              "9"
+            ]
+          ]
         },
         "CountWords": {
           "Description": "CountWords returns the approximate word count in s.",
index 883ce76d1e0f95283d69a01fd040da9fd0d6bff3..8ff4cf98f5960d32a77808b91dc7afe29244adcf 100644 (file)
@@ -41,6 +41,11 @@ func init() {
                        [][2]string{},
                )
 
+               ns.AddMethodMapping(ctx.RuneCount,
+                       nil,
+                       [][2]string{},
+               )
+
                ns.AddMethodMapping(ctx.CountWords,
                        []string{"countwords"},
                        [][2]string{},
index d7d8f2d85f917326bf6e0f991af637a0960d69fb..1864bb9e054966074206497c33924d2efbcbed7b 100644 (file)
@@ -57,6 +57,15 @@ func (ns *Namespace) CountRunes(s interface{}) (int, error) {
        return counter, nil
 }
 
+// RuneCount returns the number of runes in s.
+func (ns *Namespace) RuneCount(s interface{}) (int, error) {
+       ss, err := cast.ToStringE(s)
+       if err != nil {
+               return 0, fmt.Errorf("Failed to convert content to string: %s", err)
+       }
+       return utf8.RuneCountInString(ss), nil
+}
+
 // CountWords returns the approximate word count in s.
 func (ns *Namespace) CountWords(s interface{}) (int, error) {
        ss, err := cast.ToStringE(s)
index 69863c30dd122e5145d0b4405285e35fefca7178..22695ba08957871291e4f954dbc99191d8070771 100644 (file)
@@ -173,6 +173,33 @@ func TestCountRunes(t *testing.T) {
        }
 }
 
+func TestRuneCount(t *testing.T) {
+       t.Parallel()
+
+       for i, test := range []struct {
+               s      interface{}
+               expect interface{}
+       }{
+               {"foo bar", 7},
+               {"旁边", 2},
+               {`<div class="test">旁边</div>`, 26},
+               // errors
+               {tstNoStringer{}, false},
+       } {
+               errMsg := fmt.Sprintf("[%d] %v", i, test.s)
+
+               result, err := ns.RuneCount(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)
+       }
+}
+
 func TestCountWords(t *testing.T) {
        t.Parallel()