diff --git a/config/allconfig/allconfig.go b/config/allconfig/allconfig.go index afa72fb11ac..802000f9740 100644 --- a/config/allconfig/allconfig.go +++ b/config/allconfig/allconfig.go @@ -182,6 +182,9 @@ type Config struct { // Pagination configuration. Pagination config.Pagination `mapstructure:"-"` + // Page configuration. + Page config.PageConfig `mapstructure:"-"` + // Privacy configuration. Privacy privacy.Config `mapstructure:"-"` diff --git a/config/allconfig/alldecoders.go b/config/allconfig/alldecoders.go index c09aa0ff0a2..45cdd0de6a7 100644 --- a/config/allconfig/alldecoders.go +++ b/config/allconfig/alldecoders.go @@ -327,6 +327,25 @@ var allDecoderSetups = map[string]decodeWeight{ return err }, }, + "page": { + key: "page", + decode: func(d decodeWeight, p decodeConfig) error { + p.c.Page = config.PageConfig{ + NextPrevSortOrder: "desc", + NextPrevInSectionSortOrder: "desc", + } + if p.p.IsSet(d.key) { + if err := mapstructure.WeakDecode(p.p.Get(d.key), &p.c.Page); err != nil { + return err + } + } + + return nil + }, + getCompiler: func(c *Config) configCompiler { + return &c.Page + }, + }, "pagination": { key: "pagination", decode: func(d decodeWeight, p decodeConfig) error { diff --git a/config/commonConfig.go b/config/commonConfig.go index a615c51a76e..9dea4a2fcea 100644 --- a/config/commonConfig.go +++ b/config/commonConfig.go @@ -422,3 +422,18 @@ type Pagination struct { // Whether to disable generation of alias for the first pagination page. DisableAliases bool } + +// PageConfig configures the behavior of pages. +type PageConfig struct { + // Sort order for Page.Next and Page.Prev. Default "desc" (the default page sort order in Hugo). + NextPrevSortOrder string + + // Sort order for Page.NextInSection and Page.PrevInSection. Default "desc". + NextPrevInSectionSortOrder string +} + +func (c *PageConfig) CompileConfig(loggers.Logger) error { + c.NextPrevInSectionSortOrder = strings.ToLower(c.NextPrevInSectionSortOrder) + c.NextPrevSortOrder = strings.ToLower(c.NextPrevSortOrder) + return nil +} diff --git a/docs/data/docs.yaml b/docs/data/docs.yaml index e399426b6f5..7ac76ee3919 100644 --- a/docs/data/docs.yaml +++ b/docs/data/docs.yaml @@ -1600,6 +1600,9 @@ config: term: - html - rss + page: + nextPrevInSectionSortOrder: desc + nextPrevSortOrder: desc paginate: 0 paginatePath: "" pagination: @@ -1784,6 +1787,8 @@ config_helpers: _merge: shallow outputs: _merge: none + page: + _merge: none pagination: _merge: none params: diff --git a/hugolib/site.go b/hugolib/site.go index bbf110d1d8c..0125772e356 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -117,6 +117,9 @@ func (s *Site) prepareInits() { s.init.prevNext = init.Branch(func(context.Context) (any, error) { regularPages := s.RegularPages() + if s.conf.Page.NextPrevSortOrder == "asc" { + regularPages = regularPages.Reverse() + } for i, p := range regularPages { np, ok := p.(nextPrevProvider) if !ok { @@ -181,7 +184,11 @@ func (s *Site) prepareInits() { ) for _, section := range sections { - setNextPrev(section.RegularPages()) + ps := section.RegularPages() + if s.conf.Page.NextPrevSortOrder == "asc" { + ps = ps.Reverse() + } + setNextPrev(ps) } return nil, nil diff --git a/resources/page/pages_prev_next_integration_test.go b/resources/page/pages_prev_next_integration_test.go new file mode 100644 index 00000000000..6d86c950f29 --- /dev/null +++ b/resources/page/pages_prev_next_integration_test.go @@ -0,0 +1,62 @@ +// Copyright 2024 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 page_test + +import ( + "strings" + "testing" + + "github.com/gohugoio/hugo/hugolib" +) + +func TestNextPrevConfig(t *testing.T) { + files := ` +-- hugo.toml -- +-- content/mysection/_index.md -- +-- content/mysection/p1.md -- +--- +title: "Page 1" +weight: 10 +--- +-- content/mysection/p2.md -- +--- +title: "Page 2" +weight: 20 +--- +-- content/mysection/p3.md -- +--- +title: "Page 3" +weight: 30 +--- +-- layouts/_default/single.html -- +{{ .Title }}|Next: {{ with .Next}}{{ .Title}}{{ end }}|Prev: {{ with .Prev}}{{ .Title}}{{ end }}|NextInSection: {{ with .NextInSection}}{{ .Title}}{{ end }}|PrevInSection: {{ with .PrevInSection}}{{ .Title}}{{ end }}| + +` + b := hugolib.Test(t, files) + + b.AssertFileContent("public/mysection/p1/index.html", "Page 1|Next: |Prev: Page 2|NextInSection: |PrevInSection: Page 2|") + b.AssertFileContent("public/mysection/p2/index.html", "Page 2|Next: Page 1|Prev: Page 3|NextInSection: Page 1|PrevInSection: Page 3|") + b.AssertFileContent("public/mysection/p3/index.html", "Page 3|Next: Page 2|Prev: |NextInSection: Page 2|PrevInSection: |") + + files = strings.ReplaceAll(files, "-- hugo.toml --", `-- hugo.toml -- +[page] +nextPrevSortOrder="aSc" +nextPrevInSectionSortOrder="asC" +`) + + b = hugolib.Test(t, files) + + b.AssertFileContent("public/mysection/p1/index.html", "Page 1|Next: Page 2|Prev: |NextInSection: Page 2|PrevInSection: |") + b.AssertFileContent("public/mysection/p2/index.html", "Page 2|Next: Page 3|Prev: Page 1|NextInSection: Page 3|PrevInSection: Page 1|") + b.AssertFileContent("public/mysection/p3/index.html", "Page 3|Next: |Prev: Page 2|NextInSection: |PrevInSection: Page 2|") +}