Skip to content

feat: HTML-to-Markdown pipeline via canonical IR - #4

Merged
chaliy merged 3 commits into
mainfrom
claude/markkit-rust-library-QvYMh
Mar 27, 2026
Merged

chaliy merged 3 commits into
mainfrom
claude/markkit-rust-library-QvYMh

Conversation

@chaliy

@chaliy chaliy commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the core Parse → Normalize → Render pipeline for HTML-to-Markdown conversion.

  • Canonical IR (ir.rs): Document, 16 Node variants, ListItem with serde JSON support
  • HTML parser (html/parser.rs): scraper/html5ever, CSS include/exclude selectors, depth limiting (200), whitespace normalization, transparent container unwrapping, non-content element stripping
  • Markdown renderer (render/markdown.rs): GFM tables, nested lists, blockquotes, fenced code blocks, inline formatting, hard breaks
  • CLI: --stdin flag and - source convention for piped input
  • Python bindings: extract_html_sync() + extract_html_sync_with_options() with keyword args
  • JS bindings: extract_html_sync() synchronous function
  • Specs: IR specification, threat model (5 threat categories), comprehensive HTML extraction spec, examples spec
  • Examples: basic.rs, custom_selectors.rs, ir_access.rs, configuration.rs

Test Coverage

135 tests across 8 suites:

  • 9 unit tests (IR, format detection, whitespace, language extraction)
  • 79 integration tests (every element mapping, selectors, config, format detection, extract_bytes, edge cases)
  • 9 fixture tests (paired .html/.md input/output files)
  • 6 property-based tests (fuzz, determinism, no dangerous tags)
  • 20 security tests (XSS payloads, depth limits, malformed HTML, resource limits, unicode, null bytes)
  • 10 CLI integration tests (stdin, file, JSON output, selectors)
  • 1 doc test, 1 CLI unit test

Quality Gates

  • cargo fmt --check clean
  • cargo clippy --workspace -- -D warnings clean
  • All 135 tests green
  • Threat model documented with test references
  • CHANGELOG updated

Test plan

  • cargo test --workspace passes (135 tests)
  • cargo clippy --workspace --all-targets -- -D warnings clean
  • cargo fmt --all -- --check clean
  • All 4 examples run successfully
  • CLI stdin extraction works: echo '<h1>Hi</h1>' | markkit extract --stdin
  • Fixture tests validate exact input→output matching
  • Property tests fuzz with arbitrary input (no panics)
  • Security tests verify XSS stripping and resource limits

chaliy added 3 commits March 27, 2026 02:52
Adds the core Parse → Normalize → Render pipeline:

- ir.rs: Canonical intermediate representation (Document, Node, ListItem)
  with serde support for JSON AST output
- html/parser.rs: HTML → IR parser using scraper/html5ever with
  configurable include/exclude CSS selectors, depth limiting (200),
  whitespace normalization, and non-content element stripping
- render/markdown.rs: IR → Markdown renderer supporting headings,
  paragraphs, inline formatting, links, images, lists (nested),
  blockquotes, code blocks, tables (GFM), and thematic breaks
- extract.rs: Wires parser + renderer together with sync/async APIs
  and separate parse_html() for IR-only access

92 tests across 4 test suites:
- Unit tests (9): IR serialization, format detection, whitespace handling
- Integration tests (58): every HTML element mapping, selectors,
  full documents, edge cases, determinism
- Security tests (18): XSS payloads, deep nesting, malformed HTML,
  resource limits, unicode, null bytes
- Property tests (6): fuzz with arbitrary input, determinism,
  no dangerous tags in output
Specs:
- specs/ir-spec.md: canonical IR specification with node semantics
- specs/threat-model.md: comprehensive threat model with attack surfaces
- specs/examples-spec.md: examples directory structure spec
- specs/html-extraction.md: expanded with whitespace rules, depth limits

Test fixtures (9 paired HTML/MD files):
- basic_headings, inline_formatting, links_and_images, lists,
  code_blocks, tables, blockquotes, full_article, malformed
- html_fixtures.rs test runner validates each pair

Examples (4 standalone binaries):
- basic, custom_selectors, ir_access, configuration

CLI enhancements:
- --stdin flag and "-" source for piped input
- 9 integration tests (help, stdin, file, JSON, selectors)

Language bindings:
- Python: extract_html_sync, extract_html_sync_with_options (kwargs)
- JS: extract_html_sync
- Fix div/section/article transparent containers to emit block children
  directly into parent node list (previously dropped multi-block content)
- Add is_transparent_container() to handle div, section, article, main,
  figure, figcaption as passthrough in block context
- Add 21 new integration tests: tables edge cases, nested lists,
  renderer edge cases, config builder, format detection, extract_bytes
- Add 2 new security tests: depth limit boundary (200/201)
- Update CHANGELOG.md with all HTML pipeline additions
- Fix formatting across all files (cargo fmt)
@chaliy
chaliy merged commit 3b8b4eb into main Mar 27, 2026
7 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