feat: opt-in scored related posts and category neighbours
- golem15.journal.related_mode (category | scored, default category) and
golem15.journal.related_count (3 to 6, default 3, clamped) in
config/config.yaml; classes.ReadRelatedSettings reads them
- the default mode answers GET /posts/{slug} exactly as before
- scored: related posts ranked by 2 points per shared tag plus 1 per
shared category, ties by newest, in one scoring query
(classes.ScoredRelatedPosts), published only for visitors; the answer
adds previous_in_category and next_in_category, the neighbours by
publish time within the post's first category by name
(classes.CategoryNeighbour), in the direction of previous_post and
next_post
- TestRelatedDefaultUnchanged, TestRelatedScored (a draft and a future
post sharing every tag never shown) and TestRelatedScoredCountClamped
This commit is contained in:
@@ -169,7 +169,23 @@ func Show(app *backpack.App) http.HandlerFunc {
|
||||
payload := serializePost(post, db)
|
||||
payload["previous_post"] = serializeSibling(previousPost(db, post))
|
||||
payload["next_post"] = serializeSibling(nextPost(db, post))
|
||||
related := relatedPosts(db, post, isEditor(pr))
|
||||
// golem15.journal.related_mode: the default category mode answers as
|
||||
// it always has; scored (opt-in, P33-44) ranks the related posts by
|
||||
// shared tags and categories and adds the neighbours within the
|
||||
// post's first category (additive keys, scored mode only).
|
||||
relatedCfg := classes.ReadRelatedSettings(appConfig(app))
|
||||
var related []models.Post
|
||||
if relatedCfg.Scored() {
|
||||
related, err = classes.ScoredRelatedPosts(r.Context(), db, post, relatedCfg.Count, isEditor(pr))
|
||||
if err != nil {
|
||||
writeAPIError(w, http.StatusInternalServerError, "Internal server error")
|
||||
return
|
||||
}
|
||||
payload["previous_in_category"] = serializeSibling(classes.CategoryNeighbour(r.Context(), db, post, true))
|
||||
payload["next_in_category"] = serializeSibling(classes.CategoryNeighbour(r.Context(), db, post, false))
|
||||
} else {
|
||||
related = relatedPosts(db, post, isEditor(pr))
|
||||
}
|
||||
rows := make([]map[string]any, 0, len(related))
|
||||
for i := range related {
|
||||
rows = append(rows, serializePost(&related[i], db))
|
||||
|
||||
Reference in New Issue
Block a user