hast-util-from-html
A hast utility that parses serialized HTML into a syntax tree using parse5, with detailed error reporting.
Repository Health
Technical Analysis
hast-util-from-html is a small utility from the syntax-tree/unified ecosystem that turns raw HTML strings into a hast (HTML Abstract Syntax Tree) syntax tree. Internally it wraps parse5, the spec-compliant HTML parser, and passes the resulting document through hast-util-from-parse5 to produce a hast Root node with positional information attached to every node.
Beyond basic parsing, the package exposes fine-grained control over the roughly 60 categories of HTML parse errors defined by the WHATWG HTML spec — each can be turned off, treated as a warning, or escalated to a fatal error via an onerror callback that receives a VFileMessage. It supports both full-document and fragment parsing modes, and can parse content in the SVG namespace embedded within HTML. It is the core parsing layer that powers rehype-parse and the wider rehype/unified toolchain used to build markdown and HTML processing pipelines.
What You Get
- A single
fromHtml(value, options)function that returns a hastRootnode from an HTML string, Buffer, or VFile - Support for both full-document parsing and
fragment: trueparsing for HTML snippets - Configurable handling of ~60 distinct WHATWG parse-error codes, each settable to off/warning/fatal
- An
onerrorcallback that receives structuredVFileMessageobjects with source location, severity, and a spec URL for every parse error - Automatic HTML-to-SVG namespace switching when an
<svg>element is encountered - Complete TypeScript types for
Options,ErrorCode, andErrorSeverity, generated from JSDoc and checked with 100% type coverage
Common Use Cases
- Powering
rehype-parse, the entry point for rehype/unified pipelines that transform or lint HTML - Parsing HTML fragments pulled from a CMS or user input into an AST for sanitization with
hast-util-sanitize - Building custom static-site or documentation tooling that needs a positioned AST instead of a DOM
- Linting or auditing HTML documents by surfacing every WHATWG parse error with location and severity
- Converting HTML into hast so it can be transformed and re-serialized with
hast-util-to-html
Under The Hood
Architecture
The package is a thin, single-purpose orchestration layer: lib/index.js exports one function, fromHtml, which wraps value in a VFile if needed, chooses parse5’s parse or parseFragment based on options.fragment, and pipes the resulting parse5 document through hast-util-from-parse5 to produce a hast Root. Parse-error handling is implemented as a closure (internalOnerror) passed to parse5’s onParseError hook, which looks up each error code in a large static errors table (lib/errors.js), applies the caller’s configured severity, formats the human-readable message (substituting %c/%x placeholders with the offending character), and constructs a VFileMessage with precise start/end positions before invoking the caller’s onerror. There is no internal state beyond this single call — the module has no classes, no caching, and nothing would break elsewhere if the core abstraction changed, since it is a leaf dependency consumed by exactly one call path (rehype-parse and direct callers).
Tech Stack
Written in plain ESM JavaScript with JSDoc-based typing (no .ts source; declarations are emitted via tsc --build and checked with type-coverage at 100%). Runtime dependencies are parse5 (the HTML parser), hast-util-from-parse5 (parse5-to-hast conversion), vfile/vfile-message (file and diagnostic wrappers from the unified ecosystem), @types/hast, and devlop for lightweight runtime assertions. Build and quality tooling includes xo (ESLint preset) and prettier for formatting/linting, remark-cli with remark-preset-wooorm for markdown/readme linting, and c8 for coverage. CI runs on GitHub Actions across a matrix of Node versions with npm test, uploading coverage to Codecov.
Code Quality
Tests live in test/index.js using Node’s built-in node:test and node:assert/strict — no external test framework. Assertions are deep structural comparisons of the full hast tree the function returns, plus dedicated fixture-driven tests for each parse-error code under test/parse-error/. The project enforces 100% test coverage via c8 --100 and 100% type coverage via type-coverage, both wired into the test script so a regression on either fails CI. Error handling is explicit throughout — internalOnerror uses devlop’s assert to fail loudly on unexpected internal states rather than swallowing them. Naming and formatting are enforced by xo/prettier with no manual style drift.
What Makes It Unique
Most HTML-to-AST bridges expose parsing as an all-or-nothing operation; this package instead exposes the full WHATWG catalog of parse errors as individually configurable diagnostics with source positions and spec links, letting callers treat malformed HTML as lintable data rather than a binary parse failure. Combined with automatic SVG-namespace switching mid-document, it gives the unified/rehype ecosystem a parsing layer that is both spec-accurate and introspectable, which is why it underpins rehype-parse rather than being replaced by a simpler wrapper.
Used by 2 apps in this directory
Orama
Search · Developer Tools
A complete, embeddable search engine and RAG pipeline running in browsers, servers, and edge networks with full-text, vector, and hybrid search in under 2KB.
Zulip
Team Chat
Topic-based team chat that brings the structure of email threads to real-time messaging, so distributed teams never lose context across hundreds of concurrent conversations.