feat: add pagination to generated site category pages

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Leon Mika 2026-03-22 14:38:39 +11:00
parent 30884372d6
commit f68bac809f
3 changed files with 71 additions and 15 deletions

View file

@ -9,3 +9,9 @@
{{ template "_post_meta.html" . }} {{ template "_post_meta.html" . }}
</div> </div>
{{ end }} {{ end }}
{{ if or .PrevURL .NextURL }}
<nav class="pagination">
{{ if .PrevURL }}<a href="{{ .PrevURL }}">← Newer posts</a>{{ end }}
{{ if .NextURL }}<a href="{{ .NextURL }}">Older posts →</a>{{ end }}
</nav>
{{ end }}

View file

@ -372,7 +372,8 @@ func (b *Builder) renderCategoryPages(ctx buildContext, goCtx context.Context) e
continue continue
} }
var posts []postSingleData // Collect all posts for this category
var allPosts []postSingleData
for mp := range b.site.PostIterByCategory(goCtx, cwc.ID) { for mp := range b.site.PostIterByCategory(goCtx, cwc.ID) {
post, err := mp.Get() post, err := mp.Get()
if err != nil { if err != nil {
@ -382,7 +383,7 @@ func (b *Builder) renderCategoryPages(ctx buildContext, goCtx context.Context) e
if err != nil { if err != nil {
return err return err
} }
posts = append(posts, rp) allPosts = append(allPosts, rp)
} }
var descHTML bytes.Buffer var descHTML bytes.Buffer
@ -392,22 +393,68 @@ func (b *Builder) renderCategoryPages(ctx buildContext, goCtx context.Context) e
} }
} }
data := categorySingleData{ postsPerPage := b.site.PostsPerPage
commonData: commonData{Site: b.site}, if postsPerPage < 1 {
Category: &cwc.Category, postsPerPage = 10
DescriptionHTML: template.HTML(descHTML.String()),
Posts: posts,
Path: fmt.Sprintf("/categories/%s", cwc.Slug),
} }
if err := b.createAtPath(ctx, data.Path, func(f io.Writer) error { totalPages := (len(allPosts) + postsPerPage - 1) / postsPerPage
return b.renderTemplate(f, tmplNameCategorySingle, data) if totalPages < 1 {
}); err != nil { totalPages = 1
return err
} }
// Per-category feeds basePath := fmt.Sprintf("/categories/%s", cwc.Slug)
if err := b.renderCategoryFeed(ctx, cwc, posts); err != nil {
for page := 1; page <= totalPages; page++ {
start := (page - 1) * postsPerPage
end := start + postsPerPage
if end > len(allPosts) {
end = len(allPosts)
}
pageInfo := models.PageInfo{
CurrentPage: page,
TotalPages: totalPages,
PostsPerPage: postsPerPage,
}
var prevURL, nextURL string
if page > 1 {
if page == 2 {
prevURL = basePath + "/"
} else {
prevURL = fmt.Sprintf("%s/page/%d/", basePath, page-1)
}
}
if page < totalPages {
nextURL = fmt.Sprintf("%s/page/%d/", basePath, page+1)
}
path := basePath
if page > 1 {
path = fmt.Sprintf("%s/page/%d", basePath, page)
}
data := categorySingleData{
commonData: commonData{Site: b.site},
Category: &cwc.Category,
DescriptionHTML: template.HTML(descHTML.String()),
Posts: allPosts[start:end],
Path: path,
PageInfo: pageInfo,
PrevURL: prevURL,
NextURL: nextURL,
}
if err := b.createAtPath(ctx, path, func(f io.Writer) error {
return b.renderTemplate(f, tmplNameCategorySingle, data)
}); err != nil {
return err
}
}
// Per-category feeds (use all posts, not paginated)
if err := b.renderCategoryFeed(ctx, cwc, allPosts); err != nil {
return err return err
} }
} }

View file

@ -88,4 +88,7 @@ type categorySingleData struct {
DescriptionHTML template.HTML DescriptionHTML template.HTML
Posts []postSingleData Posts []postSingleData
Path string Path string
PageInfo models.PageInfo
PrevURL string
NextURL string
} }