initial feed implementation

This commit is contained in:
2023-09-04 22:07:58 -07:00
parent a28ee8b2f0
commit 7fb1f05a1e
17 changed files with 243 additions and 38 deletions

View File

@@ -12,6 +12,7 @@ export async function load({ url, params, data }) {
}
catch (err) {
// throw error(404, `Not found: ${url.pathname}`);
console.log(err);
throw err;
}
}

View File

@@ -1,4 +1,3 @@
import { writable } from 'svelte/store';
import { dev } from '$app/environment';
const posts = import.meta.globEager('./*.svx');
@@ -16,6 +15,19 @@ for (const path in posts) {
postData.push(posts[path].metadata);
}
let ids = new Set();
for (const postMeta of postData) {
if (postMeta.uuid === undefined) {
throw(`Missing UUID for post: ${postMeta.title}`);
}
if (ids.has(postMeta.uuid)) {
throw(`Duplicate UUID in post: ${postMeta.title}`);
}
ids.add(postMeta.uuid);
}
postData.sort((a, b) => {
// sorting in reverse, so we flip the intuitive order
if (a.date > b.date) return -1;

View File

@@ -2,6 +2,7 @@
title: Exposing Docker Containers to your LAN
description: If, for some strange reason, you should want to do such a thing.
date: 2022-03-21
uuid: 81715fb3-990e-487e-9662-fed7b7d02943
---
<script>
import Sidenote from '$lib/Sidenote.svelte';

View File

@@ -2,6 +2,7 @@
title: The Hitchiker's Guide to Mesh VPNs
description: The golden age of VPNery is upon us.
date: 2022-03-17
uuid: fc6930ef-979c-4851-bc5a-c0e1b1698061
---
<script>
import Sidenote from '$lib/Sidenote.svelte';

View File

@@ -4,6 +4,7 @@ description: Can we replace passwords with something more user-friendly?
date: 2021-04-30
draft: true
dropcap: false
uuid: 696020b3-1513-42a8-b346-634d40f0e9d9
---
<script>
import Sidenote from '$lib/Sidenote.svelte';

View File

@@ -2,6 +2,7 @@
title: 'Languages: High and Low'
description: How high is up?
date: 2022-08-19
uuid: 89ae4194-7785-4fac-a841-8bcf5a5a3a2e
draft: true
---

View File

@@ -2,6 +2,7 @@
title: Sidenotes
description: An entirely-too-detailed dive into how I implemented sidenotes for this blog.
date: 2023-08-14
uuid: c514c46e-92f3-4078-a76b-e1dafd5f7e07
---
<script>
import Sidenote from '$lib/Sidenote.svelte';

View File

@@ -2,6 +2,7 @@
title: Let's Design A Simpler SocketIO
date: 2021-10-16
description: SocketIO is packed with features. But do we really need all of them all the time?
uuid: 95cde7e7-9293-4fab-a0b4-fc6ab7da08c8
draft: true
---

View File

@@ -2,6 +2,7 @@
title: Sufficiently Advanced Technology Is Often Distinguishable From Magic
description: I see what Arthur C. Clarke was getting at, but I don't think I agree.
date: 2022-05-14
uuid: 84636766-eb78-4060-a98d-593d8d5b55c9
draft: true
---
<script>

View File

@@ -2,6 +2,7 @@
title: Thoughts on Vue vs Svelte
description: They're more similar than they are different, but they say the most bitter enemies are those who have the fewest differences.
date: 2023-06-29
uuid: 8280f0e0-6bf5-43a2-9eac-b8c2508cca29
---
<script>
import Sidenote from '$lib/Sidenote.svelte';

View File

@@ -0,0 +1,49 @@
import { tag, text, serialize } from '$lib/xml.js';
import { postData } from '../_posts/all.js';
export function GET() {
return new Response(renderFeed(), {
headers: {'Content-Type': 'text/xml'}
});
}
function renderFeed() {
const feed = tag('feed', {xmlns: 'http://www.w3.org/2005/Atom'});
feed.addTag('id', {}, [text('https://blog.jfmonty2.com')])
feed.addTag('title', {}, [text("Joe's Blog")]);
feed.addTag('link', {href: 'https://blog.jfmonty2.com/'});
const lastUpdate = iso(postData[0].updated || postData[0].date);
feed.addTag('updated', {}, [text(lastUpdate)]);
const author = feed.addTag('author');
author.addTag('name', {}, [text('Joseph Montanaro')]);
for (const post of postData) {
const entry = feed.addTag('entry');
entry.addTag('title', {}, [text(post.title)]);
entry.addTag('link', {rel: 'alternate', href: `https://blog.jfmonty2.com/${post.slug}`});
entry.addTag('id', {}, [text(post.uuid)]);
const publishedDate = iso(post.date);
entry.addTag('published', {}, [text(publishedDate)])
const updatedDate = iso(post.updated || post.date);
entry.addTag('updated', {}, [text(updatedDate)]);
entry.addTag('content', {type: 'html'}, [text(renderDescription(post))]);
}
return serialize(feed);
}
function renderDescription(post) {
return `<p>${post.description} <a href="https://blog.jfmonty2.com/${post.slug}">Read more</a></p>`;
}
function iso(datetimeStr) {
return new Date(datetimeStr).toISOString();
}

View File

@@ -6,14 +6,13 @@
<style>
#posts {
/*text-align: center;*/
max-width: 24rem;
margin-left: auto;
margin-right: auto;
max-width: var(--content-width);
margin: 0 auto;
}
.post {
border-bottom: 2px solid #eee;
margin-top: 1rem;
hr {
margin: 2rem 0;
border-color: #eee;
}
.post-date {
@@ -38,9 +37,14 @@
text-decoration: underline;
}
h3 {
display: inline;
margin: 0;
h2 {
font-size: 1.25rem;
margin-top: 0.5rem;
margin-bottom: 0.75rem;
}
h2 a {
color: currentcolor;
}
</style>
@@ -50,18 +54,22 @@
<div id="posts">
<h1 style:text-align="center">All Posts</h1>
{#each postData as post}
{#each postData as post, idx}
<div class="post">
<div class="post-date">{new Date(post.date).toISOString().split('T')[0]}</div>
<div>
<h2>
<a data-sveltekit-preload-data="hover" class="post-link" href="/{post.slug}">
<h3>{post.title}<h3>
{post.title}
</a>
{#if post.draft}
<span class="draft-notice">Draft</span>
{/if}
</div>
</h2>
<p>{post.description}</p>
</div>
{#if idx < postData.length - 1}
<hr>
{/if}
{/each}
</div>