Individual blogPosts - Server + page + Layout
This commit is contained in:
parent
74987b8408
commit
8c425f89c8
|
@ -0,0 +1,3 @@
|
|||
<article class="text-token prose prose-slate mx-auto dark:prose-invert lg:prose-lg">
|
||||
<slot />
|
||||
</article>
|
|
@ -1,63 +1,69 @@
|
|||
<script lang="ts">
|
||||
import { formatDate } from '$content/utils';
|
||||
import SEO from '$lib/components/SEO/index.svelte';
|
||||
import '$lib/assets/prism-nord.css';
|
||||
import type { Post } from '$lib/types/post';
|
||||
import Tags from '$lib/components/blog/Tags.svelte';
|
||||
|
||||
export let imagesDirectoryName: string;
|
||||
export let excerpt: string = '';
|
||||
export let date: string = '';
|
||||
export let slug: string = '';
|
||||
export let title: string;
|
||||
export let image: string;
|
||||
export let tags: string[] = [];
|
||||
export let type: 'blog' | 'projects';
|
||||
export let post: Post;
|
||||
|
||||
const {
|
||||
postTitle,
|
||||
datePublished,
|
||||
featuredImage,
|
||||
featuredImageAlt,
|
||||
lastUpdated,
|
||||
seoMetaDescription: metadescription,
|
||||
slug,
|
||||
timeToRead,
|
||||
ogImage,
|
||||
ogSquareImage,
|
||||
twitterImage
|
||||
} = post || {};
|
||||
|
||||
const breadcrumbs = [
|
||||
{ name: 'Home', slug: '' },
|
||||
{ name: 'type', slug: post.type },
|
||||
{ name: postTitle, slug }
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={excerpt} />
|
||||
<meta property="og:title" content={title} />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:description" content={excerpt} />
|
||||
<meta property="og:url" content="https://mattmor.in/{slug}" />
|
||||
<meta property="og:image" content={image} />
|
||||
<meta property="og:type" content="article:published_time" />
|
||||
<meta property="article:published_time" content={date} />
|
||||
{#each tags as tag (tag)}
|
||||
<meta property="article:tag" content={tag} />
|
||||
{/each}
|
||||
</svelte:head>
|
||||
<SEO
|
||||
article
|
||||
{breadcrumbs}
|
||||
{slug}
|
||||
{postTitle}
|
||||
{datePublished}
|
||||
{lastUpdated}
|
||||
{metadescription}
|
||||
{timeToRead}
|
||||
{featuredImage}
|
||||
{ogImage}
|
||||
{ogSquareImage}
|
||||
{twitterImage}
|
||||
/>
|
||||
|
||||
<article class="flex justify-center mt-4 mb-8">
|
||||
<div class=" w-full md:w-[50rem] leading-[177.7%]">
|
||||
<section class="flex justify-center mt-4 mb-8">
|
||||
<div
|
||||
class=" w-full md:w-[50rem] leading-[177.7%] bg-white/50 dark:bg-black/50 m-2 rounded-t-lg mx-auto"
|
||||
>
|
||||
<header>
|
||||
<img
|
||||
src="/images/{imagesDirectoryName}/{slug}/{image}"
|
||||
alt={`${title}`}
|
||||
class=" bg-black/50 w-full aspect-[21/9] max-h-[540px] rounded-t-lg"
|
||||
src={featuredImage}
|
||||
alt={featuredImageAlt}
|
||||
class=" w-full aspect-[21/9] max-h-[540px] rounded-t-lg"
|
||||
/>
|
||||
</header>
|
||||
<div class="flex-auto flex justify-between items-center py-4 px-2 bg-surface-900">
|
||||
{#if tags && tags.length > 0}
|
||||
<div class="flex mb-2 items-center gap-2">
|
||||
tags: {#each tags as tag}
|
||||
<a
|
||||
data-sveltekit-preload-data="hover"
|
||||
href="/blog?{new URLSearchParams({ tag }).toString()}"
|
||||
>
|
||||
<span class="chip variant-ghost-surface">{tag}</span>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<small>On {formatDate(date)}</small>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
<h2 class="h2" data-toc-ignore>{title}</h2>
|
||||
<div class="max-w-none text-token">
|
||||
<Tags {post} />
|
||||
<div class="space-y-4 m-8">
|
||||
<h2 class="h2" data-toc-ignore>{post.title}</h2>
|
||||
<div class="max-w-none md:w-[720px]">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
<hr class="opacity-50" />
|
||||
<footer class="p-4 flex justify-start items-center space-x-4" />
|
||||
</div>
|
||||
</article>
|
||||
</section>
|
||||
|
||||
<style lang="postcss">
|
||||
</style>
|
||||
|
|
|
@ -1,16 +1,10 @@
|
|||
<script lang="ts">
|
||||
import BlogContentLayout from '$lib/components/blog/BlogContentLayout.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import PostLayout from '$lib/components/blog/PostLayout.svelte';
|
||||
import type { PageData } from '../$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<!-- <svelte:head>
|
||||
<title>{data.post.title}</title>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content={data.post.title} />
|
||||
</svelte:head> -->
|
||||
|
||||
<BlogContentLayout post={data.post}>
|
||||
<svelte:component this={data.Component} />
|
||||
</BlogContentLayout>
|
||||
<PostLayout post={data.meta}>
|
||||
<svelte:component this={data.content} />
|
||||
</PostLayout>
|
||||
|
|
|
@ -1,14 +1,19 @@
|
|||
import { getPost, listPosts } from '$content/blog';
|
||||
import type { PageLoad } from './$types';
|
||||
import type { PageServerLoad } from './$types';
|
||||
|
||||
export const entries = async () => {
|
||||
const posts = await listPosts();
|
||||
return posts
|
||||
.filter((post) => post.slug !== undefined)
|
||||
.map((post) => ({ slug: post.slug as string }));
|
||||
};
|
||||
import { error } from '@sveltejs/kit';
|
||||
|
||||
export const load: PageLoad = async ({ params, parent }) => {
|
||||
await parent();
|
||||
return await getPost(params.slug);
|
||||
export const load: PageServerLoad = async ({ params }) => {
|
||||
try {
|
||||
const post = await import(`../../../content/blog/${params.slug}.md`);
|
||||
|
||||
return {
|
||||
content: post.default,
|
||||
meta: post.metadata
|
||||
};
|
||||
} catch (err) {
|
||||
if (err.status === 404) {
|
||||
error(404, `Could not find ${params.slug}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue