Skip to content

feat(html): declarative element rules - #37

Merged
chaliy merged 4 commits into
mainfrom
claude/project-thread-2rc0mr
Oct 27, 2026
Merged

chaliy merged 4 commits into
mainfrom
claude/project-thread-2rc0mr

Conversation

@chaliy

@chaliy chaliy commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Михайло · project thread

What changed

Site-specific HTML handling without writing Rust: map CSS selectors to IR actions.

  • rules::HtmlRule { selector, action } with ElementAction: skip, unwrap, heading{level}, paragraph, block_quote{title}, code_block{language}, inline_code, bold, italic, text.
  • MarkkitBuilder::html_rule(sel, action) / html_rules(..). Rules are checked before the built-in element mapping; the first matching rule wins. Invalid selectors fail at extraction with Error::HtmlParse.
  • Serde JSON shape ({"selector": ".callout", "action": "block_quote", "title": "Note"}), so rules can live in config files.
  • CLI: markkit extract --rules rules.json (works alongside --base-url).
  • Stripping still runs first: a rule can't resurrect <script>, <style>, forms, etc.
  • AGENTS.md: records the maintainer's approval that breaking changes are fine pre-1.0 (no deprecation shims; mark **Breaking:** in CHANGELOG).

Why

Roadmap "Extensibility": callouts, keyboard keys, ad blocks and doc-site widgets each need custom mapping. Before, the only knobs were include/exclude selectors.

Before / After

<div class="callout"><p>Heads up</p></div><span class="kbd">Ctrl</span> + C<div class="ad">Buy now</div>

Before (markkit extract --file p.html):

Heads up

Ctrl + CBuy now

After (--rules r.json with .callout → block_quote "Note", .kbd → inline_code, .ad → skip):

> **Note**
>
> Heads up

`Ctrl` + C

No rules configured: output unchanged.

Risk

  • Low. Off by default.
  • Security: rules go through the same depth limit (MAX_DEPTH) and pre-stripping as built-in mapping (html_security::element_rules_respect_depth_limit, element_rules_cannot_resurrect_stripped_elements). code_block / inline_code content goes through the existing fence and backtick escaping.

Checklist

  • Tests added or updated (each action, rule order, invalid selector, JSON round-trip, CLI --rules happy path + bad file, security)
  • Backward compatibility considered
  • Knowledge updated (formats/html-extraction.md, log), README CLI, CHANGELOG, AGENTS.md

@chaliy chaliy self-assigned this Oct 27, 2026
@chaliy
chaliy force-pushed the claude/project-thread-2rc0mr branch 2 times, most recently from 73fd520 to 55a6c9e Compare October 27, 2026 01:44
- rules::HtmlRule { selector, action } with ElementAction (skip, unwrap,
  heading, paragraph, block_quote+title, code_block, inline_code, bold,
  italic, text); serde JSON shape
- MarkkitBuilder::html_rule / html_rules; tried before built-in mapping,
  invalid selectors fail with Error::HtmlParse
- CLI: markkit extract --rules rules.json
@chaliy
chaliy force-pushed the claude/project-thread-2rc0mr branch from 55a6c9e to c5dd25b Compare October 27, 2026 02:17
@chaliy
chaliy merged commit 99d87ed into main Oct 27, 2026
13 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