hugo

Unnamed repository; edit this file 'description' to name the repository.

git clone git://git.shimmy1996.com/hugo.git
commit 0e922ffa3e84bd0f5d763586f3b24e6e32d7295e
parent 15463f835bbadd6f86158b83cb1499721ae2269f
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Tue, 26 Jul 2022 21:23:21 -0500

Add rev parameter to make last page the default

Diffstat:
Mhugolib/page__paginator.go | 11+++++++----
Mhugolib/site_render.go | 28++++++++++++----------------
Mresources/page/pagination.go | 75+++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
3 files changed, 68 insertions(+), 46 deletions(-)
diff --git a/hugolib/page__paginator.go b/hugolib/page__paginator.go
@@ -34,6 +34,7 @@ type pagePaginator struct {
 type pagePaginatorInit struct {
 	init    sync.Once
 	current *page.Pager
+	rev     bool
 }
 
 // reset resets the paginator to allow for a rebuild.
@@ -44,7 +45,7 @@ func (p *pagePaginator) reset() {
 func (p *pagePaginator) Paginate(seq any, options ...any) (*page.Pager, error) {
 	var initErr error
 	p.init.Do(func() {
-		pagerSize, err := page.ResolvePagerSize(p.source.s.Cfg, options...)
+		pagerSize, rev, err := page.ResolvePagerSize(p.source.s.Cfg, options...)
 		if err != nil {
 			initErr = err
 			return
@@ -52,13 +53,14 @@ func (p *pagePaginator) Paginate(seq any, options ...any) (*page.Pager, error) {
 
 		pd := p.source.targetPathDescriptor
 		pd.Type = p.source.outputFormat()
-		paginator, err := page.Paginate(pd, seq, pagerSize)
+		paginator, err := page.Paginate(pd, seq, pagerSize, rev)
 		if err != nil {
 			initErr = err
 			return
 		}
 
 		p.current = paginator.Pagers()[0]
+		p.rev = rev
 	})
 
 	if initErr != nil {
@@ -71,7 +73,7 @@ func (p *pagePaginator) Paginate(seq any, options ...any) (*page.Pager, error) {
 func (p *pagePaginator) Paginator(options ...any) (*page.Pager, error) {
 	var initErr error
 	p.init.Do(func() {
-		pagerSize, err := page.ResolvePagerSize(p.source.s.Cfg, options...)
+		pagerSize, rev, err := page.ResolvePagerSize(p.source.s.Cfg, options...)
 		if err != nil {
 			initErr = err
 			return
@@ -94,13 +96,14 @@ func (p *pagePaginator) Paginator(options ...any) (*page.Pager, error) {
 			pages = p.source.RegularPages()
 		}
 
-		paginator, err := page.Paginate(pd, pages, pagerSize)
+		paginator, err := page.Paginate(pd, pages, pagerSize, rev)
 		if err != nil {
 			initErr = err
 			return
 		}
 
 		p.current = paginator.Pagers()[0]
+		p.rev = rev
 	})
 
 	if initErr != nil {
diff --git a/hugolib/site_render.go b/hugolib/site_render.go
@@ -193,28 +193,24 @@ func (s *Site) renderPaginator(p *pageState, templ tpl.Template) error {
 		panic(fmt.Sprintf("invalid paginator state for %q", p.pathOrTitle()))
 	}
 
-	if f.IsHTML {
-		// Write alias for page 1
-		d.Addends = fmt.Sprintf("/%s/%d", paginatePath, 1)
-		targetPaths := page.CreateTargetPaths(d)
-
-		if err := s.writeDestAlias(targetPaths.TargetFilename, p.Permalink(), f, nil); err != nil {
-			return err
-		}
-	}
-
 	// Render pages for the rest
-	for current := p.paginator.current.Next(); current != nil; current = current.Next() {
+	for current := p.paginator.current; current != nil; current = current.Next() {
 
 		p.paginator.current = current
 		d.Addends = fmt.Sprintf("/%s/%d", paginatePath, current.PageNumber())
 		targetPaths := page.CreateTargetPaths(d)
 
-		if err := s.renderAndWritePage(
-			&s.PathSpec.ProcessingStats.PaginatorPages,
-			p.Title(),
-			targetPaths.TargetFilename, p, templ); err != nil {
-			return err
+		if f.IsHTML && current.Prev() == nil {
+			if err := s.writeDestAlias(targetPaths.TargetFilename, p.Permalink(), f, nil); err != nil {
+				return err
+			}
+		} else {
+			if err := s.renderAndWritePage(
+				&s.PathSpec.ProcessingStats.PaginatorPages,
+				p.Title(),
+				targetPaths.TargetFilename, p, templ); err != nil {
+				return err
+			}
 		}
 
 	}
diff --git a/resources/page/pagination.go b/resources/page/pagination.go
@@ -59,9 +59,10 @@ type Paginator struct {
 	paginationURLFactory
 	total int
 	size  int
+	rev   bool
 }
 
-type paginationURLFactory func(int) string
+type paginationURLFactory func(int, int) string
 
 // PageNumber returns the current page's number in the pager sequence.
 func (p *Pager) PageNumber() int {
@@ -70,7 +71,7 @@ func (p *Pager) PageNumber() int {
 
 // URL returns the URL to the current page.
 func (p *Pager) URL() template.HTML {
-	return template.HTML(p.paginationURLFactory(p.PageNumber()))
+	return template.HTML(p.paginationURLFactory(p.PageNumber(), p.TotalPages()))
 }
 
 // Pages returns the Pages on this page.
@@ -141,7 +142,7 @@ func (p *Pager) NumberOfElements() int {
 
 // HasPrev tests whether there are page(s) before the current.
 func (p *Pager) HasPrev() bool {
-	return p.PageNumber() > 1
+	return (!p.rev && p.PageNumber() > 1) || (p.rev && p.PageNumber() < p.TotalPages())
 }
 
 // Prev returns the pager for the previous page.
@@ -149,12 +150,16 @@ func (p *Pager) Prev() *Pager {
 	if !p.HasPrev() {
 		return nil
 	}
-	return p.pagers[p.PageNumber()-2]
+	if !p.rev {
+		return p.pagers[p.PageNumber()-2]
+	} else {
+		return p.pagers[p.TotalPages()-1-p.PageNumber()]
+	}
 }
 
 // HasNext tests whether there are page(s) after the current.
 func (p *Pager) HasNext() bool {
-	return p.PageNumber() < len(p.paginatedElements)
+	return (!p.rev && p.PageNumber() < len(p.paginatedElements)) || (p.rev && p.PageNumber() > 1)
 }
 
 // Next returns the pager for the next page.
@@ -162,7 +167,11 @@ func (p *Pager) Next() *Pager {
 	if !p.HasNext() {
 		return nil
 	}
-	return p.pagers[p.PageNumber()]
+	if !p.rev {
+		return p.pagers[p.PageNumber()]
+	} else {
+		return p.pagers[p.TotalPages()+1-p.PageNumber()]
+	}
 }
 
 // First returns the pager for the first page.
@@ -248,30 +257,40 @@ func splitPageGroups(pageGroups PagesGroup, size int) []paginatedElement {
 	return split
 }
 
-func ResolvePagerSize(cfg config.Provider, options ...any) (int, error) {
+func ResolvePagerSize(cfg config.Provider, options ...any) (int, bool, error) {
 	if len(options) == 0 {
-		return cfg.GetInt("paginate"), nil
+		return cfg.GetInt("paginate"), cfg.GetBool("paginateRev"), nil
 	}
 
-	if len(options) > 1 {
-		return -1, errors.New("too many arguments, 'pager size' is currently the only option")
+	if len(options) > 2 {
+		return -1, false, errors.New("too many arguments, 'pager size' and 'rev' are currently the only options")
 	}
 
 	pas, err := cast.ToIntE(options[0])
 
 	if err != nil || pas <= 0 {
-		return -1, errors.New(("'pager size' must be a positive integer"))
+		return -1, false, errors.New(("'pager size' must be a positive integer"))
+	}
+
+	if len(options) == 1 {
+		return pas, cfg.GetBool("paginateRev"), nil
 	}
 
-	return pas, nil
+	rev, err := cast.ToBoolE(options[1])
+
+	if err != nil {
+		return -1, false, errors.New(("'rev' must be a bool"))
+	}
+
+	return pas, rev, nil
 }
 
-func Paginate(td TargetPathDescriptor, seq any, pagerSize int) (*Paginator, error) {
+func Paginate(td TargetPathDescriptor, seq any, pagerSize int, rev bool) (*Paginator, error) {
 	if pagerSize <= 0 {
 		return nil, errors.New("'paginate' configuration setting must be positive to paginate")
 	}
 
-	urlFactory := newPaginationURLFactory(td)
+	urlFactory := newPaginationURLFactory(td, rev)
 
 	var paginator *Paginator
 
@@ -280,13 +299,13 @@ func Paginate(td TargetPathDescriptor, seq any, pagerSize int) (*Paginator, erro
 		return nil, err
 	}
 	if groups != nil {
-		paginator, _ = newPaginatorFromPageGroups(groups, pagerSize, urlFactory)
+		paginator, _ = newPaginatorFromPageGroups(groups, pagerSize, rev, urlFactory)
 	} else {
 		pages, err := ToPages(seq)
 		if err != nil {
 			return nil, err
 		}
-		paginator, _ = newPaginatorFromPages(pages, pagerSize, urlFactory)
+		paginator, _ = newPaginatorFromPages(pages, pagerSize, rev, urlFactory)
 	}
 
 	return paginator, nil
@@ -342,35 +361,39 @@ func probablyEqualPageLists(a1 any, a2 any) bool {
 	return p1[0] == p2[0]
 }
 
-func newPaginatorFromPages(pages Pages, size int, urlFactory paginationURLFactory) (*Paginator, error) {
+func newPaginatorFromPages(pages Pages, size int, rev bool, urlFactory paginationURLFactory) (*Paginator, error) {
 	if size <= 0 {
 		return nil, errors.New("Paginator size must be positive")
 	}
 
 	split := splitPages(pages, size)
 
-	return newPaginator(split, len(pages), size, urlFactory)
+	return newPaginator(split, len(pages), size, rev, urlFactory)
 }
 
-func newPaginatorFromPageGroups(pageGroups PagesGroup, size int, urlFactory paginationURLFactory) (*Paginator, error) {
+func newPaginatorFromPageGroups(pageGroups PagesGroup, size int, rev bool, urlFactory paginationURLFactory) (*Paginator, error) {
 	if size <= 0 {
 		return nil, errors.New("Paginator size must be positive")
 	}
 
 	split := splitPageGroups(pageGroups, size)
 
-	return newPaginator(split, pageGroups.Len(), size, urlFactory)
+	return newPaginator(split, pageGroups.Len(), size, rev, urlFactory)
 }
 
-func newPaginator(elements []paginatedElement, total, size int, urlFactory paginationURLFactory) (*Paginator, error) {
-	p := &Paginator{total: total, paginatedElements: elements, size: size, paginationURLFactory: urlFactory}
+func newPaginator(elements []paginatedElement, total, size int, rev bool, urlFactory paginationURLFactory) (*Paginator, error) {
+	p := &Paginator{total: total, paginatedElements: elements, size: size, paginationURLFactory: urlFactory, rev: rev}
 
 	var ps pagers
 
 	if len(elements) > 0 {
 		ps = make(pagers, len(elements))
 		for i := range p.paginatedElements {
-			ps[i] = &Pager{number: (i + 1), Paginator: p}
+			if !rev {
+				ps[i] = &Pager{number: (i + 1), Paginator: p}
+			} else {
+				ps[len(elements)-1-i] = &Pager{number: (i + 1), Paginator: p}
+			}
 		}
 	} else {
 		ps = make(pagers, 1)
@@ -382,11 +405,11 @@ func newPaginator(elements []paginatedElement, total, size int, urlFactory pagin
 	return p, nil
 }
 
-func newPaginationURLFactory(d TargetPathDescriptor) paginationURLFactory {
-	return func(pageNumber int) string {
+func newPaginationURLFactory(d TargetPathDescriptor, rev bool) paginationURLFactory {
+	return func(pageNumber int, totalPages int) string {
 		pathDescriptor := d
 		var rel string
-		if pageNumber > 1 {
+		if (!rev && pageNumber > 1) || (rev && pageNumber < totalPages) {
 			rel = fmt.Sprintf("/%s/%d/", d.PathSpec.PaginatePath, pageNumber)
 			pathDescriptor.Addends = rel
 		}