Paging #4

Merged
lmika merged 13 commits from feature/pages-and-paging into main 2026-03-22 05:23:54 +00:00
4 changed files with 74 additions and 10 deletions
Showing only changes of commit 30884372d6 - Show all commits

View file

@ -5,4 +5,10 @@
{{ template "_post_meta.html" . }}
</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

@ -122,7 +122,8 @@ func (b *Builder) BuildSite(outDir string) error {
}
func (b *Builder) renderPostListWithCategories(bctx buildContext, ctx context.Context) error {
var posts []postSingleData
// Collect all posts
var allPosts []postSingleData
for mp := range b.site.PostIter(ctx) {
post, err := mp.Get()
if err != nil {
@ -132,17 +133,70 @@ func (b *Builder) renderPostListWithCategories(bctx buildContext, ctx context.Co
if err != nil {
return err
}
posts = append(posts, rp)
allPosts = append(allPosts, rp)
}
pl := postListData{
commonData: commonData{Site: b.site},
Posts: posts,
postsPerPage := b.site.PostsPerPage
if postsPerPage < 1 {
postsPerPage = 10
}
return b.createAtPath(bctx, "", func(f io.Writer) error {
return b.renderTemplate(f, tmplNamePostList, pl)
})
totalPages := (len(allPosts) + postsPerPage - 1) / postsPerPage
if totalPages < 1 {
totalPages = 1
}
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 = "/posts/"
} else {
prevURL = fmt.Sprintf("/posts/page/%d/", page-1)
}
}
if page < totalPages {
nextURL = fmt.Sprintf("/posts/page/%d/", page+1)
}
pl := postListData{
commonData: commonData{Site: b.site},
Posts: allPosts[start:end],
PageInfo: pageInfo,
PrevURL: prevURL,
NextURL: nextURL,
}
// Page 1 renders at both root and /posts/
var paths []string
if page == 1 {
paths = []string{"", "/posts"}
} else {
paths = []string{fmt.Sprintf("/posts/page/%d", page)}
}
for _, path := range paths {
if err := b.createAtPath(bctx, path, func(f io.Writer) error {
return b.renderTemplate(f, tmplNamePostList, pl)
}); err != nil {
return err
}
}
}
return nil
}
func (b *Builder) renderFeeds(ctx buildContext, postIter iter.Seq[models.Maybe[*models.Post]], opts feedOptions) error {

View file

@ -38,6 +38,7 @@ func TestBuilder_BuildSite(t *testing.T) {
}
site := pubmodel.Site{
Site: models.Site{PostsPerPage: 10},
BaseURL: "https://example.com",
PostIter: func(ctx context.Context) iter.Seq[models.Maybe[*models.Post]] {
return func(yield func(models.Maybe[*models.Post]) bool) {

View file

@ -61,7 +61,10 @@ type postSingleData struct {
type postListData struct {
commonData
Posts []postSingleData
Posts []postSingleData
PageInfo models.PageInfo
PrevURL string
NextURL string
}
type layoutData struct {