A zero-copy Markdown parser for Rust. Parses markdown strings into structured sections and inline elements, borrowing directly from the input with no intermediate allocations for text content.
- Zero-copy parsing — all text slices borrow from the input
- Type-safe representation of markdown elements via
SpecialChar,Section, andInline - Fold-based state machine for single-pass block-level parsing
- Headings (levels 1-6)
- Paragraphs (with multi-line continuation)
- Code blocks (fenced with backticks, optional language)
- Unordered lists (
-,*, or+markers) - Ordered lists (with preserved start number)
- Blockquotes
- Horizontal rules (
---,***,___)
- Bold text (
**or__) - Italic text (
*or_) Codespans (backtick-delimited, CommonMark space-stripping)- Links

- Backslash escapes
use marki::MarkdownFile;
let md = MarkdownFile::parse("# Hello\n\nWorld");
for section in &md.sections {
println!("{section:?}");
}The parser operates on LF (\n) line endings. For CRLF (\r\n) input, call normalize before parsing — it returns the input borrowed when no \r is present (zero-cost), or an owned copy with \r stripped:
use marki::{normalize, MarkdownFile};
let normalized = normalize(input);
let md = MarkdownFile::parse(&normalized);- List items are single-line only (no continuation with indentation)
- Emphasis cannot span across blockquote lines (
> **bold\n> continues**is not recognized) - For CRLF (
\r\n) input, callmarki::normalizebefore parsing