/**
* Reduziert HTML aus Übungs-Kurztexten auf eine kleine erlaubte Menge von Tags (ohne Attribute).
* Für Anzeige mit dangerouslySetInnerHTML.
*/
const ALLOWED_TAGS = new Set(['b', 'strong', 'i', 'em', 'br', 'p', 'span', 'ul', 'ol', 'li'])
function cleanTree(parent) {
const nodes = Array.from(parent.childNodes)
for (const node of nodes) {
if (node.nodeType === Node.TEXT_NODE) continue
if (node.nodeType !== Node.ELEMENT_NODE) {
parent.removeChild(node)
continue
}
const tag = node.tagName.toLowerCase()
if (!ALLOWED_TAGS.has(tag)) {
while (node.firstChild) {
parent.insertBefore(node.firstChild, node)
}
parent.removeChild(node)
continue
}
while (node.attributes.length > 0) {
node.removeAttribute(node.attributes[0].name)
}
cleanTree(node)
}
}
export function sanitizeExerciseRichText(html) {
if (html == null || typeof html !== 'string') return ''
const trimmed = html.trim()
if (!trimmed) return ''
const tpl = document.createElement('template')
tpl.innerHTML = trimmed
cleanTree(tpl.content)
return tpl.innerHTML
}
export function coerceApiNameList(value) {
if (Array.isArray(value)) return value.map(String).filter((s) => s.trim())
if (typeof value === 'string') {
try {
const p = JSON.parse(value)
if (Array.isArray(p)) return p.map(String).filter((s) => s.trim())
} catch {
return []
}
}
return []
}