package server import ( "html/template" "net/http" "strings" "github.com/gin-gonic/gin" "nebbet.no/internal/db" ) type FrontpageHandler struct { DB *db.MetaDB SearchDB *db.SearchDB Templates *template.Template } type frontpageData struct { Posts []db.PostRecord Query string ActiveTag string } func NewFrontpageHandler(metaDB *db.MetaDB, searchDB *db.SearchDB, tmpl *template.Template) *FrontpageHandler { return &FrontpageHandler{DB: metaDB, SearchDB: searchDB, Templates: tmpl} } func (h *FrontpageHandler) Serve(c *gin.Context) { query := strings.TrimSpace(c.Query("q")) tag := strings.TrimSpace(c.Query("tag")) data := frontpageData{ Query: query, ActiveTag: tag, } if query != "" { // Full-text search results, err := h.SearchDB.Search(query) if err == nil { data.Posts = searchResultsToPosts(results, h.DB) } } else { posts, err := h.DB.ListPosts(false) // exclude drafts if err == nil { if tag != "" { posts = filterByTag(posts, tag) } data.Posts = posts } } c.Header("Content-Type", "text/html; charset=utf-8") if err := h.Templates.ExecuteTemplate(c.Writer, "index.html", data); err != nil { c.AbortWithStatus(http.StatusInternalServerError) } } func filterByTag(posts []db.PostRecord, tag string) []db.PostRecord { var filtered []db.PostRecord for _, p := range posts { for _, t := range p.Tags { if strings.EqualFold(t, tag) { filtered = append(filtered, p) break } } } return filtered } func searchResultsToPosts(results []db.SearchResult, metaDB *db.MetaDB) []db.PostRecord { var posts []db.PostRecord for _, r := range results { slug := strings.TrimPrefix(r.Path, "/") if slug == r.Path { continue // not a post } post, err := metaDB.GetPost(slug) if err != nil || post.Draft { continue } posts = append(posts, *post) } return posts }