From 487b210fb8a31b3636030ea960f6565b9e6b3c54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Fri, 11 Nov 2016 11:35:55 +0100 Subject: [PATCH] node to page: Handle Date and Lastmod Updates #2297 --- hugolib/hugo_sites.go | 7 - ...sites_test.go => hugo_sites_build_test.go} | 1 - hugolib/node_as_page_test.go | 157 ++++++++++++------ hugolib/page.go | 42 +++++ 4 files changed, 151 insertions(+), 56 deletions(-) rename hugolib/{hugo_sites_test.go => hugo_sites_build_test.go} (99%) diff --git a/hugolib/hugo_sites.go b/hugolib/hugo_sites.go index ba743d4f1..bf5f27755 100644 --- a/hugolib/hugo_sites.go +++ b/hugolib/hugo_sites.go @@ -31,11 +31,6 @@ import ( jww "github.com/spf13/jwalterweatherman" ) -// Temporary feature flag to ease the refactoring of node vs page, see -// https://github.com/spf13/hugo/issues/2297 -// TODO(bep) eventually remove -var nodePageFeatureFlag bool = true - // HugoSites represents the sites to build. Each site represents a language. type HugoSites struct { Sites []*Site @@ -313,8 +308,6 @@ func (s *Site) newNodePage(typ PageType) *Page { return &Page{ PageType: typ, Node: Node{ - Date: s.Info.LastChange, - Lastmod: s.Info.LastChange, Data: make(map[string]interface{}), Site: &s.Info, language: s.Language, diff --git a/hugolib/hugo_sites_test.go b/hugolib/hugo_sites_build_test.go similarity index 99% rename from hugolib/hugo_sites_test.go rename to hugolib/hugo_sites_build_test.go index a6118b5c3..05743a804 100644 --- a/hugolib/hugo_sites_test.go +++ b/hugolib/hugo_sites_build_test.go @@ -28,7 +28,6 @@ type testSiteConfig struct { } func init() { - nodePageFeatureFlag = true testCommonResetState() } diff --git a/hugolib/node_as_page_test.go b/hugolib/node_as_page_test.go index 78ccc6cef..504517494 100644 --- a/hugolib/node_as_page_test.go +++ b/hugolib/node_as_page_test.go @@ -17,6 +17,7 @@ import ( "fmt" "path/filepath" "testing" + "time" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" @@ -49,22 +50,7 @@ func TestNodesAsPage(t *testing.T) { writeLayoutsForNodeAsPageTests(t) writeNodePagesForNodeAsPageTests("", t) - // Add some regular pages - for i := 1; i <= 4; i++ { - sect := "sect1" - if i > 2 { - sect = "sect2" - } - writeSource(t, filepath.Join("content", sect, fmt.Sprintf("regular%d.md", i)), fmt.Sprintf(`--- -title: Page %02d -categories: [ - "Hugo", - "Web" -] ---- -Content Page %02d -`, i, i)) - } + writeRegularPagesForNodeAsPageTests(t) viper.Set("paginate", 1) viper.Set("title", "Hugo Rocks") @@ -76,40 +62,56 @@ Content Page %02d t.Fatalf("Failed to build site: %s", err) } + // date order: home, sect1, sect2, cat/hugo, cat/web, categories + assertFileContent(t, filepath.Join("public", "index.html"), false, "Index Title: Home Sweet Home!", "Home Content!", - "# Pages: 9") + "# Pages: 9", + "Date: 2009-01-02", + "Lastmod: 2009-01-03", + ) assertFileContent(t, filepath.Join("public", "sect1", "regular1", "index.html"), false, "Single Title: Page 01", "Content Page 01") h := s.owner - nodes := h.findAllPagesByNodeType(PageHome) - require.Len(t, nodes, 1) + nodes := h.findAllPagesByNodeTypeNotIn(PagePage) + require.Len(t, nodes, 6) - home := nodes[0] + home := nodes[5] // oldest require.True(t, home.IsHome()) require.True(t, home.IsNode()) require.False(t, home.IsPage()) + section2 := nodes[3] + require.Equal(t, "Section2", section2.Title) + pages := h.findAllPagesByNodeType(PagePage) require.Len(t, pages, 4) first := pages[0] + require.False(t, first.IsHome()) require.False(t, first.IsNode()) require.True(t, first.IsPage()) - first.Paginator() - // Check Home paginator assertFileContent(t, filepath.Join("public", "page", "2", "index.html"), false, "Pag: Page 02") // Check Sections - assertFileContent(t, filepath.Join("public", "sect1", "index.html"), false, "Section Title: Section", "Section1 Content!") - assertFileContent(t, filepath.Join("public", "sect2", "index.html"), false, "Section Title: Section", "Section2 Content!") + assertFileContent(t, filepath.Join("public", "sect1", "index.html"), false, + "Section Title: Section", "Section1 Content!", + "Date: 2009-01-04", + "Lastmod: 2009-01-05", + ) + + assertFileContent(t, filepath.Join("public", "sect2", "index.html"), false, + "Section Title: Section", "Section2 Content!", + "Date: 2009-01-06", + "Lastmod: 2009-01-07", + ) // Check Sections paginator assertFileContent(t, filepath.Join("public", "sect1", "page", "2", "index.html"), false, @@ -121,10 +123,17 @@ Content Page %02d // Check taxonomy lists assertFileContent(t, filepath.Join("public", "categories", "hugo", "index.html"), false, - "Taxonomy Title: Taxonomy Hugo", "Taxonomy Hugo Content!") + "Taxonomy Title: Taxonomy Hugo", "Taxonomy Hugo Content!", + "Date: 2009-01-08", + "Lastmod: 2009-01-09", + ) assertFileContent(t, filepath.Join("public", "categories", "web", "index.html"), false, - "Taxonomy Title: Taxonomy Web", "Taxonomy Web Content!") + "Taxonomy Title: Taxonomy Web", + "Taxonomy Web Content!", + "Date: 2009-01-10", + "Lastmod: 2009-01-11", + ) // Check taxonomy list paginator assertFileContent(t, filepath.Join("public", "categories", "hugo", "page", "2", "index.html"), false, @@ -133,7 +142,10 @@ Content Page %02d // Check taxonomy terms assertFileContent(t, filepath.Join("public", "categories", "index.html"), false, - "Taxonomy Terms Title: Taxonomy Term Categories", "Taxonomy Term Categories Content!", "k/v: hugo") + "Taxonomy Terms Title: Taxonomy Term Categories", "Taxonomy Term Categories Content!", "k/v: hugo", + "Date: 2009-01-12", + "Lastmod: 2009-01-13", + ) // There are no pages to paginate over in the taxonomy terms. @@ -174,21 +186,35 @@ func TestNodesWithNoContentFile(t *testing.T) { require.Len(t, homePage.Pages, 9) // Alias assertFileContent(t, filepath.Join("public", "index.html"), false, - "Index Title: Hugo Rocks!") + "Index Title: Hugo Rocks!", + "Date: 2010-06-12", + "Lastmod: 2010-06-13", + ) // Taxonomy list assertFileContent(t, filepath.Join("public", "categories", "hugo", "index.html"), false, - "Taxonomy Title: Hugo") + "Taxonomy Title: Hugo", + "Date: 2010-06-12", + "Lastmod: 2010-06-13", + ) // Taxonomy terms assertFileContent(t, filepath.Join("public", "categories", "index.html"), false, - "Taxonomy Terms Title: Categories") + "Taxonomy Terms Title: Categories", + ) // Sections assertFileContent(t, filepath.Join("public", "sect1", "index.html"), false, - "Section Title: Sect1s") + "Section Title: Sect1s", + "Date: 2010-06-12", + "Lastmod: 2010-06-13", + ) + assertFileContent(t, filepath.Join("public", "sect2", "index.html"), false, - "Section Title: Sect2s") + "Section Title: Sect2s", + "Date: 2008-07-06", + "Lastmod: 2008-07-09", + ) // RSS assertFileContent(t, filepath.Join("public", "customrss.xml"), false, "Recent content in Hugo Rocks! on Hugo Rocks!", " 2 { sect = "sect2" + + date, _ = time.Parse(format, "2008-07-15") // Nodes are placed in 2009 + } + date = date.Add(-24 * time.Duration(i) * time.Hour) writeSource(t, filepath.Join("content", sect, fmt.Sprintf("regular%d.%smd", i, langStr)), fmt.Sprintf(`--- title: Page %02d +lastMod : %q +date : %q categories: [ "Hugo", "Web" ] --- Content Page %02d -`, i, i)) +`, i, date.Add(time.Duration(i)*-24*time.Hour).Format(time.RFC822), date.Add(time.Duration(i)*-2*24*time.Hour).Format(time.RFC822), i)) } } @@ -440,41 +476,56 @@ func writeNodePagesForNodeAsPageTests(lang string, t *testing.T) { filename = fmt.Sprintf("_index.%s.md", lang) } - writeSource(t, filepath.Join("content", filename), `--- + format := "2006-01-02" + + date, _ := time.Parse(format, "2009-01-01") + + writeSource(t, filepath.Join("content", filename), fmt.Sprintf(`--- title: Home Sweet Home! +date : %q +lastMod : %q --- Home **Content!** -`) +`, date.Add(1*24*time.Hour).Format(time.RFC822), date.Add(2*24*time.Hour).Format(time.RFC822))) - writeSource(t, filepath.Join("content", "sect1", filename), `--- + writeSource(t, filepath.Join("content", "sect1", filename), fmt.Sprintf(`--- title: Section1 +date : %q +lastMod : %q --- Section1 **Content!** -`) - - writeSource(t, filepath.Join("content", "sect2", filename), `--- +`, date.Add(3*24*time.Hour).Format(time.RFC822), date.Add(4*24*time.Hour).Format(time.RFC822))) + writeSource(t, filepath.Join("content", "sect2", filename), fmt.Sprintf(`--- title: Section2 +date : %q +lastMod : %q --- Section2 **Content!** -`) +`, date.Add(5*24*time.Hour).Format(time.RFC822), date.Add(6*24*time.Hour).Format(time.RFC822))) - writeSource(t, filepath.Join("content", "categories", "hugo", filename), `--- + writeSource(t, filepath.Join("content", "categories", "hugo", filename), fmt.Sprintf(`--- title: Taxonomy Hugo +date : %q +lastMod : %q --- Taxonomy Hugo **Content!** -`) +`, date.Add(7*24*time.Hour).Format(time.RFC822), date.Add(8*24*time.Hour).Format(time.RFC822))) - writeSource(t, filepath.Join("content", "categories", "web", filename), `--- + writeSource(t, filepath.Join("content", "categories", "web", filename), fmt.Sprintf(`--- title: Taxonomy Web +date : %q +lastMod : %q --- Taxonomy Web **Content!** -`) +`, date.Add(9*24*time.Hour).Format(time.RFC822), date.Add(10*24*time.Hour).Format(time.RFC822))) - writeSource(t, filepath.Join("content", "categories", filename), `--- + writeSource(t, filepath.Join("content", "categories", filename), fmt.Sprintf(`--- title: Taxonomy Term Categories +date : %q +lastMod : %q --- Taxonomy Term Categories **Content!** -`) +`, date.Add(11*24*time.Hour).Format(time.RFC822), date.Add(12*24*time.Hour).Format(time.RFC822))) } func writeLayoutsForNodeAsPageTests(t *testing.T) { @@ -490,11 +541,15 @@ Index Content: {{ .Content }} Menu Item: {{ .Name }} {{ end }} {{ end }} +Date: {{ .Date.Format "2006-01-02" }} +Lastmod: {{ .Lastmod.Format "2006-01-02" }} `) writeSource(t, filepath.Join("layouts", "_default", "single.html"), ` Single Title: {{ .Title }} Single Content: {{ .Content }} +Date: {{ .Date.Format "2006-01-02" }} +Lastmod: {{ .Lastmod.Format "2006-01-02" }} `) writeSource(t, filepath.Join("layouts", "_default", "section.html"), ` @@ -504,6 +559,8 @@ Section Content: {{ .Content }} {{ range .Paginator.Pages }} Pag: {{ .Title }} {{ end }} +Date: {{ .Date.Format "2006-01-02" }} +Lastmod: {{ .Lastmod.Format "2006-01-02" }} `) // Taxonomy lists @@ -514,6 +571,8 @@ Taxonomy Content: {{ .Content }} {{ range .Paginator.Pages }} Pag: {{ .Title }} {{ end }} +Date: {{ .Date.Format "2006-01-02" }} +Lastmod: {{ .Lastmod.Format "2006-01-02" }} `) // Taxonomy terms @@ -523,5 +582,7 @@ Taxonomy Terms Content: {{ .Content }} {{ range $key, $value := .Data.Terms }} k/v: {{ $key }} / {{ printf "%=v" $value }} {{ end }} +Date: {{ .Date.Format "2006-01-02" }} +Lastmod: {{ .Lastmod.Format "2006-01-02" }} `) } diff --git a/hugolib/page.go b/hugolib/page.go index 28d4f7115..b885e7ebf 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -1365,9 +1365,51 @@ func (p *Page) prepareData(s *Site) error { p.Data["Pages"] = pages p.Pages = pages + // Now we know enough to set missing dates on home page etc. + p.updatePageDates() + return nil } +func (p *Page) updatePageDates() { + // TODO(bep) np there is a potential issue with page sorting for home pages + // etc. without front matter dates set, but let us wrap the head around + // that in another time. + if !p.PageType.IsNode() { + return + } + + if !p.Date.IsZero() { + if p.Lastmod.IsZero() { + p.Lastmod = p.Date + } + return + } else if !p.Lastmod.IsZero() { + if p.Date.IsZero() { + p.Date = p.Lastmod + } + return + } + + // Set it to the first non Zero date in children + var foundDate, foundLastMod bool + + for _, child := range p.Pages { + if !child.Date.IsZero() { + p.Date = child.Date + foundDate = true + } + if !child.Lastmod.IsZero() { + p.Lastmod = child.Lastmod + foundLastMod = true + } + + if foundDate && foundLastMod { + break + } + } +} + // Page constains some sync.Once which have a mutex, so we cannot just // copy the Page by value. So for the situations where we need a copy, // the paginators etc., we do it manually here.