Skip to content

@lanexio/parser-grammar-html

This page documents @lanexio/parser-grammar-html, the HTML grammar package implementing the full WHATWG HTML parsing algorithm, including all 23 insertion modes, adoption agency, foster parenting, and foreign content (SVG, MathML).

  • Version: Stable
  • Module name: parser-grammar-html
  • Package: @lanexio/parser-grammar-html
  • Import path: @lanexio/parser-grammar-html
  • Layer: 2 (Grammar)
  • Runtime: Universal (browser, server, edge worker)
  • Module format: ESM
  • Stability: Stable
  • Primary use case: Parse HTML documents and fragments into a flat AST.
  • You need to parse HTML documents or fragments (innerHTML) into a traversable AST.
  • You need to serialize a parsed HTML tree back to HTML source.
  • You need to sanitize HTML content against a configurable policy.
  • You need to extract text content or decode HTML entities.
BoundaryDescription
InputsUint8Array (source bytes) + optional ParseHtmlOptions
OutputsLexTree (flat AST rooted at HtmlKind.Document or HtmlKind.Fragment)
Side effectsNone
DeterminismYes (same bytes + same options produce identical tree)
External dependencies@lanexio/parser-core
Never-throw guaranteeYes for all parse entry points
Security surfaceserializeHtml() emits raw HTML (XSS risk if caller passes output to innerHTML). sanitizeHtml() mitigates this.
  1. Install the package.

    Terminal window
    pnpm add @lanexio/parser-grammar-html
  2. Import the named export.

    import { parseHtml } from '@lanexio/parser-grammar-html';
RequirementRequiredLayerNotes
@lanexio/parser-coreYes1^1.0.0
import { parseHtml } from '@lanexio/parser-grammar-html';
const encoder = new TextEncoder();
const bytes = encoder.encode('<!doctype html><p>Hello <strong>world</strong></p>');
const tree = parseHtml(bytes);
console.log(tree.nodeCount); // total nodes in the flat AST
console.log(tree.root.kind); // HtmlKind.Document
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' }
);
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);
// "<html><head></head><body><p>Hello <b>world</b></p></body></html>"
ExportTypeDescription
parseHtml(source: Uint8Array, options?: ParseHtmlOptions) => LexTreeParse HTML. Never throws.
serializeHtml(input: LexTree | LexNode, options?: SerializeHtmlOptions) => stringSerialize tree back to HTML string.
sanitizeHtml(tree: LexTree, policy?: SanitizePolicy) => LexTreeProduce a safe projection of a parsed HTML tree.
sanitizeHtmlToString(tree: LexTree, policy?: SanitizePolicy) => stringSerialize safe content to string via inline AST filtering.
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.
DEFAULT_POLICYSanitizePolicyDefault sanitization policy (allows most safe HTML).
resolvePolicy(policy?: SanitizePolicy) => SanitizePolicyResolve a policy, falling back to DEFAULT_POLICY.
isSafeUrl(url: string) => booleanCheck if a URL scheme is considered safe.
isSafeSrcset(srcset: string) => booleanCheck if a srcset attribute value is safe.
isAttributeSafe(name: string, value: string) => booleanCheck if an attribute name/value pair is safe.
isTagAllowed(tag: string) => booleanCheck if a tag is allowed by the default policy.
textContent(node: LexNode) => stringExtract plain text from an HTML tree.
decodeEntities(text: string) => stringDecode HTML character references.
RAWTEXT_ELEMENT_NAMESreadonly string[]Names of raw-text elements (script, style).
TokenKindconst objectToken type constants from the tokenizer.
tokenize(source: Uint8Array, options?: TokenizeOptions) => Token[]Tokenize HTML source bytes.
DEFAULT_CONTENT_MODESobjectDefault tokenizer content modes.
htmlGrammarLanexioParserPureGrammarGrammar descriptor for use with parser-pure.
htmlRegistrationGrammarRegistrationRegistration for the unified grammar registry.
FieldTypeRequiredDefaultDescription
modeHtmlParseModeNoHtmlParseMode.DocumentParse as a full document or as a fragment.
contextElementstringNoundefinedContext element name for fragment parsing (e.g. "div", "td", "svg").
contextElementLeafstringNoundefinedLeaf element within the foreign-namespace context for fragment parsing.
scriptingEnabledbooleanNofalseScripting flag. When true, <noscript> is raw-text content.
wasmTokenizer(source: Uint8Array) => Token[]NoundefinedOptional WASM-backed tokenizer fast-path.
FieldTypeRequiredDefaultDescription
outerbooleanNotrueWhen true, serialize the root node and all children (outerHTML). When false, serialize only children (innerHTML).
PropertyTypeDescription
rootLexNodeRoot node (HtmlKind.Document or HtmlKind.Fragment).
nodeCountnumberTotal nodes in the tree.
sourceUint8ArrayOriginal parsed bytes.
TypePurposeNotes
ParseHtmlOptionsOptions for parseHtmlSee options table above.
HtmlParseModeUnion of parse mode valuesHtmlParseMode.Document | HtmlParseMode.Fragment
SerializeHtmlOptionsOptions for serializeHtmlSee options table above.
SanitizePolicySanitization policyDefines which tags, attributes, and URLs are allowed.
HtmlParseErrorParse error descriptorReturned via error codes.
WasmScanExportsType for WASM tokenizer exportsInternal.

parseHtml supports two modes:

  • Document mode (default): parses as a full HTML document with implied <html>, <head>, <body>.
  • Fragment mode: parses as an HTML fragment in the context of a specific element (like innerHTML).

Pass a wasmTokenizer option to use the WASM-backed tokenizer as a fast-path. When the source contains no character references, the WASM tokenizer is used instead of the TypeScript tokenizer.

The HTML parser preserves semantic HTML structure (headings, landmarks, lists, image alt attributes). The serializer outputs raw HTML that can be directly injected into a browser — consuming code is responsible for ensuring semantic output.

ConcernStatus
Generated output semanticsPreserves HTML semantics (headings, landmarks, lists, alt text)
ARIA attributes in serialized outputPreserved
Semantic element round-tripYes
  • parseHtml never throws on any byte sequence. Malformed input produces LexError nodes.
  • serializeHtml() emits raw HTML. Callers must not pass the output directly to innerHTML without escaping.
  • sanitizeHtml() and sanitizeHtmlToString() provide configurable sanitization against XSS.
ThreatMitigationStatus
Malformed input byte sequencePanic-free guarantee: all inputs accepted, errors produce LexError AST nodesImplemented
XSS via serializer outputserializeHtml() emits raw HTML — caller is responsible for safe insertion. sanitizeHtml() provides policy-based filteringDocumented
PackageRelationshipLayerNotes
@lanexio/parser-coreRequires1Provides LexTree, LexNode, LexCursor
@lanexio/parser-pureConsumes4Wraps parseHtml in a unified bridge
@lanexio/parserConsumes6Re-exports parseHtml as an optional grammar
import { parseHtml, HtmlKind } from '@lanexio/parser-grammar-html';
import { LexQuery } from '@lanexio/parser-query';
const encoder = new TextEncoder();
const tree = parseHtml(encoder.encode('<ul><li>one</li><li>two</li></ul>'));
const resolver = (name: string) => (HtmlKind as Record<string, number | undefined>)[name];
const query = LexQuery.compile('Element', resolver);
for (const node of query.matches(tree)) {
console.log(node.kind, node.range);
}
VersionDateStatusNotable changes
1.0.02026-05-29CurrentInitial stable release. Apache-2.0.
  • None.