Skip to content

feat: pluggable FormatParser registry - #45

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

Last extensibility step: embedders can add formats or replace a built-in parser without forking.

  • registry::FormatParser trait: name, formats() -> &[Format], optional claims(bytes, hint), parse(bytes, &MarkkitBuilder) -> Result<ParsedDocument>. Register with MarkkitBuilder::parser(p).
  • Selection in parse_document / extract_document, after the max_input_size check: first parser whose claims is true (formats with no Format variant), else first parser listing the detected format (fill PPTX, or replace HTML/CSV/...), else the built-in.
  • Custom output goes through transforms and the shared renderer, so it gets the same escaping, max_output_size and title/metadata handling.
  • A panicking parser becomes the new Error::Parser; the deadline is checked when it returns.
  • ParsedDocument::new is public so parsers can build results.

Why

Roadmap "Extensibility": formats markkit doesn't ship (PPTX, internal formats) or site-specific replacements needed a fork.

Before / After

Before: no hook; deck.pptx is Error::UnsupportedFormat, and built-in parsers can't be swapped.

After (tests/registry.rs): a parser claiming a magic prefix handles a format with no Format variant; a parser listing Format::Html replaces the built-in:

<p>x</p>  →  ```html
              <p>x</p>
              ```

Without registered parsers: behavior unchanged (unregistered_format_still_unsupported, builtin_runs_when_nothing_claims).

Risk

  • Low. Off by default; an empty registry is skipped.
  • Custom parsers are embedder code (trusted), but they see untrusted bytes. markkit still enforces input size before, panic capture, the deadline after, and output limits on render (threat model "Extension points").
  • Breaking (approved pre-1.0): new Error::Parser variant (Error is already #[non_exhaustive]).

Checklist

  • Tests added or updated (detected-format parser, claims precedence + transforms, built-in fallback, replace built-in, panic, input size, deadline, output size)
  • Backward compatibility considered
  • Knowledge updated (formats/format-support.md, foundations/architecture.md, security/threat-model.md, log), CHANGELOG

@chaliy chaliy self-assigned this Oct 27, 2026
- registry::FormatParser (name, formats, claims, parse) and
  MarkkitBuilder::parser; consulted before built-ins
- custom parser output goes through transforms and the renderer;
  panics map to new Error::Parser
- ParsedDocument::new is public
@chaliy
chaliy force-pushed the claude/project-thread-2rc0mr branch from 6b60ec1 to 1963ef8 Compare October 27, 2026 03:30
@chaliy
chaliy merged commit 7e5e024 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