URI: 
       resource/page: Add Page.Ancestors - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 3a216186b2cfa479c250dabb64eff022a388fb40
   DIR parent 7874b96815abf1e10b2947d9b3804767108ec939
  HTML Author: Septs <github@septs.pw>
       Date:   Wed, 30 Nov 2022 12:02:57 +0800
       
       resource/page: Add Page.Ancestors
       
       Fixes #10567
       
       Diffstat:
         M docs/content/en/content-management… |      21 +++++++++------------
         M docs/content/en/variables/page.md   |       3 +++
         M hugolib/page__tree.go               |       9 +++++++++
         M hugolib/site_sections_test.go       |       6 ++++++
         M resources/page/page.go              |       3 +++
         M resources/page/page_nop.go          |       4 ++++
         M resources/page/testhelpers_test.go  |       4 ++++
       
       7 files changed, 38 insertions(+), 12 deletions(-)
       ---
   DIR diff --git a/docs/content/en/content-management/sections.md b/docs/content/en/content-management/sections.md
       @@ -63,19 +63,16 @@ If you need a specific template for a sub-section, you need to adjust either the
        With the available [section variables and methods](#section-page-variables-and-methods) you can build powerful navigation. One common example would be a partial to show Breadcrumb navigation:
        
        {{< code file="layouts/partials/breadcrumb.html" download="breadcrumb.html" >}}
       -<ol  class="nav navbar-nav">
       -  {{ template "breadcrumbnav" (dict "p1" . "p2" .) }}
       -</ol>
       -{{ define "breadcrumbnav" }}
       -{{ if .p1.Parent }}
       -{{ template "breadcrumbnav" (dict "p1" .p1.Parent "p2" .p2 )  }}
       -{{ else if not .p1.IsHome }}
       -{{ template "breadcrumbnav" (dict "p1" .p1.Site.Home "p2" .p2 )  }}
       -{{ end }}
       -<li{{ if eq .p1 .p2 }} class="active" aria-current="page" {{ end }}>
       -  <a href="{{ .p1.Permalink }}">{{ .p1.Title }}</a>
       +<ol class="nav navbar-nav">
       +<ul>
       +{{- range .Ancestors.Reverse }}
       +<li><a href="{{ .Permalink }}">{{ .Title }}</a></li>
       +{{- end }}
       +<li class="active" aria-current="page">
       +<a href="{{ .Permalink }}">{{ .Title }}</a>
        </li>
       -{{ end }}
       +</ul>
       +</ol>
        {{< /code >}}
        
        ## Section Page Variables and Methods
   DIR diff --git a/docs/content/en/variables/page.md b/docs/content/en/variables/page.md
       @@ -32,6 +32,9 @@ See [`.Scratch`](/functions/scratch/) for page-scoped, writable variables.
        .Aliases
        : aliases of this page
        
       +.Ancestors
       +: get the ancestors of each page, simplify [breadcrumb navigation]({{< relref "content-management/sections#example-breadcrumb-navigation" >}}) implementation complexity  
       +
        .BundleType
        : the [bundle] type: `leaf`, `branch`, or an empty string if the page is not a bundle.
        
   DIR diff --git a/hugolib/page__tree.go b/hugolib/page__tree.go
       @@ -178,6 +178,15 @@ func (pt pageTree) Parent() page.Page {
                return b.p
        }
        
       +func (pt pageTree) Ancestors() (parents page.Pages) {
       +        parent := pt.Parent()
       +        for parent != nil {
       +                parents = append(parents, parent)
       +                parent = parent.Parent()
       +        }
       +        return
       +}
       +
        func (pt pageTree) Sections() page.Pages {
                if pt.p.bucket == nil {
                        return nil
   DIR diff --git a/hugolib/site_sections_test.go b/hugolib/site_sections_test.go
       @@ -181,12 +181,14 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                                c.Assert(err, qt.IsNil)
                                c.Assert(active, qt.Equals, true)
                                c.Assert(p.FirstSection(), qt.Equals, p)
       +                        c.Assert(len(p.Ancestors()), qt.Equals, 1)
                        }},
                        {"l1", func(c *qt.C, p page.Page) {
                                c.Assert(p.Title(), qt.Equals, "L1s")
                                c.Assert(len(p.Pages()), qt.Equals, 4) // 2 pages + 2 sections
                                c.Assert(p.Parent().IsHome(), qt.Equals, true)
                                c.Assert(len(p.Sections()), qt.Equals, 2)
       +                        c.Assert(len(p.Ancestors()), qt.Equals, 1)
                        }},
                        {"l1,l2", func(c *qt.C, p page.Page) {
                                c.Assert(p.Title(), qt.Equals, "T2_-1")
       @@ -195,6 +197,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                                c.Assert(p.Parent().Title(), qt.Equals, "L1s")
                                c.Assert(p.RelPermalink(), qt.Equals, "/l1/l2/")
                                c.Assert(len(p.Sections()), qt.Equals, 1)
       +                        c.Assert(len(p.Ancestors()), qt.Equals, 2)
        
                                for _, child := range p.Pages() {
                                        if child.IsSection() {
       @@ -237,6 +240,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                                c.Assert(p.Pages()[0].File().Path(), qt.Equals, filepath.FromSlash("l1/l2_2/page_2_2_1.md"))
                                c.Assert(p.Parent().Title(), qt.Equals, "L1s")
                                c.Assert(len(p.Sections()), qt.Equals, 0)
       +                        c.Assert(len(p.Ancestors()), qt.Equals, 2)
                        }},
                        {"l1,l2,l3", func(c *qt.C, p page.Page) {
                                nilp, _ := p.GetPage("this/does/not/exist")
       @@ -245,6 +249,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                                c.Assert(len(p.Pages()), qt.Equals, 2)
                                c.Assert(p.Parent().Title(), qt.Equals, "T2_-1")
                                c.Assert(len(p.Sections()), qt.Equals, 0)
       +                        c.Assert(len(p.Ancestors()), qt.Equals, 3)
        
                                l1 := getPage(p, "/l1")
                                isDescendant, err := l1.IsDescendant(p)
       @@ -307,6 +312,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }}
                }
        
                c.Assert(home, qt.Not(qt.IsNil))
       +        c.Assert(len(home.Ancestors()), qt.Equals, 0)
        
                c.Assert(len(home.Sections()), qt.Equals, 9)
                c.Assert(s.Info.Sections(), deepEqualsPages, home.Sections())
   DIR diff --git a/resources/page/page.go b/resources/page/page.go
       @@ -407,6 +407,9 @@ type TreeProvider interface {
                // To get a section's subsections, see Page's Sections method.
                Parent() Page
        
       +        // Ancestors returns the ancestors of each page
       +        Ancestors() Pages
       +
                // Sections returns this section's subsections, if any.
                // Note that for non-sections, this method will always return an empty list.
                Sections() Pages
   DIR diff --git a/resources/page/page_nop.go b/resources/page/page_nop.go
       @@ -348,6 +348,10 @@ func (p *nopPage) Parent() Page {
                return nil
        }
        
       +func (p *nopPage) Ancestors() Pages {
       +        return nil
       +}
       +
        func (p *nopPage) Path() string {
                return ""
        }
   DIR diff --git a/resources/page/testhelpers_test.go b/resources/page/testhelpers_test.go
       @@ -416,6 +416,10 @@ func (p *testPage) Parent() Page {
                panic("not implemented")
        }
        
       +func (p *testPage) Ancestors() Pages {
       +        panic("not implemented")
       +}
       +
        func (p *testPage) Path() string {
                return p.path
        }