Add date-based archives per section

This commit is contained in:
Jan-Lukas Else 2023-02-24 18:34:17 +01:00
parent 503b98327f
commit a89a9cafa3
3 changed files with 80 additions and 49 deletions

View File

@ -145,7 +145,7 @@ func (a *goBlog) blogRouter(blog string, conf *configBlog) func(r chi.Router) {
r.Group(a.blogTaxonomiesRouter(conf)) r.Group(a.blogTaxonomiesRouter(conf))
// Dates // Dates
r.Group(a.blogDatesRouter(conf)) r.With(a.privateModeHandler, a.cacheMiddleware).Group(a.blogDatesRouter(conf))
// Photos // Photos
r.Group(a.blogPhotosRouter(conf)) r.Group(a.blogPhotosRouter(conf))
@ -209,10 +209,15 @@ func (a *goBlog) blogSectionsRouter(conf *configBlog) func(r chi.Router) {
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
secPath := conf.getRelativePath(section.Name) secPath := conf.getRelativePath(section.Name)
r.Use(middleware.WithValue(indexConfigKey, &indexConfig{ r.Use(middleware.WithValue(indexConfigKey, &indexConfig{
path: secPath, path: secPath,
section: section, section: section,
title: section.Title,
description: section.Description,
})) }))
r.Get(secPath, a.serveIndex) r.Route(secPath, func(r chi.Router) {
r.Get("/", a.serveIndex)
r.Group(a.blogDatesRouter(conf))
})
r.Get(secPath+feedPath, a.serveIndex) r.Get(secPath+feedPath, a.serveIndex)
r.Get(secPath+paginationPath, a.serveIndex) r.Get(secPath+paginationPath, a.serveIndex)
}) })
@ -246,11 +251,6 @@ func (a *goBlog) blogTaxonomiesRouter(conf *configBlog) func(r chi.Router) {
// Blog - Dates // Blog - Dates
func (a *goBlog) blogDatesRouter(conf *configBlog) func(r chi.Router) { func (a *goBlog) blogDatesRouter(conf *configBlog) func(r chi.Router) {
return func(r chi.Router) { return func(r chi.Router) {
r.Use(
a.privateModeHandler,
a.cacheMiddleware,
)
yearPath := conf.getRelativePath(`/{year:(x|\d{4})}`) yearPath := conf.getRelativePath(`/{year:(x|\d{4})}`)
r.Get(yearPath, a.serveDate) r.Get(yearPath, a.serveDate)
r.Get(yearPath+feedPath, a.serveDate) r.Get(yearPath+feedPath, a.serveDate)

View File

@ -5,6 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
"path"
"reflect" "reflect"
"strings" "strings"
"time" "time"
@ -219,7 +220,32 @@ func (a *goBlog) serveDeleted(w http.ResponseWriter, r *http.Request) {
} }
func (a *goBlog) serveDate(w http.ResponseWriter, r *http.Request) { func (a *goBlog) serveDate(w http.ResponseWriter, r *http.Request) {
var year, month, day int year, month, day, title, datePath := a.extractDate(r)
if year == 0 && month == 0 && day == 0 {
a.serve404(w, r)
return
}
var ic *indexConfig
if cv := r.Context().Value(indexConfigKey); cv != nil {
origIc := *(cv.(*indexConfig))
copyIc := origIc
ic = &copyIc
ic.path = path.Join(ic.path, datePath)
ic.title = fmt.Sprintf("%s: %s", ic.title, title)
} else {
_, bc := a.getBlog(r)
ic = &indexConfig{
path: bc.getRelativePath(datePath),
title: title,
}
}
ic.year = year
ic.month = month
ic.day = day
a.serveIndex(w, r.WithContext(context.WithValue(r.Context(), indexConfigKey, ic)))
}
func (a *goBlog) extractDate(r *http.Request) (year, month, day int, title, datePath string) {
if ys := chi.URLParam(r, "year"); ys != "" && ys != "x" { if ys := chi.URLParam(r, "year"); ys != "" && ys != "x" {
year = stringToInt(ys) year = stringToInt(ys)
} }
@ -229,38 +255,29 @@ func (a *goBlog) serveDate(w http.ResponseWriter, r *http.Request) {
if ds := chi.URLParam(r, "day"); ds != "" { if ds := chi.URLParam(r, "day"); ds != "" {
day = stringToInt(ds) day = stringToInt(ds)
} }
if year == 0 && month == 0 && day == 0 { titleBuf, pathBuf := bufferpool.Get(), bufferpool.Get()
a.serve404(w, r) defer bufferpool.Put(titleBuf, pathBuf)
return
}
title, dPath := bufferpool.Get(), bufferpool.Get()
if year != 0 { if year != 0 {
_, _ = fmt.Fprintf(title, "%0004d", year) _, _ = fmt.Fprintf(titleBuf, "%0004d", year)
_, _ = fmt.Fprintf(dPath, "%0004d", year) _, _ = fmt.Fprintf(pathBuf, "%0004d", year)
} else { } else {
_, _ = title.WriteString("XXXX") _, _ = titleBuf.WriteString("XXXX")
_, _ = dPath.WriteString("x") _, _ = pathBuf.WriteString("x")
} }
if month != 0 { if month != 0 {
_, _ = fmt.Fprintf(title, "-%02d", month) _, _ = fmt.Fprintf(titleBuf, "-%02d", month)
_, _ = fmt.Fprintf(dPath, "/%02d", month) _, _ = fmt.Fprintf(pathBuf, "/%02d", month)
} else if day != 0 { } else if day != 0 {
_, _ = title.WriteString("-XX") _, _ = titleBuf.WriteString("-XX")
_, _ = dPath.WriteString("/x") _, _ = pathBuf.WriteString("/x")
} }
if day != 0 { if day != 0 {
_, _ = fmt.Fprintf(title, "-%02d", day) _, _ = fmt.Fprintf(titleBuf, "-%02d", day)
_, _ = fmt.Fprintf(dPath, "/%02d", day) _, _ = fmt.Fprintf(pathBuf, "/%02d", day)
} }
_, bc := a.getBlog(r) title = titleBuf.String()
a.serveIndex(w, r.WithContext(context.WithValue(r.Context(), indexConfigKey, &indexConfig{ datePath = pathBuf.String()
path: bc.getRelativePath(dPath.String()), return
year: year,
month: month,
day: day,
title: title.String(),
})))
bufferpool.Put(title, dPath)
} }
type indexConfig struct { type indexConfig struct {
@ -324,17 +341,17 @@ func (a *goBlog) serveIndex(w http.ResponseWriter, r *http.Request) {
a.serveError(w, r, err.Error(), http.StatusInternalServerError) a.serveError(w, r, err.Error(), http.StatusInternalServerError)
return return
} }
// Meta // Title
title := ic.title var title string
description := ic.description if ic.title != "" {
if ic.tax != nil { title = ic.title
} else if ic.tax != nil {
title = fmt.Sprintf("%s: %s", ic.tax.Title, ic.taxValue) title = fmt.Sprintf("%s: %s", ic.tax.Title, ic.taxValue)
} else if ic.section != nil {
title = ic.section.Title
description = ic.section.Description
} else if search != "" { } else if search != "" {
title = fmt.Sprintf("%s: %s", bc.Search.Title, search) title = fmt.Sprintf("%s: %s", bc.Search.Title, search)
} }
// Description
description := ic.description
// Check if feed // Check if feed
if ft := feedType(chi.URLParam(r, "feed")); ft != noFeed { if ft := feedType(chi.URLParam(r, "feed")); ft != noFeed {
a.generateFeed(blog, ft, w, r, posts, title, description) a.generateFeed(blog, ft, w, r, posts, title, description)

View File

@ -1,10 +1,11 @@
package main package main
import ( import (
"database/sql"
"encoding/xml" "encoding/xml"
"fmt"
"io" "io"
"net/http" "net/http"
"path"
"time" "time"
"github.com/araddon/dateparse" "github.com/araddon/dateparse"
@ -117,6 +118,12 @@ func (a *goBlog) serveSitemapBlogArchives(w http.ResponseWriter, r *http.Request
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(section.Name)), Loc: a.getFullAddress(bc.getRelativePath(section.Name)),
}) })
datePaths, _ := a.sitemapDatePaths(b, []string{section.Name})
for _, p := range datePaths {
sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(path.Join(section.Name, p))),
})
}
} }
} }
// Taxonomies // Taxonomies
@ -138,7 +145,7 @@ func (a *goBlog) serveSitemapBlogArchives(w http.ResponseWriter, r *http.Request
} }
} }
// Date based archives // Date based archives
datePaths, _ := a.sitemapDatePaths(b) datePaths, _ := a.sitemapDatePaths(b, []string{})
for _, p := range datePaths { for _, p := range datePaths {
sm.Add(&sitemap.URL{ sm.Add(&sitemap.URL{
Loc: a.getFullAddress(bc.getRelativePath(p)), Loc: a.getFullAddress(bc.getRelativePath(p)),
@ -187,15 +194,16 @@ func (a *goBlog) writeSitemapXML(w http.ResponseWriter, _ *http.Request, sm any)
} }
const sitemapDatePathsSql = ` const sitemapDatePathsSql = `
with alldates as ( with filteredposts as ( %s ),
alldates as (
select distinct select distinct
substr(published, 1, 4) as year, substr(published, 1, 4) as year,
substr(published, 6, 2) as month, substr(published, 6, 2) as month,
substr(published, 9, 2) as day substr(published, 9, 2) as day
from ( from (
select tolocal(coalesce(published, '')) as published select tolocal(published) as published
from posts from filteredposts
where blog = @blog and status = @status and published != '' where coalesce(published, '') != ''
) )
) )
select distinct '/' || year from alldates select distinct '/' || year from alldates
@ -211,8 +219,14 @@ union
select distinct '/x/x/' || day from alldates; select distinct '/x/x/' || day from alldates;
` `
func (a *goBlog) sitemapDatePaths(blog string) (paths []string, err error) { func (a *goBlog) sitemapDatePaths(blog string, sections []string) (paths []string, err error) {
rows, err := a.db.Query(sitemapDatePathsSql, sql.Named("blog", blog), sql.Named("status", statusPublished)) query, args := buildPostsQuery(&postsRequestConfig{
blog: blog,
sections: sections,
status: []postStatus{statusPublished},
visibility: []postVisibility{visibilityPublic},
}, "published")
rows, err := a.db.Query(fmt.Sprintf(sitemapDatePathsSql, query), args...)
if err != nil { if err != nil {
return nil, err return nil, err
} }