const ENTITIES: Record = { '&': '&', '<': '<', '>': '>', '"': '"', ''': "'", ''': "'", ' ': '\u00A0', '©': '©', '®': '®', '™': '™', '—': '—', '–': '–', '‘': '\u2018', '’': '\u2019', '“': '\u201C', '”': '\u201D', '…': '…', '•': '•', '·': '·', '¶': '¶', '§': '§', '†': '†', '‡': '‡', '‰': '‰', '′': '′', '″': '″', '«': '«', '»': '»', '‹': '‹', '›': '›', '¢': '¢', '£': '£', '¥': '¥', '€': '€', '¤': '¤', '×': '×', '÷': '÷', '±': '±', '−': '−', '≤': '≤', '≥': '≥', '≠': '≠', '≈': '≈', '≡': '≡', '∑': '∑', '∏': '∏', '√': '√', '∞': '∞', '∫': '∫', '∂': '∂', '∇': '∇', '∈': '∈', '∉': '∉', '∋': '∋', '⊂': '⊂', '⊃': '⊃', '⊆': '⊆', '⊇': '⊇', '∪': '∪', '∩': '∩', '∅': '∅', '∀': '∀', '∃': '∃', '∧': '∧', '∨': '∨', '¬': '¬', '∠': '∠', '⊥': '⊥', '∴': '∴', '∼': '∼', '≅': '≅', '∝': '∝', '°': '°', '¼': '¼', '½': '½', '¾': '¾', '¹': '¹', '²': '²', '³': '³', 'µ': 'µ', '←': '←', '↑': '↑', '→': '→', '↓': '↓', '↔': '↔', '⇐': '⇐', '⇑': '⇑', '⇒': '⇒', '⇓': '⇓', '⇔': '⇔', 'Α': 'Α', 'α': 'α', 'Β': 'Β', 'β': 'β', 'Γ': 'Γ', 'γ': 'γ', 'Δ': 'Δ', 'δ': 'δ', 'Ε': 'Ε', 'ε': 'ε', 'Ζ': 'Ζ', 'ζ': 'ζ', 'Η': 'Η', 'η': 'η', 'Θ': 'Θ', 'θ': 'θ', 'Ι': 'Ι', 'ι': 'ι', 'Κ': 'Κ', 'κ': 'κ', 'Λ': 'Λ', 'λ': 'λ', 'Μ': 'Μ', 'μ': 'μ', 'Ν': 'Ν', 'ν': 'ν', 'Ξ': 'Ξ', 'ξ': 'ξ', 'Ο': 'Ο', 'ο': 'ο', 'Π': 'Π', 'π': 'π', 'Ρ': 'Ρ', 'ρ': 'ρ', 'Σ': 'Σ', 'σ': 'σ', 'ς': 'ς', 'Τ': 'Τ', 'τ': 'τ', 'Υ': 'Υ', 'υ': 'υ', 'Φ': 'Φ', 'φ': 'φ', 'Χ': 'Χ', 'χ': 'χ', 'Ψ': 'Ψ', 'ψ': 'ψ', 'Ω': 'Ω', 'ω': 'ω', '¡': '¡', '¿': '¿', 'ª': 'ª', 'º': 'º', '´': '´', '¸': '¸', '¨': '¨', '¯': '¯', '­': '\u00AD', '¦': '¦', '♠': '♠', '♣': '♣', '♥': '♥', '♦': '♦', '◊': '◊', '‍': '\u200D', '‌': '\u200C', }; export function decodeEntities(text: string): string { return text .replace(/&[a-zA-Z][a-zA-Z0-9]*;/g, m => ENTITIES[m] ?? m) .replace(/&#(\d+);/g, (_, n) => { const code = parseInt(n, 10); return code > 0 && code <= 0x10FFFF ? String.fromCodePoint(code) : ''; }) .replace(/&#x([0-9a-fA-F]+);/g, (_, n) => { const code = parseInt(n, 16); return code > 0 && code <= 0x10FFFF ? String.fromCodePoint(code) : ''; }); } export function escapeHtml(text: string): string { return text.replace(/&/g, '&').replace(//g, '>'); } export function escapeAttr(text: string): string { return text.replace(/&/g, '&').replace(/"/g, '"').replace(//g, '>'); }