feat: Implement series

This commit is contained in:
Leni Aniva 2025-01-25 15:06:09 -08:00
parent d18c3f62c7
commit 56e6efc795
Signed by: aniva
GPG Key ID: 4D9B1C8D10EA4C50
3 changed files with 79 additions and 4 deletions

View File

@ -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<Post[]> { export async function getPosts(filter: { tag?: string, series?: string }) : Promise<Post[]> {
const allPostFiles = import.meta.glob('$content/post/*.md'); const allPostFiles = import.meta.glob('$content/post/*.md');
const iterablePostFiles = Object.entries(allPostFiles); const iterablePostFiles = Object.entries(allPostFiles);

View File

@ -1,7 +1,8 @@
<script lang="ts"> <script lang="ts">
import { TrackPrevious, TrackNext } from 'svelte-radix';
import type { PageData } from './$types'; import type { PageData } from './$types';
export let data: PageData; export let data: PageData;
const { post, Content } = data; const { post, Content, seriesNeighbours } = data;
import siteMetadata from '$content/metadata.json'; import siteMetadata from '$content/metadata.json';
import PostHeader from '$lib/components/PostHeader.svelte'; import PostHeader from '$lib/components/PostHeader.svelte';
</script> </script>
@ -17,3 +18,39 @@
<Content /> <Content />
</article> </article>
<hr /> <hr />
<ul id="series">
{#each seriesNeighbours as { name, prevSlug, prevTitle, nextSlug, nextTitle }}
<li class="series-neighbour">
{#if prevTitle}
<a href="/post/{prevSlug}">{prevTitle}</a>
<p class="dummy"><TrackPrevious /></p>
{/if}
<p class="series-tag">{name}</p>
{#if nextTitle}
<p class="dummy"><TrackNext /></p>
<a href="/post/{nextSlug}">{nextTitle}</a>
{/if}
</li>
{/each}
</ul>
<style>
#series {
text-align: center;
}
.series-tag {
color: var(--series);
display: inline-block;
}
.dummy {
display: inline-block;
color: rgba(128,128,128, .6);
vertical-align: middle;
padding-left: 1em;
padding-right: 1em;
}
.series-neighbour {
padding-left: 2em;
padding-right: 2em;
}
</style>

View File

@ -1,16 +1,54 @@
import { error } from '@sveltejs/kit'; import { error } from '@sveltejs/kit';
import type { PageLoad } from './$types'; 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 }) => { export const load: PageLoad = async ({ params }) => {
try { try {
const post = await import(`$content/post/${params.slug}.md`); const post = await import(`$content/post/${params.slug}.md`);
if (!post) throw error(404); if (!post) throw error(404);
const metadata: Post = transformPostMeta(post.metadata, params.slug);
const Content = post.default; 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 { return {
post: transformPostMeta(post.metadata, params.slug), name: series,
prevSlug,
prevTitle,
nextSlug,
nextTitle,
};
}));
return {
post: metadata,
Content, Content,
seriesNeighbours,
}; };
} }
catch { catch {