shithub: hugo

Download patch

ref: c297d7451f6e71c9e790802ce807625a260da443
parent: 4e99d6b54c53e353b111dcaf039364704f751a2c
author: spf13 <[email protected]>
date: Fri Jun 6 12:15:19 EDT 2014

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

--- a/docs/content/templates/content.md
+++ b/docs/content/templates/content.md
@@ -65,8 +65,8 @@
 This content template is used for [spf13.com](http://spf13.com).
 It makes use of [partial templates](/layout/partials)
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
     {{ $baseurl := .Site.BaseUrl }}
 
     <section id="main">
@@ -105,8 +105,8 @@
         </div>
     </aside>
 
-    {{ template "partials/disqus.html" . }}
-    {{ template "partials/footer.html" . }}
+    {{ partial "disqus.html" . }}
+    {{ partial "footer.html" . }}
 
 
 ## project/single.html
@@ -114,8 +114,8 @@
 It makes use of [partial templates](/layout/partials)
 
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
     {{ $baseurl := .Site.BaseUrl }}
 
     <section id="main">
@@ -152,7 +152,7 @@
     </div>
     {{ end }}
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
 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
--- a/docs/content/templates/homepage.md
+++ b/docs/content/templates/homepage.md
@@ -54,7 +54,7 @@
     <head>
         <meta charset="utf-8">
 
-        {{ template "partials/meta.html" . }}
+        {{ partial "meta.html" . }}
 
         <base href="{{ .Site.BaseUrl }}">
         <title>{{ .Site.Title }}</title>
@@ -61,11 +61,11 @@
         <link rel="canonical" href="{{ .Permalink }}">
         <link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Site.Title }}" />
 
-        {{ template "partials/head_includes.html" . }}
+        {{ partial "head_includes.html" . }}
     </head>
     <body lang="en">
 
-    {{ template "partials/subheader.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -75,4 +75,4 @@
       </div>
     </section>
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
--- a/docs/content/templates/list.md
+++ b/docs/content/templates/list.md
@@ -107,8 +107,8 @@
 [view](/templates/views/) called either "li" or "summary" which this example site
 defined.
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -121,7 +121,7 @@
       </div>
     </section>
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
 ### Example taxonomy template (tag.html)
 This content template is used for [spf13.com](http://spf13.com).
@@ -129,8 +129,8 @@
 [view](/templates/views/) called either "li" or "summary" which this example site
 defined.
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -141,7 +141,7 @@
       </div>
     </section>
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
 ## Ordering Content
 
--- a/docs/content/templates/partials.md
+++ b/docs/content/templates/partials.md
@@ -14,11 +14,16 @@
 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
 that can be included anywhere. As you create the rest of your templates
-you will include templates from the /layout/partials directory. Hugo
-doesn't know anything about partials, it's simply a convention that you
-may likely find beneficial.
+you will include templates from the /layout/partials directory.
 
+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
 partials so I can include those in all the full page layouts.  There is
 nothing special about header.html and footer.html other than they seem
@@ -32,6 +37,21 @@
 By ensuring that we only reference [variables](/layout/variables/)
 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
 This header template is used for [spf13.com](http://spf13.com).
 
@@ -40,7 +60,7 @@
     <head>
         <meta charset="utf-8">
 
-        {{ template "partials/meta.html" . }}
+        {{ partial "meta.html" . }}
 
         <base href="{{ .Site.BaseUrl }}">
         <title> {{ .Title }} : spf13.com </title>
@@ -47,7 +67,7 @@
         <link rel="canonical" href="{{ .Permalink }}">
         {{ if .RSSlink }}<link href="{{ .RSSlink }}" rel="alternate" type="application/rss+xml" title="{{ .Title }}" />{{ end }}
 
-        {{ template "partials/head_includes.html" . }}
+        {{ partial "head_includes.html" . }}
     </head>
     <body lang="en">
 
--- a/docs/content/templates/terms.md
+++ b/docs/content/templates/terms.md
@@ -70,8 +70,8 @@
 
 .Data.Terms is an map of terms => [contents]
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -86,7 +86,7 @@
       </div>
     </section>
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
 
 ## Ordering
@@ -97,8 +97,8 @@
 
 ## Example indexes.html file (alphabetical)
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -111,12 +111,12 @@
        </ul>
       </div>
     </section>
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
 ## Example indexes.html file (ordered)
 
-    {{ template "partials/header.html" . }}
-    {{ template "partials/subheader.html" . }}
+    {{ partial "header.html" . }}
+    {{ partial "subheader.html" . }}
 
     <section id="main">
       <div>
@@ -130,5 +130,5 @@
       </div>
     </section>
 
-    {{ template "partials/footer.html" }}
+    {{ partial "footer.html" }}
 
--- a/docs/content/themes/creation.md
+++ b/docs/content/themes/creation.md
@@ -42,6 +42,15 @@
 
 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
 
--- a/docs/content/themes/customizing.md
+++ b/docs/content/themes/customizing.md
@@ -12,7 +12,6 @@
 Hugo themes permit you to supplement or override any template or file
 from within your working directory.
 
-
 ## Replacing Static files
 
 If you would like to include a different file than the theme ships
@@ -27,12 +26,17 @@
 Anytime Hugo looks for a matching template it will first check the
 working directory before looking in the theme directory. If you would
 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
 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
-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**
 
 ## Replace an archetype
--- a/docs/layouts/_default/single.html
+++ b/docs/layouts/_default/single.html
@@ -1,3 +1,3 @@
-{{ template "partials/header.html" . }}
+{{ partial "header.html" . }}
 {{ .Content }}
-{{ template "partials/footer.html" . }}
+{{ partial "footer.html" . }}
--- a/hugolib/template.go
+++ b/hugolib/template.go
@@ -1,6 +1,7 @@
 package hugolib
 
 import (
+	"bytes"
 	"errors"
 	"html"
 	"html/template"
@@ -14,8 +15,11 @@
 
 	"github.com/eknkc/amber"
 	"github.com/spf13/hugo/helpers"
+	jww "github.com/spf13/jwalterweatherman"
 )
 
+var localTemplates *template.Template
+
 func Eq(x, y interface{}) bool {
 	return reflect.DeepEqual(x, y)
 }
@@ -192,6 +196,8 @@
 		errors:   make([]*templateErr, 0),
 	}
 
+	localTemplates = &templates.Template
+
 	funcMap := template.FuncMap{
 		"urlize":      helpers.Urlize,
 		"sanitizeurl": helpers.SanitizeUrl,
@@ -215,6 +221,7 @@
 		"lower":       func(a string) string { return strings.ToLower(a) },
 		"upper":       func(a string) string { return strings.ToUpper(a) },
 		"title":       func(a string) string { return strings.Title(a) },
+		"partial":     Partial,
 	}
 
 	templates.Funcs(funcMap)
@@ -221,6 +228,36 @@
 
 	templates.LoadEmbedded()
 	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() {