const NAMED_ENTITIES: Readonly> = { amp: "&", apos: "'", gt: ">", lt: "<", nbsp: " ", quot: "\"", }; function decodeCodePoint(codePoint: number, fallback: string): string { return Number.isInteger(codePoint) && codePoint >= 0 && codePoint <= 0x10ffff ? String.fromCodePoint(codePoint) : fallback; } export function decodeHtmlEntities(value: string): string { return value.replace(/&(#x[0-9a-f]+|#[0-9]+|[a-z][a-z0-9]+);?/gi, (match, entity: string) => { const normalized = entity.toLowerCase(); if (normalized.startsWith("#x")) { return decodeCodePoint(Number.parseInt(normalized.slice(2), 16), match); } if (normalized.startsWith("#")) { return decodeCodePoint(Number.parseInt(normalized.slice(1), 10), match); } return NAMED_ENTITIES[normalized] ?? match; }); }