hast-util-to-html

Serializes hast syntax trees into WHATWG-compliant HTML strings, with fine-grained control over escaping, quoting, and tag omission.

Library
npm
v9.0.5
118stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
43/100Fair
Development Activity0
Maintenance32
Community68
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture85
Code Quality92
Innovation55
Learning Curve65

hast-util-to-html is the canonical HTML serializer for the unified/hast ecosystem, turning a hast syntax tree back into a WHATWG-compliant HTML string. It underlies rehype-stringify, the terminal stringifier used by nearly every rehype and remark-to-HTML pipeline, which is why it sits at extremely high npm download volume despite a small, focused API surface.

Beyond straightforward serialization, it exposes a large set of formatting options — omitting optional tags, tightening attribute whitespace, smart-quoting, self-closing SVG elements, and configuring character-reference encoding — so the same tree can be rendered as readable markup for humans or minified output for production bundles, all while automatically toggling between HTML and SVG serialization rules as it walks the tree.

What You Get

  • A single toHtml(tree, options) export with no default export, fully typed via JSDoc-derived TypeScript declarations
  • Automatic HTML/SVG namespace switching when the tree crosses an <svg> boundary, so attribute casing and void-element rules stay correct
  • Over a dozen formatting knobs (quoting, tag omission, tight attributes, doctype casing) for producing either readable or byte-minimal output
  • Configurable character-reference and XSS-safety controls (allowDangerousHtml, allowDangerousCharacters) that default to safe encoding unless explicitly disabled

Common Use Cases

  • Serializing a processed hast tree back to HTML at the end of a rehype pipeline, typically via rehype-stringify
  • Building HTML minifiers or pretty-printers on top of hast by toggling the tight/omission options
  • Round-tripping HTML through hast-util-from-html → transform → hast-util-to-html
  • Re-emitting sanitized (via hast-util-sanitize) user content back to safe HTML strings

Under The Hood

Architecture The library is a thin dispatch layer over a zwitch-based visitor: lib/handle/index.js builds a zwitch('type', ...) switch keyed on hast node type (comment, doctype, element, raw, root, text), each handled by its own small file in lib/handle/. lib/index.js owns the public toHtml() entry point, builds a shared State object (settings, current quote/alternative quote, active schema from property-information) and exposes one/all recursion helpers that the individual handlers call back into; lib/handle/element.js is the largest handler (~265 lines) because it owns attribute serialization, self-closing/void-element logic, and the HTML↔SVG schema swap on <svg> boundaries. Optional-tag omission is fully isolated into lib/omission/ (opening.js, closing.js, omission.js), which element.js consults only when omitOptionalTags is set — a clean separation between “always correct” serialization and “legal but aggressive” minification behavior.

Tech Stack Plain ESM JavaScript ("type": "module") with zero build step for runtime — types ship via a tsc --build pass emitting .d.ts/.d.ts.map declaration files from JSDoc comments, checked with type-coverage (configured for 100% strict coverage in package.json). Runtime dependencies are all narrowly-scoped unified-ecosystem utilities: property-information (attribute/schema knowledge), stringify-entities (character-reference encoding), zwitch (type-based dispatch), plus small helpers (ccount, comma-separated-tokens, space-separated-tokens, html-void-elements, hast-util-whitespace). Linting/formatting run through xo (ESLint config) and prettier; CI (.github/workflows/main.yml) runs the test suite across two Node LTS lines and uploads coverage to Codecov.

Code Quality Testing is extensive and enforced strictly: test/ contains 30+ files, with dedicated suites per node type (element.js, comment.js, doctype.js, text.js, raw.js, root.js) plus an entire subset (omission-*.js, 20+ files) exercising every individual optional-tag-omission rule (e.g. omission-closing-tbody.js, omission-opening-html.js) and a dedicated security.js suite for XSS-relevant escaping behavior. The test npm script chains build (typecheck + type-coverage) → format (remark/prettier/xo —fix) → test-coverage, and test-coverage runs c8 --100, meaning the project fails CI on anything less than 100% statement coverage. This is a notably higher bar than most npm packages in this size class.

API Design The public surface is intentionally minimal — one function, one options object, no classes or default export — which keeps the getting-started cost close to zero (import {toHtml} from 'hast-util-to-html'; toHtml(tree)). Every option is documented inline via JSDoc @property tags with defaults spelled out, and the README mirrors that same structure field-by-field, so IDE tooltips and the docs site stay in lockstep. The main ergonomic cost is the sheer number of formatting options (15+), most of which exist purely to support minifier/pretty-printer use cases rather than everyday serialization, but sensible false defaults mean the common case needs no configuration at all.

Used by 8 apps in this directory

Go
62%
Apache 2.0

Harness Open Source

Developer Tools · Devops · Code Editors

38,251

A unified open source DevOps platform combining Git hosting, CI/CD pipelines, cloud development environments, and artifact registries in a single self-hosted system.

View details
89
Repo Health
79
Technical
64
Dependency
Built with
Go62%
TypeScript34%
Updated 3 days ago
Go
56%
Other

Multica

AI Assistants · AI Development

49,056

Turn coding agents into real teammates — assign issues, track progress, and compound reusable skills across a vendor-neutral, self-hosted platform.

View details
85
Repo Health
83
Technical
69
Dependency
Built with
Go56%
TypeScript39%
Updated 2 days ago
Go
75%
Other

Notifuse

Marketing

2,170

Open-source, self-hosted alternative to Mailchimp, Brevo, and Klaviyo — send newsletters and transactional emails without per-email pricing or vendor lock-in.

View details
82
Repo Health
80
Technical
66
Dependency
Built with
Go75%
TypeScript23%
Updated 2 days ago
TypeScript
98%
Other

Novu

Developer Tools

39,870

Open-source communication infrastructure that connects your products and AI agents to every channel your users live on — Inbox, Email, SMS, Push, Chat, and more.

View details
93
Repo Health
80
Technical
64
Dependency
Built with
TypeScript98%
Updated yesterday
TypeScript
98%
Other

Orama

Search · Developer Tools

10,547

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.

View details
74
Repo Health
83
Technical
68
Dependency
Built with
TypeScript98%
Updated 1 months ago
Python
54%
Other

PostHog

Analytics · Monitoring · Developer Tools

39,612

The all-in-one open source product platform combining analytics, session replay, feature flags, error tracking, AI observability, and a built-in data warehouse in a single self-hostable stack.

View details
92
Repo Health
80
Technical
65
Dependency
Built with
Python54%
TypeScript36%
Updated today
TypeScript
71%
Apache 2.0

Supabase

Developer Tools · Databases · Search

108,912

The open-source Postgres development platform that replaces Firebase with authentication, real-time APIs, edge functions, storage, and vector embeddings — all built on PostgreSQL.

View details
90
Repo Health
91
Technical
62
Dependency
Built with
TypeScript71%
MDX26%
Updated today
Python
57%
Apache 2.0

Zulip

Team Chat

25,855

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.

View details
96
Repo Health
86
Technical
61
Dependency
Built with
Python57%
TypeScript19%
JavaScript10%
Updated yesterday

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search