From 13b067b5064cc1c59ade383612906fce944dcf33 Mon Sep 17 00:00:00 2001 From: spf13 Date: Thu, 9 Jan 2014 17:27:39 -0500 Subject: [PATCH] Adding support for embedded templates --- template/bundle/template.go | 337 ++++++++++++++++++------------------ 1 file changed, 173 insertions(+), 164 deletions(-) diff --git a/template/bundle/template.go b/template/bundle/template.go index 8ce8561c0..2137d0187 100644 --- 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), "
") {
-		str = str[strings.Index(str, "
")+11:]
-	}
-	if strings.HasSuffix(strings.TrimSpace(str), "
") { - str = str[:strings.LastIndex(str, "
")] - } - return template.HTML(helpers.Highlight(html.UnescapeString(str), lang)) + if strings.HasPrefix(strings.TrimSpace(str), "
") {
+        str = str[strings.Index(str, "
")+11:]
+    }
+    if strings.HasSuffix(strings.TrimSpace(str), "
") { + str = str[:strings.LastIndex(str, "
")] + } + 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) }