Portfolio/server/routes/rss.xml.get.ts
2026-09-08 19:54:06 +02:00

45 lines
1.5 KiB
TypeScript

import { listPosts } from '~~/server/utils/posts'
import { getSiteData } from '~~/server/utils/site'
const escape = (s: string) =>
s.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
export default defineEventHandler(async (event) => {
const base = useRuntimeConfig().public.siteUrl.replace(/\/+$/, '')
const posts = (await listPosts()).filter((p) => !p.draft).slice(0, 30)
const site = await getSiteData()
const items = posts
.map(
(post) => ` <item>
<title>${escape(post.title)}</title>
<link>${base}/blog/${post.slug}</link>
<guid isPermaLink="true">${base}/blog/${post.slug}</guid>
<pubDate>${new Date(post.date).toUTCString()}</pubDate>
<description>${escape(post.description)}</description>
${post.tags.map((t) => ` <category>${escape(t)}</category>`).join('\n')}
</item>`,
)
.join('\n')
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>${escape(site.domain)}</title>
<link>${base}</link>
<description>${escape(site.description)}</description>
<language>en</language>
<lastBuildDate>${new Date().toUTCString()}</lastBuildDate>
<atom:link href="${base}/rss.xml" rel="self" type="application/rss+xml"/>
${items}
</channel>
</rss>`
setHeader(event, 'content-type', 'application/rss+xml; charset=utf-8')
setHeader(event, 'cache-control', 'public, max-age=600')
return xml
})