shithub: hugo

Download patch

ref: 54a2790fce03ef4bc7798a7e4c38ba5bfffe2314
parent: 689cda17403ba752305f469fdcc385b7a31b0bdb
author: Noah Campbell <[email protected]>
date: Wed Oct 2 05:34:41 EDT 2013

Use io.Pipe for chaning render tasks.

Also clean up logic for finding layouts.

--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -376,7 +376,7 @@
 			layout = p.Layout()
 		}
 
-		err := s.render(p, layout, "_default/single.html", p.TargetPath())
+		err := s.render(p, p.TargetPath(), layout, "_default/single.html")
 		if err != nil {
 			return err
 		}
@@ -401,7 +401,7 @@
 
 			var base string
 			base = plural + "/" + k
-			err := s.render(n, layout, "_default/indexes.html", base+".html")
+			err := s.render(n, base+".html", layout, "_default/indexes.html")
 			if err != nil {
 				return err
 			}
@@ -408,11 +408,9 @@
 
 			if a := s.Tmpl.Lookup("rss.xml"); a != nil {
 				// XML Feed
-				y := s.NewXMLBuffer()
 				n.Url = helpers.Urlize(plural + "/" + k + ".xml")
 				n.Permalink = permalink(s, n.Url)
-				s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-				err = s.WritePublic(base+".xml", y)
+				err := s.render(n, base+".xml", "rss.xml")
 				if err != nil {
 					return err
 				}
@@ -436,7 +434,7 @@
 			n.Data["Index"] = s.Indexes[plural]
 			n.Data["OrderedIndex"] = s.Info.Indexes[plural]
 
-			err := s.render(n, layout, "_default/indexesindexes.html", plural+"/index.html")
+			err := s.render(n, plural+"/index.html", layout)
 			if err != nil {
 				return err
 			}
@@ -456,7 +454,7 @@
 		n.Data["Pages"] = data
 		layout := "indexes/" + section + ".html"
 
-		err := s.render(n, layout, "_default/index.html", section)
+		err := s.render(n, section, layout, "_default/index.html")
 		if err != nil {
 			return err
 		}
@@ -465,12 +463,7 @@
 			// XML Feed
 			n.Url = helpers.Urlize(section + ".xml")
 			n.Permalink = template.HTML(string(n.Site.BaseUrl) + n.Url)
-			y := s.NewXMLBuffer()
-			s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-			err = s.WritePublic(section+"/index.xml", y)
-			if err != nil {
-				return err
-			}
+			return s.render(n, section+"/index.html", "rss.xml")
 		}
 	}
 	return nil
@@ -491,7 +484,7 @@
 			n.Data["Pages"] = s.Pages[:9]
 		}
 	}
-	err := s.render(n, "index.html", "_default/index.html", "/")
+	err := s.render(n, "/", "index.html")
 	if err != nil {
 		return err
 	}
@@ -501,9 +494,7 @@
 		n.Url = helpers.Urlize("index.xml")
 		n.Title = "Recent Content"
 		n.Permalink = permalink(s, "index.xml")
-		y := s.NewXMLBuffer()
-		s.Tmpl.ExecuteTemplate(y, "rss.xml", n)
-		err = s.WritePublic("index.xml", y)
+		err := s.render(n, "index.html", "rss.xml")
 		if err != nil {
 			return err
 		}
@@ -513,7 +504,7 @@
 		n.Url = helpers.Urlize("404.html")
 		n.Title = "404 Page not found"
 		n.Permalink = permalink(s, "404.html")
-		return s.render(n, "404.html", "_default/404.html", "404.html")
+		return s.render(n, "404.html", "404.html")
 	}
 
 	return nil
@@ -547,41 +538,39 @@
 	}
 }
 
-func (s *Site) render(d interface{}, layout, defaultLayout, out string) (err error) {
-	r, err := s.renderThingOrDefault(d, layout, defaultLayout)
-	if err != nil {
-		return err
-	}
+func (s *Site) render(d interface{}, out string, layouts ...string) (err error) {
+	reader, writer := io.Pipe()
 
-	err = s.WritePublic(out, r)
-	if err != nil {
-		return err
-	}
-	return
+	layout := s.findFirstLayout(layouts...)
+	go func() {
+		err = s.renderThing(d, layout, writer)
+		if err != nil {
+			panic(err)
+		}
+	}()
+
+	return s.WritePublic(out, reader)
 }
 
-func (s *Site) renderThing(d interface{}, layout string) (*bytes.Buffer, error) {
-	if s.Tmpl.Lookup(layout) == nil {
-		return nil, fmt.Errorf("Layout not found: %s", layout)
+func (s *Site) findFirstLayout(layouts ...string) string {
+	for _, layout := range layouts {
+		if s.Tmpl.Lookup(layout) != nil {
+			return layout
+		}
 	}
-	buffer := new(bytes.Buffer)
-	err := s.Tmpl.ExecuteTemplate(buffer, layout, d)
-	return buffer, err
+	panic("Unable to find layout.")
 }
 
-func (s *Site) renderThingOrDefault(d interface{}, layout string, defaultLayout string) (*bytes.Buffer, error) {
-	content, err := s.renderThing(d, layout)
-	if err != nil {
-		var err2 error
-		content, err2 = s.renderThing(d, defaultLayout)
-		if err2 == nil {
-			return content, err2
-		}
+func (s *Site) renderThing(d interface{}, layout string, w io.WriteCloser) error {
+	// If the template doesn't exist, then return, but leave the Writer open
+	if s.Tmpl.Lookup(layout) == nil {
+		return fmt.Errorf("Layout not found: %s", layout)
 	}
-	return content, err
+	defer w.Close()
+	return s.Tmpl.ExecuteTemplate(w, layout, d)
 }
 
-func (s *Site) NewXMLBuffer() *bytes.Buffer {
+func (s *Site) whyNewXMLBuffer() *bytes.Buffer {
 	header := "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n"
 	return bytes.NewBufferString(header)
 }
--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -2,6 +2,7 @@
 
 import (
 	"bytes"
+	"io"
 	"fmt"
 	"github.com/spf13/hugo/source"
 	"github.com/spf13/hugo/target"
@@ -46,11 +47,11 @@
 	return p
 }
 
-func TestDegeneraterenderThingMissingTemplate(t *testing.T) {
+func TestDegenerateRenderThingMissingTemplate(t *testing.T) {
 	p, _ := ReadFrom(strings.NewReader(PAGE_SIMPLE_TITLE), "content/a/file.md")
 	s := new(Site)
 	s.prepTemplates()
-	_, err := s.renderThing(p, "foobar")
+	err := s.renderThing(p, "foobar", nil)
 	if err == nil {
 		t.Errorf("Expected err to be returned when missing the template.")
 	}
@@ -65,8 +66,19 @@
 	}
 }
 
+type nopCloser struct {
+	io.Writer
+}
+
+func (nopCloser) Close() error { return nil }
+
+func NopCloser(w io.Writer) io.WriteCloser {
+	return nopCloser{w}
+}
+
 func matchRender(t *testing.T, s *Site, p *Page, tmplName string, expected string) {
-	content, err := s.renderThing(p, tmplName)
+	content := new(bytes.Buffer)
+	err := s.renderThing(p, tmplName, NopCloser(content))
 	if err != nil {
 		t.Fatalf("Unable to render template.")
 	}
@@ -103,8 +115,9 @@
 		}
 
 		p.Content = template.HTML(p.Content)
-		html, err2 := s.renderThing(p, templateName)
-		if err2 != nil {
+		html := new(bytes.Buffer)
+		err = s.renderThing(p, templateName, NopCloser(html))
+		if err != nil {
 			t.Errorf("Unable to render html: %s", err)
 		}
 
@@ -151,9 +164,9 @@
 
 		var err2 error
 		if test.missing {
-			err2 = s.render(p, "missing", templateName, "out")
+			err2 = s.render(p, "out", "missing", templateName)
 		} else {
-			err2 = s.render(p, templateName, "missing_default", "out")
+			err2 = s.render(p, "out", templateName, "missing_default")
 		}
 
 		if err2 != nil {