Add option to not generate aliases for first page of pagination pages

Also consolidate the pagination configuration into a struct.

Closes #12572
This commit is contained in:
Bjørn Erik Pedersen 2024-06-07 17:38:33 +02:00
parent 1cdd3d0a9e
commit 9c4e14eb4f
9 changed files with 135 additions and 14 deletions

View file

@ -179,6 +179,9 @@ type Config struct {
// Server configuration. // Server configuration.
Server config.Server `mapstructure:"-"` Server config.Server `mapstructure:"-"`
// Pagination configuration.
Pagination config.Pagination `mapstructure:"-"`
// Privacy configuration. // Privacy configuration.
Privacy privacy.Config `mapstructure:"-"` Privacy privacy.Config `mapstructure:"-"`
@ -369,6 +372,17 @@ func (c *Config) CompileConfig(logger loggers.Logger) error {
return err return err
} }
// Legacy paginate values.
if c.Paginate != 0 {
hugo.Deprecate("site config key paginate", "Use paginator.defaultPageSize instead.", "v0.128.0")
c.Pagination.DefaultPageSize = c.Paginate
}
if c.PaginatePath != "" {
hugo.Deprecate("site config key paginatePath", "Use paginator.path instead.", "v0.128.0")
c.Pagination.Path = c.PaginatePath
}
c.C = &ConfigCompiled{ c.C = &ConfigCompiled{
Timeout: timeout, Timeout: timeout,
BaseURL: baseURL, BaseURL: baseURL,
@ -557,9 +571,11 @@ type RootConfig struct {
HasCJKLanguage bool HasCJKLanguage bool
// The default number of pages per page when paginating. // The default number of pages per page when paginating.
// Deprecated: Use the Pagination struct.
Paginate int Paginate int
// The path to use when creating pagination URLs, e.g. "page" in /page/2/. // The path to use when creating pagination URLs, e.g. "page" in /page/2/.
// Deprecated: Use the Pagination struct.
PaginatePath string PaginatePath string
// Whether to pluralize default list titles. // Whether to pluralize default list titles.

View file

@ -102,3 +102,85 @@ suffixes = ["html", "xhtml"]
b.Assert(contentTypes.HTML.Suffixes(), qt.DeepEquals, []string{"html", "xhtml"}) b.Assert(contentTypes.HTML.Suffixes(), qt.DeepEquals, []string{"html", "xhtml"})
b.Assert(contentTypes.Markdown.Suffixes(), qt.DeepEquals, []string{"md", "mdown", "markdown"}) b.Assert(contentTypes.Markdown.Suffixes(), qt.DeepEquals, []string{"md", "mdown", "markdown"})
} }
func TestPaginationConfigOld(t *testing.T) {
files := `
-- hugo.toml --
[languages.en]
weight = 1
paginatePath = "page-en"
[languages.de]
weight = 2
paginatePath = "page-de"
paginate = 20
`
b := hugolib.Test(t, files)
confEn := b.H.Sites[0].Conf.Pagination()
confDe := b.H.Sites[1].Conf.Pagination()
b.Assert(confEn.Path, qt.Equals, "page-en")
b.Assert(confEn.DefaultPageSize, qt.Equals, 10)
b.Assert(confDe.Path, qt.Equals, "page-de")
b.Assert(confDe.DefaultPageSize, qt.Equals, 20)
}
func TestPaginationConfigNew(t *testing.T) {
files := `
-- hugo.toml --
[languages.en]
weight = 1
[languages.en.pagination]
defaultPageSize = 20
[languages.de]
weight = 2
[languages.de.pagination]
path = "page-de"
`
b := hugolib.Test(t, files)
confEn := b.H.Sites[0].Conf.Pagination()
confDe := b.H.Sites[1].Conf.Pagination()
b.Assert(confEn.Path, qt.Equals, "page")
b.Assert(confEn.DefaultPageSize, qt.Equals, 20)
b.Assert(confDe.Path, qt.Equals, "page-de")
b.Assert(confDe.DefaultPageSize, qt.Equals, 10)
}
func TestPaginationConfigDisableAliases(t *testing.T) {
files := `
-- hugo.toml --
disableKinds = ["taxonomy", "term"]
[pagination]
disableAliases = true
defaultPageSize = 2
-- layouts/_default/list.html --
{{ $paginator := .Paginate site.RegularPages }}
{{ template "_internal/pagination.html" . }}
{{ range $paginator.Pages }}
{{ .Title }}
{{ end }}
-- content/p1.md --
---
title: "p1"
---
-- content/p2.md --
---
title: "p2"
---
-- content/p3.md --
---
title: "p3"
---
`
b := hugolib.Test(t, files)
b.AssertFileExists("public/page/1/index.html", false)
b.AssertFileContent("public/page/2/index.html", "pagination-default")
}

View file

@ -327,6 +327,22 @@ var allDecoderSetups = map[string]decodeWeight{
return err return err
}, },
}, },
"pagination": {
key: "pagination",
decode: func(d decodeWeight, p decodeConfig) error {
p.c.Pagination = config.Pagination{
DefaultPageSize: 10,
Path: "page",
}
if p.p.IsSet(d.key) {
if err := mapstructure.WeakDecode(p.p.Get(d.key), &p.c.Pagination); err != nil {
return err
}
}
return nil
},
},
"privacy": { "privacy": {
key: "privacy", key: "privacy",
decode: func(d decodeWeight, p decodeConfig) error { decode: func(d decodeWeight, p decodeConfig) error {

View file

@ -248,12 +248,8 @@ func (c ConfigLanguage) CreateTitle(s string) string {
return c.config.C.CreateTitle(s) return c.config.C.CreateTitle(s)
} }
func (c ConfigLanguage) Paginate() int { func (c ConfigLanguage) Pagination() config.Pagination {
return c.config.Paginate return c.config.Pagination
}
func (c ConfigLanguage) PaginatePath() string {
return c.config.PaginatePath
} }
func (c ConfigLanguage) StaticDirs() []string { func (c ConfigLanguage) StaticDirs() []string {

View file

@ -194,8 +194,8 @@ func (l configLoader) applyDefaultConfig() error {
"footnoteAnchorPrefix": "", "footnoteAnchorPrefix": "",
"footnoteReturnLinkContents": "", "footnoteReturnLinkContents": "",
"newContentEditor": "", "newContentEditor": "",
"paginate": 10, "paginate": 0, // Moved into the paginator struct in Hugo v0.128.0.
"paginatePath": "page", "paginatePath": "", // Moved into the paginator struct in Hugo v0.128.0.
"summaryLength": 70, "summaryLength": 70,
"rssLimit": -1, "rssLimit": -1,
"sectionPagesMenu": "", "sectionPagesMenu": "",

View file

@ -410,3 +410,15 @@ func DecodeServer(cfg Provider) (Server, error) {
return *s, nil return *s, nil
} }
// Pagination configures the pagination behavior.
type Pagination struct {
// Default number of elements per page in pagination.
DefaultPageSize int
// The path element used during pagination.
Path string
// WHether to disable generation of alias for the first pagination page.
DisableAliases bool
}

View file

@ -52,8 +52,7 @@ type AllProvider interface {
DefaultContentLanguageInSubdir() bool DefaultContentLanguageInSubdir() bool
IsLangDisabled(string) bool IsLangDisabled(string) bool
SummaryLength() int SummaryLength() int
Paginate() int Pagination() Pagination
PaginatePath() string
BuildExpired() bool BuildExpired() bool
BuildFuture() bool BuildFuture() bool
BuildDrafts() bool BuildDrafts() bool

View file

@ -223,7 +223,7 @@ func (s *Site) logMissingLayout(name, layout, kind, outputFormat string) {
// renderPaginator must be run after the owning Page has been rendered. // renderPaginator must be run after the owning Page has been rendered.
func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error { func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error {
paginatePath := s.conf.PaginatePath paginatePath := s.Conf.Pagination().Path
d := p.targetPathDescriptor d := p.targetPathDescriptor
f := p.s.rc.Format f := p.s.rc.Format
@ -233,7 +233,7 @@ func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error {
panic(fmt.Sprintf("invalid paginator state for %q", p.pathOrTitle())) panic(fmt.Sprintf("invalid paginator state for %q", p.pathOrTitle()))
} }
if f.IsHTML { if f.IsHTML && !s.Conf.Pagination().DisableAliases {
// Write alias for page 1 // Write alias for page 1
d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1) d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1)
targetPaths := page.CreateTargetPaths(d) targetPaths := page.CreateTargetPaths(d)

View file

@ -263,7 +263,7 @@ func splitPageGroups(pageGroups PagesGroup, size int) []paginatedElement {
func ResolvePagerSize(conf config.AllProvider, options ...any) (int, error) { func ResolvePagerSize(conf config.AllProvider, options ...any) (int, error) {
if len(options) == 0 { if len(options) == 0 {
return conf.Paginate(), nil return conf.Pagination().DefaultPageSize, nil
} }
if len(options) > 1 { if len(options) > 1 {
@ -400,7 +400,7 @@ func newPaginationURLFactory(d TargetPathDescriptor) paginationURLFactory {
pathDescriptor := d pathDescriptor := d
var rel string var rel string
if pageNumber > 1 { if pageNumber > 1 {
rel = fmt.Sprintf("/%s/%d/", d.PathSpec.Cfg.PaginatePath(), pageNumber) rel = fmt.Sprintf("/%s/%d/", d.PathSpec.Cfg.Pagination().Path, pageNumber)
pathDescriptor.Addends = rel pathDescriptor.Addends = rel
} }