aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/templates/blog
diff options
context:
space:
mode:
authorgrm <grm@eyesin.space>2026-09-16 00:00:57 +0300
committergrm <grm@eyesin.space>2026-09-16 00:00:57 +0300
commit839343a3108734a15e331b542a20ed9c77ef582b (patch)
treea6aabc8719c16398bf1ccd874a7efe865b364a9e /internal/web/templates/blog
parent628dcb814ece6335667e2b719049728aa161d8c9 (diff)
downloadblogspace-839343a3108734a15e331b542a20ed9c77ef582b.tar.gz
blogspace-839343a3108734a15e331b542a20ed9c77ef582b.tar.bz2
blogspace-839343a3108734a15e331b542a20ed9c77ef582b.zip
Add a search box module and a search page
Readers had no way to find a post. The new "search" module goes in the header (a bar under the nav) or a side column (a box with a heading) and is a plain GET form to /search, so it works without JavaScript. The results page lists the published posts of every page whose title or Markdown body matches the query — case-insensitive, each word literal, spaces meaning "anything in between", in order — as title, date and a short snippet with the match marked, 20 per page. modules.kind is a CHECK constraint, so a migration widens it; "search" becomes a reserved page slug so the literal route keeps winning over /{page}. moduleHasSettings now takes the module: a header search box has no heading, hence nothing to edit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/templates/blog')
-rw-r--r--internal/web/templates/blog/search.html23
1 files changed, 23 insertions, 0 deletions
diff --git a/internal/web/templates/blog/search.html b/internal/web/templates/blog/search.html
new file mode 100644
index 0000000..b146f5e
--- /dev/null
+++ b/internal/web/templates/blog/search.html
@@ -0,0 +1,23 @@
+{{define "title"}}{{if .Data.q}}{{tf "Results for “%s”" .Data.q}}{{else}}{{t "Search"}}{{end}} · {{.Blog.Title}}{{end}}
+{{define "content"}}
+<h1 class="page-title">{{if .Data.q}}{{tf "Results for “%s”" .Data.q}}{{else}}{{t "Search"}}{{end}}</h1>
+<div class="search-page">{{template "searchform" .}}</div>
+{{if not .Data.q}}<p class="muted">{{t "Type a word or two to find posts."}}</p>
+{{else if not .Data.hits}}<p class="muted">{{tf "Nothing matched “%s”." .Data.q}}</p>
+{{else}}
+<p class="muted small">{{if eq .Data.total 1}}{{t "One post matches."}}{{else}}{{tf "%d posts match." .Data.total}}{{end}}</p>
+<ul class="search-results">
+{{range .Data.hits}}<li>
+ <a href="/{{.PageSlug}}/{{.Slug}}">{{.Title}}</a>{{if $.Data.theme.ShowDates}} <span class="post-date">{{postdate $.Data.theme.DateFormat .CreatedAt}}</span>{{end}}
+ <p class="snippet">{{.Snippet}}</p>
+</li>
+{{end}}</ul>
+{{if gt .Data.lastPage 1}}
+<div class="pager">
+ {{if gt .Data.pageNum 1}}<a href="/search?q={{.Data.q}}&amp;p={{sub .Data.pageNum 1}}">&larr; {{t "Newer"}}</a>{{end}}
+ <span>{{tf "Page %d of %d" .Data.pageNum .Data.lastPage}}</span>
+ {{if lt .Data.pageNum .Data.lastPage}}<a href="/search?q={{.Data.q}}&amp;p={{add .Data.pageNum 1}}">{{t "Older"}} &rarr;</a>{{end}}
+</div>
+{{end}}
+{{end}}
+{{end}}