diff options
author | Bjørn Erik Pedersen <[email protected]> | 2017-07-02 20:14:06 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2017-07-04 09:11:49 +0200 |
commit | a1d260b41a6673adef679ec4e262c5f390432cf5 (patch) | |
tree | f9a86343fb6a73defb0805578d25eb72c6afb534 | |
parent | dd9b1baab0cb860a3eb32fd9043bac18cab3f9f0 (diff) | |
download | hugo-a1d260b41a6673adef679ec4e262c5f390432cf5.tar.gz hugo-a1d260b41a6673adef679ec4e262c5f390432cf5.zip |
hugolib: Extend the sections API
This commit adds some section related methods that have been asked for:
* .CurrentSection
* .IsDescendant
* .IsAncestor
Fixes #3591
-rw-r--r-- | helpers/general.go | 32 | ||||
-rw-r--r-- | helpers/general_test.go | 39 | ||||
-rw-r--r-- | hugolib/permalinks.go | 2 | ||||
-rw-r--r-- | hugolib/site_sections.go | 60 | ||||
-rw-r--r-- | hugolib/site_sections_test.go | 36 |
5 files changed, 155 insertions, 14 deletions
diff --git a/helpers/general.go b/helpers/general.go index 7901be654..552e4d0bf 100644 --- a/helpers/general.go +++ b/helpers/general.go @@ -194,6 +194,38 @@ func ReaderContains(r io.Reader, subslice []byte) bool { return false } +// HasStringsPrefix tests whether the string slice s begins with prefix slice s. +func HasStringsPrefix(s, prefix []string) bool { + return len(s) >= len(prefix) && compareStringSlices(s[0:len(prefix)], prefix) +} + +// HasStringsSuffix tests whether the string slice s ends with suffix slice s. +func HasStringsSuffix(s, suffix []string) bool { + return len(s) >= len(suffix) && compareStringSlices(s[len(s)-len(suffix):], suffix) +} + +func compareStringSlices(a, b []string) bool { + if a == nil && b == nil { + return true + } + + if a == nil || b == nil { + return false + } + + if len(a) != len(b) { + return false + } + + for i := range a { + if a[i] != b[i] { + return false + } + } + + return true +} + // ThemeSet checks whether a theme is in use or not. func (p *PathSpec) ThemeSet() bool { return p.theme != "" diff --git a/helpers/general_test.go b/helpers/general_test.go index ee4ed2370..4d82bc0cf 100644 --- a/helpers/general_test.go +++ b/helpers/general_test.go @@ -64,6 +64,45 @@ func TestFirstUpper(t *testing.T) { } } +func TestHasStringsPrefix(t *testing.T) { + for i, this := range []struct { + s []string + prefix []string + expect bool + }{ + {[]string{"a"}, []string{"a"}, true}, + {[]string{}, []string{}, true}, + {[]string{"a", "b", "c"}, []string{"a", "b"}, true}, + {[]string{"d", "a", "b", "c"}, []string{"a", "b"}, false}, + {[]string{"abra", "ca", "dabra"}, []string{"abra", "ca"}, true}, + {[]string{"abra", "ca"}, []string{"abra", "ca", "dabra"}, false}, + } { + result := HasStringsPrefix(this.s, this.prefix) + if result != this.expect { + t.Fatalf("[%d] got %t but expected %t", i, result, this.expect) + } + } +} + +func TestHasStringsSuffix(t *testing.T) { + for i, this := range []struct { + s []string + suffix []string + expect bool + }{ + {[]string{"a"}, []string{"a"}, true}, + {[]string{}, []string{}, true}, + {[]string{"a", "b", "c"}, []string{"b", "c"}, true}, + {[]string{"abra", "ca", "dabra"}, []string{"abra", "ca"}, false}, + {[]string{"abra", "ca", "dabra"}, []string{"ca", "dabra"}, true}, + } { + result := HasStringsSuffix(this.s, this.suffix) + if result != this.expect { + t.Fatalf("[%d] got %t but expected %t", i, result, this.expect) + } + } +} + var containsTestText = (`На берегу пустынных волн Стоял он, дум великих полн, И вдаль глядел. Пред ним широко diff --git a/hugolib/permalinks.go b/hugolib/permalinks.go index 6f26f098a..14d0cba5e 100644 --- a/hugolib/permalinks.go +++ b/hugolib/permalinks.go @@ -186,7 +186,7 @@ func pageToPermalinkSection(p *Page, _ string) (string, error) { func pageToPermalinkSections(p *Page, _ string) (string, error) { // TODO(bep) we have some superflous URLize in this file, but let's // deal with that later. - return path.Join(p.current().sections...), nil + return path.Join(p.CurrentSection().sections...), nil } func init() { diff --git a/hugolib/site_sections.go b/hugolib/site_sections.go index 1dd010092..4f4a217d5 100644 --- a/hugolib/site_sections.go +++ b/hugolib/site_sections.go @@ -19,6 +19,8 @@ import ( "strconv" "strings" + "github.com/gohugoio/hugo/helpers" + radix "github.com/hashicorp/go-immutable-radix" ) @@ -42,10 +44,9 @@ func (p *Page) Parent() *Page { return p.parent } -// current returns the page's current section. +// CurrentSection returns the page's current section or the page itself if home or a section. // Note that this will return nil for pages that is not regular, home or section pages. -// Note that for paginated sections and home pages, this will return the original page pointer. -func (p *Page) current() *Page { +func (p *Page) CurrentSection() *Page { v := p if v.origOnCopy != nil { v = v.origOnCopy @@ -65,20 +66,59 @@ func (p *Page) InSection(other interface{}) (bool, error) { return false, nil } - if po, ok := other.(*PageOutput); ok { - other = po.Page + pp, err := unwrapPage(other) + if err != nil { + return false, err } - pp, ok := other.(*Page) - if !ok { - return false, fmt.Errorf("%T not supported in InSection", other) + if pp == nil { + return false, nil } - if pp == nil { + return pp.CurrentSection() == p.CurrentSection(), nil +} + +// IsDescendant returns whether the current page is a descendant of the given page. +// Note that this method is not relevant for taxonomy lists and taxonomy terms pages. +func (p *Page) IsDescendant(other interface{}) (bool, error) { + pp, err := unwrapPage(other) + if err != nil { + return false, err + } + + if pp.Kind == KindPage && len(p.sections) == len(pp.sections) { + // A regular page is never its section's descendant. return false, nil } + return helpers.HasStringsPrefix(p.sections, pp.sections), nil +} - return pp.current() == p.current(), nil +// IsAncestor returns whether the current page is an ancestor of the given page. +// Note that this method is not relevant for taxonomy lists and taxonomy terms pages. +func (p *Page) IsAncestor(other interface{}) (bool, error) { + pp, err := unwrapPage(other) + if err != nil { + return false, err + } + + if p.Kind == KindPage && len(p.sections) == len(pp.sections) { + // A regular page is never its section's ancestor. + return false, nil + } + + return helpers.HasStringsPrefix(pp.sections, p.sections), nil +} + +func unwrapPage(in interface{}) (*Page, error) { + if po, ok := in.(*PageOutput); ok { + in = po.Page + } + + pp, ok := in.(*Page) + if !ok { + return nil, fmt.Errorf("%T not supported", in) + } + return pp, nil } // Sections returns this section's subsections, if any. diff --git a/hugolib/site_sections_test.go b/hugolib/site_sections_test.go index 77a85099c..441391197 100644 --- a/hugolib/site_sections_test.go +++ b/hugolib/site_sections_test.go @@ -166,7 +166,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }} home := p.Parent() assert.True(home.IsHome()) assert.Len(p.Sections(), 0) - assert.Equal(home, home.current()) + assert.Equal(home, home.CurrentSection()) active, err := home.InSection(home) assert.NoError(err) assert.True(active) @@ -187,7 +187,7 @@ PAG|{{ .Title }}|{{ $sect.InSection . }} assert.Len(p.Sections(), 1) for _, child := range p.Pages { - assert.Equal(p, child.current()) + assert.Equal(p, child.CurrentSection()) active, err := child.InSection(p) assert.NoError(err) assert.True(active) @@ -197,9 +197,23 @@ PAG|{{ .Title }}|{{ $sect.InSection . }} active, err = p.InSection(p.s.getPage(KindHome)) assert.NoError(err) assert.False(active) + + isAncestor, err := p.IsAncestor(child) + assert.NoError(err) + assert.True(isAncestor) + isAncestor, err = child.IsAncestor(p) + assert.NoError(err) + assert.False(isAncestor) + + isDescendant, err := p.IsDescendant(child) + assert.NoError(err) + assert.False(isDescendant) + isDescendant, err = child.IsDescendant(p) + assert.NoError(err) + assert.True(isDescendant) } - assert.Equal(p, p.current()) + assert.Equal(p, p.CurrentSection()) }}, {"l1,l2_2", func(p *Page) { @@ -214,6 +228,22 @@ PAG|{{ .Title }}|{{ $sect.InSection . }} assert.Len(p.Pages, 2) assert.Equal("T2_-1", p.Parent().Title) assert.Len(p.Sections(), 0) + + l1 := p.s.getPage(KindSection, "l1") + isDescendant, err := l1.IsDescendant(p) + assert.NoError(err) + assert.False(isDescendant) + isDescendant, err = p.IsDescendant(l1) + assert.NoError(err) + assert.True(isDescendant) + + isAncestor, err := l1.IsAncestor(p) + assert.NoError(err) + assert.True(isAncestor) + isAncestor, err = p.IsAncestor(l1) + assert.NoError(err) + assert.False(isAncestor) + }}, {"perm a,link", func(p *Page) { assert.Equal("T9_-1", p.Title) |