mdz.ts

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.

view source

Declarations
#

18 declarations

mdz_parse
#

mdz.ts view source

(text: string): MdzNode[] import {mdz_parse} from '@fuzdev/mdz/mdz.js';

Parses text to an array of MdzNode.

Two phases: MdzLexer tokenizes the input into a flat MdzToken[] stream, then MdzTokenParser builds the MdzNode[] tree from the tokens.

text

type string

returns

MdzNode[]

MdzNode
#

MdzNodeBase
#

mdz.ts view source

MdzNodeBase import type {MdzNodeBase} from '@fuzdev/mdz/mdz.js';

type

type string

start

type number

end

type number

MdzNodeBlockquote
#

mdz.ts view source

MdzNodeBlockquote import type {MdzNodeBlockquote} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Blockquote'

children

Block children — a quote's content is a mini-document, so anything that can appear at the top level can appear here (Paragraph | Heading | Hr | List | Codeblock | Blockquote).

type Array<MdzNode>

MdzNodeBold
#

mdz.ts view source

MdzNodeBold import type {MdzNodeBold} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Bold'

children

type Array<MdzNode>

MdzNodeCode
#

mdz.ts view source

MdzNodeCode import type {MdzNodeCode} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Code'

content

The code content (identifier/module name).

type string

MdzNodeCodeblock
#

mdz.ts view source

MdzNodeCodeblock import type {MdzNodeCodeblock} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Codeblock'

lang

Language hint, if provided.

type string | null

content

Raw code content.

type string

MdzNodeComponent
#

mdz.ts view source

MdzNodeComponent import type {MdzNodeComponent} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Component'

name

Svelte component name (e.g. Alert, Card).

type string

children

type Array<MdzNode>

MdzNodeElement
#

mdz.ts view source

MdzNodeElement import type {MdzNodeElement} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Element'

name

HTML element name (e.g. div, span, aside).

type string

children

type Array<MdzNode>

MdzNodeHeading
#

mdz.ts view source

MdzNodeHeading import type {MdzNodeHeading} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Heading'

level

type 1 | 2 | 3 | 4 | 5 | 6

id

Slugified heading text for fragment links.

type string

children

Inline formatting allowed.

type Array<MdzNode>

MdzNodeHr
#

MdzNodeItalic
#

mdz.ts view source

MdzNodeItalic import type {MdzNodeItalic} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Italic'

children

type Array<MdzNode>

MdzNodeLink
#

MdzNodeList
#

mdz.ts view source

MdzNodeList import type {MdzNodeList} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'List'

ordered

type boolean

start_number?

First item's authored number (ordered only) — the <ol start> attribute.

type number

children

type Array<MdzNodeListItem>

MdzNodeListItem
#

mdz.ts view source

MdzNodeListItem import type {MdzNodeListItem} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'ListItem'

number?

Authored number (ordered only); the renderer ignores it, tooling and the future formatter use it.

type number

children

Inline run first, then block children (Paragraph | List | Codeblock | Blockquote).

type Array<MdzNode>

MdzNodeParagraph
#

mdz.ts view source

MdzNodeParagraph import type {MdzNodeParagraph} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Paragraph'

children

type Array<MdzNode>

MdzNodeStrikethrough
#

mdz.ts view source

MdzNodeStrikethrough import type {MdzNodeStrikethrough} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Strikethrough'

children

type Array<MdzNode>

MdzNodeText
#

mdz.ts view source

MdzNodeText import type {MdzNodeText} from '@fuzdev/mdz/mdz.js';

inheritance

extends: MdzNodeBase

type

type 'Text'

content

type string

Depends on
#

Imported by
#