aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/blog
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/blog')
-rw-r--r--src/lib/blog/InfoCard.svelte0
-rw-r--r--src/lib/blog/Post.svelte45
-rw-r--r--src/lib/blog/Post.ts28
-rw-r--r--src/lib/blog/TableWrapper.svelte15
4 files changed, 88 insertions, 0 deletions
diff --git a/src/lib/blog/InfoCard.svelte b/src/lib/blog/InfoCard.svelte
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/lib/blog/InfoCard.svelte
diff --git a/src/lib/blog/Post.svelte b/src/lib/blog/Post.svelte
new file mode 100644
index 0000000..2c61621
--- /dev/null
+++ b/src/lib/blog/Post.svelte
@@ -0,0 +1,45 @@
+<script lang="ts" module>
+ export * from './Post';
+</script>
+
+<script lang="ts">
+ import { parsePostMetadata, type Post } from './Post';
+
+ let {
+ post,
+ filename,
+ }: {
+ post: Post;
+ filename?: string;
+ } = $props();
+
+ let meta = $derived(parsePostMetadata(post.metadata));
+
+ let PostComp = $derived(post.default);
+</script>
+
+<div class="flex justify-center">
+ <div class="max-w-2xl w-full">
+ <h1 class="font-space-grotesk text-5xl mt-8 mb-4">
+ <span class="text-accent-primary select-none">:&nbsp;</span
+ >{meta.title}<span class="text-accent-primary select-none">;</span>
+ </h1>
+ <p class="my-4 font-genericmono">
+ ctime: {meta.created.toISOString().split('T')[0]}<span class="select-none"
+ >&MediumSpace;▒&MediumSpace;</span
+ >mtime: {meta.updated.toISOString().split('T')[0]}{#if filename}<span
+ class="select-none">&MediumSpace;▒&MediumSpace;</span
+ ><a
+ href={encodeURI(
+ `https://codeberg.org/dmpmem/tilde/src/branch/master/src/routes/blog/${filename}`,
+ )}
+ class="quicklink"
+ target="_blank"
+ rel="noopener noreferrer">src</a
+ >{/if}
+ </p>
+ <article id="postmd">
+ <PostComp />
+ </article>
+ </div>
+</div>
diff --git a/src/lib/blog/Post.ts b/src/lib/blog/Post.ts
new file mode 100644
index 0000000..440dffa
--- /dev/null
+++ b/src/lib/blog/Post.ts
@@ -0,0 +1,28 @@
+
+import type { Component } from 'svelte';
+
+export type PostMetadata<Parsed extends boolean = false> = {
+ title: string;
+ blurb: string;
+ author: string | null;
+ slug: string;
+ id: string | number;
+ created: Parsed extends true ? Date : string;
+ updated: Parsed extends true ? Date : string;
+};
+export type Post<MetadataParsed extends boolean = false> = {
+ metadata: PostMetadata<MetadataParsed>;
+ default: Component;
+};
+
+export const parsePostMetadata = (
+ m: PostMetadata<boolean>,
+): PostMetadata<true> => ({
+ ...m,
+ created: new Date(m.created),
+ updated: new Date(m.updated),
+});
+export const parsePost = (p: Post<boolean>): Post<true> => ({
+ ...p,
+ metadata: parsePostMetadata(p.metadata),
+});
diff --git a/src/lib/blog/TableWrapper.svelte b/src/lib/blog/TableWrapper.svelte
new file mode 100644
index 0000000..ddf3d73
--- /dev/null
+++ b/src/lib/blog/TableWrapper.svelte
@@ -0,0 +1,15 @@
+<script lang="ts">
+ import type { Snippet } from 'svelte';
+
+ const {
+ children,
+ maxwidth = false,
+ }: {
+ children: Snippet;
+ maxwidth?: boolean;
+ } = $props();
+</script>
+
+<div class={{ 'formatted-table my-1': true, 'w-max': !maxwidth }}>
+ {@render children()}
+</div>