ref: 13b067b5064cc1c59ade383612906fce944dcf33
parent: f78e2cb854a639789fdac37a19f895435a18a938
author: spf13 <steve.francia@gmail.com>
date: Thu Jan 9 12:27:39 EST 2014
Adding support for embedded templates
--- a/template/bundle/template.go
+++ b/template/bundle/template.go
@@ -1,235 +1,244 @@
package bundle
import (
- "errors"
- "github.com/eknkc/amber"
- "github.com/spf13/hugo/helpers"
- "html"
- "html/template"
- "io"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "strconv"
- "strings"
+ "errors"
+ "github.com/eknkc/amber"
+ "github.com/spf13/hugo/helpers"
+ "html"
+ "html/template"
+ "io"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "reflect"
+ "strconv"
+ "strings"
)
func Gt(a interface{}, b interface{}) bool {- var left, right int64
- av := reflect.ValueOf(a)
+ var left, right int64
+ av := reflect.ValueOf(a)
- switch av.Kind() {- case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
- left = int64(av.Len())
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- left = av.Int()
- case reflect.String:
- left, _ = strconv.ParseInt(av.String(), 10, 64)
- }
+ switch av.Kind() {+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
+ left = int64(av.Len())
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ left = av.Int()
+ case reflect.String:
+ left, _ = strconv.ParseInt(av.String(), 10, 64)
+ }
- bv := reflect.ValueOf(b)
+ bv := reflect.ValueOf(b)
- switch bv.Kind() {- case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
- right = int64(bv.Len())
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- right = bv.Int()
- case reflect.String:
- right, _ = strconv.ParseInt(bv.String(), 10, 64)
- }
+ switch bv.Kind() {+ case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
+ right = int64(bv.Len())
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ right = bv.Int()
+ case reflect.String:
+ right, _ = strconv.ParseInt(bv.String(), 10, 64)
+ }
- return left > right
+ return left > right
}
// First is exposed to templates, to iterate over the first N items in a
// rangeable list.
func First(limit int, seq interface{}) (interface{}, error) {- if limit < 1 {- return nil, errors.New("can't return negative/empty count of items from sequence")- }
+ if limit < 1 {+ return nil, errors.New("can't return negative/empty count of items from sequence")+ }
- seqv := reflect.ValueOf(seq)
- // this is better than my first pass; ripped from text/template/exec.go indirect():
- for ; seqv.Kind() == reflect.Ptr || seqv.Kind() == reflect.Interface; seqv = seqv.Elem() {- if seqv.IsNil() {- return nil, errors.New("can't iterate over a nil value")- }
- if seqv.Kind() == reflect.Interface && seqv.NumMethod() > 0 {- break
- }
- }
+ seqv := reflect.ValueOf(seq)
+ // this is better than my first pass; ripped from text/template/exec.go indirect():
+ for ; seqv.Kind() == reflect.Ptr || seqv.Kind() == reflect.Interface; seqv = seqv.Elem() {+ if seqv.IsNil() {+ return nil, errors.New("can't iterate over a nil value")+ }
+ if seqv.Kind() == reflect.Interface && seqv.NumMethod() > 0 {+ break
+ }
+ }
- switch seqv.Kind() {- case reflect.Array, reflect.Slice, reflect.String:
- // okay
- default:
- return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())- }
- if limit > seqv.Len() {- limit = seqv.Len()
- }
- return seqv.Slice(0, limit).Interface(), nil
+ switch seqv.Kind() {+ case reflect.Array, reflect.Slice, reflect.String:
+ // okay
+ default:
+ return nil, errors.New("can't iterate over " + reflect.ValueOf(seq).Type().String())+ }
+ if limit > seqv.Len() {+ limit = seqv.Len()
+ }
+ return seqv.Slice(0, limit).Interface(), nil
}
func IsSet(a interface{}, key interface{}) bool {- av := reflect.ValueOf(a)
- kv := reflect.ValueOf(key)
+ av := reflect.ValueOf(a)
+ kv := reflect.ValueOf(key)
- switch av.Kind() {- case reflect.Array, reflect.Chan, reflect.Slice:
- if int64(av.Len()) > kv.Int() {- return true
- }
- case reflect.Map:
- if kv.Type() == av.Type().Key() {- return av.MapIndex(kv).IsValid()
- }
- }
+ switch av.Kind() {+ case reflect.Array, reflect.Chan, reflect.Slice:
+ if int64(av.Len()) > kv.Int() {+ return true
+ }
+ case reflect.Map:
+ if kv.Type() == av.Type().Key() {+ return av.MapIndex(kv).IsValid()
+ }
+ }
- return false
+ return false
}
func ReturnWhenSet(a interface{}, index int) interface{} {- av := reflect.ValueOf(a)
+ av := reflect.ValueOf(a)
- switch av.Kind() {- case reflect.Array, reflect.Slice:
- if av.Len() > index {+ switch av.Kind() {+ case reflect.Array, reflect.Slice:
+ if av.Len() > index {- avv := av.Index(index)
- switch avv.Kind() {- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- return avv.Int()
- case reflect.String:
- return avv.String()
- }
- }
- }
+ avv := av.Index(index)
+ switch avv.Kind() {+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return avv.Int()
+ case reflect.String:
+ return avv.String()
+ }
+ }
+ }
- return ""
+ return ""
}
func Highlight(in interface{}, lang string) template.HTML {- var str string
- av := reflect.ValueOf(in)
- switch av.Kind() {- case reflect.String:
- str = av.String()
- }
+ var str string
+ av := reflect.ValueOf(in)
+ switch av.Kind() {+ case reflect.String:
+ str = av.String()
+ }
- if strings.HasPrefix(strings.TrimSpace(str), "<pre><code>") {- str = str[strings.Index(str, "<pre><code>")+11:]
- }
- if strings.HasSuffix(strings.TrimSpace(str), "</code></pre>") {- str = str[:strings.LastIndex(str, "</code></pre>")]
- }
- return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
+ if strings.HasPrefix(strings.TrimSpace(str), "<pre><code>") {+ str = str[strings.Index(str, "<pre><code>")+11:]
+ }
+ if strings.HasSuffix(strings.TrimSpace(str), "</code></pre>") {+ str = str[:strings.LastIndex(str, "</code></pre>")]
+ }
+ return template.HTML(helpers.Highlight(html.UnescapeString(str), lang))
}
func SafeHtml(text string) template.HTML {- return template.HTML(text)
+ return template.HTML(text)
}
type Template interface {- ExecuteTemplate(wr io.Writer, name string, data interface{}) error- Lookup(name string) *template.Template
- Templates() []*template.Template
- New(name string) *template.Template
- LoadTemplates(absPath string)
- AddTemplate(name, tpl string) error
+ ExecuteTemplate(wr io.Writer, name string, data interface{}) error+ Lookup(name string) *template.Template
+ Templates() []*template.Template
+ New(name string) *template.Template
+ LoadTemplates(absPath string)
+ AddTemplate(name, tpl string) error
}
type templateErr struct {- name string
- err error
+ name string
+ err error
}
type GoHtmlTemplate struct {- template.Template
- errors []*templateErr
+ template.Template
+ errors []*templateErr
}
func NewTemplate() Template {- var templates = &GoHtmlTemplate{- Template: *template.New(""),- errors: make([]*templateErr, 0),
- }
+ var templates = &GoHtmlTemplate{+ Template: *template.New(""),+ errors: make([]*templateErr, 0),
+ }
- funcMap := template.FuncMap{- "urlize": helpers.Urlize,
- "gt": Gt,
- "isset": IsSet,
- "echoParam": ReturnWhenSet,
- "safeHtml": SafeHtml,
- "first": First,
- "highlight": Highlight,
- }
+ funcMap := template.FuncMap{+ "urlize": helpers.Urlize,
+ "gt": Gt,
+ "isset": IsSet,
+ "echoParam": ReturnWhenSet,
+ "safeHtml": SafeHtml,
+ "first": First,
+ "highlight": Highlight,
+ }
- templates.Funcs(funcMap)
- return templates
+ templates.Funcs(funcMap)
+
+ templates.LoadEmbedded()
+ return templates
}
+func (t *GoHtmlTemplate) LoadEmbedded() {+}
+
+func (t *GoHtmlTemplate) AddInternalTemplate(prefix, name, tpl string) error {+ return t.AddTemplate("_internal/"+prefix+"/"+name, tpl)+}
+
func (t *GoHtmlTemplate) AddTemplate(name, tpl string) error {- _, err := t.New(name).Parse(tpl)
- if err != nil {- t.errors = append(t.errors, &templateErr{name: name, err: err})- }
- return err
+ _, err := t.New(name).Parse(tpl)
+ if err != nil {+ t.errors = append(t.errors, &templateErr{name: name, err: err})+ }
+ return err
}
func (t *GoHtmlTemplate) AddTemplateFile(name, path string) error {- b, err := ioutil.ReadFile(path)
- if err != nil {- return err
- }
- s := string(b)
- _, err = t.New(name).Parse(s)
- if err != nil {- t.errors = append(t.errors, &templateErr{name: name, err: err})- }
- return err
+ b, err := ioutil.ReadFile(path)
+ if err != nil {+ return err
+ }
+ s := string(b)
+ _, err = t.New(name).Parse(s)
+ if err != nil {+ t.errors = append(t.errors, &templateErr{name: name, err: err})+ }
+ return err
}
func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string {- return filepath.ToSlash(path[len(base)+1:])
+ return filepath.ToSlash(path[len(base)+1:])
}
func ignoreDotFile(path string) bool {- return filepath.Base(path)[0] == '.'
+ return filepath.Base(path)[0] == '.'
}
func (t *GoHtmlTemplate) LoadTemplates(absPath string) {- walker := func(path string, fi os.FileInfo, err error) error {- if err != nil {- return nil
- }
+ walker := func(path string, fi os.FileInfo, err error) error {+ if err != nil {+ return nil
+ }
- if !fi.IsDir() {- if ignoreDotFile(path) {- return nil
- }
+ if !fi.IsDir() {+ if ignoreDotFile(path) {+ return nil
+ }
- tplName := t.generateTemplateNameFrom(absPath, path)
+ tplName := t.generateTemplateNameFrom(absPath, path)
- if strings.HasSuffix(path, ".amber") {- compiler := amber.New()
- // Parse the input file
- if err := compiler.ParseFile(path); err != nil {- return nil
- }
+ if strings.HasSuffix(path, ".amber") {+ compiler := amber.New()
+ // Parse the input file
+ if err := compiler.ParseFile(path); err != nil {+ return nil
+ }
- // note t.New(tplName)
- if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {- return err
- }
+ // note t.New(tplName)
+ if _, err := compiler.CompileWithTemplate(t.New(tplName)); err != nil {+ return err
+ }
- } else {- t.AddTemplateFile(tplName, path)
- }
- }
- return nil
- }
+ } else {+ t.AddTemplateFile(tplName, path)
+ }
+ }
+ return nil
+ }
- filepath.Walk(absPath, walker)
+ filepath.Walk(absPath, walker)
}
--
⑨