import type { CollectionRSS } from '../@types/astro'; import parser from 'fast-xml-parser'; import { canonicalURL } from './util.js'; /** Validates createCollection.rss */ export function validateRSS(rss: CollectionRSS, filename: string): void { if (!rss.title) throw new Error(`[${filename}] rss.title required`); if (!rss.description) throw new Error(`[${filename}] rss.description required`); if (typeof rss.item !== 'function') throw new Error(`[${filename}] rss.item() function required`); } /** Generate RSS 2.0 feed */ export function generateRSS(input: { data: T[]; site: string } & CollectionRSS, filename: string): string { let xml = ``; xml += ``; // title, description, customData xml += `<![CDATA[${input.title}]]>`; xml += ``; xml += `${canonicalURL('/feed/' + filename + '.xml', input.site)}`; if (typeof input.customData === 'string') xml += input.customData; // items if (!Array.isArray(input.data) || !input.data.length) throw new Error(`[${filename}] data() returned no items. Can’t generate RSS feed.`); for (const item of input.data) { xml += ``; const result = input.item(item); // validate if (typeof result !== 'object') throw new Error(`[${filename}] rss.item() expected to return an object, returned ${typeof result}.`); if (!result.title) throw new Error(`[${filename}] rss.item() returned object but required "title" is missing.`); if (!result.link) throw new Error(`[${filename}] rss.item() returned object but required "link" is missing.`); xml += `<![CDATA[${result.title}]]>`; xml += `${canonicalURL(result.link, input.site)}`; if (result.description) xml += ``; if (result.pubDate) { // note: this should be a Date, but if user provided a string or number, we can work with that, too. if (typeof result.pubDate === 'number' || typeof result.pubDate === 'string') { result.pubDate = new Date(result.pubDate); } else if (result.pubDate instanceof Date === false) { throw new Error('[${filename}] rss.item().pubDate must be a Date'); } xml += `${result.pubDate.toUTCString()}`; } if (typeof result.customData === 'string') xml += result.customData; xml += ``; } xml += ``; // validate user’s inputs to see if it’s valid XML const isValid = parser.validate(xml); if (isValid !== true) { // If valid XML, isValid will be `true`. Otherwise, this will be an error object. Throw. throw new Error(isValid as any); } return xml; }