Spec Compliance
CommonMark
Showdown ships a commonmark flavor that makes the converter follow the
CommonMark spec. With this flavor enabled, Showdown passes
647 of the 652 examples in the CommonMark spec test suite. The handful of remaining
examples are intentional deviations, documented under Known differences.
Enabling CommonMark
The recommended way is to set the commonmark flavor, which turns on all of the CommonMark
options at once:
showdown.setFlavor('commonmark');
const converter = new showdown.Converter();
converter.setFlavor('commonmark');
const converter = new showdown.Converter(showdown.getFlavorOptions('commonmark'));
CommonMark options
CommonMark compliance is controlled by a single option, cmSpec
(boolean, default false, introduced in 3.0.0), plus the companion
decodeEntities option. The commonmark flavor turns
both on (along with noHeaderId and requireSpaceBeforeHeadingText). Prefer the flavor unless
you have a specific reason to set the options yourself.
cmSpec switches both block-level and inline parsing from Showdown's legacy matching to the
CommonMark spec. What it covers:
| Area | What it does |
|---|---|
| Emphasis | Parse emphasis / strong emphasis with the CommonMark delimiter-run (flanking) algorithm. |
| Autolinks | Recognize CommonMark autolinks <scheme:uri> and <email> without entity-encoding. |
| Links & images | Parse links, images and link reference definitions per the spec (balanced-paren and <...> destinations, backslash escapes, in-URL entity decoding, alt-text flattening). |
| Inline raw HTML | Recognize inline raw HTML with the strict CommonMark grammar; malformed tags are escaped instead of passed through. |
| HTML blocks | Recognize HTML blocks using the 7 CommonMark block types instead of Showdown's balanced-tag matching. |
| Block quotes | Parse block quotes as CommonMark container blocks (empty >, splitting at blank lines, lazy continuation). |
| Lists | Parse lists with a CommonMark container-block parser (marker/delimiter splitting, ordered start, loose/tight, indentation-based nesting). |
| Unified inline | Parse all inline content with a single unified CommonMark parser (one delimiter stack). |
| Tabs | Expand tabs to 4-column tab stops in block-structure indentation (content tabs are preserved). |
| Containers | Parse leaf blocks (fenced code, HTML blocks, link reference definitions, indented code) in the context of their containing block quote / list item. |
The separate decodeEntities option resolves HTML5 named
and numeric character references (©, #, ಫ) to their characters. It is kept
independent of cmSpec because it is also useful on its own.
Options that still apply under cmSpec
cmSpec only replaces the parsers for the constructs in the table above. Showdown's other options
keep working on top of it, so you can combine CommonMark parsing with Showdown/GFM extras:
| Group | Options |
|---|---|
| Inline extras | emoji, underline, strikethrough, ellipsis |
| Links & images | ghMentions, ghMentionsLink, simplifiedAutoLink, httpsAutoLinks, encodeEmails, parseImgDimensions, relativePathBaseUrl |
| Lists | tasklists, moreStyling |
| Tables | tables, tablesHeaderId |
| Code blocks | ghCodeBlocks, omitExtraWLInCodeBlocks |
| Headings | noHeaderId, prefixHeaderId, rawHeaderId, headerLevelStart, requireSpaceBeforeHeadingText |
| Document / misc | completeHTMLDocument, metadata, simpleLineBreaks, smartIndentationFix |
The links/images, underline and tasklists/moreStyling groups work under cmSpec as of
3.0.0 — the GFM extras are applied on top of the CommonMark constructs.
Options that have no effect under cmSpec
These tweak Showdown's legacy parsers, which cmSpec replaces with its own — so they are silently
ignored when cmSpec is on. In each case the CommonMark behavior is the intended one:
| Option | Why it is ignored |
|---|---|
literalMidWordUnderscores |
CommonMark's flanking rules already keep intra-word _ literal. |
disableForced4SpacesIndentedSublists |
The CommonMark list parser has its own indentation rules. |
splitAdjacentBlockquotes |
The CommonMark block-quote parser handles adjacency per spec. |
backslashEscapesHTMLTags |
cmSpec already escapes backslash-escaped </> via standard CommonMark backslash escapes. |
Known differences
The commonmark flavor diverges from the spec in a few intentional, documented ways.
Empty ATX headings
Showdown doesn't support empty headings (spec example 79).
#
<p>#</p>
<h1></h1>
Fenced-code language classes
For a fenced code block with an info string, CommonMark emits a single language-<lang> class.
Showdown emits both the bare language name and the language--prefixed class.
``` ruby
foo
```
<pre><code class="ruby language-ruby">foo
</code></pre>
<pre><code class="language-ruby">foo
</code></pre>
Other intentional deviations
A few spec examples are intentionally not followed because they are self-contradictory, malformed, or describe behavior that GitHub Flavored Markdown also rejects:
- Thematic breaks examples 43 and 61 (malformed input /
<hr>inside a list)
GitHub Flavored Markdown (GFM)
Showdown ships a gfm flavor (also reachable under its former name github, kept as an alias)
that targets the GitHub Flavored Markdown spec. GFM is defined as
CommonMark plus a set of extensions, so the flavor builds on cmSpec and layers the
GFM extensions (tables, task lists, strikethrough, autolink literals, @-mentions, emoji,
footnotes, …) on top. Footnotes are also reversible via
makeMarkdown (see HTML to Markdown).
Because the flavor uses the CommonMark base, every CommonMark known difference
also applies to gfm — empty ATX headings, the dual fenced-code language classes, and the
malformed thematic-break examples included. The items below are the additional, intentional
deviations specific to the GFM table extension.
Known differences (GFM extensions)
Table column alignment
GFM renders per-column alignment with the HTML align attribute. Showdown uses an inline
style="text-align:…" instead: the align attribute is obsolete in HTML5, so the CSS form is the
modern equivalent.
| abc | defghi |
| :-: | -----------: |
| bar | baz |
<th style="text-align:center;">abc</th>
<th style="text-align:right;">defghi</th>
<th align="center">abc</th>
<th align="right">defghi</th>
Empty table body
For a table with a header and delimiter row but no body rows, Showdown always emits an empty
<tbody></tbody>; GFM omits the <tbody> entirely. The empty element is invisible and most
browsers inject one anyway, so Showdown keeps its table output shape consistent regardless of
whether the table has body rows.
| abc | def |
| --- | --- |
<table>
<thead><tr><th>abc</th><th>def</th></tr></thead>
<tbody></tbody>
</table>
<table>
<thead><tr><th>abc</th><th>def</th></tr></thead>
</table>