Parsing splits one text run into several Text nodes at each character reference (`<p>a & b</p>` gives 3 child nodes)
Les mainteneurs répondent en général sous 5 jours
Évaluation
- Difficulté
- 2/5
- Temps estimé
- 1-3 heures
- Accessibilité débutants
- 68/100
- Type d'issue
- Bug
- Clarté
- Plutôt claire
- Activité
- Active
- Stack technique
- html, javascript
Piste de recherche
Commence par le gestionnaire ontext dans esm/shared/parse-from-string.js, qui, selon l’issue, ajoute un nœud Text pour chaque callback du parseur. Compare son comportement avec celui de DomHandler de htmlparser2, puis ajoute un test de régression pour du balisage contenant des références de caractères. Le travail est terminé lorsque l’analyse de l’exemple produit un nœud Text avec les données "a & b" et que la couverture existante reste à 100 %.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Description
Parsing <p>a & b</p> gives the <p> three Text nodes ("a ", "&", " b"). The HTML parsing algorithm appends each character to the previous Text node, and jsdom gives one Text node, "a & b". Code that walks childNodes and treats each Text node as one run sees extra runs wherever the source has an entity. normalize() merges them afterwards, but every consumer of parsed output has to know to call it on every subtree, and a spec parser never produces the split in the first place ("insert a character": https://html.spec.whatwg.org/multipage/parsing.html#insert-a-character).
Asks:
- Should the parser merge text into the previous Text node when the previous sibling under the same parent is a Text node, as the HTML parsing algorithm does?
- If yes, I can open a PR that changes
esm/only, with a test, keeping coverage at 100%.
Environment: linkedom 0.18.14 (npm, latest) and main at e2ee208, htmlparser2 10.1.0, Node 24.14.1, macOS.
Test case:
import { DOMParser } from 'linkedom'
const doc = new DOMParser().parseFromString('<!doctype html><html><body><p>a & b</p></body></html>', 'text/html')
const p = doc.querySelector('p')
console.log('textContent:', JSON.stringify(p.textContent))
console.log('childNodes.length:', p.childNodes.length)
console.log('childNodes data:', JSON.stringify([...p.childNodes].map((n) => n.data)))
Output:
textContent: "a & b"
childNodes.length: 3
childNodes data: ["a ","&"," b"]
Expected: childNodes.length: 1, data ["a & b"] (what jsdom 29.1.1 returns for the same markup).
| Input | linkedom Text nodes | jsdom Text nodes |
|---|---|---|
<p>a and b</p> |
1 | 1 |
<p>a & b</p> |
3 | 1 |
<p>x < y > z ©</p> |
6 | 1 |
parseHTML gives the same result as DOMParser (3 nodes for <p>a & b</p>).
Raw output (npm 0.18.14, main e2ee208, variants, htmlparser2)
$ node repro.mjs # linkedom 0.18.14 from npm
textContent: "a & b"
childNodes.length: 3
childNodes data: ["a ","&"," b"]
$ node repro-main.mjs # main e2ee208 esm/
textContent: "a & b"
childNodes.length: 3
childNodes data: ["a ","&"," b"]
$ node variants.mjs
no entity: 1 ["a and b"]
&: 3 ["a ","&"," b"]
< > ©: 6 ["x ","<"," y ",">"," z ","©"]
parseHTML: 3
$ node htmlparser2-ontext.mjs # htmlparser2 10.1.0, decodeEntities: true
htmlparser2 ontext calls: ["a ","&"," b"]
$ node jsdom-control.mjs
jsdom childNodes.length: 1 ["a & b"]
Where it comes from: htmlparser2 with decodeEntities: true calls ontext once per piece around each character reference. The ontext handler in parseFromString appends a new Text node for every call:
htmlparser2's own DomHandler merges each ontext piece into the previous Text node (domhandler 5.0.3, lib/index.js, ontext), so with the same callbacks it yields one node for <p>a & b</p>.
No existing issue found for this; the closest are #62 and #71, which are about serializing entities, not the node split.
- Langage dominant
- HTML
- Étoiles
- 2.1k
- Forks
- 117
- Merge moyen
- 4 j 13 h
- PR mergées (30 j)
- 2
Préparer son environnement
Ce projet ne fournit ni conteneur de développement, ni Dockerfile, ni guide de contribution : l'installation est à votre charge. Commencez par son README, et consultez notre guide de la première contribution pour les étapes générales.
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Autres issues de WebReflection/linkedom
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
WebReflection/linkedom#365 ·
Les mainteneurs répondent en général sous 5 jours
-
SVG elements in an HTML document report an upper-cased tagName ("PATH" instead of "path")Peut-être pris @jonasporto l’a pris il y a 9 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 85/100
WebReflection/linkedom#344 · 1 commentaire ·
Les mainteneurs répondent en général sous 5 jours
-
`TextElement.toString()` puts the element text back at the first `><` of the start tag, so an attribute value containing `><` swallows the text of `<style>`, `<script>`, `<title>` and `<textarea>`Peut-être pris @vsolano9 l’a pris il y a 22 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
WebReflection/linkedom#341 · 1 commentaire ·
Les mainteneurs répondent en général sous 5 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 82/100
WebReflection/linkedom#340 · 1 commentaire ·
Les mainteneurs répondent en général sous 5 jours
-
Element#matches() compiles the selector on every callPeut-être pris @jonasporto l’a pris il y a 22 jours. Ouverte
Difficulté 2/5 1-3 heures Accessibilité débutants 35/100
WebReflection/linkedom#348 · 1 commentaire ·
Les mainteneurs répondent en général sous 5 jours
Toutes les issues de WebReflection/linkedom
Issues similaires
-
`Time.at(t, in: nil)` returns UTC instead of the local time (or the time zone of `t`), unlike CRubyOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
PageParameters.hashCode is inconsistent with equals for named parameters in a different orderOuverte
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
Les mainteneurs répondent en général sous 1 jour
-
bug implicit-state
Difficulté 2/5 1-3 heures Accessibilité débutants 78/100
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100
PecanProject/sipnet#435 · 1 commentaire ·
Les mainteneurs répondent en général sous 2 jours
-
Difficulté 2/5 1-3 heures Accessibilité débutants 68/100