import { d as list } from "./store-D_2h-weW.js";
//#region src/feed.ts
function escapeXml(s) {
	return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
}
function entryUrl(siteUrl, e) {
	return `${siteUrl.replace(/\/+$/, "")}/${e.type}/${e.slug}`;
}
function publishedOnly(entries) {
	return entries.filter((e) => e.status === "published" && e.publishedAt !== null).sort((a, b) => b.publishedAt.getTime() - a.publishedAt.getTime());
}
/** Pure projection of PUBLISHED entries to RSS 2.0 or JSON Feed 1.1. No deps, no I/O. */
function toFeed(entries, format, meta) {
	const items = publishedOnly(entries);
	if (format === "json") return JSON.stringify({
		version: "https://jsonfeed.org/version/1.1",
		title: meta.title,
		home_page_url: meta.siteUrl,
		feed_url: meta.feedUrl,
		...meta.description ? { description: meta.description } : {},
		items: items.map((e) => ({
			id: entryUrl(meta.siteUrl, e),
			url: entryUrl(meta.siteUrl, e),
			title: e.title,
			content_html: e.body,
			date_published: e.publishedAt.toISOString(),
			...e.terms.filter((t) => t.taxonomy === "tag").map((t) => t.slug).length ? { tags: e.terms.filter((t) => t.taxonomy === "tag").map((t) => t.slug) } : {}
		}))
	});
	const itemsXml = items.map((e) => {
		const url = entryUrl(meta.siteUrl, e);
		return [
			"    <item>",
			`      <title>${escapeXml(e.title)}</title>`,
			`      <link>${escapeXml(url)}</link>`,
			`      <guid isPermaLink="true">${escapeXml(url)}</guid>`,
			`      <pubDate>${e.publishedAt.toUTCString()}</pubDate>`,
			`      <description>${escapeXml(e.body)}</description>`,
			"    </item>"
		].join("\n");
	}).join("\n");
	return [
		"<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
		"<rss version=\"2.0\">",
		"  <channel>",
		`    <title>${escapeXml(meta.title)}</title>`,
		`    <link>${escapeXml(meta.siteUrl)}</link>`,
		`    <description>${escapeXml(meta.description ?? meta.title)}</description>`,
		itemsXml,
		"  </channel>",
		"</rss>"
	].filter((line) => line !== "").join("\n");
}
/**
* Safe-by-construction public feed (visibility spec §3.1). Lists with the ANONYMOUS
* viewer (`null`) then formats — so the ONLY entries it can ever syndicate are the
* published+public anonymous-floor set. Use this for any public syndication route:
* it has no viewer arg to get wrong, making the read-floor STRUCTURAL not disciplinary.
* (`toFeed` remains for adopters who already hold an anonymous-listed array.)
*/
async function feedFrom(db, query, format, meta, opts) {
	return toFeed(await list(db, query, null, opts), format, meta);
}
//#endregion
export { feedFrom, toFeed };
