ref: 13b067b5064cc1c59ade383612906fce944dcf33
parent: f78e2cb854a639789fdac37a19f895435a18a938
author: spf13 <[email protected]>
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)
}