v0.18.13 - Empty non-void HTML elements inside <foreignObject> are serialized as XML self-closing (<div/>)
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 68/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Tranquilo
- Stack tecnológico
- html, node.js
- Área
- web-dev
Línea de trabajo
Comienza con la reproducción proporcionada de parseHTML y sigue document.body.innerHTML a través de la serialización, centrándote en el manejo de namespaces en foreignObject. Confirma que los elementos HTML que no son void usan etiquetas de cierre explícitas, mientras que los elementos HTML void enumerados pueden autocerrarse, y verifica después que el resultado serializado haga round-trip sin tragarse el contenido de los elementos hermanos.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Empty non-void HTML elements inside <foreignObject> are serialized as XML self-closing (<div/>), producing invalid HTML that swallows following content
Summary
When an empty HTML element (e.g. <div>, <p>, <span>) appears inside an SVG <foreignObject>, parseHTML(...).document.toString() / .innerHTML serializes it using XML self-closing syntax (<div/>) instead of an explicit start/end tag pair (<div></div>).
Per the HTML standard, the self-closing slash is ignored on non-void HTML elements, so <div/> is parsed as an open <div>. Because <foreignObject> is an HTML integration point (its subtree is parsed as HTML, not SVG), this output is invalid: when a spec-compliant HTML parser (i.e. any browser) re-parses it, the unclosed <div> swallows every following sibling — the rest of the <foreignObject>, the rest of the <svg>, and all content after it.
The result is that a serialized document round-tripped through linkedom renders blank / severely mis-nested in a browser.
Environment
- linkedom: 0.18.13
- Node: v22.16.0
Minimal reproduction
const { parseHTML } = require('linkedom');
const input = '<svg><foreignObject><div></div></foreignObject></svg>';
const { document } = parseHTML('<!DOCTYPE html><html><body>' + input + '</body></html>');
console.log(document.body.innerHTML);
Actual output
<svg><foreignobject><div /></foreignobject></svg>
Expected output
<svg><foreignObject><div></div></foreignObject></svg>
<div> is a non-void HTML element and must be serialized as <div></div>. (foreignObject should also retain its camelCase — see note below.)
Scope / characterization
Only empty non-void elements in an SVG/foreignObject context are affected:
| Input | Output | Correct? |
|---|---|---|
<svg><foreignObject><div></div></foreignObject></svg> |
<div /> |
❌ self-closed |
<svg><foreignObject><p></p></foreignObject></svg> |
<p /> |
❌ self-closed |
<svg><foreignObject><div>hi</div></foreignObject></svg> |
<div>hi</div> |
✅ (non-empty) |
<div></div> (plain HTML) |
<div></div> |
✅ (outside SVG) |
So the trigger is: an empty element serialized while it is (incorrectly) treated as being in the XML/SVG namespace, even though <foreignObject> switches its subtree back to the HTML namespace.
Why it matters
<div/> is not equivalent to <div></div> in HTML. Given sibling content:
parseHTML('<!DOCTYPE html><body><svg><foreignObject><div></div><span>X</span></foreignObject></svg>')
.document.body.innerHTML
// => <svg><foreignobject><div /><span>X</span></foreignobject></svg>
linkedom keeps <span> as a sibling internally, but the emitted string is not round-trippable: a browser parsing <div /><span>X</span> inside a foreignObject nests <span> (and everything after) inside the <div>. Real-world impact: serializing a captured page that contains an inline SVG icon built with <foreignObject><div .../></foreignObject> (common on e.g. google.com) makes the whole page render blank.
Suggested fix
Elements inside a <foreignObject> are in the HTML namespace and should follow HTML serialization rules: only the HTML void elements (area, base, br, col, embed, hr, img, input, link, meta, param, source, track, wbr) may be self-closed; all other elements must be serialized with an explicit end tag.
- Lenguaje dominante
- HTML
- Estrellas
- 2.1k
- Forks
- 108
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de WebReflection/linkedom
-
`el.style.property = ''` and `e.style.setProperty('property', '')` should delete the propertyAbierto
Dificultad 3/5 1-2 días Aptitud para principiantes 52/100
WebReflection/linkedom#327 · 1 comentario ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 48/100
WebReflection/linkedom#326 · 5 comentarios ·
-
Build Apps For AI Agent.Abierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 15/100
WebReflection/linkedom#321 · 1 comentario ·
-
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
WebReflection/linkedom#318 · 6 comentarios ·
-
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
WebReflection/linkedom#317 · 2 reacciones ·
Todos los issues de WebReflection/linkedom
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 88/100
openedx/frontend-app-authoring#3274 ·
Los mantenedores suelen responder en 1 día
-
Unconfirmed bug
Dificultad 1/5 Menos de una hora Aptitud para principiantes 88/100
luanti-org/luanti#17605 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
microsoft/fluentui-blazor#5364 ·
Los mantenedores suelen responder en 1 día
-
COLEAD websiteAbiertoneeds-triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
wagtail/madewithwagtail#236 · 1 comentario ·
Los mantenedores suelen responder en 4 días
-
Design only Leadership Survey SLFS
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
bcgov/digital-journeys#2293 ·