ref: 79f8bb625d2a7379d8eb0afa7e144444b4567e3d
parent: a1e32439fbab314cab6f5c3ecb962b8ac7bd9069
author: digitalcraftsman <[email protected]>
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)
}
}