Skip to content

Syntax

The whole language, on one page. Five block types and five inline forms: all of them Markdown, meaning exactly what you expect.

There is one place where simplemark is narrower than CommonMark, and it is the reason the format exists: the flanking rule.

Blocks

Blocks are separated by blank lines.

Block Spelling
Paragraph consecutive non-blank lines
Heading # Title through ###### Title
Verbatim a blank line, then lines indented by 4; or a ``` fence
Bullet list - item
Ordered list 1. item

Paragraphs

Consecutive non-blank lines are one paragraph, joined and reflowed to the reader's width. Line breaks in the source are not preserved; the whitespace between words is.

Reformat the single paragraph so it fits in lines
of no more than the given width.

No block may interrupt a paragraph

This is the most important rule in the language, and the one that differs most from CommonMark. A -, 1. or ``` at the start of a line is a block marker only when the previous line is blank.

Docstrings are hard-wrapped, so a sentence can easily put a number at the start of a line by accident:

My favourite number is probably the number
1. It is the smallest natural number.

CommonMark turns that into a paragraph followed by an ordered list. Simplemark leaves it as one paragraph and tells you CommonMark would disagree (CM002). There is also no lazy continuation, for the same reason.

Headings

# Module overview

## Parameters

One to six #, a space, then the text. A trailing run of # is dropped, as in CommonMark. #NoSpace is not a heading.

Headings are in the language on familiarity grounds rather than on evidence: 7 docstrings in 7272 use them. Markdown without # surprises people, so they are here.

With no styling available they render underlined, so the distinction survives a dumb terminal:

Module overview
===============

Verbatim blocks

Content that must survive exactly: doctests, examples, aligned tables. A blank line, then indent by four.

The recognised escapes are:

    "\n"     newline
    "\t"     tab

A ``` fence works too, and is the only way to hold content that starts with something that looks like markup. Common indentation is removed, internal indentation is kept.

Note that :: is not special; that is reStructuredText. Example:: renders with both colons and earns L001 under --compat.

Lists

- one
- two
- three

1. first
2. second

Only - for bullets, only N. for ordered. Continuation lines align under the text:

- a long item that runs past the width and
  continues here, aligned under the text

A sublist needs a preceding blank line:

- fruits

  - apple
  - orange

An item can hold several blocks, including verbatim ones, as long as they stay indented.

Inline

Inline Canonical Also accepted
Code ``x`` `x`
Strong **x**
Emphasis *x*
Link <https://example.com> [text](url)
Escape \ before a character simplemark uses

Code spans

Raises ``ValueError`` if ``n`` is negative.

This is the answer to "how do I mark a parameter name". CommonMark's rule: a run of backticks closed by an equal run, so `x`, ``x`` and ```x``` are all the same thing, and doubling lets the content hold a backtick.

Emphasis and strong

Set *followlinks* to visit symlinks.
This is a **breaking change**.

Inline markup does not nest. **bold with ``code`` inside** keeps the backticks literal, because reST forbids nesting and simplemark follows reST. This is why the parser needs no delimiter stack.

The flanking rule

One rule replaces CommonMark's seventeen:

A * or ** run opens only if preceded by the start of the text, whitespace, or opening punctuation, and followed by a non-space. It closes only if preceded by a non-space and followed by the end of the text, whitespace, or closing punctuation.

Emphasis therefore never occurs inside a word, which is what makes Python prose safe with no escaping:

Text Result
Set *followlinks* to True. emphasis on followlinks
Call f(*args, **kwargs) literal
Compute 10**e literal
x = xc*10**xe, compute x**y. literal
The __init__ method literal
Matches *.py globs literal

The last four are all mangled by CommonMark. See what it leaves out for the measurements.

See <https://example.com> for details.

Both forms. Neither is broken across lines by reflow. [bracketed] prose stays literal; 349 stdlib docstrings contain it and none can be confused with a link, because a link needs the following (.

Escapes

A backslash before a character simplemark assigns meaning to makes it literal:

A literal \*star\* and \`tick\`.

The escapable set is deliberately small (only the characters the language actually uses), so \d, \n and C:\dir stay literal in ordinary prose with no doubling.

Preprocessing

Before parsing, simplemark normalises line endings, expands tabs to four columns, strips trailing whitespace, drops leading and trailing blank lines, and removes the docstring's margin.

The margin is not computed the way inspect.cleandoc computes it. See the rationale; cleandoc flattens a verbatim block when that block is the only indented content in the docstring, which affects 179 standard library docstrings.

Complete example

# Conversion

Convert `source` between formats.

The recognised escapes are:

    "\n"     newline
    "\t"     tab

Set *strict* to raise on an unknown escape.  The **default**
copies it through unchanged.

- accepts `str` and `bytes`
- returns the same type it was given

See <https://example.com/formats>.

That uses every construct in the language.