Many Markdown surprises come from precedence, not bugs.
Practice focus
- Container vs leaf block resolution.
- Thematic break vs list marker conflicts.
- Paragraph interruption rules.
Why precedence is central to Markdown
Markdown syntax looks simple because punctuation is reused in intuitive ways. The same characters, however, can have different meanings depending on position and context. A dash can be part of normal prose, a list marker, a thematic break, or a setext heading underline. A hash sign can be text, an escaped character, or a heading marker. A greater-than sign can be a literal character, raw HTML, or a block quote marker. Precedence rules decide which interpretation wins.
CommonMark makes these decisions explicit. The parser does not evaluate every possible interpretation equally and then choose the one a human might prefer. It follows deterministic rules. Block structure is recognized before inline structure. Some block constructs can interrupt paragraphs and others cannot. When two block interpretations are possible, the specification defines which one takes priority.
This matters because Markdown documents often evolve over time. A line that was ordinary prose can become syntax after a small edit. A documentation page might gain a list, a thematic break, or a heading without the author realizing a nearby line changed interpretation. Understanding precedence lets you predict these shifts instead of discovering them after publishing.
Block parsing as a state machine
A practical way to understand block parsing is to imagine a parser moving line by line while maintaining state. It knows whether it is inside a list item, block quote, code block, HTML block, or paragraph. Each new line either continues the current structure, opens a new block, closes one or more containers, or becomes part of a paragraph.
Container blocks are especially stateful. A block quote can continue across multiple lines. A list item can contain multiple paragraphs and nested structures. Indentation determines whether a line belongs to the current container or starts something outside it. Blank lines can loosen list tightness or separate paragraphs. The parser’s job is to convert that sequence of lines into a tree.
Because Markdown allows lazy continuation in some contexts, visual alignment is not always the same as structural nesting. A line inside a paragraph in a block quote may continue without a repeated > marker. This is convenient for authors, but it also means that parser state matters more than appearance. When debugging nested Markdown, always ask what container the parser is currently inside.
Paragraph interruption
Paragraph interruption is one of the most important sources of edge cases. A normal paragraph can be interrupted by some block starts. For example, an ATX heading can interrupt a paragraph in CommonMark. Thematic breaks can also interrupt paragraphs. Indented code blocks cannot interrupt paragraphs in the same way, which helps preserve ordinary indented prose.
The reason for these rules is compatibility and readability. If every indented line became code immediately, many ordinary documents would break. If headings required blank lines everywhere, authors would find the syntax less forgiving. CommonMark balances historical Markdown behavior with precise parsing.
For robust writing, use blank lines around major block structures even when the parser does not require them. This improves portability and readability. It also reduces the chance that another dialect or renderer will interpret the boundary differently.
Ambiguous examples
Consider a line of three dashes after text. It may become a setext heading underline, not a thematic break. That is because setext heading interpretation can take precedence in the right context. If you intended a horizontal rule, use blank lines or a different marker pattern such as ***. If you intended a heading, be aware that the previous paragraph line may be consumed as the heading text.
Now consider a list followed by a line that looks like a thematic break. Depending on the marker and indentation, it may terminate the list, become a thematic break inside a list item, or start a new structure. These distinctions matter when writing changelogs, tutorials, and API docs because list structure affects generated HTML and accessibility.
Another common issue is accidental ordered lists. A line beginning with 1986. can be parsed as an ordered list item. If the number is part of a sentence, escape the period: 1986\. in source. This is not a parser bug. It is the expected result of ordered list marker recognition.
Testing precedence with Dingus
The CommonMark Dingus is the fastest way to build intuition. Paste a small ambiguous sample, inspect the HTML, then change one character. Add a blank line. Escape a marker. Change indentation. Switch --- to ***. You will quickly see which rule is responsible for the output.
This habit is valuable for teams. Instead of debating what Markdown should do, you can link to a spec example or produce a minimal Dingus case. That changes the conversation from opinion to reproducible behavior.
Production implications
In a production Markdown system, precedence rules affect more than preview rendering. They affect search extraction, table of contents generation, heading anchors, document splitting, preview diffs, and content validation. If a heading fails to parse as a heading, it may disappear from navigation. If a list becomes loose unexpectedly, rendered spacing changes. If a code block swallows text, a tutorial can become unreadable.
For this reason, authoring guidelines should include precedence-aware rules. Require blank lines around headings and thematic breaks. Recommend consistent list markers. Encourage fenced code blocks instead of indentation for technical examples. Use linting where possible. These simple policies reduce the surface area of parser surprises.
FAQ
What is Markdown precedence?
Markdown precedence is the set of rules that decides which interpretation wins when source text could match multiple syntax constructs.
Why does block syntax beat inline syntax?
CommonMark parses block structure before inline content. This makes the document tree deterministic and explains why list markers or headings can win over inline-looking text.
Why did my horizontal rule become a heading?
A line of dashes after paragraph text can be interpreted as a setext heading underline. Add blank lines or use another thematic break marker if you want a horizontal rule.
How can I avoid accidental lists?
Escape the period in number-like text at the beginning of a line, or rewrite the sentence so it does not match ordered list marker syntax.
Should I rely on optional blank-line behavior?
For portability, no. Even when CommonMark permits interruption, blank lines improve readability and reduce cross-renderer surprises.
Related tutorials
- Review the underlying tree in CommonMark Document Model.
- Practice block constructs in Markdown Headings, Paragraphs, Line Breaks, and Thematic Breaks.
- Continue container behavior in Markdown Lists, Blockquotes, and Container Blocks.
- Validate examples with CommonMark Test Suite and Dingus.
- Explore implementation strategy in Markdown Parser Implementation Theory.
Continue with Headings, Paragraphs, and Line Breaks.