/** * Feed parser dispatcher * @module feeds/parser */ import { parseAtom } from "./atom.js"; import { parseHfeed } from "./hfeed.js"; import { parseJsonFeed } from "./jsonfeed.js"; import { parseRss } from "./rss.js"; /** * Detect feed type from content * @param {string} content - Feed content * @param {string} contentType - HTTP Content-Type header * @returns {string} Feed type: 'rss' | 'atom' | 'jsonfeed' | 'hfeed' | 'unknown' */ export function detectFeedType(content, contentType = "") { const ct = contentType.toLowerCase(); // Check Content-Type header first if (ct.includes("application/json") || ct.includes("application/feed+json")) { return "jsonfeed"; } if (ct.includes("application/atom+xml")) { return "atom"; } if ( ct.includes("application/rss+xml") || ct.includes("application/xml") || ct.includes("text/xml") ) { // Need to check content to distinguish RSS from Atom const trimmed = content.trim(); if ( trimmed.includes("} Parsed feed with metadata and items */ export async function parseFeed(content, feedUrl, options = {}) { const feedType = detectFeedType(content, options.contentType); switch (feedType) { case "rss": { return parseRss(content, feedUrl); } case "atom": { return parseAtom(content, feedUrl); } case "jsonfeed": { return parseJsonFeed(content, feedUrl); } case "hfeed": { return parseHfeed(content, feedUrl); } case "activitypub": { throw new Error( `URL returns ActivityPub JSON instead of a feed. Try the direct feed URL (e.g., ${feedUrl}feed/)`, ); } default: { throw new Error(`Unable to detect feed type for ${feedUrl}`); } } } export { parseAtom } from "./atom.js"; export { parseHfeed } from "./hfeed.js"; export { parseJsonFeed } from "./jsonfeed.js"; export { parseRss } from "./rss.js";