URI: 
       tpl: Return all errors from casting - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 5498a1bd5616903fce3df687adf43d19e1c4e4c4
   DIR parent d3627b1747c18eb18279012afe5ba7174bdaa869
  HTML Author: Cameron Moore <moorereason@gmail.com>
       Date:   Fri, 12 Aug 2016 17:43:15 -0500
       
       tpl: Return all errors from casting
       
       Most non-boolean template functions should return errors.
       
       Fixes #2354
       
       Diffstat:
         M tpl/template_funcs.go               |      76 +++++++++++++++++++++++--------
         M tpl/template_funcs_test.go          |      60 +++++++++++++++++++++++---------
       
       2 files changed, 100 insertions(+), 36 deletions(-)
       ---
   DIR diff --git a/tpl/template_funcs.go b/tpl/template_funcs.go
       @@ -447,7 +447,10 @@ func findRE(expr string, content interface{}, limit ...int) ([]string, error) {
                        return nil, err
                }
        
       -        conv := cast.ToString(content)
       +        conv, err := cast.ToStringE(content)
       +        if err != nil {
       +                return nil, err
       +        }
                if len(limit) > 0 {
                        return re.FindAllString(conv, limit[0]), nil
                }
       @@ -1204,12 +1207,15 @@ var markdownTrimPrefix = []byte("<p>")
        var markdownTrimSuffix = []byte("</p>\n")
        
        // markdownify renders a given string from Markdown to HTML.
       -func markdownify(in interface{}) template.HTML {
       -        text := cast.ToString(in)
       +func markdownify(in interface{}) (template.HTML, error) {
       +        text, err := cast.ToStringE(in)
       +        if err != nil {
       +                return "", err
       +        }
                m := helpers.RenderBytes(&helpers.RenderingContext{Content: []byte(text), PageFmt: "markdown"})
                m = bytes.TrimPrefix(m, markdownTrimPrefix)
                m = bytes.TrimSuffix(m, markdownTrimSuffix)
       -        return template.HTML(m)
       +        return template.HTML(m), nil
        }
        
        // jsonify encodes a given object to JSON.
       @@ -1219,7 +1225,6 @@ func jsonify(v interface{}) (template.HTML, error) {
                        return "", err
                }
                return template.HTML(b), nil
       -
        }
        
        // emojify "emojifies" the given string.
       @@ -1568,14 +1573,20 @@ func readFile(fs *afero.BasePathFs, filename string) (string, error) {
        // It returns the contents as a string.
        // There is a upper size limit set at 1 megabytes.
        func readFileFromWorkingDir(i interface{}) (string, error) {
       -        return readFile(hugofs.WorkingDir(), cast.ToString(i))
       +        s, err := cast.ToStringE(i)
       +        if err != nil {
       +                return "", err
       +        }
       +        return readFile(hugofs.WorkingDir(), s)
        }
        
        // readDirFromWorkingDir listst the directory content relative to the
        // configured WorkingDir.
        func readDirFromWorkingDir(i interface{}) ([]os.FileInfo, error) {
       -
       -        path := cast.ToString(i)
       +        path, err := cast.ToStringE(i)
       +        if err != nil {
       +                return nil, err
       +        }
        
                list, err := afero.ReadDir(hugofs.WorkingDir(), path)
        
       @@ -1587,25 +1598,34 @@ func readDirFromWorkingDir(i interface{}) ([]os.FileInfo, error) {
        }
        
        // safeHTMLAttr returns a given string as html/template HTMLAttr content.
       -func safeHTMLAttr(a interface{}) template.HTMLAttr {
       -        return template.HTMLAttr(cast.ToString(a))
       +func safeHTMLAttr(a interface{}) (template.HTMLAttr, error) {
       +        s, err := cast.ToStringE(a)
       +        return template.HTMLAttr(s), err
        }
        
        // safeCSS returns a given string as html/template CSS content.
       -func safeCSS(a interface{}) template.CSS {
       -        return template.CSS(cast.ToString(a))
       +func safeCSS(a interface{}) (template.CSS, error) {
       +        s, err := cast.ToStringE(a)
       +        return template.CSS(s), err
        }
        
        // safeURL returns a given string as html/template URL content.
       -func safeURL(a interface{}) template.URL {
       -        return template.URL(cast.ToString(a))
       +func safeURL(a interface{}) (template.URL, error) {
       +        s, err := cast.ToStringE(a)
       +        return template.URL(s), err
        }
        
        // safeHTML returns a given string as html/template HTML content.
       -func safeHTML(a interface{}) template.HTML { return template.HTML(cast.ToString(a)) }
       +func safeHTML(a interface{}) (template.HTML, error) {
       +        s, err := cast.ToStringE(a)
       +        return template.HTML(s), err
       +}
        
        // safeJS returns the given string as a html/template JS content.
       -func safeJS(a interface{}) template.JS { return template.JS(cast.ToString(a)) }
       +func safeJS(a interface{}) (template.JS, error) {
       +        s, err := cast.ToStringE(a)
       +        return template.JS(s), err
       +}
        
        // mod returns a % b.
        func mod(a, b interface{}) (int64, error) {
       @@ -1801,9 +1821,25 @@ func htmlUnescape(in interface{}) (string, error) {
                return html.UnescapeString(conv), nil
        }
        
       +func absURL(a interface{}) (template.HTML, error) {
       +        s, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", nil
       +        }
       +        return template.HTML(helpers.AbsURL(s)), nil
       +}
       +
       +func relURL(a interface{}) (template.HTML, error) {
       +        s, err := cast.ToStringE(a)
       +        if err != nil {
       +                return "", nil
       +        }
       +        return template.HTML(helpers.RelURL(s)), nil
       +}
       +
        func init() {
                funcMap = template.FuncMap{
       -                "absURL":       func(a interface{}) template.HTML { return template.HTML(helpers.AbsURL(cast.ToString(a))) },
       +                "absURL":       absURL,
                        "add":          func(a, b interface{}) (interface{}, error) { return helpers.DoArithmetic(a, b, '+') },
                        "after":        after,
                        "apply":        apply,
       @@ -1834,7 +1870,7 @@ func init() {
                        "humanize":     humanize,
                        "in":           in,
                        "index":        index,
       -                "int":          func(v interface{}) int { return cast.ToInt(v) },
       +                "int":          func(v interface{}) (int, error) { return cast.ToIntE(v) },
                        "intersect":    intersect,
                        "isSet":        isSet,
                        "isset":        isSet,
       @@ -1856,7 +1892,7 @@ func init() {
                        "readDir":      readDirFromWorkingDir,
                        "readFile":     readFileFromWorkingDir,
                        "ref":          ref,
       -                "relURL":       func(a interface{}) template.HTML { return template.HTML(helpers.RelURL(cast.ToString(a))) },
       +                "relURL":       relURL,
                        "relref":       relRef,
                        "replace":      replace,
                        "replaceRE":    replaceRE,
       @@ -1875,7 +1911,7 @@ func init() {
                        "slicestr":     slicestr,
                        "sort":         sortSeq,
                        "split":        split,
       -                "string":       func(v interface{}) string { return cast.ToString(v) },
       +                "string":       func(v interface{}) (string, error) { return cast.ToStringE(v) },
                        "sub":          func(a, b interface{}) (interface{}, error) { return helpers.DoArithmetic(a, b, '-') },
                        "substr":       substr,
                        "title":        func(a string) string { return strings.Title(a) },
   DIR diff --git a/tpl/template_funcs_test.go b/tpl/template_funcs_test.go
       @@ -1740,7 +1740,10 @@ func TestMarkdownify(t *testing.T) {
                        {"Hello **World!**", template.HTML("Hello <strong>World!</strong>")},
                        {[]byte("Hello Bytes **World!**"), template.HTML("Hello Bytes <strong>World!</strong>")},
                } {
       -                result := markdownify(this.in)
       +                result, err := markdownify(this.in)
       +                if err != nil {
       +                        t.Fatalf("[%d] unexpected error in markdownify", i, err)
       +                }
                        if !reflect.DeepEqual(result, this.expect) {
                                t.Errorf("[%d] markdownify got %v (type %v) but expected %v (type %v)", i, result, reflect.TypeOf(result), this.expect, reflect.TypeOf(this.expect))
                        }
       @@ -2127,12 +2130,17 @@ func TestSafeHTML(t *testing.T) {
                        }
        
                        buf.Reset()
       -                err = tmpl.Execute(buf, safeHTML(this.str))
       +                v, err := safeHTML(this.str)
       +                if err != nil {
       +                        t.Fatalf("[%d] unexpected error in safeHTML: %s", i, err)
       +                }
       +
       +                err = tmpl.Execute(buf, v)
                        if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTML returns unexpected error: %s", i, err)
       +                        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)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeHTML, got %v but expected %v", i, buf.String(), this.expectWithEscape)
                        }
                }
        }
       @@ -2162,12 +2170,17 @@ func TestSafeHTMLAttr(t *testing.T) {
                        }
        
                        buf.Reset()
       -                err = tmpl.Execute(buf, safeHTMLAttr(this.str))
       +                v, err := safeHTMLAttr(this.str)
                        if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeHTMLAttr returns unexpected error: %s", i, err)
       +                        t.Fatalf("[%d] unexpected error in safeHTMLAttr: %s", i, err)
       +                }
       +
       +                err = tmpl.Execute(buf, v)
       +                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)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeHTMLAttr, got %v but expected %v", i, buf.String(), this.expectWithEscape)
                        }
                }
        }
       @@ -2197,12 +2210,17 @@ func TestSafeCSS(t *testing.T) {
                        }
        
                        buf.Reset()
       -                err = tmpl.Execute(buf, safeCSS(this.str))
       +                v, err := safeCSS(this.str)
                        if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeCSS returns unexpected error: %s", i, err)
       +                        t.Fatalf("[%d] unexpected error in safeCSS: %s", i, err)
       +                }
       +
       +                err = tmpl.Execute(buf, v)
       +                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)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeCSS, got %v but expected %v", i, buf.String(), this.expectWithEscape)
                        }
                }
        }
       @@ -2232,12 +2250,17 @@ func TestSafeJS(t *testing.T) {
                        }
        
                        buf.Reset()
       -                err = tmpl.Execute(buf, safeJS(this.str))
       +                v, err := safeJS(this.str)
       +                if err != nil {
       +                        t.Fatalf("[%d] unexpected error in safeJS: %s", i, err)
       +                }
       +
       +                err = tmpl.Execute(buf, v)
                        if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeJS returns unexpected error: %s", i, err)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeJS returns unexpected error: %s", i, err)
                        }
                        if buf.String() != this.expectWithEscape {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeJS, got %v but expected %v", i, buf.String(), this.expectWithEscape)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeJS, got %v but expected %v", i, buf.String(), this.expectWithEscape)
                        }
                }
        }
       @@ -2267,12 +2290,17 @@ func TestSafeURL(t *testing.T) {
                        }
        
                        buf.Reset()
       -                err = tmpl.Execute(buf, safeURL(this.str))
       +                v, err := safeURL(this.str)
       +                if err != nil {
       +                        t.Fatalf("[%d] unexpected error in safeURL: %s", i, err)
       +                }
       +
       +                err = tmpl.Execute(buf, v)
                        if err != nil {
       -                        t.Errorf("[%d] execute template with an escaped string value by SafeURL returns unexpected error: %s", i, err)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeURL returns unexpected error: %s", i, err)
                        }
                        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)
       +                        t.Errorf("[%d] execute template with an escaped string value by safeURL, got %v but expected %v", i, buf.String(), this.expectWithEscape)
                        }
                }
        }