diff --git a/www/src/content.config.ts b/www/src/content.config.ts index a1e3299..4cfff53 100644 --- a/www/src/content.config.ts +++ b/www/src/content.config.ts @@ -11,6 +11,7 @@ const md = defineCollection({ pinned: z.boolean().optional(), category: z.string().optional(), draft: z.boolean().optional(), + related: z.array(z.string()).optional(), }) }); diff --git a/www/src/lib/md.ts b/www/src/lib/md.ts index da1c497..573ebb9 100644 --- a/www/src/lib/md.ts +++ b/www/src/lib/md.ts @@ -41,6 +41,14 @@ function sortPosts(posts: PostWithDates[]): PostWithDates[] { }); } +export function resolveRelatedPosts( + slugs: string[], + allPosts: PostWithDates[], +): PostWithDates[] { + const bySlug = new Map(allPosts.map(p => [getSlug(p.id), p])); + return slugs.flatMap(s => bySlug.get(s) ?? []); +} + export function organizePostsByCategory(posts: PostWithDates[]): { grouped: Record; categories: string[]; diff --git a/www/src/pages/draft/[slug].astro b/www/src/pages/draft/[slug].astro index 2ef5d6e..1d13e56 100644 --- a/www/src/pages/draft/[slug].astro +++ b/www/src/pages/draft/[slug].astro @@ -4,8 +4,8 @@ export const prerender = false; import { getCollection, render } from 'astro:content'; import { requireAdminSession } from '../../lib/auth'; import Layout from '../../layouts/Layout.astro'; -import { formatDate } from '../../lib/format'; -import { getSlug, enrichPostWithDates } from '../../lib/md'; +import { formatDate, formatListItem } from '../../lib/format'; +import { getSlug, enrichPostWithDates, enrichPostsWithDates, resolveRelatedPosts } from '../../lib/md'; const { session, error } = await requireAdminSession(Astro.request); if (error) return error; @@ -19,8 +19,10 @@ if (!rawPost) { return new Response('Not found', { status: 404 }); } +const allPosts = enrichPostsWithDates(rawPosts); const post = enrichPostWithDates(rawPost); const { Content } = await render(post); +const related = post.data.related ? resolveRelatedPosts(post.data.related, allPosts) : []; --- @@ -29,4 +31,10 @@ const { Content } = await render(post);

{formatDate(post.dates.created)}{post.dates.updated && ` (updated ${formatDate(post.dates.updated)})`}

+{related.length > 0 && ( +
+ related +
 formatListItem(p.dates.created, `/draft/${getSlug(p.id)}`, p.data.title)).join('\n')} />
+  
+)}
diff --git a/www/src/pages/md/[slug].astro b/www/src/pages/md/[slug].astro index 8ea8d6c..2cea63e 100644 --- a/www/src/pages/md/[slug].astro +++ b/www/src/pages/md/[slug].astro @@ -1,19 +1,21 @@ --- import { getCollection, render } from 'astro:content'; import Layout from '../../layouts/Layout.astro'; -import { formatDate } from '../../lib/format'; -import { getSlug, enrichPostWithDates } from '../../lib/md'; +import { formatDate, formatListItem } from '../../lib/format'; +import { getSlug, enrichPostWithDates, enrichPostsWithDates, resolveRelatedPosts } from '../../lib/md'; export async function getStaticPaths() { - const posts = await getCollection('md', ({ data }) => data.draft !== true); - return posts.map(post => ({ + const rawPosts = await getCollection('md', ({ data }) => data.draft !== true); + const allPosts = enrichPostsWithDates(rawPosts); + return allPosts.map(post => ({ params: { slug: getSlug(post.id) }, - props: { post: enrichPostWithDates(post) } + props: { post, allPosts } })); } -const { post } = Astro.props; +const { post, allPosts } = Astro.props; const { Content } = await render(post); +const related = post.data.related ? resolveRelatedPosts(post.data.related, allPosts) : []; --- @@ -22,4 +24,10 @@ const { Content } = await render(post);

{formatDate(post.dates.created)}{post.dates.updated && ` (updated ${formatDate(post.dates.updated)})`}

+{related.length > 0 && ( +
+ related +
 formatListItem(p.dates.created, `/md/${getSlug(p.id)}`, p.data.title)).join('\n')} />
+  
+)}