Skip to content

Parsing HTML

Package: @lanexio/parser-grammar-html Stable
Layer: 2 (Grammar). Depends only on @lanexio/parser-core.
Runtime: Universal (browser, server, edge worker).

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 {
parseHtml,
serializeHtml,
HtmlKind,
HtmlField,
HtmlParseMode,
type ParseHtmlOptions,
type SerializeHtmlOptions,
} from '@lanexio/parser-grammar-html';
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 nodes
console.log(tree.root.kind); // Document root kind id

parseHtml accepts a Uint8Array. Always use TextEncoder when converting a string to bytes.

FieldTypeDefaultDescription
modeHtmlParseMode'document'Parse as a full document or as a fragment.
contextElementstringundefinedContext element name for fragment parsing (e.g. 'body').
contextElementLeafstringundefinedLeaf element name for void-element fragments.
scriptingEnabledbooleanfalseWhether scripting is considered enabled. Affects <noscript> 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.

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.

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>"
FieldTypeDefaultDescription
outerbooleantrueWhen true, serialize the root node and all its children (outerHTML semantics). When false, serialize only the children (innerHTML semantics).
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 element
const root = tree.root;
const first = root.child(0);
if (first) {
console.log(serializeHtml(first, { outer: false }));
}
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 nodes
const 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.

ExportTypeDescription
parseHtml(source: Uint8Array, options?: ParseHtmlOptions) => LexTreeParse HTML. Never throws.
serializeHtml(input: LexTree | LexNode, options?: SerializeHtmlOptions) => stringSerialize to HTML string.
HtmlKindconst objectNumeric kind IDs for all HTML node types.
HtmlFieldconst objectNumeric field IDs for HTML attributes and slots.
HTML_FIELD_NAMES_BY_IDreadonly string[]Field name lookup by numeric field ID.
HtmlParseModeconst objectDocument, Fragment
HtmlParseErrorCodeconst objectParse error code constants.
htmlGrammarLanexio ParserPureGrammarGrammar descriptor for use with parser-pure.