Skip to content

Commit

Permalink
Added RSS feed route and links.
Browse files Browse the repository at this point in the history
  • Loading branch information
corigne committed Jul 31, 2024
1 parent 525da42 commit 679874d
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 9 deletions.
2 changes: 1 addition & 1 deletion frontend/src/lib/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import { dev } from "$app/environment";

export const title = "njodoin::devlog";
export const description = "devlog and resume site made with SvelteKit";
export const url = dev ? "http://localhost:5173/" : "https://dev.misfits.rip";
export const url = dev ? "http://localhost:5173" : "https://jodoin.io";
14 changes: 8 additions & 6 deletions frontend/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
<svelte:head>
<script lang="ts">
import Footer from "./components/Footer.svelte"
import Header from "./components/Header.svelte"
import '../app.css'
import { url } from '../lib/config'
</script>

<svelte:head>
<link rel="alternate" type="application/rss+xml" title="Subscribe to the jodoin.io RSS Feed!" href={`${url}/rss.xml`} />
<script>
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
Expand All @@ -19,11 +26,6 @@

</svelte:head>

<script lang="ts">
import Footer from "./components/Footer.svelte"
import Header from "./components/Header.svelte"
import '../app.css'
</script>

<div class="flex flex-col h-screen items-center overflow-scroll">
<Header />
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/routes/api/posts/+server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ async function getPosts():Promise<BlogPost[]> {

export async function GET() {
const posts = await getPosts()
return json(posts)
return json(posts.filter((post) => post.published))
}
2 changes: 1 addition & 1 deletion frontend/src/routes/components/Header.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import ThemeToggle from './ThemeToggle.svelte';
<a href="/contact">contact</a>
</li>
<li>
<a href="/" >rss</a>
<a href={`${config.url}/rss.xml`} target="_blank">rss</a>
</li>
</ul>

Expand Down
63 changes: 63 additions & 0 deletions frontend/src/routes/rss.xml/+server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import type { BlogPost } from "$lib/types";
import * as config from "$lib/config"

async function getPosts():Promise<BlogPost[]> {
const posts: BlogPost[] = []

const paths = import.meta.glob('/src/blogposts/*.md', { eager: true })

for (const path in paths) {
const file = paths[path]
const slug = path.split('/').at(-1)?.replace('.md', '') as string
if (file && typeof file === 'object' && 'metadata' in file) {
const metadata = file.metadata as Omit<BlogPost, 'slug'>
const post = { ...metadata, slug } satisfies BlogPost
metadata.published && posts.push(post)
}
}
posts.sort((a: BlogPost, b:BlogPost) => new Date(a.date).getTime() - new Date(b.date).getTime())
return posts
}

const render = (posts: BlogPost[]) => {
const body = `<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<atom:link rel="self" href="${config.url}/rss.xml"/>
<title>Nathan Jodoin's Devlog</title>
<link>${config.url}</link>
<description>Nathan Jodoin's blog, with topics including software,
computer science, and random thoughts.</description>
${
posts.map( (post) => {
(post.published)
?
`<item>
<guid>${config.url}/blog/${post.slug}</guid>
<title>${post.title}</title>
<link>${config.url}/blog/${post.slug}</link>
<description>${post.description}</description>
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
</item>`
: ''
}).join('')
}
</channel>
</rss>
`
return body
}

export async function GET(): Promise<Response> {
const posts = await getPosts()
const body = render(posts);
const headers = {
'Cache-Control': `max-age=0, s-max-age=${600}`,
'Content-Type': 'application/xml'
};
const response = new Response(body)
for (let [key, value] of Object.entries(headers)) {
response.headers.set(key, value)
}
return response;
}

0 comments on commit 679874d

Please sign in to comment.