Parser Boundary
mdwright-document is the only production crate that invokes pulldown-cmark.
Markdown is semantically total after mdwright canonicalises source bytes, but the parser implementation can still panic on malformed edge cases. The document crate contains that implementation risk:
- source bytes are canonicalised into one parser input;
- parser iteration is collected eagerly inside one private
catch_unwindboundary; - parser panics become
mdwright_document::ParseError; - document facts, signatures, HTML rendering, and block checkpoints are built only after successful collection.
Callers do not catch parser panics. They parse source with:
#![allow(unused)] fn main() { let doc = mdwright_document::Document::parse(source)?; }
Operations over an existing Document stay pure over recognised facts. Formatting a parsed document remains infallible:
#![allow(unused)] fn main() { let formatted = mdwright_format::format_document(&doc, &opts); }
Source-convenience APIs are fallible because they cross the parser boundary:
#![allow(unused)] fn main() { let formatted = mdwright_format::format_source(source, &opts)?; let html = mdwright_document::render_html(source)?; }
The transactional formatter uses the same policy for verification reparses. If a candidate output cannot be parsed, the
candidate is rejected and the unverified bytes are not committed. CLI and LSP delivery turn ParseError into controlled
file/editor diagnostics; they do not install parser-specific panic handlers.