summaryrefslogtreecommitdiffstats
path: root/tpl/template.go
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-03-27 20:43:49 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2017-04-02 23:13:10 +0200
commit8b5b558bb515e80da640f5e114169874771b61e4 (patch)
tree5755e77efe3120963d012dccbd91d916180485e0 /tpl/template.go
parent27610ddd011e8172d00e02275f948c3f1ed43e4f (diff)
tpl: Rework to handle both text and HTML templates
Before this commit, Hugo used `html/template` for all Go templates. While this is a fine choice for HTML and maybe also RSS feeds, it is painful for plain text formats such as CSV, JSON etc. This commit fixes that by using the `IsPlainText` attribute on the output format to decide what to use. A couple of notes: * The above requires a nonambiguous template name to type mapping. I.e. `/layouts/_default/list.json` will only work if there is only one JSON output format, `/layouts/_default/list.mytype.json` will always work. * Ambiguous types will fall back to HTML. * Partials inherits the text vs HTML identificator of the container template. This also means that plain text templates can only include plain text partials. * Shortcode templates are, by definition, currently HTML templates only. Fixes #3221
Diffstat (limited to 'tpl/template.go')
-rw-r--r--tpl/template.go111
1 files changed, 93 insertions, 18 deletions
diff --git a/tpl/template.go b/tpl/template.go
index b94fc3242..617aa84ec 100644
--- a/tpl/template.go
+++ b/tpl/template.go
@@ -1,28 +1,103 @@
+// Copyright 2017-present The Hugo Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
package tpl
import (
- "html/template"
"io"
+
+ "text/template/parse"
+
+ "html/template"
+ texttemplate "text/template"
+
+ bp "github.com/spf13/hugo/bufferpool"
)
-// TODO(bep) make smaller
-type Template interface {
- ExecuteTemplate(wr io.Writer, name string, data interface{}) error
- ExecuteTemplateToHTML(context interface{}, layouts ...string) template.HTML
- Lookup(name string) *template.Template
- Templates() []*template.Template
- New(name string) *template.Template
- GetClone() *template.Template
- RebuildClone() *template.Template
- LoadTemplates(absPath string)
- LoadTemplatesWithPrefix(absPath, prefix string)
+var (
+ _ TemplateExecutor = (*TemplateAdapter)(nil)
+)
+
+// TemplateHandler manages the collection of templates.
+type TemplateHandler interface {
+ TemplateFinder
AddTemplate(name, tpl string) error
- AddTemplateFileWithMaster(name, overlayFilename, masterFilename string) error
- AddAceTemplate(name, basePath, innerPath string, baseContent, innerContent []byte) error
- AddInternalTemplate(prefix, name, tpl string) error
- AddInternalShortcode(name, tpl string) error
- Partial(name string, contextList ...interface{}) template.HTML
+ AddLateTemplate(name, tpl string) error
+ LoadTemplates(absPath, prefix string)
PrintErrors()
- Funcs(funcMap template.FuncMap)
+
MarkReady()
+ RebuildClone()
+}
+
+// TemplateFinder finds templates.
+type TemplateFinder interface {
+ Lookup(name string) *TemplateAdapter
+}
+
+// Template is the common interface between text/template and html/template.
+type Template interface {
+ Execute(wr io.Writer, data interface{}) error
+ Name() string
+}
+
+// TemplateExecutor adds some extras to Template.
+type TemplateExecutor interface {
+ Template
+ ExecuteToString(data interface{}) (string, error)
+ Tree() string
+}
+
+// TemplateAdapter implements the TemplateExecutor interface.
+type TemplateAdapter struct {
+ Template
+}
+
+// ExecuteToString executes the current template and returns the result as a
+// string.
+func (t *TemplateAdapter) ExecuteToString(data interface{}) (string, error) {
+ b := bp.GetBuffer()
+ defer bp.PutBuffer(b)
+ if err := t.Execute(b, data); err != nil {
+ return "", err
+ }
+ return b.String(), nil
+}
+
+// Tree returns the template Parse tree as a string.
+// Note: this isn't safe for parallel execution on the same template
+// vs Lookup and Execute.
+func (t *TemplateAdapter) Tree() string {
+ var tree *parse.Tree
+ switch tt := t.Template.(type) {
+ case *template.Template:
+ tree = tt.Tree
+ case *texttemplate.Template:
+ tree = tt.Tree
+ default:
+ panic("Unknown template")
+ }
+
+ if tree.Root == nil {
+ return ""
+ }
+ s := tree.Root.String()
+
+ return s
+}
+
+// TemplateTestMocker adds a way to override some template funcs during tests.
+// The interface is named so it's not used in regular application code.
+type TemplateTestMocker interface {
+ SetFuncs(funcMap map[string]interface{})
}