DOM Manipulation
Relevant source files
The following files were used as context for generating this wiki page:
DOM manipulation within htmlparser2 is achieved through the integration of several specialized modules. While the core Parser provides a low-level callback interface for efficient stream processing, it works in tandem with domhandler to construct a Document Object Model (DOM) tree. Once a DOM tree is produced, developers use the domutils module to search, modify, and serialize the structure back into HTML.
The library is designed for speed and flexibility, offering a "forgiving" approach to HTML parsing that handles malformed markup, implicit tag closing, and foreign contexts like SVG and MathML. It serves as the foundation for higher-level libraries such as Cheerio, which provides a jQuery-like API for DOM manipulation.
Sources: README.md:1-25, package.json:52-56, src/index.ts:32-40
DOM Construction Architecture
The process of creating a DOM starts with the Parser translating raw text into events, which are then consumed by a DomHandler. The resulting DOM tree consists of nodes defined by the domhandler package (e.g., Document, Element).
The flow of data from raw HTML input to a structured DOM tree available for manipulation.
Sources: src/index.ts:37-43, README.md:95-110
Core API Methods for DOM Generation
The project exports specific helper methods to streamline the creation of DOM structures from strings or streams.
| Method | Description | Return Type |
|---|---|---|
parseDocument(data, options) | Parses a string and returns a complete DOM tree. | Document |
createDocumentStream(callback, options) | Creates a parser instance attached to a DOM handler for streaming data. | Parser |
Sources: src/index.ts:37-67, src/index.spec.ts:30-47
DOM Searching and Querying
The library re-exports DomUtils, which provides essential functions for traversing and searching the DOM tree. For more complex queries, the ecosystem includes css-select for CSS selector support.
Key Query Functions
getElementById(id, dom): Locates a single element by its ID attribute.getElementsByTagName(name, dom): Returns an array of elements matching a specific tag name.findAll(test, dom): Finds all elements that satisfy a custom boolean test function.textContent(node): Extracts all text content from a node and its descendants.
Sources: README.md:120-143, src/index.ts:101
Sequence of retrieving text content from a DOM node using DomUtils.
Sources: README.md:139-140, src/Parser.ts:279-285
Modifying the Tree
DomUtils allows for direct structural changes to the DOM tree. These modifications are reflected in the node references maintained by the DomHandler.
Manipulation Operations
| Operation | Description |
|---|---|
removeElement(el) | Removes the specified element from the DOM tree. |
appendChild(parent, child) | Adds a node to the end of the parent's children list. |
prependChild(parent, child) | Adds a node to the beginning of the parent's children list. |
replaceElement(oldEl, newEl) | Replaces an existing element with a new one. |
Sources: README.md:158-175, src/index.ts:101
Parsing Special Contexts
The Parser handles DOM manipulation logic during the parsing phase, particularly regarding tag relationships and auto-closing. This logic is governed by predefined sets such as voidElements and openImpliesClose.
Implicit Closing Logic
In HTML mode, certain tags implicitly close others to maintain a valid DOM structure as defined by the spec.
- Table Sections:
<tbody>auto-closes<tfoot>and<thead>. - List Items:
<li>auto-closes a preceding<li>. - Paragraphs:
<p>auto-closes another<p>. - Form Elements:
<input>or<select>will close other open form tags.
Sources: src/Parser.ts:25-78, src/Parser.spec.ts:153-188
Foreign Content (SVG/MathML)
When the parser enters an <svg> or <math> tag, it switches to a foreign context. In this mode, self-closing tags (e.g., <circle />) are recognized even if xmlMode is false, and tag names are adjusted for proper casing (e.g., foreignobject becomes foreignObject).
Sources: src/Parser.ts:107-160, src/Parser.ts:394-405, src/index.spec.ts:35-38
Serialization
After manipulation, the DOM tree can be converted back into an HTML or XML string. While the dom-serializer package is the primary tool, htmlparser2 exposes this functionality through DomUtils.getOuterHTML.
import * as htmlparser2 from "htmlparser2";
const dom = htmlparser2.parseDocument("<ul><li>Apple</li></ul>");
const items = htmlparser2.DomUtils.getElementsByTagName("li", dom);
htmlparser2.DomUtils.removeElement(items[0]);
const html = htmlparser2.DomUtils.getOuterHTML(dom);
// Result: "<ul></ul>"
Sources: README.md:155-177
Summary
DOM manipulation in htmlparser2 is a multi-stage process involving the Parser for event generation, DomHandler for tree construction, and DomUtils for modification and traversal. The system is designed to be highly efficient, supporting streaming inputs and providing hooks for custom tokenizers and handlers, while ensuring compatibility with standard HTML and XML document structures.
Sources: README.md:10-25, src/index.ts:1-30