diff options
Diffstat (limited to 'internal/web/handlers_blog.go')
| -rw-r--r-- | internal/web/handlers_blog.go | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/internal/web/handlers_blog.go b/internal/web/handlers_blog.go index c6030f2..e842e84 100644 --- a/internal/web/handlers_blog.go +++ b/internal/web/handlers_blog.go @@ -4,8 +4,11 @@ import ( "encoding/xml" "errors" "net/http" + "regexp" "strconv" + "strings" "time" + "unicode/utf8" "github.com/gramanas/blogspace/internal/store" ) @@ -143,6 +146,38 @@ func (s *Server) handleBlogTag(w http.ResponseWriter, r *http.Request) { s.render(w, r, "blog/tag.html", v) } +// handleBlogSearch lists the published posts matching ?q= (see searchPattern), +// from every page of the blog. A blank query shows just the box; no matches +// is an ordinary result, not a 404. +func (s *Server) handleBlogSearch(w http.ResponseWriter, r *http.Request) { + q := strings.TrimSpace(r.URL.Query().Get("q")) + if utf8.RuneCountInString(q) > maxSearchRunes { + q = string([]rune(q)[:maxSearchRunes]) + } + v, err := s.blogView(r) + if err != nil { + s.serverError(w, err) + return + } + v["q"] = q + pattern := searchPattern(q) + if pattern != "" { + n := pageNum(r) + posts, total, err := blogStore(r).SearchPublishedPosts(r.Context(), pattern, searchPerPage, (n-1)*searchPerPage) + if err != nil { + s.serverError(w, err) + return + } + re := regexp.MustCompile("(?is)" + pattern) // (?s): "." crosses lines as it does in Postgres; QuoteMeta output always compiles + hits := make([]searchHit, 0, len(posts)) + for _, p := range posts { + hits = append(hits, searchHit{Post: p, Snippet: searchSnippet(p.BodyMD, re)}) + } + v["hits"], v["total"], v["pageNum"], v["lastPage"] = hits, total, n, (total+searchPerPage-1)/searchPerPage + } + s.render(w, r, "blog/search.html", v) +} + func (s *Server) handleBlogPost(w http.ResponseWriter, r *http.Request) { page, err := blogStore(r).PageBySlug(r.Context(), r.PathValue("page")) if err != nil { |
