From d18c3f62c787fd3b308b2b4627c49c82e99779ce Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sun, 27 Oct 2024 20:17:42 -0700 Subject: [PATCH 1/4] refactor: Add series filter on `getPosts` --- src/lib/posts.ts | 9 ++++++--- src/routes/tag/[slug]/+page.ts | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/posts.ts b/src/lib/posts.ts index d0fe91f..9984e6d 100644 --- a/src/lib/posts.ts +++ b/src/lib/posts.ts @@ -15,7 +15,8 @@ export function transformPostMeta(metadata: PostMetadata, slug: string) : Post { }; } -export async function getPosts(tag: string | null = null) : Promise { +// Generates a list of all posts filtering by tags and series +export async function getPosts(filter: { tag?: string, series?: string }) : Promise { const allPostFiles = import.meta.glob('$content/post/*.md'); const iterablePostFiles = Object.entries(allPostFiles); @@ -27,8 +28,10 @@ export async function getPosts(tag: string | null = null) : Promise { return transformPostMeta(metadata, slug); }) ); - if (tag) - posts = posts.filter(post => post.tags.includes(tag)) + if (filter?.tag) + posts = posts.filter(post => post.tags.includes(filter.tag!)) + if (filter?.series) + posts = posts.filter(post => post.series?.includes(filter.series!) ?? false) posts.sort((post1, post2) => { const date1: Date = post1.date; diff --git a/src/routes/tag/[slug]/+page.ts b/src/routes/tag/[slug]/+page.ts index f3a0fe0..6d2fafd 100644 --- a/src/routes/tag/[slug]/+page.ts +++ b/src/routes/tag/[slug]/+page.ts @@ -2,7 +2,7 @@ import type { PageLoad } from './$types'; import { getPosts } from '$lib/posts'; export const load: PageLoad = async ({ params }) => { - const posts = await getPosts(params.slug); + const posts = await getPosts({ tag: params.slug }); return { name: params.slug, posts, From 56e6efc795777f5c74768886553091fb6c2efabe Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 25 Jan 2025 15:06:09 -0800 Subject: [PATCH 2/4] feat: Implement series --- src/lib/posts.ts | 2 +- src/routes/post/[slug]/+page.svelte | 39 ++++++++++++++++++++++++++- src/routes/post/[slug]/+page.ts | 42 +++++++++++++++++++++++++++-- 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/lib/posts.ts b/src/lib/posts.ts index 9984e6d..ecfc429 100644 --- a/src/lib/posts.ts +++ b/src/lib/posts.ts @@ -15,7 +15,7 @@ export function transformPostMeta(metadata: PostMetadata, slug: string) : Post { }; } -// Generates a list of all posts filtering by tags and series +// Generates a list of all posts filtering by tags and series, reverse chronologically ordered. export async function getPosts(filter: { tag?: string, series?: string }) : Promise { const allPostFiles = import.meta.glob('$content/post/*.md'); const iterablePostFiles = Object.entries(allPostFiles); diff --git a/src/routes/post/[slug]/+page.svelte b/src/routes/post/[slug]/+page.svelte index 22fcab7..f7609be 100644 --- a/src/routes/post/[slug]/+page.svelte +++ b/src/routes/post/[slug]/+page.svelte @@ -1,7 +1,8 @@ @@ -17,3 +18,39 @@
+
    + {#each seriesNeighbours as { name, prevSlug, prevTitle, nextSlug, nextTitle }} +
  • + {#if prevTitle} + {prevTitle} +

    + {/if} +

    {name}

    + {#if nextTitle} +

    + {nextTitle} + {/if} +
  • + {/each} +
+ + diff --git a/src/routes/post/[slug]/+page.ts b/src/routes/post/[slug]/+page.ts index 974b02e..a974f60 100644 --- a/src/routes/post/[slug]/+page.ts +++ b/src/routes/post/[slug]/+page.ts @@ -1,16 +1,54 @@ import { error } from '@sveltejs/kit'; import type { PageLoad } from './$types'; -import { transformPostMeta } from '$lib/posts'; +import type { Post } from '$lib/types' +import { getPosts, transformPostMeta } from '$lib/posts'; export const load: PageLoad = async ({ params }) => { try { const post = await import(`$content/post/${params.slug}.md`); if (!post) throw error(404); + const metadata: Post = transformPostMeta(post.metadata, params.slug); const Content = post.default; + const seriesNeighbours : { + name: string, + prevSlug?: string, + prevTitle?: string, + nextSlug?: string, + nextTitle?: string, + }[] = await Promise.all(post.metadata.series.map(async (series: string) => { + const postInSeries: Post[] = await getPosts({ series }); + + let prevSlug = null; + let prevTitle = null; + let nextSlug = null; + let nextTitle = null; + + for (const p of postInSeries) { + if (p.date > metadata.date) { + nextSlug = p.slug; + nextTitle = p.title; + } + if (p.date < metadata.date) { + prevSlug = p.slug; + prevTitle = p.title; + break; + } + } + + return { + name: series, + prevSlug, + prevTitle, + nextSlug, + nextTitle, + }; + })); + return { - post: transformPostMeta(post.metadata, params.slug), + post: metadata, Content, + seriesNeighbours, }; } catch { From 7d9fe36140e54f057c6461e4cc6b7cf4b1fcf75d Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 25 Jan 2025 15:17:34 -0800 Subject: [PATCH 3/4] test: Series navigation test --- tests/series-tags.spec.ts | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tests/series-tags.spec.ts diff --git a/tests/series-tags.spec.ts b/tests/series-tags.spec.ts new file mode 100644 index 0000000..b2dc6eb --- /dev/null +++ b/tests/series-tags.spec.ts @@ -0,0 +1,9 @@ +import { expect, test } from '@playwright/test'; + +test('Navigate in series', async ({ page }) => { + await page.goto('/post'); + await page.getByText('Placeholder 2').click(); + await expect(page).toHaveURL("/post/placeholder2/"); + await page.getByText('Placeholder 1').click(); + await expect(page).toHaveURL("/post/placeholder1/"); +}); From 662a298b28cc33174926ac1870cd9b74fc056be6 Mon Sep 17 00:00:00 2001 From: Leni Aniva Date: Sat, 25 Jan 2025 15:36:12 -0800 Subject: [PATCH 4/4] fix: Posts with empty series --- src/routes/post/[slug]/+page.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/routes/post/[slug]/+page.ts b/src/routes/post/[slug]/+page.ts index a974f60..151f390 100644 --- a/src/routes/post/[slug]/+page.ts +++ b/src/routes/post/[slug]/+page.ts @@ -16,13 +16,13 @@ export const load: PageLoad = async ({ params }) => { prevTitle?: string, nextSlug?: string, nextTitle?: string, - }[] = await Promise.all(post.metadata.series.map(async (series: string) => { + }[] = await Promise.all((metadata.series || []).map(async (series: string) => { const postInSeries: Post[] = await getPosts({ series }); - let prevSlug = null; - let prevTitle = null; - let nextSlug = null; - let nextTitle = null; + let prevSlug = undefined; + let prevTitle = undefined; + let nextSlug = undefined; + let nextTitle = undefined; for (const p of postInSeries) { if (p.date > metadata.date) {