feat(blog): build per-post searchText, wire to PostRow and featured
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
44d4d327a1
commit
5ac622e576
2 changed files with 32 additions and 1 deletions
3
src/components/molecules/BlogSearch.astro
Normal file
3
src/components/molecules/BlogSearch.astro
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
// Stub — real implementation lands in Task 4.
|
||||||
|
---
|
||||||
|
|
@ -5,6 +5,7 @@ import Mark from "~/components/atoms/Mark.astro";
|
||||||
import PostRow from "~/components/molecules/PostRow.astro";
|
import PostRow from "~/components/molecules/PostRow.astro";
|
||||||
import YearHead from "~/components/molecules/YearHead.astro";
|
import YearHead from "~/components/molecules/YearHead.astro";
|
||||||
import InkArrow from "~/components/atoms/InkArrow.astro";
|
import InkArrow from "~/components/atoms/InkArrow.astro";
|
||||||
|
import BlogSearch from "~/components/molecules/BlogSearch.astro";
|
||||||
import { blog } from "~/lib/urls";
|
import { blog } from "~/lib/urls";
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
|
||||||
|
|
@ -25,6 +26,32 @@ for (const post of rest) {
|
||||||
byYear.set(year, bucket);
|
byYear.set(year, bucket);
|
||||||
}
|
}
|
||||||
const yearGroups = Array.from(byYear.entries()).sort(([a], [b]) => b - a);
|
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<string, string>();
|
||||||
|
for (const post of posts) {
|
||||||
|
searchTextById.set(post.id, buildSearchText(post));
|
||||||
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
|
|
@ -53,7 +80,7 @@ const yearGroups = Array.from(byYear.entries()).sort(([a], [b]) => b - a);
|
||||||
|
|
||||||
{
|
{
|
||||||
featured && (
|
featured && (
|
||||||
<article class="feature">
|
<article class="feature" data-featured data-search={searchTextById.get(featured.id) ?? ""}>
|
||||||
<div class="cutframe img">
|
<div class="cutframe img">
|
||||||
<div class="grain" />
|
<div class="grain" />
|
||||||
<img class="wm" src="/assets/mark-rings.svg" alt="" />
|
<img class="wm" src="/assets/mark-rings.svg" alt="" />
|
||||||
|
|
@ -91,6 +118,7 @@ const yearGroups = Array.from(byYear.entries()).sort(([a], [b]) => b - a);
|
||||||
href={blog(`/posts/${post.id}/`)}
|
href={blog(`/posts/${post.id}/`)}
|
||||||
deck={post.data.standfirst}
|
deck={post.data.standfirst}
|
||||||
tag={post.data.tag}
|
tag={post.data.tag}
|
||||||
|
searchText={searchTextById.get(post.id) ?? ""}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue