Which Markdown parsers apply emphasis delimiters inside words under CommonMark flanking rules
0 reputation · 01 Feb 2025, 16:35 UTC
0 reputation · 01 Feb 2025, 16:35 UTC
Predicting how emphasis delimiters are rendered inside words matters for documentation that contains identifiers, URLs and code-like text. The rendering is not uniform across Markdown implementations.
CommonMark defines left and right flanking rules for emphasis delimiters, which restricts underscore emphasis inside words while allowing asterisk emphasis under specific boundary conditions. The original Markdown specification does not formally define flanking rules, leaving treatment of constructs such as _foo_bar_ and *a*b* to implementation choice. The unresolved decision is whether emphasis should be permitted inside alphanumeric words, and how mixed delimiters like *_text_* are opened and closed.
Which Markdown implementations consistently apply CommonMark flanking rules for underscore versus asterisk? Does CommonMark 0.30 and later consistently disallow underscore emphasis inside words while permitting asterisk emphasis in some boundary cases? What remains unresolved about emphasis handling inside identifiers across CommonMark and original Markdown?
32775 reputation · 02 Feb 2025, 03:31 UTC
CommonMark-compliant reference implementations apply left and right flanking rules to emphasis delimiters. The canonical implementations are the C library cmark and the official ports that implement the CommonMark spec: commonmark.js, python-commonmark, and commonmark-java. These parsers treat * and _ differently under flanking and consistently disallow underscore emphasis inside words.
CommonMark 0.30 and later stabilised the flanking rules. Under those rules underscore emphasis is restricted inside words, while asterisk emphasis is less restrictive and can open/close at word boundaries where the preceding or following character is whitespace or punctuation.
Original Markdown as described by John Gruber does not formally define flanking rules. Parsers derived from the original spec such as Markdown.pl and many early PHP/Python ports historically allowed emphasis inside words for both * and _, leading to divergence from CommonMark. Mixed delimiters like *_text_* are evaluated as separate delimiters with their own flanking checks in CommonMark, which remains a common source of inconsistency in non-compliant parsers.
Many libraries advertise CommonMark support but deviate on emphasis edge cases, especially for underscores inside identifiers, URLs and code-like text. Mixed delimiter and consecutive delimiter sequences are the most common source of inconsistent rendering even among libraries that claim compliance. Exact behaviour for *_text_* and _*text*_ depends on the flanking status of each * and _ individually, not as a combined token.
Original Markdown leaves treatment of _foo_bar_ and *a*b* implementation-defined. There is no single authoritative behaviour for emphasis inside identifiers across original Markdown implementations.
To give a definitive recommendation for your documentation, which parser and version are you using in production?
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.