aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/layout.go
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/layout.go
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/layout.go')
-rw-r--r--internal/web/layout.go16
1 files changed, 10 insertions, 6 deletions
diff --git a/internal/web/layout.go b/internal/web/layout.go
index b8069a0..0d51068 100644
--- a/internal/web/layout.go
+++ b/internal/web/layout.go
@@ -12,9 +12,9 @@ import (
// Modules a blogger can put in each area. Header modules are the big
// blocks; the side columns take the small boxes; the footer its own set.
var moduleKinds = map[string][]string{
- "header": {"title", "logo", "menu"},
- "left": {"menu", "recent", "archive", "tags", "tagcloud", "logo", "html"},
- "right": {"menu", "recent", "archive", "tags", "tagcloud", "logo", "html"},
+ "header": {"title", "logo", "menu", "search"},
+ "left": {"menu", "search", "recent", "archive", "tags", "tagcloud", "logo", "html"},
+ "right": {"menu", "search", "recent", "archive", "tags", "tagcloud", "logo", "html"},
"above": {"html"},
"below": {"html"},
"footer": {"text", "rss", "sitemap", "html"},
@@ -29,6 +29,7 @@ var moduleNames = map[string]string{
"recent": "Recent posts",
"tags": "Tags",
"tagcloud": "Tag cloud",
+ "search": "Search box",
"html": "Custom HTML",
"rss": "RSS link",
"text": "Footer text",
@@ -52,11 +53,14 @@ func allowedKind(area, kind string) bool {
return false
}
-// moduleHasSettings says whether the module has an edit page.
-func moduleHasSettings(kind string) bool {
- switch kind {
+// moduleHasSettings says whether the module has an edit page. Header modules
+// show no heading, so a search box there has nothing to edit.
+func moduleHasSettings(m store.Module) bool {
+ switch m.Kind {
case "html", "text", "recent", "archive", "sitemap", "tags", "tagcloud":
return true
+ case "search":
+ return m.Area != "header"
}
return false
}