Add base64Decode and base64Encode template functions

Fixes #1416
This commit is contained in:
digitalcraftsman 2015-09-12 21:45:12 +02:00 committed by Bjørn Erik Pedersen
parent a1e32439fb
commit 79f8bb625d
3 changed files with 145 additions and 53 deletions

View file

@ -650,3 +650,33 @@ In this version, we are now sorting the tags, converting them to links with "pos
{{ 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.

View file

@ -16,6 +16,7 @@ package tpl
import (
"bitbucket.org/pkg/inflect"
"bytes"
"encoding/base64"
"errors"
"fmt"
"html"
@ -1318,60 +1319,88 @@ func ModBool(a, b interface{}) (bool, error) {
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 @@ func init() {
return inflect.Singularize(word), nil
},
}
}

View file

@ -2,6 +2,7 @@ package tpl
import (
"bytes"
"encoding/base64"
"errors"
"fmt"
"html/template"
@ -1581,3 +1582,36 @@ func TestSafeURL(t *testing.T) {
}
}
}
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)
}
}