import { decodeHtmlEntities } from "../../../../../utils/html-entities";
export interface FeedElement {
name: string;
localName: string;
namespace: string;
namespaces: Record;
attributes: Record;
base: string;
content: (FeedElement | string)[];
innerStart: number;
innerEnd: number;
}
export function resolveFeedUrl(value: string, base: string): string {
if (!value.trim()) return "";
try { return new URL(value.trim(), base).href; } catch { return ""; }
}
// Read the structure of a syndication document without executing declarations or
// resolving entities. Descendant source/content metadata must not impersonate
// an entry's direct children. This is deliberately not a validating XML parser.
export function parseFeedXml(xml: string, base: string): FeedElement | null {
const tokens = /"'\[]|"[^"]*"|'[^']*')*>|||<\?[\s\S]*?\?>|<\/?[A-Za-z_][\w.:-]*(?:[^<>"']|"[^"]*"|'[^']*')*>|[^<]+/g;
const stack: FeedElement[] = [];
let root: FeedElement | null = null;
let offset = 0;
for (const match of xml.matchAll(tokens)) {
if (match.index !== offset) return null;
const token = match[0];
offset += token.length;
if (token.startsWith("