htmd

A fast, turndown.js-inspired HTML to Markdown converter for Rust with rich options and table support.

Library
Cargo
v0.5.5
451stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
75/100Good
Development Activity88
Maintenance88
Community40
Maturity44
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
85/100Excellent
Architecture85
Code Quality88
Innovation86
Learning Curve80

htmd is a Rust library that converts HTML into clean Markdown, closely modeled on the popular turndown.js JavaScript converter. It passes all of turndown.js’s test cases, supports HTML-to-Markdown table conversion, and keeps its dependency footprint minimal by relying only on html5ever for parsing.

Designed for speed and correctness, htmd converts a 1.37MB Wikipedia page in roughly 16ms and exposes a builder-based API for skipping tags, customizing output options, and registering per-tag handlers. A faithful mode can preserve raw HTML for elements Markdown cannot represent, making it a solid choice for content pipelines, scrapers, and LLM ingestion.

What You Get

  • A one-line htmd::convert function plus a builder-based HtmlToMarkdown API for advanced configuration
  • Full turndown.js-compatible conversion that passes all of turndown.js’s test cases
  • HTML table to Markdown table conversion out of the box
  • Configurable Options covering heading style, list markers, code-block fences, link styles, and more
  • Custom per-tag handlers and tag-skipping for fine-grained control over output
  • A faithful mode that preserves raw HTML for tags Markdown cannot express

Common Use Cases

  • Converting scraped or fetched web pages into Markdown for storage or display
  • Preparing clean Markdown text from HTML for LLM ingestion and RAG pipelines
  • Building content-migration tools that move HTML documents into Markdown-based systems
  • Normalizing rich HTML email or CMS content into portable Markdown

Under The Hood

Architecture - The entry point src/lib.rs parses HTML into an html5ever RcDom via html_to_tree, then walks the tree with dom_walker::walk_node, dispatching each element to a registered ElementHandler. Handlers live in src/element_handler (one module per tag family: headings, list, li, table, td_th, anchor, code, pre, blockquote, and more), each returning a HandlerResult that the walker concatenates and post-trims. A builder assembles ElementHandlers keyed by tag, so custom handlers and tag-skipping simply insert into that map.

Tech Stack - Written in Rust (edition 2024), htmd depends only on html5ever and markup5ever_rcdom for parsing plus phf for compile-time perfect-hash tag lookup. Dev tooling uses criterion for benchmarks and indoc, scraper, and pretty_assertions for tests. Options are modeled as plain enums in src/options.rs (HeadingStyle, HrStyle, CodeBlockFence, BulletListMarker, TranslationMode, etc.) with sensible defaults.

Code Quality - The codebase is well factored, with a clear DOM-walk plus per-tag-handler separation and doc-commented public types. Testing is thorough: roughly 86 test functions across tests/ (basic, link, list, table, and turndown-compatibility suites) plus inline unit tests, and the README documents passing all turndown.js cases. Naming is consistent and error handling surfaces through std::io::Result.

API Design - The public surface is deliberately small and ergonomic: htmd::convert for a one-liner and HtmlToMarkdown::builder() for a fluent, chainable configuration flow (options, skip_tags, add_handler, scripting_enabled). Custom handlers are ordinary closures receiving an Element, and the converter is Send/Sync-friendly for multithreaded use, keeping boilerplate minimal to get started.

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