Skip to content

0.3.0: html2markdown (HTML to Markdown) - #1

Merged
jaredlynskey merged 1 commit into
mainfrom
html2markdown
Oct 15, 2026
Merged

jaredlynskey merged 1 commit into
mainfrom
html2markdown

Conversation

@jaredlynskey

Copy link
Copy Markdown
Owner

Adds html2markdown(html, *, base_url=None): HTML to CommonMark with GitHub's tables and strikethrough.

  • Inline links and images, [text](url) / ![alt](src), made absolute with base_url
  • Pipe tables (spans as empty cells, an empty header row when the HTML has none, layout tables as paragraphs)
  • Fenced code blocks tagged with their language; # headings, - bullets, _em_, **strong**, ~~strike~~
  • Escapes only where Markdown would misread the text; formatting that can't be written safely is checked with pulldown-cmark and rewritten

Checks

  • Round trip (render the Markdown back with markdown-it, compare words, links and images with the page): 25 real pages, 172 Hugo pages and 50,000 random documents clean. tests/markdown_check.py, run in CI by tests/test_markdown.py.
  • markdownlint: 195 of 197 converted pages clean; the rest are lists the source numbers from 2 and one construct (**_x_**-style signatures) with no single-style form.
  • html2text() output byte-identical to 0.2.0 (275 page/option hashes).
  • 3–13× faster than markdownify, html2text and html-to-markdown on real pages.

Merging and tagging v0.3.0 publishes to PyPI.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WobasfsvfjJy3c6nkovhov

New html2markdown(html, *, base_url=None) (src/markdown.rs) walks the DOM
html2text parses and writes CommonMark with GitHub's tables and
strikethrough: inline links and images with absolute URLs, pipe tables,
fenced code tagged with its language, `_em_` and `**strong**`, `-` bullets,
and escapes only where Markdown would otherwise misread the text. Each
paragraph with formatting is checked against the flanking rules and read
back with pulldown-cmark; if it doesn't parse as intended it is rewritten
with `*`, then without the formatting, so no stray delimiters reach the
output.

Checked by rendering the Markdown back with markdown-it and comparing words,
links and images with the page (tests/markdown_check.py): 25 real pages,
172 Hugo pages and 50,000 random documents round-trip clean. markdownlint
passes on 195 of 197 converted pages; the other two have lists the source
numbers from 2, and one bold-italic construct that can only be written with
both `_` and `*`. Hostile nesting and table spans stay linear.

html2text() output is byte-identical to 0.2.0 (275 page/option hashes).

Also: pin the fork commit that exports NodeData and resolve_url; tests and
README; html2markdown in the PGO training and the benchmark; the round-trip
tests' dependencies in CI.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01WobasfsvfjJy3c6nkovhov
@jaredlynskey
jaredlynskey merged commit 6f3b30c into main Oct 15, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant