mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Adding 'partial' template function to add theme / local awareness to the partials directory.
This commit is contained in:
parent
4e99d6b54c
commit
c297d7451f
9 changed files with 106 additions and 36 deletions
|
@ -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
|
||||||
|
|
|
@ -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" }}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 didn’t 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 won’t 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">
|
||||||
|
|
||||||
|
|
|
@ -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" }}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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 won’t know to look for the local /layouts first**
|
Hugo won’t know to look for the local /layouts first**
|
||||||
|
|
||||||
## Replace an archetype
|
## Replace an archetype
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
{{ template "partials/header.html" . }}
|
{{ partial "header.html" . }}
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
{{ template "partials/footer.html" . }}
|
{{ partial "footer.html" . }}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in a new issue