diff --git a/docs/content/templates/functions.md b/docs/content/templates/functions.md index 29f265832..350d0782a 100644 --- a/docs/content/templates/functions.md +++ b/docs/content/templates/functions.md @@ -525,6 +525,26 @@ Converts all characters in string to uppercase. e.g. `{{upper "BatMan"}}` β†’ "BATMAN" +### countwords + +`countwords` tries to convert the passed content to a string and counts each word +in it. The template functions works similar to [.WordCount]({{< relref "templates/variables.md#page-variables" >}}). + +```html +{{ "Hugo is a static site generator." | countwords }} + +``` + + +### countrunes + +Alternatively to counting all words , `countrunes` determines the number of runes in the content and excludes any whitespace. This can become useful if you have to deal with +CJK-like languages. + +```html +{{ "Hello, δΈ–η•Œ" | countrunes }} + +``` ## URLs diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go index 8368bac84..e7166ea1c 100644 --- a/tpl/template_funcs.go +++ b/tpl/template_funcs.go @@ -26,6 +26,7 @@ import ( "strconv" "strings" "time" + "unicode/utf8" "bitbucket.org/pkg/inflect" @@ -1385,6 +1386,43 @@ func Base64Encode(content interface{}) (string, error) { return base64.StdEncoding.EncodeToString([]byte(conv)), nil } +func CountWords(content interface{}) (int, error) { + conv, err := cast.ToStringE(content) + + if err != nil { + return 0, errors.New("Failed to convert content to string: " + err.Error()) + } + + counter := 0 + for _, word := range strings.Fields(helpers.StripHTML(conv)) { + runeCount := utf8.RuneCountInString(word) + if len(word) == runeCount { + counter++ + } else { + counter += runeCount + } + } + + return counter, nil +} + +func CountRunes(content interface{}) (int, error) { + conv, err := cast.ToStringE(content) + + if err != nil { + return 0, errors.New("Failed to convert content to string: " + err.Error()) + } + + counter := 0 + for _, r := range helpers.StripHTML(conv) { + if !helpers.IsWhitespace(r) { + counter++ + } + } + + return counter, nil +} + func init() { funcMap = template.FuncMap{ "urlize": helpers.URLize, @@ -1444,6 +1482,8 @@ func init() { "getenv": func(varName string) string { return os.Getenv(varName) }, "base64Decode": Base64Decode, "base64Encode": Base64Encode, + "countwords": CountWords, + "countrunes": CountRunes, "pluralize": func(in interface{}) (string, error) { word, err := cast.ToStringE(in) if err != nil {