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
This commit is contained in:
Bjørn Erik Pedersen
2017-03-27 20:43:49 +02:00
parent 73c1c7b69d
commit 5c5efa03d2
31 changed files with 1208 additions and 840 deletions

View File

@@ -22,6 +22,8 @@ import (
"runtime"
"strings"
"github.com/spf13/hugo/tpl"
jww "github.com/spf13/jwalterweatherman"
"github.com/spf13/hugo/helpers"
@@ -35,18 +37,19 @@ const (
var defaultAliasTemplates *template.Template
func init() {
//TODO(bep) consolidate
defaultAliasTemplates = template.New("")
template.Must(defaultAliasTemplates.New("alias").Parse(alias))
template.Must(defaultAliasTemplates.New("alias-xhtml").Parse(aliasXHtml))
}
type aliasHandler struct {
Templates *template.Template
t tpl.TemplateHandler
log *jww.Notepad
allowRoot bool
}
func newAliasHandler(t *template.Template, l *jww.Notepad, allowRoot bool) aliasHandler {
func newAliasHandler(t tpl.TemplateHandler, l *jww.Notepad, allowRoot bool) aliasHandler {
return aliasHandler{t, l, allowRoot}
}
@@ -56,12 +59,19 @@ func (a aliasHandler) renderAlias(isXHTML bool, permalink string, page *Page) (i
t = "alias-xhtml"
}
template := defaultAliasTemplates
if a.Templates != nil {
template = a.Templates
t = "alias.html"
var templ *tpl.TemplateAdapter
if a.t != nil {
templ = a.t.Lookup("alias.html")
}
if templ == nil {
def := defaultAliasTemplates.Lookup(t)
if def != nil {
templ = &tpl.TemplateAdapter{def}
}
}
data := struct {
Permalink string
Page *Page
@@ -71,7 +81,7 @@ func (a aliasHandler) renderAlias(isXHTML bool, permalink string, page *Page) (i
}
buffer := new(bytes.Buffer)
err := template.ExecuteTemplate(buffer, t, data)
err := templ.Execute(buffer, data)
if err != nil {
return nil, err
}
@@ -83,8 +93,7 @@ func (s *Site) writeDestAlias(path, permalink string, p *Page) (err error) {
}
func (s *Site) publishDestAlias(allowRoot bool, path, permalink string, p *Page) (err error) {
handler := newAliasHandler(s.Tmpl.Lookup("alias.html"), s.Log, allowRoot)
handler := newAliasHandler(s.Tmpl, s.Log, allowRoot)
isXHTML := strings.HasSuffix(path, ".xhtml")