Skip to content

Instantly share code, notes, and snippets.

@NotNite
Created September 25, 2024 21:13
Show Gist options
  • Save NotNite/dedfa28a26f8b3ceb482c230d90ad2c6 to your computer and use it in GitHub Desktop.
Save NotNite/dedfa28a26f8b3ceb482c230d90ad2c6 to your computer and use it in GitHub Desktop.
Astro Container RSS rendering
import rss, { type RSSFeedItem } from "@astrojs/rss";
import { getCollection } from "astro:content";
import type { APIContext } from "astro";
import { getContainerRenderer } from "@astrojs/mdx";
import { loadRenderers } from "astro:container";
import { experimental_AstroContainer as AstroContainer } from "astro/container";
import { transform, walk } from "ultrahtml";
import sanitize from "ultrahtml/transformers/sanitize";
import { getBaseURL } from "@/utils";
import RSSRenderer from "@/components/RSSRenderer.astro";
export async function fixLinks(html: string, baseUrl: string) {
return await transform(html, [
async (node) => {
await walk(node, (node) => {
if (node.name === "a" && node.attributes.href?.startsWith("/")) {
node.attributes.href = baseUrl + node.attributes.href;
}
if (node.name === "img" && node.attributes.src?.startsWith("/")) {
node.attributes.src = baseUrl + node.attributes.src;
}
});
return node;
},
sanitize({ dropElements: ["script", "style"] })
]);
}
export async function GET(context: APIContext) {
const baseUrl = getBaseURL(context);
const blog = await getCollection("blog");
const items: RSSFeedItem[] = [];
const renderers = await loadRenderers([getContainerRenderer()]);
const container = await AstroContainer.create({
renderers
});
for (const post of blog) {
let html = await container.renderToString(RSSRenderer, {
params: { slug: post.slug }
});
html = await fixLinks(html, baseUrl);
items.push({
title: post.data.title,
description: post.data.description,
pubDate: post.data.date,
link: baseUrl + `/blog/${post.slug}`,
content: html
});
}
return await rss({
title: "notnite's blog",
description: "My ramblings assembled into one tidy place",
site: context.site!,
items
});
}
---
import type { ValidContentEntrySlug } from "astro:content";
import { getEntry } from "astro:content";
const { slug } = Astro.params;
const entry = await getEntry("blog", slug as ValidContentEntrySlug<"blog">);
const { Content } = await entry.render();
---
<Content />
import type { APIContext } from "astro";
export function getBaseURL(context?: APIContext) {
let baseUrl = import.meta.env.PROD
? import.meta.env.SITE
: (context?.url?.origin ?? "http://localhost:4321");
if (baseUrl.at(-1) === "/") baseUrl = baseUrl.slice(0, -1);
return baseUrl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment