Parsing HTML
Package: @lanexio/parser-grammar-html Stable
Layer: 2 (Grammar). Depends only on @lanexio/parser-core.
Runtime: Universal (browser, server, edge worker).
Overview
Section titled “Overview”parseHtml implements the full WHATWG HTML parsing algorithm, including all 23 insertion mode state machines, adoption agency, foster parenting, and foreign content (SVG, MathML). It passes all 5,199 html5lib tree-construction tests (5,241 total in the full package suite) and all 2,766 tokenizer tests.
Parse input is always a Uint8Array. Output is always a LexTree, even for empty or malformed input.
Import
Section titled “Import”import { parseHtml, serializeHtml, HtmlKind, HtmlField, HtmlParseMode, type ParseHtmlOptions, type SerializeHtmlOptions,} from '@lanexio/parser-grammar-html';Parse a document
Section titled “Parse a document”import { parseHtml } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();const tree = parseHtml(encoder.encode('<!doctype html><html><body><p>Hello</p></body></html>'));
console.log(tree.nodeCount); // total nodesconsole.log(tree.root.kind); // Document root kind idparseHtml accepts a Uint8Array. Always use TextEncoder when converting a string to bytes.
ParseHtmlOptions
Section titled “ParseHtmlOptions”| Field | Type | Default | Description |
|---|---|---|---|
mode | HtmlParseMode | 'document' | Parse as a full document or as a fragment. |
contextElement | string | undefined | Context element name for fragment parsing (e.g. 'body'). |
contextElementLeaf | string | undefined | Leaf element name for void-element fragments. |
scriptingEnabled | boolean | false | Whether scripting is considered enabled. Affects <noscript> parsing. |
Fragment parsing
Section titled “Fragment parsing”import { parseHtml, HtmlParseMode } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();const tree = parseHtml( encoder.encode('<li>Item one</li><li>Item two</li>'), { mode: HtmlParseMode.Fragment, contextElement: 'ul' });Fragment parsing is how browsers parse innerHTML. Pass the tag name of the context element.
Detect LexError nodes
Section titled “Detect LexError nodes”import { parseHtml } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();const tree = parseHtml(encoder.encode('<table><p>bad nesting'));
for (const node of tree.root.children()) { if (node.hasError) { console.log('parse error at', node.range); }}parseHtml never throws. Malformed input — bad nesting, unclosed tags, illegal characters — produces LexError nodes in the AST. The parser always recovers and continues.
Serialize back to HTML
Section titled “Serialize back to HTML”import { parseHtml, serializeHtml } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();const tree = parseHtml(encoder.encode('<p>Hello <b>world</b>'));
const html = serializeHtml(tree);console.log(html); // "<html><head></head><body><p>Hello <b>world</b></p></body></html>"SerializeHtmlOptions
Section titled “SerializeHtmlOptions”| Field | Type | Default | Description |
|---|---|---|---|
outer | boolean | true | When true, serialize the root node and all its children (outerHTML semantics). When false, serialize only the children (innerHTML semantics). |
Partial serialization
Section titled “Partial serialization”import { parseHtml, serializeHtml } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();const tree = parseHtml(encoder.encode('<div><p>First</p><p>Second</p></div>'));
// Serialize only the children of the first elementconst root = tree.root;const first = root.child(0);if (first) { console.log(serializeHtml(first, { outer: false }));}HtmlKind constants
Section titled “HtmlKind constants”import { HtmlKind } from '@lanexio/parser-grammar-html';
// HtmlKind is a const object. Use 'as const' pattern, never enum.const kind: typeof HtmlKind[keyof typeof HtmlKind] = HtmlKind.Element;
// Example: walk only element nodesconst cursor = tree.cursor();do { if (cursor.current.kind === HtmlKind.Element) { console.log('element at', cursor.current.range); }} while (cursor.gotoFirstChild() || cursor.gotoNextSibling() || cursor.gotoParent());HtmlKind is a const object. Numeric kind IDs are stable across versions. Never use raw numbers — always reference HtmlKind.<name> so that future kind additions don’t silently break your code.
Full exports
Section titled “Full exports”| Export | Type | Description |
|---|---|---|
parseHtml | (source: Uint8Array, options?: ParseHtmlOptions) => LexTree | Parse HTML. Never throws. |
serializeHtml | (input: LexTree | LexNode, options?: SerializeHtmlOptions) => string | Serialize to HTML string. |
HtmlKind | const object | Numeric kind IDs for all HTML node types. |
HtmlField | const object | Numeric field IDs for HTML attributes and slots. |
HTML_FIELD_NAMES_BY_ID | readonly string[] | Field name lookup by numeric field ID. |
HtmlParseMode | const object | Document, Fragment |
HtmlParseErrorCode | const object | Parse error code constants. |
htmlGrammar | Lanexio ParserPureGrammar | Grammar descriptor for use with parser-pure. |