ref: 79f8bb625d2a7379d8eb0afa7e144444b4567e3d
parent: a1e32439fbab314cab6f5c3ecb962b8ac7bd9069
author: digitalcraftsman <digitalcraftsman@users.noreply.github.com>
date: Sat Sep 12 17:45:12 EDT 2015
Add base64Decode and base64Encode template functions Fixes #1416
--- a/docs/content/templates/functions.md
+++ b/docs/content/templates/functions.md
@@ -650,3 +650,33 @@
{{ end }}`apply` does not work when receiving the sequence as an argument through a pipeline.
+
+***
+
+### base64Encode and base64Decode
+
+`base64Encode` and `base64Decode` let you easily decode content with a base64 enconding and vice versa through pipes. Let's take a look at an example:
+
+
+ {{ "Hello world" | base64Encode }}+ <!-- will output "SGVsbG8gd29ybGQ=" and -->
+
+ {{ "SGVsbG8gd29ybGQ=" | base64Decode }}+ <!-- becomes "Hello world" again. -->
+
+You can also pass other datatypes as argument to the template function which tries
+to convert them. Now we use an integer instead of a string:
+
+
+ {{ 42 | base64Encode | base64Decode }}+ <!-- will output "42". Both functions always return a string. -->
+
+**Tip:** Using base64 to decode and encode becomes really powerful if we have to handle
+responses of APIs.
+
+ {{ $resp := getJSON "https://api.github.com/repos/spf13/hugo/readme" }}+ {{ $resp.content | base64Decode | markdownify }}+
+ The response of the Github API contains the base64-encoded version of the [README.md](https://github.com/spf13/hugo/blob/master/README.md) in the Hugo repository.
+Now we can decode it and parse the Markdown. The final output will look similar to the
+rendered version in Github.
--- a/tpl/template_funcs.go
+++ b/tpl/template_funcs.go
@@ -16,6 +16,7 @@
import (
"bitbucket.org/pkg/inflect"
"bytes"
+ "encoding/base64"
"errors"
"fmt"
"html"
@@ -1318,60 +1319,88 @@
return res == int64(0), nil
}
+func Base64Decode(content interface{}) (string, error) {+ conv, err := cast.ToStringE(content)
+
+ if err != nil {+ return "", err
+ }
+
+ dec, err := base64.StdEncoding.DecodeString(conv)
+
+ if err != nil {+ return "", err
+ }
+
+ return string(dec), nil
+}
+
+func Base64Encode(content interface{}) (string, error) {+ conv, err := cast.ToStringE(content)
+
+ if err != nil {+ return "", err
+ }
+
+ return base64.StdEncoding.EncodeToString([]byte(conv)), nil
+}
+
func init() { funcMap = template.FuncMap{- "urlize": helpers.URLize,
- "sanitizeURL": helpers.SanitizeURL,
- "sanitizeurl": helpers.SanitizeURL,
- "eq": Eq,
- "ne": Ne,
- "gt": Gt,
- "ge": Ge,
- "lt": Lt,
- "le": Le,
- "in": In,
- "slicestr": Slicestr,
- "substr": Substr,
- "split": Split,
- "intersect": Intersect,
- "isSet": IsSet,
- "isset": IsSet,
- "echoParam": ReturnWhenSet,
- "safeHTML": SafeHTML,
- "safeCSS": SafeCSS,
- "safeURL": SafeURL,
- "absURL": func(a string) template.HTML { return template.HTML(helpers.AbsURL(a)) },- "relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },- "markdownify": Markdownify,
- "first": First,
- "last": Last,
- "after": After,
- "where": Where,
- "delimit": Delimit,
- "sort": Sort,
- "highlight": Highlight,
- "add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },- "sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },- "div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },- "mod": Mod,
- "mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },- "modBool": ModBool,
- "lower": func(a string) string { return strings.ToLower(a) },- "upper": func(a string) string { return strings.ToUpper(a) },- "title": func(a string) string { return strings.Title(a) },- "partial": Partial,
- "ref": Ref,
- "relref": RelRef,
- "apply": Apply,
- "chomp": Chomp,
- "replace": Replace,
- "trim": Trim,
- "dateFormat": DateFormat,
- "getJSON": GetJSON,
- "getCSV": GetCSV,
- "readDir": ReadDir,
- "seq": helpers.Seq,
- "getenv": func(varName string) string { return os.Getenv(varName) },+ "urlize": helpers.URLize,
+ "sanitizeURL": helpers.SanitizeURL,
+ "sanitizeurl": helpers.SanitizeURL,
+ "eq": Eq,
+ "ne": Ne,
+ "gt": Gt,
+ "ge": Ge,
+ "lt": Lt,
+ "le": Le,
+ "in": In,
+ "slicestr": Slicestr,
+ "substr": Substr,
+ "split": Split,
+ "intersect": Intersect,
+ "isSet": IsSet,
+ "isset": IsSet,
+ "echoParam": ReturnWhenSet,
+ "safeHTML": SafeHTML,
+ "safeCSS": SafeCSS,
+ "safeURL": SafeURL,
+ "absURL": func(a string) template.HTML { return template.HTML(helpers.AbsURL(a)) },+ "relURL": func(a string) template.HTML { return template.HTML(helpers.RelURL(a)) },+ "markdownify": Markdownify,
+ "first": First,
+ "last": Last,
+ "after": After,
+ "where": Where,
+ "delimit": Delimit,
+ "sort": Sort,
+ "highlight": Highlight,
+ "add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },+ "sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },+ "div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },+ "mod": Mod,
+ "mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },+ "modBool": ModBool,
+ "lower": func(a string) string { return strings.ToLower(a) },+ "upper": func(a string) string { return strings.ToUpper(a) },+ "title": func(a string) string { return strings.Title(a) },+ "partial": Partial,
+ "ref": Ref,
+ "relref": RelRef,
+ "apply": Apply,
+ "chomp": Chomp,
+ "replace": Replace,
+ "trim": Trim,
+ "dateFormat": DateFormat,
+ "getJSON": GetJSON,
+ "getCSV": GetCSV,
+ "readDir": ReadDir,
+ "seq": helpers.Seq,
+ "getenv": func(varName string) string { return os.Getenv(varName) },+ "base64Decode": Base64Decode,
+ "base64Encode": Base64Encode,
"pluralize": func(in interface{}) (string, error) {word, err := cast.ToStringE(in)
if err != nil {@@ -1387,5 +1416,4 @@
return inflect.Singularize(word), nil
},
}
-
}
--- a/tpl/template_funcs_test.go
+++ b/tpl/template_funcs_test.go
@@ -2,6 +2,7 @@
import (
"bytes"
+ "encoding/base64"
"errors"
"fmt"
"html/template"
@@ -1579,5 +1580,38 @@
if buf.String() != this.expectWithEscape { t.Errorf("[%d] execute template with an escaped string value by SafeURL, got %v but expected %v", i, buf.String(), this.expectWithEscape)}
+ }
+}
+
+func TestBase64Decode(t *testing.T) {+ testStr := "abc123!?$*&()'-=@~"
+ enc := base64.StdEncoding.EncodeToString([]byte(testStr))
+ result, err := Base64Decode(enc)
+
+ if err != nil {+ t.Error("Base64Decode:", err)+ }
+
+ if result != testStr {+ t.Errorf("Base64Decode: got '%s', expected '%s'", result, testStr)+ }
+}
+
+func TestBase64Encode(t *testing.T) {+ testStr := "YWJjMTIzIT8kKiYoKSctPUB+"
+ dec, err := base64.StdEncoding.DecodeString(testStr)
+
+ if err != nil {+ t.Error("Base64Encode: the DecodeString function of the base64 package returned an error.", err)+ }
+
+ result, err := Base64Encode(string(dec))
+
+ if err != nil {+ t.Errorf("Base64Encode: Can't cast arg '%s' into a string.", testStr)+ }
+
+ if result != testStr {+ t.Errorf("Base64Encode: got '%s', expected '%s'", result, testStr)}
}
--
⑨