mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Add SafeHtmlAttr, SafeCSS template function
This allows a template user to keep a safe HTML attribute or CSS string as is in a template. This is implementation of @anthonyfok great insight Fix #784, #347
This commit is contained in:
parent
53b4ab4cf3
commit
f5946ea3dd
2 changed files with 150 additions and 35 deletions
|
@ -910,6 +910,14 @@ func SafeHtml(text string) template.HTML {
|
||||||
return template.HTML(text)
|
return template.HTML(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SafeHtmlAttr(text string) template.HTMLAttr {
|
||||||
|
return template.HTMLAttr(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SafeCSS(text string) template.CSS {
|
||||||
|
return template.CSS(text)
|
||||||
|
}
|
||||||
|
|
||||||
func doArithmetic(a, b interface{}, op rune) (interface{}, error) {
|
func doArithmetic(a, b interface{}, op rune) (interface{}, error) {
|
||||||
av := reflect.ValueOf(a)
|
av := reflect.ValueOf(a)
|
||||||
bv := reflect.ValueOf(b)
|
bv := reflect.ValueOf(b)
|
||||||
|
@ -1230,41 +1238,43 @@ func (t *GoHtmlTemplate) LoadTemplates(absPath string) {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
funcMap = template.FuncMap{
|
funcMap = template.FuncMap{
|
||||||
"urlize": helpers.Urlize,
|
"urlize": helpers.Urlize,
|
||||||
"sanitizeurl": helpers.SanitizeUrl,
|
"sanitizeurl": helpers.SanitizeUrl,
|
||||||
"eq": Eq,
|
"eq": Eq,
|
||||||
"ne": Ne,
|
"ne": Ne,
|
||||||
"gt": Gt,
|
"gt": Gt,
|
||||||
"ge": Ge,
|
"ge": Ge,
|
||||||
"lt": Lt,
|
"lt": Lt,
|
||||||
"le": Le,
|
"le": Le,
|
||||||
"in": In,
|
"in": In,
|
||||||
"intersect": Intersect,
|
"intersect": Intersect,
|
||||||
"isset": IsSet,
|
"isset": IsSet,
|
||||||
"echoParam": ReturnWhenSet,
|
"echoParam": ReturnWhenSet,
|
||||||
"safeHtml": SafeHtml,
|
"safeHtml": SafeHtml,
|
||||||
"markdownify": Markdownify,
|
"safeHtmlAttr": SafeHtmlAttr,
|
||||||
"first": First,
|
"safeCSS": SafeCSS,
|
||||||
"where": Where,
|
"markdownify": Markdownify,
|
||||||
"delimit": Delimit,
|
"first": First,
|
||||||
"sort": Sort,
|
"where": Where,
|
||||||
"highlight": Highlight,
|
"delimit": Delimit,
|
||||||
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
"sort": Sort,
|
||||||
"sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
|
"highlight": Highlight,
|
||||||
"div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
|
"add": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '+') },
|
||||||
"mod": Mod,
|
"sub": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '-') },
|
||||||
"mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
|
"div": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '/') },
|
||||||
"modBool": ModBool,
|
"mod": Mod,
|
||||||
"lower": func(a string) string { return strings.ToLower(a) },
|
"mul": func(a, b interface{}) (interface{}, error) { return doArithmetic(a, b, '*') },
|
||||||
"upper": func(a string) string { return strings.ToUpper(a) },
|
"modBool": ModBool,
|
||||||
"title": func(a string) string { return strings.Title(a) },
|
"lower": func(a string) string { return strings.ToLower(a) },
|
||||||
"partial": Partial,
|
"upper": func(a string) string { return strings.ToUpper(a) },
|
||||||
"ref": Ref,
|
"title": func(a string) string { return strings.Title(a) },
|
||||||
"relref": RelRef,
|
"partial": Partial,
|
||||||
"apply": Apply,
|
"ref": Ref,
|
||||||
"chomp": Chomp,
|
"relref": RelRef,
|
||||||
"replace": Replace,
|
"apply": Apply,
|
||||||
"trim": Trim,
|
"chomp": Chomp,
|
||||||
|
"replace": Replace,
|
||||||
|
"trim": Trim,
|
||||||
}
|
}
|
||||||
|
|
||||||
chompRegexp = regexp.MustCompile("[\r\n]+$")
|
chompRegexp = regexp.MustCompile("[\r\n]+$")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package tpl
|
package tpl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
@ -826,3 +827,107 @@ func TestMarkdownify(t *testing.T) {
|
||||||
t.Errorf("Markdownify: got '%s', expected '%s'", result, expect)
|
t.Errorf("Markdownify: got '%s', expected '%s'", result, expect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSafeHtml(t *testing.T) {
|
||||||
|
for i, this := range []struct {
|
||||||
|
str string
|
||||||
|
tmplStr string
|
||||||
|
expectWithoutEscape string
|
||||||
|
expectWithEscape string
|
||||||
|
}{
|
||||||
|
{`<div></div>`, `{{ . }}`, `<div></div>`, `<div></div>`},
|
||||||
|
} {
|
||||||
|
tmpl, err := template.New("test").Parse(this.tmplStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unable to create new html template %q: %s", this.tmplStr, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = tmpl.Execute(buf, this.str)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithoutEscape {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
err = tmpl.Execute(buf, SafeHtml(this.str))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeHtml returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithEscape {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeHtml, got %v but expected %v", i, buf.String(), this.expectWithEscape)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSafeHtmlAttr(t *testing.T) {
|
||||||
|
for i, this := range []struct {
|
||||||
|
str string
|
||||||
|
tmplStr string
|
||||||
|
expectWithoutEscape string
|
||||||
|
expectWithEscape string
|
||||||
|
}{
|
||||||
|
{`href="irc://irc.freenode.net/#golang"`, `<a {{ . }}>irc</a>`, `<a ZgotmplZ>irc</a>`, `<a href="irc://irc.freenode.net/#golang">irc</a>`},
|
||||||
|
} {
|
||||||
|
tmpl, err := template.New("test").Parse(this.tmplStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unable to create new html template %q: %s", this.tmplStr, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = tmpl.Execute(buf, this.str)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithoutEscape {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
err = tmpl.Execute(buf, SafeHtmlAttr(this.str))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeHtmlAttr returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithEscape {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeHtmlAttr, got %v but expected %v", i, buf.String(), this.expectWithEscape)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSafeCSS(t *testing.T) {
|
||||||
|
for i, this := range []struct {
|
||||||
|
str string
|
||||||
|
tmplStr string
|
||||||
|
expectWithoutEscape string
|
||||||
|
expectWithEscape string
|
||||||
|
}{
|
||||||
|
{`width: 60px;`, `<div style="{{ . }}"></div>`, `<div style="ZgotmplZ"></div>`, `<div style="width: 60px;"></div>`},
|
||||||
|
} {
|
||||||
|
tmpl, err := template.New("test").Parse(this.tmplStr)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] unable to create new html template %q: %s", this.tmplStr, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
err = tmpl.Execute(buf, this.str)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithoutEscape {
|
||||||
|
t.Errorf("[%d] execute template with a raw string value, got %v but expected %v", i, buf.String(), this.expectWithoutEscape)
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.Reset()
|
||||||
|
err = tmpl.Execute(buf, SafeCSS(this.str))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeCSS returns unexpected error: %s", i, err)
|
||||||
|
}
|
||||||
|
if buf.String() != this.expectWithEscape {
|
||||||
|
t.Errorf("[%d] execute template with an escaped string value by SafeCSS, got %v but expected %v", i, buf.String(), this.expectWithEscape)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue