From b14b61af37f0428545af0d191a27170434e4aad2 Mon Sep 17 00:00:00 2001 From: Noah Campbell Date: Fri, 30 Aug 2013 17:18:05 -0700 Subject: [PATCH] Externalize the writing of content to a target Introducing the target module in hugo. This provides the simple interface for writing content given a label (filename) and a io.Reader containing the content to be written. If site.Target is not set, it defaults back to the original behavior of writing to file system. In hugolib/site_url_test.go I have an InMemoryTarget for testing purposes and use it to see if the final output of a render matches. --- hugolib/site.go | 8 ++++- hugolib/site_url_test.go | 69 ++++++++++++++++++++++++++++++++++++++++ target/file.go | 9 ++++++ 3 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 hugolib/site_url_test.go create mode 100644 target/file.go diff --git a/hugolib/site.go b/hugolib/site.go index 320e2516b..d9128e9cf 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -18,6 +18,7 @@ import ( "bytes" "errors" "fmt" + "github.com/spf13/hugo/target" "github.com/spf13/nitro" "html/template" "io/ioutil" @@ -40,6 +41,7 @@ type Site struct { Info SiteInfo Shortcodes map[string]ShortcodeFunc timer *nitro.B + Target target.Publisher } type SiteInfo struct { @@ -628,7 +630,7 @@ func (s *Site) NewNode() Node { func (s *Site) RenderThing(d interface{}, layout string) (*bytes.Buffer, error) { if s.Tmpl.Lookup(layout) == nil { - return nil, errors.New("Layout not found") + return nil, errors.New(fmt.Sprintf("Layout not found: %s", layout)) } buffer := new(bytes.Buffer) err := s.Tmpl.ExecuteTemplate(buffer, layout, d) @@ -654,6 +656,10 @@ func (s *Site) NewXMLBuffer() *bytes.Buffer { func (s *Site) WritePublic(path string, content []byte) { + if s.Target != nil { + s.Target.Publish(path, bytes.NewReader(content)) + } + if s.Config.Verbose { fmt.Println(path) } diff --git a/hugolib/site_url_test.go b/hugolib/site_url_test.go new file mode 100644 index 000000000..6384f797b --- /dev/null +++ b/hugolib/site_url_test.go @@ -0,0 +1,69 @@ +package hugolib + +import ( + "bytes" + "io" + "path/filepath" + "strings" + "testing" +) + +const SLUG_DOC_1 = "---\ntitle: slug doc 1\nslug: slug-doc-1\n---\nslug doc 1 content" +const SLUG_DOC_2 = "---\ntitle: slug doc 2\nslug: slug-doc-2\n---\nslug doc 2 content" + +const INDEX_TEMPLATE = "{{ range .Data.Pages }}.{{ end }}" + +func must(err error) { + if err != nil { + panic(err) + } +} + +func mustReturn(ret *Page, err error) *Page { + if err != nil { + panic(err) + } + return ret +} + +type InMemoryTarget struct { + files map[string][]byte +} + +func (t *InMemoryTarget) Publish(label string, reader io.Reader) (err error) { + if t.files == nil { + t.files = make(map[string][]byte) + } + bytes := new(bytes.Buffer) + bytes.ReadFrom(reader) + t.files[label] = bytes.Bytes() + return +} + +func TestPageCount(t *testing.T) { + target := new(InMemoryTarget) + s := &Site{Target: target} + s.prepTemplates() + must(s.addTemplate("indexes/blue.html", INDEX_TEMPLATE)) + s.Files = append(s.Files, "blue/doc1.md") + s.Files = append(s.Files, "blue/doc2.md") + s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_1), filepath.FromSlash("content/blue/doc1.md")))) + s.Pages = append(s.Pages, mustReturn(ReadFrom(strings.NewReader(SLUG_DOC_2), filepath.FromSlash("content/blue/doc2.md")))) + + if err := s.BuildSiteMeta(); err != nil { + t.Errorf("Unable to build site metadata: %s", err) + } + + if err := s.RenderLists(); err != nil { + t.Errorf("Unable to render site lists: %s", err) + } + + blueIndex := target.files["blue/index.html"] + if blueIndex == nil { + t.Errorf("No indexed rendered. %v", target.files) + } + + if len(blueIndex) != 2 { + t.Errorf("Number of pages does not equal 2, got %d. %q", len(blueIndex), blueIndex) + } +} diff --git a/target/file.go b/target/file.go new file mode 100644 index 000000000..a80d73dbe --- /dev/null +++ b/target/file.go @@ -0,0 +1,9 @@ +package target + +import ( + "io" +) + +type Publisher interface { + Publish(string, io.Reader) error +}