Adding 'partial' template function to add theme / local awareness to the partials directory.

This commit is contained in:
spf13 2014-06-06 16:15:19 -04:00
parent 4e99d6b54c
commit c297d7451f
9 changed files with 106 additions and 36 deletions

View file

@ -65,8 +65,8 @@ same as the other types but the directory must be called "\_default".
This content template is used for [spf13.com](http://spf13.com). This content template is used for [spf13.com](http://spf13.com).
It makes use of [partial templates](/layout/partials) It makes use of [partial templates](/layout/partials)
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
{{ $baseurl := .Site.BaseUrl }} {{ $baseurl := .Site.BaseUrl }}
<section id="main"> <section id="main">
@ -105,8 +105,8 @@ It makes use of [partial templates](/layout/partials)
</div> </div>
</aside> </aside>
{{ template "partials/disqus.html" . }} {{ partial "disqus.html" . }}
{{ template "partials/footer.html" . }} {{ partial "footer.html" . }}
## project/single.html ## project/single.html
@ -114,8 +114,8 @@ This content template is used for [spf13.com](http://spf13.com).
It makes use of [partial templates](/layout/partials) It makes use of [partial templates](/layout/partials)
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
{{ $baseurl := .Site.BaseUrl }} {{ $baseurl := .Site.BaseUrl }}
<section id="main"> <section id="main">
@ -152,7 +152,7 @@ It makes use of [partial templates](/layout/partials)
</div> </div>
{{ end }} {{ end }}
{{ template "partials/footer.html" }} {{ partial "footer.html" }}
Notice how the project/single.html template uses an additional parameter unique Notice how the project/single.html template uses an additional parameter unique
to this template. This doesn't need to be defined ahead of time. If the key is to this template. This doesn't need to be defined ahead of time. If the key is

View file

@ -54,18 +54,18 @@ It makes use of [partial templates](/templates/partials) and uses a similar appr
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
{{ template "partials/meta.html" . }} {{ partial "meta.html" . }}
<base href="{{ .Site.BaseUrl }}"> <base href="{{ .Site.BaseUrl }}">
<title>{{ .Site.Title }}</title> <title>{{ .Site.Title }}</title>
<link rel="canonical" href="{{ .Permalink }}"> <link rel="canonical" href="{{ .Permalink }}">
<link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" /> <link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" />
{{ template "partials/head_includes.html" . }} {{ partial "head_includes.html" . }}
</head> </head>
<body lang="en"> <body lang="en">
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -75,4 +75,4 @@ It makes use of [partial templates](/templates/partials) and uses a similar appr
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}

View file

@ -107,8 +107,8 @@ It makes use of [partial templates](/templates/partials). All examples use a
[view](/templates/views/) called either "li" or "summary" which this example site [view](/templates/views/) called either "li" or "summary" which this example site
defined. defined.
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -121,7 +121,7 @@ defined.
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}
### Example taxonomy template (tag.html) ### Example taxonomy template (tag.html)
This content template is used for [spf13.com](http://spf13.com). This content template is used for [spf13.com](http://spf13.com).
@ -129,8 +129,8 @@ It makes use of [partial templates](/templates/partials). All examples use a
[view](/templates/views/) called either "li" or "summary" which this example site [view](/templates/views/) called either "li" or "summary" which this example site
defined. defined.
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -141,7 +141,7 @@ defined.
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}
## Ordering Content ## Ordering Content

View file

@ -14,9 +14,14 @@ weight: 80
It's not a requirement to have this, but in practice it's very It's not a requirement to have this, but in practice it's very
convenient to split out common template portions into a partial template convenient to split out common template portions into a partial template
that can be included anywhere. As you create the rest of your templates that can be included anywhere. As you create the rest of your templates
you will include templates from the /layout/partials directory. Hugo you will include templates from the /layout/partials directory.
doesn't know anything about partials, it's simply a convention that you
may likely find beneficial. Partials are especially important for themes as it gives users an opportunity
to overwrite just a small part of your theme, while maintaining future compatibility.
In fact theme developers may want to include a few partials with empty html
files in the theme just so end users have an easy place to inject their
customized content.
I've found it helpful to include a header and footer template in I've found it helpful to include a header and footer template in
@ -32,6 +37,21 @@ like good names to use for inclusion in your other templates.
By ensuring that we only reference [variables](/layout/variables/) By ensuring that we only reference [variables](/layout/variables/)
used for both nodes and pages we can use the same partials for both. used for both nodes and pages we can use the same partials for both.
## Partial vs Template
Version v0.12 of Hugo introduced the partial call inside the template system.
This is a change to the way partials were handled previously inside the
template system. This is a change to hthe way partials were handled previously.
Previously Hugo didnt treat partials specially and you could include a partial
template with the `template` call in the standard template language.
With the addition of the theme system in v0.11 it became apparent that a theme
& override aware partial was needed.
When using Hugo v0.12 and above please use the `partial` call (and leave out
the “partial/” path). The old approach will still work, but wont benefit from
the ability to have users override the partial theme file with local layouts.
## example header.html ## example header.html
This header template is used for [spf13.com](http://spf13.com). This header template is used for [spf13.com](http://spf13.com).
@ -40,14 +60,14 @@ This header template is used for [spf13.com](http://spf13.com).
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
{{ template "partials/meta.html" . }} {{ partial "meta.html" . }}
<base href="{{ .Site.BaseUrl }}"> <base href="{{ .Site.BaseUrl }}">
<title> {{ .Title }} : spf13.com </title> <title> {{ .Title }} : spf13.com </title>
<link rel="canonical" href="{{ .Permalink }}"> <link rel="canonical" href="{{ .Permalink }}">
{{ if .RSSlink }}<link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }} {{ if .RSSlink }}<link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }}
{{ template "partials/head_includes.html" . }} {{ partial "head_includes.html" . }}
</head> </head>
<body lang="en"> <body lang="en">

View file

@ -70,8 +70,8 @@ content tagged with each tag.
.Data.Terms is an map of terms => [contents] .Data.Terms is an map of terms => [contents]
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -86,7 +86,7 @@ content tagged with each tag.
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}
## Ordering ## Ordering
@ -97,8 +97,8 @@ number of content assigned to that key or alphabetically.
## Example indexes.html file (alphabetical) ## Example indexes.html file (alphabetical)
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -111,12 +111,12 @@ number of content assigned to that key or alphabetically.
</ul> </ul>
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}
## Example indexes.html file (ordered) ## Example indexes.html file (ordered)
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ template "partials/subheader.html" . }} {{ partial "subheader.html" . }}
<section id="main"> <section id="main">
<div> <div>
@ -130,5 +130,5 @@ number of content assigned to that key or alphabetically.
</div> </div>
</section> </section>
{{ template "partials/footer.html" }} {{ partial "footer.html" }}

View file

@ -42,6 +42,15 @@ The default single file layout is located at `layouts/_default/single.html`.
The default list file layout is located at `layouts/_default/list.html` The default list file layout is located at `layouts/_default/list.html`
### Partial Templates
Theme creators should liberally use [partial templates](/templates/partials)
throughout their theme files. Not only is a good DRY practice to include shared
code, but partials are a special template type that enables the themes end user
to be able to overwrite just a small piece of a file or inject code into the
theme from their local /layouts. These partial templates are perfect for easy
injection into the theme with minimal maintenance to ensure future
compatibility.
### Static ### Static

View file

@ -12,7 +12,6 @@ weight: 40
Hugo themes permit you to supplement or override any template or file Hugo themes permit you to supplement or override any template or file
from within your working directory. from within your working directory.
## Replacing Static files ## Replacing Static files
If you would like to include a different file than the theme ships If you would like to include a different file than the theme ships
@ -27,12 +26,17 @@ in the same relative path /static/js/jQuery.min.js.
Anytime Hugo looks for a matching template it will first check the Anytime Hugo looks for a matching template it will first check the
working directory before looking in the theme directory. If you would working directory before looking in the theme directory. If you would
like to modify a template simply create that template in your local like to modify a template simply create that template in your local
layouts directory. In the [template documentation](/templates/overview/) layouts directory. In the [template documentation](/templates/overview)
each different template type explains the rules it uses to determine each different template type explains the rules it uses to determine
which template to use. which template to use.
This is especially helpful when the theme creator used [partial
templates](/templates/partials). These partial templates are perfect for easy
injection into the theme with minimal maintenance to ensure future
compatibility.
**warning.. This only works for templates that Hugo knows about. If the **warning.. This only works for templates that Hugo knows about. If the
theme creates partial template files in a creatively named directory theme imports template files in a creatively named directory
Hugo wont know to look for the local /layouts first** Hugo wont know to look for the local /layouts first**
## Replace an archetype ## Replace an archetype

View file

@ -1,3 +1,3 @@
{{ template "partials/header.html" . }} {{ partial "header.html" . }}
{{ .Content }} {{ .Content }}
{{ template "partials/footer.html" . }} {{ partial "footer.html" . }}

View file

@ -1,6 +1,7 @@
package hugolib package hugolib
import ( import (
"bytes"
"errors" "errors"
"html" "html"
"html/template" "html/template"
@ -14,8 +15,11 @@ import (
"github.com/eknkc/amber" "github.com/eknkc/amber"
"github.com/spf13/hugo/helpers" "github.com/spf13/hugo/helpers"
jww "github.com/spf13/jwalterweatherman"
) )
var localTemplates *template.Template
func Eq(x, y interface{}) bool { func Eq(x, y interface{}) bool {
return reflect.DeepEqual(x, y) return reflect.DeepEqual(x, y)
} }
@ -192,6 +196,8 @@ func NewTemplate() Template {
errors: make([]*templateErr, 0), errors: make([]*templateErr, 0),
} }
localTemplates = &templates.Template
funcMap := template.FuncMap{ funcMap := template.FuncMap{
"urlize": helpers.Urlize, "urlize": helpers.Urlize,
"sanitizeurl": helpers.SanitizeUrl, "sanitizeurl": helpers.SanitizeUrl,
@ -215,6 +221,7 @@ func NewTemplate() Template {
"lower": func(a string) string { return strings.ToLower(a) }, "lower": func(a string) string { return strings.ToLower(a) },
"upper": func(a string) string { return strings.ToUpper(a) }, "upper": func(a string) string { return strings.ToUpper(a) },
"title": func(a string) string { return strings.Title(a) }, "title": func(a string) string { return strings.Title(a) },
"partial": Partial,
} }
templates.Funcs(funcMap) templates.Funcs(funcMap)
@ -223,6 +230,36 @@ func NewTemplate() Template {
return templates return templates
} }
func Partial(name string, context interface{}) template.HTML {
if strings.HasPrefix("partials/", name) {
name = name[8:]
}
return ExecuteTemplateToHTML(context, "partials/"+name, "theme/partials/"+name)
}
func ExecuteTemplate(context interface{}, layouts ...string) *bytes.Buffer {
buffer := new(bytes.Buffer)
worked := false
for _, layout := range layouts {
if localTemplates.Lookup(layout) != nil {
localTemplates.ExecuteTemplate(buffer, layout, context)
worked = true
break
}
}
if !worked {
jww.ERROR.Println("Unable to render", layouts)
jww.ERROR.Println("Expecting to find a template in either the theme/layouts or /layouts in one of the following relative locations", layouts)
}
return buffer
}
func ExecuteTemplateToHTML(context interface{}, layouts ...string) template.HTML {
b := ExecuteTemplate(context, layouts...)
return template.HTML(string(b.Bytes()))
}
func (t *GoHtmlTemplate) LoadEmbedded() { func (t *GoHtmlTemplate) LoadEmbedded() {
t.EmbedShortcodes() t.EmbedShortcodes()
t.EmbedTemplates() t.EmbedTemplates()