ref: b8d3651242947bbea46df8d6a9f0477406070019
parent: e9008b91fa0d5b0cc79c1133cd3658134ed6777d
author: Cameron Moore <[email protected]>
date: Mon Feb 8 11:57:52 EST 2016
tpl: Add replaceRE function This commit addes a `replaceRE` template function. Regexp patterns are compiled once and cached.
--- a/docs/content/templates/functions.md
+++ b/docs/content/templates/functions.md
@@ -451,6 +451,13 @@
e.g. `{{ replace "Batman and Robin" "Robin" "Catwoman" }}` → "Batman and Catwoman"
+### replaceRE
+Replaces all occurrences of a regular expression with the replacement pattern.
+
+e.g. `{{ replaceRE "^https?://([^/]+).*" "$1" "http://gohugo.io/docs" }}` → "gohugo.io"
+e.g. `{{ "http://gohugo.io/docs" | replaceRE "^https?://([^/]+).*" "$1" }}` → "gohugo.io"
+
+
### safeHTML
Declares the provided string as a "safe" HTML document fragment
so Go html/template will not filter it. It should not be used
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -29,6 +29,7 @@
"math/rand"
"os"
"reflect"
+ "regexp"
"sort"
"strconv"
"strings"
@@ -1230,6 +1231,37 @@
return strings.Replace(aStr, bStr, cStr, -1), nil
}
+var regexpCache = make(map[string]*regexp.Regexp)
+
+// replaceRE exposes a regular expression replacement function to the templates.
+func replaceRE(pattern, repl, src interface{}) (_ string, err error) {
+ patternStr, err := cast.ToStringE(pattern)
+ if err != nil {
+ return
+ }
+
+ replStr, err := cast.ToStringE(repl)
+ if err != nil {
+ return
+ }
+
+ srcStr, err := cast.ToStringE(src)
+ if err != nil {
+ return
+ }
+
+ if _, ok := regexpCache[patternStr]; !ok {
+ re, err2 := regexp.Compile(patternStr)
+ if err2 != nil {
+ return "", err2
+ }
+
+ regexpCache[patternStr] = re
+ }
+
+ return regexpCache[patternStr].ReplaceAllString(srcStr, replStr), err
+}
+
// dateFormat converts the textual representation of the datetime string into
// the other form or returns it of the time.Time value. These are formatted
// with the layout string
@@ -1717,6 +1749,7 @@
"relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },
"relref": relRef,
"replace": replace,
+ "replaceRE": replaceRE,
"safeCSS": safeCSS,
"safeHTML": safeHTML,
"safeJS": safeJS,
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -1781,6 +1781,27 @@
assert.NotNil(t, e, "tstNoStringer cannot be converted to string")
}
+func TestReplaceRE(t *testing.T) {
+ for i, val := range []struct {
+ pattern string
+ repl string
+ src string
+ expect string
+ ok bool
+ }{
+ {"^https?://([^/]+).*", "$1", "http://gohugo.io/docs", "gohugo.io", true},
+ {"^https?://([^/]+).*", "$2", "http://gohugo.io/docs", "", true},
+ {"(ab)", "AB", "aabbaab", "aABbaAB", true},
+ {"(ab", "AB", "aabb", "", false}, // invalid re
+ } {
+ v, err := replaceRE(val.pattern, val.repl, val.src)
+ if (err == nil) != val.ok {
+ t.Errorf("[%d] %s", i, err)
+ }
+ assert.Equal(t, val.expect, v)
+ }
+}
+
func TestTrim(t *testing.T) {
for i, this := range []struct {