Consider root and current section's content type if set in front matter
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 30 Jun 2018 11:03:26 +0000 (13:03 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Sat, 30 Jun 2018 11:10:04 +0000 (13:10 +0200)
This should allow for less duplication of templates. Before this commit it was possible to override the content page of a given page/section, but only one page at a time.

Full "template sets" can now be inherited by setting `type: blog` etc. in the section content page's front matter, and that type will be considered when looking for layouts for all pages in that section.

For nested sections, it will use consider both `type` set in the current section first, then `type` set in the first section below home, e.g. `/docs`.

This commit also adds a new Page method: `FirstSection`. This navigates up to the first section below home (e.g. `/docs`). For the home page it will return itself.

Fixes #4891

hugolib/page.go
hugolib/site_sections.go
hugolib/site_sections_test.go
output/layout.go
output/layout_test.go

index 322660647e8bc5f4707d84028a84d68756680150..458b96b285601b041eb1b196c3ae541d71f60bdc 100644 (file)
@@ -405,12 +405,26 @@ func (p *Page) createLayoutDescriptor() output.LayoutDescriptor {
        default:
        }
 
+       var typeCurrentSection string
+       var typeRootSection string
+       curr := p.CurrentSection()
+       // Make sure we use the contentType only. This is the value from front matter.
+       if curr != nil {
+               typeCurrentSection = curr.contentType
+       }
+       first := p.FirstSection()
+       if first != nil {
+               typeRootSection = first.contentType
+       }
+
        return output.LayoutDescriptor{
-               Kind:    p.Kind,
-               Type:    p.Type(),
-               Lang:    p.Lang(),
-               Layout:  p.Layout,
-               Section: section,
+               Kind:               p.Kind,
+               Type:               p.Type(),
+               Lang:               p.Lang(),
+               Layout:             p.Layout,
+               Section:            section,
+               TypeCurrentSection: typeCurrentSection,
+               TypeFirstSection:   typeRootSection,
        }
 }
 
index c8bca03e3d3fa001675170471dbcfebce83acb80..2537b5d245f70b3ead54be01facfd83d703f2117 100644 (file)
@@ -58,6 +58,29 @@ func (p *Page) CurrentSection() *Page {
        return v.parent
 }
 
+// FirstSection returns the section on level 1 below home, e.g. "/docs".
+// For the home page, this will return itself.
+func (p *Page) FirstSection() *Page {
+       v := p
+       if v.origOnCopy != nil {
+               v = v.origOnCopy
+       }
+
+       if v.parent == nil || v.parent.IsHome() {
+               return v
+       }
+
+       parent := v.parent
+       for {
+               current := parent
+               parent = parent.parent
+               if parent == nil || parent.IsHome() {
+                       return current
+               }
+       }
+
+}
+
 // InSection returns whether the given page is in the current section.
 // Note that this will always return false for pages that are
 // not either regular, home or section pages.
index a1b80407cdf0855fb2a4d37ceff9c521b940c18e..9a75f65f97fe84183558e15cb91b65c1f4719b6f 100644 (file)
@@ -176,6 +176,8 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                        active, err := home.InSection(home)
                        assert.NoError(err)
                        assert.True(active)
+                       assert.Equal(p, p.FirstSection())
+
                }},
                {"l1", func(p *Page) {
                        assert.Equal("L1s", p.title)
@@ -250,6 +252,8 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                        assert.NoError(err)
                        assert.False(isAncestor)
 
+                       assert.Equal(l1, p.FirstSection())
+
                }},
                {"perm a,link", func(p *Page) {
                        assert.Equal("T9_-1", p.title)
index f83490d817c09fa338b630bd28d06471c643d56d..2483093b0b34d58f5fed2c9a9f8ceddd3e5a03a9 100644 (file)
@@ -35,6 +35,12 @@ type LayoutDescriptor struct {
        Kind    string
        Lang    string
        Layout  string
+
+       // Any potential type set in the page's current section and the root section
+       // it lives in.
+       TypeFirstSection    string
+       TypeCurrentSection string
+
        // LayoutOverride indicates what we should only look for the above layout.
        LayoutOverride bool
 }
@@ -127,6 +133,14 @@ func resolvePageTemplate(d LayoutDescriptor, f Format) []string {
                b.addTypeVariations(d.Type)
        }
 
+       if d.TypeCurrentSection != "" {
+               b.addTypeVariations(d.TypeCurrentSection)
+       }
+
+       if d.TypeFirstSection != "" {
+               b.addTypeVariations(d.TypeFirstSection)
+       }
+
        switch d.Kind {
        case "page":
                b.addLayoutVariations("single")
index 4b958e9ffb2456e4eb143b50e00e86f453d4909b..6754ddb39df3c791d5dfb5b66c8b837fa7d033f8 100644 (file)
@@ -90,8 +90,13 @@ func TestLayout(t *testing.T) {
                        []string{"_default/mylayout.amp.html", "_default/single.amp.html", "_default/mylayout.html", "_default/single.html"}, 4},
                {"Page with layout and type", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype"}, "", ampType,
                        []string{"myttype/mylayout.amp.html", "myttype/single.amp.html", "myttype/mylayout.html"}, 8},
-               {"Page with layout and type with subtype", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype"}, "", ampType,
-                       []string{"myttype/mysubtype/mylayout.amp.html", "myttype/mysubtype/single.amp.html", "myttype/mysubtype/mylayout.html"}, 8},
+               {"Page with layout and type with subtype", LayoutDescriptor{Kind: "page", Layout: "mylayout", Type: "myttype/mysubtype", TypeCurrentSection: "cst"}, "", ampType,
+                       []string{"myttype/mysubtype/mylayout.amp.html", "myttype/mysubtype/single.amp.html", "myttype/mysubtype/mylayout.html"}, 12},
+               {"Page with type in section", LayoutDescriptor{Kind: "page", TypeCurrentSection: "cst"}, "", ampType,
+                       []string{"cst/single.amp.html", "cst/single.html", "_default/single.amp.html", "_default/single.html"}, 4},
+               {"Page with type in root section", LayoutDescriptor{Kind: "page", TypeFirstSection: "cst"}, "", ampType,
+                       []string{"cst/single.amp.html", "cst/single.html", "_default/single.amp.html", "_default/single.html"}, 4},
+
                // RSS
                {"RSS Home", LayoutDescriptor{Kind: "home"}, "", RSSFormat,
                        []string{"index.rss.xml", "home.rss.xml", "rss.xml"}, 15},