diff --git a/common/collections/order.go b/common/collections/order.go new file mode 100644 index 000000000..4bdc3b4ac --- /dev/null +++ b/common/collections/order.go @@ -0,0 +1,20 @@ +// Copyright 2020 The Hugo Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package collections + +type Order interface { + // Ordinal is a zero-based ordinal that represents the order of an object + // in a collection. + Ordinal() int +} diff --git a/hugolib/content_map.go b/hugolib/content_map.go index ddcc70707..8af553478 100644 --- a/hugolib/content_map.go +++ b/hugolib/content_map.go @@ -264,6 +264,7 @@ func (b *cmInsertKeyBuilder) newTopLevel() { } type contentBundleViewInfo struct { + ordinal int name viewName termKey string termOrigin string diff --git a/hugolib/content_map_page.go b/hugolib/content_map_page.go index 7516a7029..8c7ecc341 100644 --- a/hugolib/content_map_page.go +++ b/hugolib/content_map_page.go @@ -579,7 +579,6 @@ func (m *pageMap) attachPageToViews(s string, b *contentNode) { if vals == nil { continue } - w := getParamToLower(b.p, viewName.plural+"_weight") weight, err := cast.ToIntE(w) if err != nil { @@ -587,11 +586,12 @@ func (m *pageMap) attachPageToViews(s string, b *contentNode) { // weight will equal zero, so let the flow continue } - for _, v := range vals { + for i, v := range vals { termKey := m.s.getTaxonomyKey(v) bv := &contentNode{ viewInfo: &contentBundleViewInfo{ + ordinal: i, name: viewName, termKey: termKey, termOrigin: v, diff --git a/hugolib/page.go b/hugolib/page.go index 083e702ed..baf5e7f69 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -132,6 +132,7 @@ func (p *pageState) GitInfo() *gitmap.GitInfo { } // GetTerms gets the terms defined on this page in the given taxonomy. +// The pages returned will be ordered according to the front matter. func (p *pageState) GetTerms(taxonomy string) page.Pages { if p.treeRef == nil { return nil @@ -147,8 +148,9 @@ func (p *pageState) GetTerms(taxonomy string) page.Pages { m.taxonomies.WalkQuery(pageMapQuery{Prefix: prefix}, func(s string, n *contentNode) bool { key := s + self - if _, found := m.taxonomyEntries.Get(key); found { - pas = append(pas, n.p) + if tn, found := m.taxonomyEntries.Get(key); found { + vi := tn.(*contentNode).viewInfo + pas = append(pas, pageWithOrdinal{pageState: n.p, ordinal: vi.ordinal}) } return false }) @@ -1006,3 +1008,22 @@ func (s *Site) sectionsFromFile(fi source.File) []string { return parts } + +var ( + _ page.Page = (*pageWithOrdinal)(nil) + _ collections.Order = (*pageWithOrdinal)(nil) + _ pageWrapper = (*pageWithOrdinal)(nil) +) + +type pageWithOrdinal struct { + ordinal int + *pageState +} + +func (p pageWithOrdinal) Ordinal() int { + return p.ordinal +} + +func (p pageWithOrdinal) page() page.Page { + return p.pageState +} diff --git a/hugolib/taxonomy_test.go b/hugolib/taxonomy_test.go index 97058dd19..64f560d25 100644 --- a/hugolib/taxonomy_test.go +++ b/hugolib/taxonomy_test.go @@ -644,12 +644,12 @@ Cats Paginator {{ range $cats.Paginator.Pages }}{{ .RelPermalink }}|{{ end }}:EN Categories Pages: /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END Funny Pages: /section/p1/|/section/p2/|:END Cats Pages: /section/p1/|/section/|:END -P1 Terms: /categories/cats/|/categories/funny/|:END -Section Terms: /categories/birds/|/categories/cats/|/categories/dogs/|:END +P1 Terms: /categories/funny/|/categories/cats/|:END +Section Terms: /categories/cats/|/categories/dogs/|/categories/birds/|:END Home Terms: /categories/dogs/|/categories/gorillas/|:END Cats Paginator /section/p1/|/section/|:END -Category Paginator /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END -`) +Category Paginator /categories/birds/|/categories/cats/|/categories/dogs/|/categories/funny/|/categories/gorillas/|:END`, + ) b.AssertFileContent("public/404.html", "\n404 Terms: :END\n\t") b.AssertFileContent("public/categories/funny/index.xml", `http://example.com/section/p1/`) b.AssertFileContent("public/categories/index.xml", `http://example.com/categories/funny/`) diff --git a/resources/page/pages_sort.go b/resources/page/pages_sort.go index b0e7f8e32..85817ffda 100644 --- a/resources/page/pages_sort.go +++ b/resources/page/pages_sort.go @@ -16,6 +16,8 @@ package page import ( "sort" + "github.com/gohugoio/hugo/common/collections" + "github.com/gohugoio/hugo/resources/resource" "github.com/gohugoio/hugo/compare" @@ -37,6 +39,19 @@ type pageSorter struct { // pageBy is a closure used in the Sort.Less method. type pageBy func(p1, p2 Page) bool +func getOrdinals(p1, p2 Page) (int, int) { + p1o, ok1 := p1.(collections.Order) + if !ok1 { + return -1, -1 + } + p2o, ok2 := p2.(collections.Order) + if !ok2 { + return -1, -1 + } + + return p1o.Ordinal(), p2o.Ordinal() +} + // Sort stable sorts the pages given the receiver's sort order. func (by pageBy) Sort(pages Pages) { ps := &pageSorter{ @@ -49,8 +64,12 @@ func (by pageBy) Sort(pages Pages) { var ( // DefaultPageSort is the default sort func for pages in Hugo: - // Order by Weight, Date, LinkTitle and then full file path. + // Order by Ordinal, Weight, Date, LinkTitle and then full file path. DefaultPageSort = func(p1, p2 Page) bool { + o1, o2 := getOrdinals(p1, p2) + if o1 != o2 && o1 != -1 && o2 != -1 { + return o1 < o2 + } if p1.Weight() == p2.Weight() { if p1.Date().Unix() == p2.Date().Unix() { c := compare.Strings(p1.LinkTitle(), p2.LinkTitle())