StrictMark: rational Markdown

Markdown is a wonderful lightweight markup — minimal, easy to read and write, widely supported — but precedent-based: it codified diverse practices, so it is messy and inconsistent. StrictMark is Markdown refactored: a rational subset that keeps every feature while shrinking the grammar to its shortest formal form, for a uniform, unambiguous syntax. It reuses existing Markdown tooling without legacy weight, and is the markup every Beagle wiki page uses, from the Home overview to the Verbs vocabulary.

Markdown critique

Markdown implementations disagree — Vim, VS Code, and the output HTML all differ — and the textbook fix, a formal grammar, is blocked by the syntax itself: every element has its own shape and those shapes interact, so N elements spawn N×N corner cases.

StrictMark principles

StrictMark makes a Markdown subset a proper markup language by formalizing its grammar — a minimal hypertext markup, not an elephantine HTML engine. Feature sprawl is held back by transclusion, not new syntax. This document is itself StrictMark.

The block layer

Every line carries its markup at line start, in 4-char quads — the block stack — as (INDENT|QUOTE)* (LIST|LEAF)?; absent a leaf, a paragraph is implied. One line, one classification: a line whose prefix is off-grammar is a paragraph, and nothing later can reinterpret it.

The inline layer

Markdown inline markup looks easy but is not: ambiguity makes it hard to implement. StrictMark treats it all as bracketing — brackets matched by regex, effective only when they satisfy precedence. The cuts are deliberate; inline formatting is secondary by design.

Block elements

Every block element in three aspects: its quad shape, its same-line content, and its deeper-line content mode. Every block ends at a dedent — the one law needs no column; the paragraph is the exception, joining same-depth lines until a blank or a marker. The div and the quote are prefix quads — repeatable, nesting containers; the rest are markers, plus the markerless paragraph.

    element    quad shape        same line          one quad deeper
    ---------  ----------------  -----------------  ----------------
    div        4 sp / one tab    rest of the stack  child blocks
    quote      '>' + 3 sp        rest of the stack  child blocks
    bullet     '-' + 3 sp        item text          child blocks
    numbered   1-3 digits, '.'   item text          child blocks
    todo       '-[' state ']'    item text          child blocks
    header     1-4 '#', padded   header text        header text
    fence      4 backticks       info string        verbatim bytes
    ref def    '[x]:'            url "title"        url/title text
    meta pair  Key + ':'         verbatim value     more value text
    ruler      4 dashes          caption text       caption text
    paragraph  (none)            inline text        (same-depth join)

Headers

StrictMark allows four header levels, ATX only. The marker is a run of 1-4 # filling one quad, padded with spaces in any column; the level is the COUNT of #, and a full quad needs no gap space. A header may span lines: its text continues one quad deeper, joined into one heading.

    #   Top header
    ##  Subheader
    ### Small header
    #### Smallest header
      # padding sits in any column
    ####Smallest, gapless

Lists

The unordered marker is the dash -; * is dropped as ambiguous and + as unpopular — there must be one way only. Ordered lists use 12. (digits then dot), again four chars per level; a TODO item is a dash plus a bracketed one-char state, -[ ], its own four-char block.

    -   bulleted item
    -   still bulleted
        1.  nested numbered list
        2.  more numbered
        plain paragraph, nested, indented 4 chars
    -   resume the bulleted list

Blockquotes

Blockquote markup is one > and three spaces, in any order — a prefix quad like the indent, so quotes nest and any block sits inside one (> 1. x is a numbered item in a quote). A quoted block's continuation lines repeat the same quote prefix; there is no indent-only continuation for quotes.

    >   #   Quoted header
    >   Quoted paragraph text.

Code blocks

A code block opens with a fence — four backticks, then optionally the info string naming the language. The body is verbatim, one quad deeper; the continuation law applies as everywhere, so a dedent ends the block and the closing fence is optional.

    console.log("JavaScript is the best worst lang ever");

Rulers

The ruler is a quad of four dashes, optionally followed by a caption — ---- cut at this line — that continues one quad deeper like header text. The dash run stops at four: a fifth dash makes the line a paragraph, never a ruler captioned with dashes. The legacy 3-dash form is accepted on read.

Meta pairs

A meta pair is a leaf block carrying machine-readable page metadata: a capitalized three-letter key, a colon, the gap space, then the value — Who: gritzko. Key plus colon is exactly four chars, a native-width marker. The grammar fixes only the shape; each pocket registers the keys it recognizes (todo lists the ticket keys) and unknown keys are legal markup with no semantics.

Spans

The emphasis family is one bracket template: a single-character symmetric pair whose opener touches the following non-space. Code spans and escapes are the two degenerate brackets — one with a verbatim body, one with a one-char body.

Links, images, transclusion

StrictMark links come in exactly two cases, both defined out of line: an explicit [text text][l] pairing any display text with a one-symbol label l, and a shortcut [page] that keys on the bracket text, so a page name is its own key.

    see [Replicated Object Notation][1]
    [1]: http://doc.replicated.cc/ron.sm "What is RON"

    a bare [StrictMark] link, defined below
    [StrictMark]: StrictMark.mkd "the markup"

    ![here is the table][T]
    [T]: /table?@tab "this might be any object"

CommonMark compatibility

StrictMark is a CommonMark subset in spirit and most pages render fine on GitHub raw; the divergences below are declared, and a few writing conventions keep the rendered output aligned. When the two disagree, StrictMark wins.

Grammar

The structural layer is a regular language and the inline layer is regex-matched brackets, so the whole parser stays compact. The canonical grammar lives in the Beagle source, not in prose — the block machine and the inline Ragel machine below.