import fs from 'node:fs/promises'; import { Feed } from 'feed'; import marked from 'marked'; import type { Translations } from '~/locale/translations.ts'; import { getPosts } from '~/server/blog.ts'; import { loadSuml, loadSumlFromBase } from '~/server/loader.ts'; import { rootDir } from '~/server/paths.ts'; import parseMarkdown from '~/src/parseMarkdown.ts'; import { Translator } from '~/src/translator.ts'; const config = global.config; const translations = loadSuml('translations') as Translations; const baseTranslations = loadSumlFromBase('locale/_base/translations') as Translations; const translator = new Translator(translations, baseTranslations, config); export default defineCachedEventHandler(async () => { const runtimeConfig = useRuntimeConfig(); const posts = await getPosts(); const feed = new Feed({ title: `${translator.translate('title')} • ${translator.translate('links.blog')}`, description: translator.translate('description'), id: runtimeConfig.public.baseUrl, link: `${runtimeConfig.public.baseUrl}/blog.atom`, language: config.locale, image: `${runtimeConfig.public.baseUrl}/icon.png`, favicon: `${runtimeConfig.public.baseUrl}/icon.png`, updated: new Date(posts[0].date), copyright: '', }); for (const post of posts) { const markdownContent = await fs.readFile(`${rootDir}/data/blog/${post.slug}.md`, 'utf-8'); const markdown = marked(markdownContent); const parsed = await parseMarkdown(markdown, translator); feed.addItem({ title: post.title, id: `${runtimeConfig.public.baseUrl}/${config.links.blogRoute}/${post.slug}`, link: `${runtimeConfig.public.baseUrl}/${config.links.blogRoute}/${post.slug}`, description: parsed.intro ?? undefined, content: parsed.content ?? undefined, author: post.authors.map((author) => ({ name: author, link: author.startsWith('@') ? `${runtimeConfig.public.baseUrl}/${author}` : undefined, })), date: new Date(post.date), image: post.hero ? `${runtimeConfig.public.baseUrl}${post.hero.src}` : undefined, }); } return new Response(feed.atom1(), { headers: { 'Content-Type': 'application/rss+xml; charset=utf-8', }, }); }, { maxAge: Infinity, });