node-html-markdown

A fast, dependency-light HTML-to-Markdown converter for Node.js and the browser, tuned for speed at scale.

Library
npm
v2.0.0
269 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
39 /100 Needs Attention
Development Activity 0
Maintenance 20
Community 56
Maturity 60
Momentum 20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
71 /100 Good
Architecture 82
Code Quality 68
Innovation 80
Learning Curve 55

node-html-markdown (NHM) converts HTML into clean, human-readable Markdown, built specifically to handle high-volume conversion workloads without sacrificing output quality. It parses HTML with node-html-parser (or the native browser DOMParser when available) and walks the resulting tree with a tag-driven translator system, producing consistent spacing and escaping rules instead of the noisy, inconsistent line breaks common to other converters.

The library exposes both a one-shot static translate() method and an instantiable class for reuse across many conversions, plus a customizable translator registry so consumers can override or add handling for specific HTML elements — including separate translator sets for links, tables, and code blocks. It supports both single HTML strings and batches of named files in one call, making it a practical drop-in for pipelines that need to convert large amounts of HTML into Markdown quickly.

What You Get

  • A NodeHtmlMarkdown class and static translate() method for one-off or repeated HTML-to-Markdown conversions
  • A tag-driven translator system covering headings, lists, tables, links, images, code blocks, and inline formatting out of the box
  • Support for converting single HTML strings or a FileCollection of multiple named HTML documents in a single call
  • Configurable options for code fences, bullet markers, emphasis/strong/strike delimiters, escaping rules, and link reference definitions
  • A separate benchmark suite comparing throughput against alternatives like Turndown

Common Use Cases

  • Bulk-converting scraped or CMS-exported HTML content into Markdown for static site generators or documentation pipelines
  • Normalizing rich-text editor output (HTML) into Markdown before storing it or feeding it to an LLM
  • Building content-migration scripts that need to process gigabytes of HTML daily without becoming a bottleneck
  • Converting email or webpage HTML into readable Markdown summaries for archiving or note-taking tools

Under The Hood

Architecture

NHM’s architecture separates parsing, tree-walking, and per-element rendering into distinct layers: main.ts’s NodeHtmlMarkdown class owns configuration and merges default, custom, and table/code/anchor-specific translator collections at construction time; utilities.ts#parseHTML produces the DOM tree via node-html-parser (or a native DOMParser fallback); and visitor.ts’s Visitor class performs a two-pass walk — first an optimizeTree pass that flags nodes worth visiting to skip empty branches, then a recursive visitNode pass that looks up a TranslatorConfig or TranslatorConfigFactory per tag from config.ts’s defaultTranslators and applies prefix/postfix/content/postprocess rules while tracking per-node metadata (list depth, table context, whitespace state) in a NodeMetadataMap. This translator-registry pattern means adding support for a new tag or overriding an existing one is a matter of registering a config object rather than touching the walker itself, and swapping childTranslators mid-walk (e.g. inside <a>, <table>, or <code>) is how NHM scopes different rendering rules to specific subtrees without extra branching in the visitor.

Tech Stack

The library is TypeScript-only (strict mode, ES2017 target, CommonJS build) with a single runtime dependency, node-html-parser, and no other production dependencies. Testing runs on Jest via ts-jest against a dedicated test/tsconfig.json, with coverage reported to Coveralls; CI (GitHub Actions) runs the full build and coverage suite across multiple Node.js versions. The package ships pre-compiled dist/ output (built via a tsc + ts-patch prepare step) and includes a self-contained benchmark/ workspace that measures conversion throughput against Turndown, treating performance-regression testing as a first-class part of the toolchain rather than an afterthought.

Code Quality

Test coverage spans several focused suites — default tag handling, options behavior, table conversion, code-block handling, and special-case regressions — each asserting exact Markdown string output rather than loose pattern matches, which catches subtle spacing regressions early. There’s no separate ESLint/Prettier config in the repo, so style enforcement leans on TypeScript’s strict compiler settings rather than a dedicated linter. Error handling is minimal by design since the library is a pure transform with no I/O; the code favors small, well-typed pure functions in utilities.ts (newline trimming, whitespace analysis, tag-surrounding logic) over larger stateful classes, keeping most logic easy to unit test in isolation.

API Design NHM’s main differentiator is treating Markdown-conversion speed as a design constraint rather than an incidental property: the tree-walker deliberately pre-optimizes which nodes are worth visiting before the real render pass, and the project publishes ongoing benchmark comparisons in its README showing it outperforming Turndown across a wide range of payload sizes. Its public API is intentionally small — a single class plus a static convenience method — while still exposing enough extension points (per-tag translator overrides, separate table/code/anchor translator sets, link-reference-definition mode) to handle edge cases without requiring most consumers to touch the internals at all.

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