72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
import { error } from '@sveltejs/kit';
|
|
import type { BlogPost, RawBlogPost } from '$lib/types';
|
|
import type { MetaTagsProps } from 'svelte-meta-tags';
|
|
|
|
/** @type {import('./$types').PageLoad} */
|
|
export async function load({ params, fetch }) {
|
|
try {
|
|
const response = await fetch('/api/blog');
|
|
const posts: BlogPost[] = await response.json();
|
|
|
|
const blog: RawBlogPost = await import(`../../../blog/${params.slug}.md`);
|
|
|
|
return {
|
|
content: blog.default,
|
|
meta: blog.metadata,
|
|
slug: params.slug,
|
|
pageMetaTags: getPageMetaTags(blog),
|
|
relatedPosts: getRelatedPosts(posts, blog.metadata.tags, params.slug)
|
|
};
|
|
} catch (e) {
|
|
error(404, `Could not find ${params.slug}`);
|
|
}
|
|
}
|
|
|
|
function getRelatedPosts(posts: BlogPost[], tags: string[], slug: string) {
|
|
const related = posts
|
|
.filter((post) => post.tags.some((tag) => tags.includes(tag)) && post.slug !== slug)
|
|
.map((post) => ({
|
|
...post,
|
|
rank: post.tags.filter((tag) => tags.includes(tag)).length
|
|
}))
|
|
.sort((a, b) => b.rank - a.rank);
|
|
|
|
const topPosts = related.filter((post) => post.rank > 1);
|
|
|
|
if (topPosts.length > 2) {
|
|
return topPosts.sort(() => Math.random() - 0.5).slice(0, 2);
|
|
}
|
|
|
|
return related.slice(0, 2);
|
|
}
|
|
|
|
function getPageMetaTags(blog: RawBlogPost): MetaTagsProps {
|
|
return Object.freeze({
|
|
title: blog.metadata.title,
|
|
description: blog.metadata.description,
|
|
openGraph: {
|
|
title: blog.metadata.title,
|
|
description: blog.metadata.description,
|
|
images: [
|
|
{
|
|
url: blog.metadata.imageUrl,
|
|
alt: blog.metadata.title,
|
|
width: 280,
|
|
height: 200,
|
|
secureUrl: blog.metadata.imageUrl,
|
|
type: 'image/jpeg'
|
|
}
|
|
]
|
|
},
|
|
twitter: {
|
|
handle: '@classroomio',
|
|
site: '@classroomio',
|
|
cardType: 'summary_large_image' as const,
|
|
title: blog.metadata.title,
|
|
description: blog.metadata.description,
|
|
image: blog.metadata.imageUrl,
|
|
imageAlt: `${blog.metadata.title} OG`
|
|
}
|
|
}) satisfies MetaTagsProps;
|
|
}
|