diff options
Diffstat (limited to 'src/routes/blog')
| -rw-r--r-- | src/routes/blog/+page.server.ts | 13 | ||||
| -rw-r--r-- | src/routes/blog/+page.svelte | 52 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]-[slug]/+page.server.ts | 2 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]-[slug]/+page.svelte | 8 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]-[slug]/+page.ts | 2 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]/+page.server.ts | 12 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]/+page.svelte | 31 | ||||
| -rw-r--r-- | src/routes/blog/[id=int]/+page.ts | 12 | ||||
| -rw-r--r-- | src/routes/blog/base-post.svx | 15 | ||||
| -rw-r--r-- | src/routes/blog/dynamic-posts.ts | 4 | ||||
| -rw-r--r-- | src/routes/blog/posts.ts | 6 | ||||
| -rw-r--r-- | src/routes/blog/posts/test-post.svx | 190 |
12 files changed, 347 insertions, 0 deletions
diff --git a/src/routes/blog/+page.server.ts b/src/routes/blog/+page.server.ts new file mode 100644 index 0000000..7c4726e --- /dev/null +++ b/src/routes/blog/+page.server.ts @@ -0,0 +1,13 @@ +import { parsePost, type Post } from '$/lib/blog/Post.svelte' + +const posts = import.meta.glob("./posts/*.svx") as Record<string, () => Promise<Post>> +const returnedData = Promise.all(Object.entries(posts).map(v => v[1]().then(r => [v[0], { + ...parsePost(r as Post), + default: null, +}] as const))); + +export const load = async () => { + return { + posts: Object.fromEntries(await returnedData) + } +} diff --git a/src/routes/blog/+page.svelte b/src/routes/blog/+page.svelte new file mode 100644 index 0000000..627b55c --- /dev/null +++ b/src/routes/blog/+page.svelte @@ -0,0 +1,52 @@ +<script lang="ts"> + import { resolve } from '$app/paths'; + import type { PageProps } from './$types'; + + let { data }: PageProps = $props(); +</script> + +<div class="flex justify-center"> + <div class="max-w-2xl w-full"> + <div class="font-genericmono"> + <h1 class="font-space-grotesk text-5xl mt-8 mb-4"> + <span class="text-red-400 select-none">❯ </span>ls + <span class="text-red-400">'</span>blog posts<span class="text-red-400" + >'</span + ><span class="text-red-400 select-none">;</span> + </h1> + {#each Object.entries(data.posts) as [_filename, post]} + <div class="flex gap-2"> + <div class="flex flex-col items-end"> + <a + href={resolve('/blog/[id=int]-[slug]', { + id: post.metadata.id.toString(), + slug: post.metadata.slug, + })} + class="text-red-400 transition-all afterunderline-red-400 hover:afterunderline-hoverstate hover:text-white" + >link</a + > + <a + href={resolve('/blog/[id=int]', { + id: post.metadata.id.toString(), + })} + class="text-red-400 transition-all afterunderline-red-400 hover:afterunderline-hoverstate hover:text-white" + >short</a + > + </div> + <div class="flex flex-col"> + <table> + <tbody> + {#each Object.entries( { ...post.metadata, slug: undefined, id: undefined, created: undefined, updated: undefined }, ).filter((v) => v[1] !== undefined) as v} + <tr> + <td class="pr-1 align-top">{v[0]}:</td> + <td class="pl-1 align-top">{JSON.stringify(v[1])}</td> + </tr> + {/each} + </tbody> + </table> + </div> + </div> + {/each} + </div> + </div> +</div> diff --git a/src/routes/blog/[id=int]-[slug]/+page.server.ts b/src/routes/blog/[id=int]-[slug]/+page.server.ts new file mode 100644 index 0000000..be8b7c0 --- /dev/null +++ b/src/routes/blog/[id=int]-[slug]/+page.server.ts @@ -0,0 +1,2 @@ +import { load as pageload } from '../[id=int]/+page.server'; +export const load = pageload; diff --git a/src/routes/blog/[id=int]-[slug]/+page.svelte b/src/routes/blog/[id=int]-[slug]/+page.svelte new file mode 100644 index 0000000..088ae00 --- /dev/null +++ b/src/routes/blog/[id=int]-[slug]/+page.svelte @@ -0,0 +1,8 @@ +<script lang="ts"> + import type { PageProps } from './$types'; + import Page from '../[id=int]/+page.svelte'; + + let props: PageProps = $props(); +</script> + +<Page {...props} /> diff --git a/src/routes/blog/[id=int]-[slug]/+page.ts b/src/routes/blog/[id=int]-[slug]/+page.ts new file mode 100644 index 0000000..1b54560 --- /dev/null +++ b/src/routes/blog/[id=int]-[slug]/+page.ts @@ -0,0 +1,2 @@ +import { load as pageload } from '../[id=int]/+page'; +export const load = pageload; diff --git a/src/routes/blog/[id=int]/+page.server.ts b/src/routes/blog/[id=int]/+page.server.ts new file mode 100644 index 0000000..e295257 --- /dev/null +++ b/src/routes/blog/[id=int]/+page.server.ts @@ -0,0 +1,12 @@ +import { parsePost } from '$/lib/blog/Post.svelte' +import rawPosts from '../posts.js'; + +const posts = Promise.all(Object.entries(rawPosts).map(async post => [post[0], parsePost(await post[1])] as const)); +const postMap = posts.then(posts => posts.map(post => [post[1].metadata.id.toString(), { + metadata: post[1].metadata, + filename: post[0], +}])).then(v => new Map(v)); + +export const load = async (req) => ({ + post: (await postMap).get(req.params.id), +}); diff --git a/src/routes/blog/[id=int]/+page.svelte b/src/routes/blog/[id=int]/+page.svelte new file mode 100644 index 0000000..84d33ef --- /dev/null +++ b/src/routes/blog/[id=int]/+page.svelte @@ -0,0 +1,31 @@ +<script lang="ts"> + import { replaceState } from '$app/navigation'; + import { onMount, tick } from 'svelte'; + + import type { PageProps } from './$types'; + import { resolve } from '$app/paths'; + import { page } from '$app/state'; + import { forceTrailingSlash } from '$/lib'; + import Post from '$/lib/blog/Post.svelte'; + + let { data }: PageProps = $props(); + + let route = $derived( + forceTrailingSlash( + resolve('/blog/[id=int]-[slug]', { + id: data.post.metadata.id.toString(), + slug: data.post.metadata.slug, + }), + ), + ); + + onMount(() => { + tick().then(() => replaceState(route, page.state)); + }); +</script> + +<svelte:head> + <link rel="canonical" href={new URL(route, page.url).href} /> +</svelte:head> + +<Post post={data.post} filename={data.filename} /> diff --git a/src/routes/blog/[id=int]/+page.ts b/src/routes/blog/[id=int]/+page.ts new file mode 100644 index 0000000..ea2803f --- /dev/null +++ b/src/routes/blog/[id=int]/+page.ts @@ -0,0 +1,12 @@ +import { error } from '@sveltejs/kit'; +import posts from '../dynamic-posts.js'; + +export const load = async ({ data }) => { + const filename = data.post?.filename; + if (!filename) throw error(404, 'Post not found.') + const post = (await posts[filename]()); + return { + post, + filename, + } +} diff --git a/src/routes/blog/base-post.svx b/src/routes/blog/base-post.svx new file mode 100644 index 0000000..394eaa2 --- /dev/null +++ b/src/routes/blog/base-post.svx @@ -0,0 +1,15 @@ +--- +title: "Base Post" +blurb: "Awawawa Ipsum dolor the neobot is in the washing machine" +author: "7222e800" +slug: "base-post" +id: -1 + +# Timestamps are in ISO8601 UTC (`date -u +%Y-%m-%dT%H:%M:%SZ`) +created: "2026-01-14T01:25:14Z" +updated: "2026-01-14T01:25:14Z" +--- + +# Base Post + +This is an example base post. diff --git a/src/routes/blog/dynamic-posts.ts b/src/routes/blog/dynamic-posts.ts new file mode 100644 index 0000000..93ecfec --- /dev/null +++ b/src/routes/blog/dynamic-posts.ts @@ -0,0 +1,4 @@ +import type { Post } from '$/lib/blog/Post.svelte'; + +export const posts = import.meta.glob("./posts/*.svx") as Record<string, () => Promise<Post>> +export default posts diff --git a/src/routes/blog/posts.ts b/src/routes/blog/posts.ts new file mode 100644 index 0000000..5336bb0 --- /dev/null +++ b/src/routes/blog/posts.ts @@ -0,0 +1,6 @@ +import type { Post } from '$/lib/blog/Post.svelte'; + +export const posts = import.meta.glob("./posts/*.svx", { + eager: true +}) as Record<string, Promise<Post>> +export default posts diff --git a/src/routes/blog/posts/test-post.svx b/src/routes/blog/posts/test-post.svx new file mode 100644 index 0000000..b12b25a --- /dev/null +++ b/src/routes/blog/posts/test-post.svx @@ -0,0 +1,190 @@ +--- +title: "Test Post" +blurb: "Awawawa Ipsum dolor the neobot is in the washing machine" +author: "7222e800" +slug: "test-post" +id: -1 + +# Timestamps are in ISO8601 UTC (`date -u +%Y-%m-%dT%H:%M:%SZ`) +created: "2026-01-14T01:25:14Z" +updated: "2026-01-14T01:25:14Z" +--- + +<script lang="ts"> + import TableWrapper from '$/lib/blog/TableWrapper.svelte'; +</script> + +# Test Post + +this is a test blog post. + +## elements + +## markdown + +[this is a link](https://en.wikipedia.org/wiki/Catgirl). + +*this is italic*, and _this is too_. __this is underscore bolded__, and **this is asterisk bolded**. + +`this is single backticked`. + +```js +console.log('and this is a codeblock'); +``` + +> and this is a quote +> +> a multiline one + +### unwrapped table + +| | awawa | test | +|-------|-------|-------| +| **a** | b | k | +| **z** | c | | +| **f** | d | f | + +### wrapped table + +<TableWrapper> + +| | awawa | test | +|-------|-------|-------| +| **a** | b | k | +| **z** | c | | +| **f** | d | f | + +</TableWrapper> + +# section testing + +## h2 + +This is an example test post. + +## h2 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +Corporis voluptatibus magni dolorem. Et ipsum dolor occaecati. Ut error sunt ipsam vel dignissimos. + +Fuga animi voluptate sint nam consequatur adipisci. Nesciunt voluptatum eaque dolorum. Eos non animi aut aut. Debitis dolorum ducimus aspernatur facere aspernatur quasi. + +Praesentium at et alias est consectetur debitis sit cumque. Necessitatibus ratione et magni optio necessitatibus ut eius. Optio facere exercitationem consequuntur soluta ratione in. Corporis provident quia minima dicta vel et a. + +### h3 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +Corporis voluptatibus magni dolorem. Et ipsum dolor occaecati. Ut error sunt ipsam vel dignissimos. + +Fuga animi voluptate sint nam consequatur adipisci. Nesciunt voluptatum eaque dolorum. Eos non animi aut aut. Debitis dolorum ducimus aspernatur facere aspernatur quasi. + +Praesentium at et alias est consectetur debitis sit cumque. Necessitatibus ratione et magni optio necessitatibus ut eius. Optio facere exercitationem consequuntur soluta ratione in. Corporis provident quia minima dicta vel et a. + +#### h4 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +Corporis voluptatibus magni dolorem. Et ipsum dolor occaecati. Ut error sunt ipsam vel dignissimos. + +Fuga animi voluptate sint nam consequatur adipisci. Nesciunt voluptatum eaque dolorum. Eos non animi aut aut. Debitis dolorum ducimus aspernatur facere aspernatur quasi. + +Praesentium at et alias est consectetur debitis sit cumque. Necessitatibus ratione et magni optio necessitatibus ut eius. Optio facere exercitationem consequuntur soluta ratione in. Corporis provident quia minima dicta vel et a. + +### h3 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +#### h4 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +#### h4 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +## h2 + +Autem ut nam sapiente et a magni. Qui maiores in qui earum. Veniam veniam omnis id architecto. Et optio et et molestias. + +Eaque cum dolores ut enim voluptatibus id velit velit. Iure eveniet alias doloribus. Ratione in in est aspernatur. + +## some code + +```ts +/* + Copyright (C) 2024-2026 memdmp + + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by Affero, Inc., at version 1. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Affero General Public License for more details. + + You should have received a copy of the Affero General Public License along with this program. If not, see <https://spdx.org/licenses/AGPL-1.0-only>. +*/ +import { Animation, MultiObjectKeyframe } from '@memdmp/keyframegen'; +import { + biosStepInterval, + biosSteps, + getDelay, + login, + ttyLines, +} from './shared.ts'; +import fs from 'node:fs'; +import esbuild from 'esbuild'; +console.log('hi'); +const anim = new Animation(); +let ttyCtr = 0; +const stages = [ + anim.selector('.anmroot #bios'), + anim.selector('.anmroot #grub'), + anim.selector('.anmroot #grub-term'), + anim.selector('.anmroot #openrc'), + ...ttyLines.flatMap((v) => + v.kind === 'clear' ? [anim.selector('.anmroot #tty-' + ttyCtr++)] : [], + ), +]; +const handleSteps: Step[] = [ + // (n) => { + // toStage(0); + // anim.in(500, n); + // }, + ...biosStepHandlers, + ...grubStepHandlers, + ...openrcStepHandlers(1), + ...ttyStepHandlers, + (n) => { + const s = anim.selector('.anmroot #app .hidden-after-anim'); + s.style(visibleStyles); + anim._internal_timeline.now += 1; + s.style(hiddenStyles); + anim.in(1000, n); + }, +]; +fs.writeFileSync( + 'src/routes/anim.css', + `${comment} +${esbuild.buildSync({ + stdin: { + contents: `${exported} +${tail}`, + loader: 'css', + }, + write: false, + minify: false, + }).outputFiles![0].text + }`, +); +``` |