mdz — strict markdown dialect built for streaming, Svelte authoring, docs
sites, and untrusted content.
Created for two motivating use cases: rendering TSDoc/JSDoc comments on
docs websites (with domain-specific behavior like linkifying backticked
identifiers) and authoring content with Svelte components. It also has a
streaming parser that extends the same grammar to LLM output.
This module is the synchronous entry: mdz_parse parses a complete string
to an MdzNode tree. It is the canonical reference parser — the streaming
pipeline (mdz_stream_parser.ts) emits opcodes that converge on the same
tree, asserted by parity tests.
The dialect supports:
- inline formatting:
code, bold, italic, strikethrough - auto-detected links: external URLs (
https://...) and internal paths (/path) - markdown links:
[text](url) with custom display text - inline code in backticks (creates
Code nodes; auto-linking to identifiers/modules
is handled by the rendering layer via MdzNodeView.svelte) - paragraph breaks (blank lines)
- block elements: headings, horizontal rules, lists, blockquotes, code blocks
- HTML elements and Svelte components (opt-in via context)
Whitespace: the parser preserves whitespace in text node content (single
newlines stay literal \n, no <br> nodes), while structural whitespace is
interpreted — blank lines separate paragraphs, extra blank lines collapse,
and a line of only whitespace (spaces, tabs, \r) counts as blank, so an
invisible trailing space never changes document structure.
Presentation is the renderer's choice: by default whitespace collapses like
standard markdown (single newlines are soft breaks), and the whitespace
prop on Mdz/MdzStream opts into pre-line or pre-wrap rendering.
Design philosophy
- False negatives over false positives: When in doubt, treat as plain text.
Block elements can interrupt paragraphs without blank lines; inline formatting is strict.
- One way to do things: Single unambiguous syntax per feature. No alternatives.
- Explicit over implicit: Clear delimiters and column-0 requirements avoid ambiguity.
- Simple over complete: Prefer simple parsing rules over complex edge case handling.
- No implicit retroactivity: the grammar admits no construct where later input changes
the rendering of unboundedly-earlier output, so the streaming pipeline corrects only via
bounded, explicit opcodes and never re-parses.
Status
Pre-stable — breaking changes are expected as the dialect matures.
Next: attributes, editing.