diff --git a/src/components/molecules/BlogSearch.astro b/src/components/molecules/BlogSearch.astro new file mode 100644 index 0000000..e39a11d --- /dev/null +++ b/src/components/molecules/BlogSearch.astro @@ -0,0 +1,3 @@ +--- +// Stub — real implementation lands in Task 4. +--- diff --git a/src/pages/blog/index.astro b/src/pages/blog/index.astro index 36fc6f2..9fa00a2 100644 --- a/src/pages/blog/index.astro +++ b/src/pages/blog/index.astro @@ -5,6 +5,7 @@ import Mark from "~/components/atoms/Mark.astro"; import PostRow from "~/components/molecules/PostRow.astro"; import YearHead from "~/components/molecules/YearHead.astro"; import InkArrow from "~/components/atoms/InkArrow.astro"; +import BlogSearch from "~/components/molecules/BlogSearch.astro"; import { blog } from "~/lib/urls"; import { getCollection } from "astro:content"; @@ -25,6 +26,32 @@ for (const post of rest) { byYear.set(year, bucket); } const yearGroups = Array.from(byYear.entries()).sort(([a], [b]) => b - a); + +// Build the per-post `data-search` string at build time. We concatenate the +// searchable fields, lowercase, strip a small set of markdown punctuation, and +// collapse whitespace. Body text is the raw markdown from the content +// collection entry's `.body` property — MDX expressions that survive end up as +// literal text, which is harmless for substring matching. +function buildSearchText(post: (typeof posts)[number]): string { + const parts = [ + post.data.title, + post.data.tag, + post.data.standfirst, + post.data.description, + post.body ?? "", + ].filter(Boolean) as string[]; + return parts + .join(" ") + .toLowerCase() + .replace(/[#*_>`\[\]()]/g, " ") + .replace(/\s+/g, " ") + .trim(); +} + +const searchTextById = new Map(); +for (const post of posts) { + searchTextById.set(post.id, buildSearchText(post)); +} --- b - a); { featured && ( -
+
@@ -91,6 +118,7 @@ const yearGroups = Array.from(byYear.entries()).sort(([a], [b]) => b - a); href={blog(`/posts/${post.id}/`)} deck={post.data.standfirst} tag={post.data.tag} + searchText={searchTextById.get(post.id) ?? ""} /> ))}