feat: moved content back into this repository, and moved private content out
This commit is contained in:
parent
7fb4035f31
commit
63a079deb1
14 changed files with 62 additions and 132 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
[submodule "www/src/content"]
|
|
||||||
path = www/src/content
|
|
||||||
url = git@github.com:Llywelwyn/wynne.rs-content.git
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 01cb4bd1a06375ff1bdc0bc4e64024a1041fd908
|
|
||||||
|
|
@ -14,16 +14,6 @@ const md = defineCollection({
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const dnd = defineCollection({
|
|
||||||
loader: glob({ pattern: '**/*.md', base: './src/content/dnd' }),
|
|
||||||
schema: z.object({
|
|
||||||
title: z.string(),
|
|
||||||
pinned: z.boolean().optional(),
|
|
||||||
category: z.string().optional(),
|
|
||||||
related: z.array(z.string()).optional(),
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const bookmarks = defineCollection({
|
const bookmarks = defineCollection({
|
||||||
loader: file('./src/content/bookmarks.yaml', {
|
loader: file('./src/content/bookmarks.yaml', {
|
||||||
parser: (text) => {
|
parser: (text) => {
|
||||||
|
|
@ -38,4 +28,4 @@ const bookmarks = defineCollection({
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
export const collections = { md, dnd, bookmarks };
|
export const collections = { md, bookmarks };
|
||||||
|
|
|
||||||
19
www/src/content/bookmarks.yaml
Normal file
19
www/src/content/bookmarks.yaml
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
- date: 2026-01-23
|
||||||
|
title: personal websites with a /now page
|
||||||
|
url: https://nownownow.com/
|
||||||
|
|
||||||
|
- date: 2025-04-18
|
||||||
|
title: Accessible UK Train Timetables
|
||||||
|
url: https://traintimes.org.uk/
|
||||||
|
|
||||||
|
- date: 2024-05-20
|
||||||
|
title: Game Programming Patterns
|
||||||
|
url: https://gameprogrammingpatterns.com/contents.html
|
||||||
|
|
||||||
|
- date: 2023-09-04
|
||||||
|
title: Procedural Map Generation Techniques
|
||||||
|
url: https://www.youtube.com/watch?v=TlLIOgWYVpI
|
||||||
|
|
||||||
|
- date: 2023-09-04
|
||||||
|
title: Procedural Level Design in Brogue and Beyond
|
||||||
|
url: https://www.youtube.com/watch?v=Uo9-IcHhq_w
|
||||||
33
www/src/content/md/hello-world.md
Normal file
33
www/src/content/md/hello-world.md
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
---
|
||||||
|
title: hello world
|
||||||
|
pinned: true
|
||||||
|
---
|
||||||
|
|
||||||
|
i've always kept my projects online and public, and i've always had some sort of homepage. it was originally bebo, then some sites i made through school, then facebook.
|
||||||
|
|
||||||
|
:right[i liked farmville but otherwise didnt use facebook much]
|
||||||
|
|
||||||
|
my next site after that was one that i kept updated for years. but every time i updated it, i also tacked on features i liked, and then ultimately it became a mess of ideas. it was never supposed to be well-engineered, but i like clean code and i ended up too busy fixing things to do anything new or interesting
|
||||||
|
|
||||||
|
so i deleted everything i could think of that was even remotely fancy and made this
|
||||||
|
|
||||||
|
there's one bit of javascript on this site, and that's the [/random](https://wynne.rs/random/) route to take you to a random page
|
||||||
|
|
||||||
|
everything else is mostly vanilla. there's no pagination or searching, though i did add categorisation
|
||||||
|
|
||||||
|
plain text files are hosted and indexed at [/txt](https://wynne.rs/txt/),
|
||||||
|
|
||||||
|
longer form things are in categories at [/md](https://wynne.rs/md/),
|
||||||
|
|
||||||
|
there are [/bookmarks](https://wynne.rs/bookmarks/) for things that link elsewhere,
|
||||||
|
|
||||||
|
and there's a [/guestbook](https://wynne.rs/guestbook/) that used to have placeable stickers and selectable card backgrounds, and hand-drawn art and pagination, and a gallery section where people could paint pictures, and... is now just a list of names and the text that was left, which i prefer
|
||||||
|
|
||||||
|
:right[the old guestbook still exists; its just not the one i link anymore]
|
||||||
|
|
||||||
|
in the end, everything on this site is visible straight from the index page in one massive list, ordered by date, with pinned posts at the top of their respective category.
|
||||||
|
|
||||||
|
and that's it. i don't need anything else to archive things i care about
|
||||||
|
|
||||||
|
cheers,
|
||||||
|
lewis x
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
import type { CollectionEntry } from 'astro:content';
|
|
||||||
import { getSlug, resolveRelatedPosts } from './md';
|
|
||||||
|
|
||||||
type DndPost = CollectionEntry<'dnd'>;
|
|
||||||
|
|
||||||
export { getSlug, resolveRelatedPosts };
|
|
||||||
|
|
||||||
export function organizePostsByCategory(posts: DndPost[]): {
|
|
||||||
grouped: Record<string, DndPost[]>;
|
|
||||||
categories: string[];
|
|
||||||
} {
|
|
||||||
const grouped = posts.reduce((acc, post) => {
|
|
||||||
const category = post.data.category ?? 'dnd';
|
|
||||||
if (!acc[category]) acc[category] = [];
|
|
||||||
acc[category].push(post);
|
|
||||||
return acc;
|
|
||||||
}, {} as Record<string, DndPost[]>);
|
|
||||||
|
|
||||||
const categories = Object.keys(grouped).sort((a, b) => {
|
|
||||||
if (a === 'dnd') return -1;
|
|
||||||
if (b === 'dnd') return 1;
|
|
||||||
return a.localeCompare(b);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const category of categories) {
|
|
||||||
grouped[category] = grouped[category].slice().sort((a, b) => {
|
|
||||||
if (a.data.pinned && !b.data.pinned) return -1;
|
|
||||||
if (!a.data.pinned && b.data.pinned) return 1;
|
|
||||||
return a.data.title.localeCompare(b.data.title);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return { grouped, categories };
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
import { getCollection, render } from 'astro:content';
|
import { getCollection, render } from 'astro:content';
|
||||||
import Layout from '../../layouts/Layout.astro';
|
import Layout from '../layouts/Layout.astro';
|
||||||
import { formatDate, formatListItem } from '../../lib/format';
|
import { formatDate, formatListItem } from '../lib/format';
|
||||||
import { getSlug, enrichPostWithDates, enrichPostsWithDates, resolveRelatedPosts } from '../../lib/md';
|
import { getSlug, enrichPostWithDates, enrichPostsWithDates, resolveRelatedPosts } from '../lib/md';
|
||||||
|
|
||||||
export async function getStaticPaths() {
|
export async function getStaticPaths() {
|
||||||
const rawPosts = await getCollection('md');
|
const rawPosts = await getCollection('md');
|
||||||
|
|
@ -27,7 +27,7 @@ const related = post.data.related ? resolveRelatedPosts(post.data.related, allPo
|
||||||
{related.length > 0 && (
|
{related.length > 0 && (
|
||||||
<details open>
|
<details open>
|
||||||
<summary>related</summary>
|
<summary>related</summary>
|
||||||
<pre set:html={related.map(p => formatListItem(p.dates.created, `/md/${getSlug(p.id)}`, p.data.title)).join('\n')} />
|
<pre set:html={related.map(p => formatListItem(p.dates.created, `/${getSlug(p.id)}`, p.data.title)).join('\n')} />
|
||||||
</details>
|
</details>
|
||||||
)}
|
)}
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
@ -1,38 +0,0 @@
|
||||||
---
|
|
||||||
export const prerender = false;
|
|
||||||
|
|
||||||
import { getCollection, render } from 'astro:content';
|
|
||||||
import { requireAdminSession } from '../../lib/auth';
|
|
||||||
import Layout from '../../layouts/Layout.astro';
|
|
||||||
import { getSlug, resolveRelatedPosts } from '../../lib/dnd';
|
|
||||||
|
|
||||||
const { session, error } = await requireAdminSession(Astro.request);
|
|
||||||
if (error) return error;
|
|
||||||
if (!session) return Astro.redirect('/api/auth/signin');
|
|
||||||
|
|
||||||
const slug = Astro.params.slug;
|
|
||||||
const allPosts = await getCollection('dnd');
|
|
||||||
const post = allPosts.find(p => getSlug(p.id) === slug);
|
|
||||||
|
|
||||||
if (!post) {
|
|
||||||
return new Response('Not found', { status: 404 });
|
|
||||||
}
|
|
||||||
|
|
||||||
const { Content } = await render(post);
|
|
||||||
const related = post.data.related ? resolveRelatedPosts(post.data.related, allPosts) : [];
|
|
||||||
---
|
|
||||||
<Layout title={`${post.data.title} - lewis m.w.`}>
|
|
||||||
|
|
||||||
<article>
|
|
||||||
<h1>{post.data.title}</h1>
|
|
||||||
<Content />
|
|
||||||
</article>
|
|
||||||
{related.length > 0 && (
|
|
||||||
<details open>
|
|
||||||
<summary>related</summary>
|
|
||||||
<pre set:html={related.map(p =>
|
|
||||||
`<a href="/dnd/${getSlug(p.id)}">${p.data.title}</a>`
|
|
||||||
).join('\n')} />
|
|
||||||
</details>
|
|
||||||
)}
|
|
||||||
</Layout>
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
---
|
|
||||||
export const prerender = false;
|
|
||||||
|
|
||||||
import { getCollection } from 'astro:content';
|
|
||||||
import { requireAdminSession } from '../../lib/auth';
|
|
||||||
import Layout from '../../layouts/Layout.astro';
|
|
||||||
import { organizePostsByCategory, getSlug } from '../../lib/dnd';
|
|
||||||
import map from '../../content/dnd/drakkenheim/map.jpg';
|
|
||||||
|
|
||||||
const { session, error } = await requireAdminSession(Astro.request);
|
|
||||||
if (error) return error;
|
|
||||||
if (!session) return Astro.redirect('/api/auth/signin');
|
|
||||||
|
|
||||||
const posts = await getCollection('dnd');
|
|
||||||
const { grouped, categories: sortedCategories } = organizePostsByCategory(posts);
|
|
||||||
---
|
|
||||||
<Layout title="dnd - lewis m.w.">
|
|
||||||
|
|
||||||
<p class="muted">logged in as {session.user?.name} <a href="/api/auth/signout">sign out</a></p>
|
|
||||||
|
|
||||||
<img src={map.src} alt="Drakkenheim map" />
|
|
||||||
|
|
||||||
{sortedCategories.length === 0 ? (
|
|
||||||
<p class="muted">nothing here</p>
|
|
||||||
) : (
|
|
||||||
sortedCategories.map(category => (
|
|
||||||
<details open>
|
|
||||||
<summary>{category}</summary>
|
|
||||||
<pre set:html={grouped[category].map(post =>
|
|
||||||
`<a href="/dnd/${getSlug(post.id)}">${post.data.title}</a>${post.data.pinned ? ' [pinned]' : ''}`
|
|
||||||
).join('\n')} />
|
|
||||||
</details>
|
|
||||||
))
|
|
||||||
)}
|
|
||||||
</Layout>
|
|
||||||
|
|
@ -14,7 +14,7 @@ export async function GET(context: APIContext) {
|
||||||
...posts.map(post => ({
|
...posts.map(post => ({
|
||||||
title: post.data.title,
|
title: post.data.title,
|
||||||
pubDate: post.dates.created,
|
pubDate: post.dates.created,
|
||||||
link: `/md/${getSlug(post.id)}`,
|
link: `/${getSlug(post.id)}`,
|
||||||
description: post.data.title,
|
description: post.data.title,
|
||||||
})),
|
})),
|
||||||
...txtFiles.map(txt => ({
|
...txtFiles.map(txt => ({
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ try {
|
||||||
<details open>
|
<details open>
|
||||||
<summary>{category}</summary>
|
<summary>{category}</summary>
|
||||||
<pre set:html={[
|
<pre set:html={[
|
||||||
...categoryPosts.slice(0, 10).map(post => formatListItem(post.dates.created, `/md/${getSlug(post.id)}`, post.data.title, { pinned: post.data.pinned })),
|
...categoryPosts.slice(0, 10).map(post => formatListItem(post.dates.created, `/${getSlug(post.id)}`, post.data.title, { pinned: post.data.pinned })),
|
||||||
...(categoryPosts.length > 10 ? [`<a href="/md/">+${categoryPosts.length - 10} more</a>`] : [])
|
...(categoryPosts.length > 10 ? [`<a href="/md/">+${categoryPosts.length - 10} more</a>`] : [])
|
||||||
].join('\n')} />
|
].join('\n')} />
|
||||||
</details>
|
</details>
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ const { grouped, categories: sortedCategories } = organizePostsByCategory(posts)
|
||||||
{sortedCategories.map(category => (
|
{sortedCategories.map(category => (
|
||||||
<details open>
|
<details open>
|
||||||
<summary>{category}</summary>
|
<summary>{category}</summary>
|
||||||
<pre set:html={grouped[category].map(post => formatListItem(post.dates.created, `/md/${getSlug(post.id)}`, post.data.title, { pinned: post.data.pinned })).join('\n')} />
|
<pre set:html={grouped[category].map(post => formatListItem(post.dates.created, `/${getSlug(post.id)}`, post.data.title, { pinned: post.data.pinned })).join('\n')} />
|
||||||
</details>
|
</details>
|
||||||
))}
|
))}
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export async function GET(context: APIContext) {
|
||||||
const txtFiles = getTxtFileNames();
|
const txtFiles = getTxtFileNames();
|
||||||
|
|
||||||
const urls = [
|
const urls = [
|
||||||
...posts.map(post => `/md/${getSlug(post.id)}`),
|
...posts.map(post => `/${getSlug(post.id)}`),
|
||||||
...txtFiles.map(txt => `/${txt}`),
|
...txtFiles.map(txt => `/${txt}`),
|
||||||
...bookmarks.map(b => b.data.url),
|
...bookmarks.map(b => b.data.url),
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@ export async function GET(context: APIContext) {
|
||||||
|
|
||||||
const urls = [
|
const urls = [
|
||||||
'/',
|
'/',
|
||||||
'/md',
|
...posts.map(post => `/${getSlug(post.id)}`),
|
||||||
...posts.map(post => `/md/${getSlug(post.id)}`),
|
|
||||||
'/txt',
|
'/txt',
|
||||||
...txtFiles.map(txt => `/${txt}`),
|
...txtFiles.map(txt => `/${txt}`),
|
||||||
'/bookmarks',
|
'/bookmarks',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue