shithub: hugo

Download patch

ref: 3ff25b37a3d327646255572072d6686d48a142e9
parent: 75c38071d8c61e2e1a56ae1949766b4144b68305
author: Bjørn Erik Pedersen <[email protected]>
date: Wed Nov 2 17:34:19 EDT 2016

node to page: Handle RSS

Updates #2297

--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -17,6 +17,7 @@
 	"errors"
 	"fmt"
 	"os"
+	"path"
 	"strings"
 	"sync"
 	"time"
@@ -390,6 +391,11 @@
 	// TODO(bep) np check node title etc.
 	s := h.Sites[0]
 
+	// TODO(bep) np
+	for _, p := range s.Pages {
+		p.setNodeTypeVars(s)
+	}
+
 	home := s.findPagesByNodeType(NodeHome)
 
 	// home page
@@ -460,7 +466,7 @@
 		language: s.Language,
 	}
 
-	return &Page{Node: n}
+	return &Page{Node: n, site: s}
 }
 
 func (s *Site) newHomePage() *Page {
@@ -489,6 +495,7 @@
 	}
 
 	// TODO(bep) np check set url
+	p.URLPath.URL = path.Join(plural, key)
 
 	return p
 }
@@ -509,7 +516,7 @@
 	} else {
 		p.Title = sectionName
 	}
-
+	p.URLPath.URL = name
 	return p
 }
 
@@ -612,8 +619,6 @@
 					// No need to process it again.
 					continue
 				}
-
-				p.setNodeTypeVars(s)
 
 				// If we got this far it means that this is either a new Page pointer
 				// or a template or similar has changed so wee need to do a rerendering
--- a/hugolib/node_as_page_test.go
+++ b/hugolib/node_as_page_test.go
@@ -31,8 +31,8 @@
 */
 
 func TestNodesAsPage(t *testing.T) {
-	//jww.SetStdoutThreshold(jww.LevelDebug)
-	jww.SetStdoutThreshold(jww.LevelFatal)
+	jww.SetStdoutThreshold(jww.LevelDebug)
+	//jww.SetStdoutThreshold(jww.LevelFatal)
 
 	nodePageFeatureFlag = true
 	defer toggleNodePageFeatureFlag()
@@ -105,6 +105,8 @@
 	}
 
 	viper.Set("paginate", 1)
+	viper.Set("title", "Hugo Rocks")
+	viper.Set("rssURI", "customrss.xml")
 
 	s := newSiteDefaultLang()
 
@@ -172,11 +174,18 @@
 
 	// There are no pages to paginate over in the taxonomy terms.
 
+	// RSS
+	assertFileContent(t, filepath.Join("public", "customrss.xml"), false, "Recent content in Home Sweet Home! on Hugo Rocks", "<rss")
+	assertFileContent(t, filepath.Join("public", "sect1", "customrss.xml"), false, "Recent content in Section1 on Hugo Rocks", "<rss")
+	assertFileContent(t, filepath.Join("public", "sect2", "customrss.xml"), false, "Recent content in Section2 on Hugo Rocks", "<rss")
+	assertFileContent(t, filepath.Join("public", "categories", "hugo", "customrss.xml"), false, "Recent content in Taxonomy Hugo on Hugo Rocks", "<rss")
+	assertFileContent(t, filepath.Join("public", "categories", "web", "customrss.xml"), false, "Recent content in Taxonomy Web on Hugo Rocks", "<rss")
+
 }
 
 func TestNodesWithNoContentFile(t *testing.T) {
-	//jww.SetStdoutThreshold(jww.LevelDebug)
-	jww.SetStdoutThreshold(jww.LevelFatal)
+	jww.SetStdoutThreshold(jww.LevelDebug)
+	//jww.SetStdoutThreshold(jww.LevelFatal)
 
 	nodePageFeatureFlag = true
 	defer toggleNodePageFeatureFlag()
@@ -203,6 +212,7 @@
 
 	viper.Set("paginate", 1)
 	viper.Set("title", "Hugo Rocks!")
+	viper.Set("rssURI", "customrss.xml")
 
 	s := newSiteDefaultLang()
 
@@ -233,6 +243,13 @@
 		"Section Title: Sect1s")
 	assertFileContent(t, filepath.Join("public", "sect2", "index.html"), false,
 		"Section Title: Sect2s")
+
+	// RSS
+	assertFileContent(t, filepath.Join("public", "customrss.xml"), false, "Recent content in Hugo Rocks! on Hugo Rocks!", "<rss")
+	assertFileContent(t, filepath.Join("public", "sect1", "customrss.xml"), false, "Recent content in Sect1s on Hugo Rocks!", "<rss")
+	assertFileContent(t, filepath.Join("public", "sect2", "customrss.xml"), false, "Recent content in Sect2s on Hugo Rocks!", "<rss")
+	assertFileContent(t, filepath.Join("public", "categories", "hugo", "customrss.xml"), false, "Recent content in Hugo on Hugo Rocks!", "<rss")
+	assertFileContent(t, filepath.Join("public", "categories", "web", "customrss.xml"), false, "Recent content in Web on Hugo Rocks!", "<rss")
 
 }
 
--- a/hugolib/page.go
+++ b/hugolib/page.go
@@ -95,6 +95,8 @@
 	PageMeta
 	Source
 	Position `json:"-"`
+
+	// TODO(bep) np pointer, or remove
 	Node
 
 	GitInfo *gitmap.GitInfo
@@ -496,6 +498,29 @@
 	return layouts(p.Type(), layout)
 }
 
+// TODO(bep) np consolidate and test these NodeType switches
+// rssLayouts returns RSS layouts to use for the RSS version of this page, nil
+// if no RSS should be rendered.
+func (p *Page) rssLayouts() []string {
+	switch p.NodeType {
+	case NodeHome:
+		return []string{"rss.xml", "_default/rss.xml", "_internal/_default/rss.xml"}
+	case NodeSection:
+		section := p.sections[0]
+		return []string{"section/" + section + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}
+	case NodeTaxonomy:
+		singular := p.site.taxonomiesPluralSingular[p.sections[0]]
+		return []string{"taxonomy/" + singular + ".rss.xml", "_default/rss.xml", "rss.xml", "_internal/_default/rss.xml"}
+	case NodeTaxonomyTerms:
+	// No RSS for taxonomy terms
+	case NodePage:
+		// No RSS for regular pages
+	}
+
+	return nil
+
+}
+
 func layouts(types string, layout string) (layouts []string) {
 	t := strings.Split(types, "/")
 
@@ -1246,7 +1271,7 @@
 		if !ok {
 			return fmt.Errorf("Data for section %s not found", p.Section())
 		}
-		p.Data["Pages"] = sectionData
+		p.Data["Pages"] = sectionData.Pages()
 	case NodeTaxonomy:
 		plural := p.sections[0]
 		term := p.sections[1]
@@ -1278,7 +1303,7 @@
 // the paginators etc., we do it manually here.
 // TODO(bep) np do better
 func (p *Page) copy() *Page {
-	c := &Page{Node: Node{NodeType: p.NodeType}}
+	c := &Page{Node: Node{NodeType: p.NodeType, Site: p.Site}}
 	c.Title = p.Title
 	c.Data = p.Data
 	c.Date = p.Date
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -2322,6 +2322,7 @@
 }
 
 func (s *Site) renderAndWriteXML(name string, dest string, d interface{}, layouts ...string) error {
+	jww.DEBUG.Printf("Render XML for %q to %q", name, dest)
 	renderBuffer := bp.GetBuffer()
 	defer bp.PutBuffer(renderBuffer)
 	renderBuffer.WriteString("<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\" ?>\n")
--- a/hugolib/site_render.go
+++ b/hugolib/site_render.go
@@ -76,6 +76,10 @@
 				results <- err
 			}
 		}
+
+		if err := s.renderRSS(p); err != nil {
+			results <- err
+		}
 	}
 }
 
@@ -119,5 +123,27 @@
 
 		}
 	}
+	return nil
+}
+
+func (s *Site) renderRSS(p *Page) error {
+	layouts := p.rssLayouts()
+
+	if layouts == nil {
+		// No RSS for this NodeType
+		return nil
+	}
+
+	// TODO(bep) np check RSS titles
+	rssNode := p.copy()
+
+	// TODO(bep) np todelido URL
+	rssURI := s.Language.GetString("rssURI")
+	rssNode.URLPath.URL = path.Join(rssNode.URLPath.URL, rssURI)
+
+	if err := s.renderAndWriteXML(rssNode.Title, rssNode.URLPath.URL, rssNode, s.appendThemeTemplates(layouts)...); err != nil {
+		return err
+	}
+
 	return nil
 }