# CommonMark Spec: The Test Suite Behind Modern Markdown Parsers

> The CommonMark repository holds the specification itself, not a parser. It defines what Markdown means and ships over 500 embedded examples that any implementation can run as conformance tests.

**commonmark/commonmark-spec** — CommonMark spec, with reference implementations in C and JavaScript

- Repository: https://github.com/commonmark/commonmark-spec
- Website: http://commonmark.org
- Stars: 5,149 · Forks: 359
- Language: Python
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/commonmark-commonmark-spec

## The Problem: Markdown Has No Single Definition

John Gruber's canonical syntax description leaves many aspects of the syntax undetermined, and the README says so directly. That gap is the reason this repository exists. Every Markdown implementation fills the blanks differently, so a document that renders one way in one tool can render another way in the next. CommonMark is a rationalized version of Markdown syntax with a written specification and BSD-licensed reference implementations in C and JavaScript. The audience is narrow and specific: people writing or maintaining a Markdown parser, people building tooling that has to agree with someone else's parser, and people who need to settle an argument about what a given construct should produce. If you just want to write Markdown in an editor, you are not the user. You are downstream of this repository, usually without knowing it.

## spec.txt, Embedded Examples and the Test Runner

The spec source is a single file, spec.txt. It is basically a Markdown file in which code examples use a shorthand form: a fenced block labelled example, the Markdown source, a line containing a single period, and the expected HTML output. Those examples double as conformance tests, and the README puts the count at over 500. The test runner lives in test/spec_tests.py. You point it at an executable with --program, and it feeds each example through that program and compares the output to the expected HTML. The same script can dump the tests as JSON with --dump-tests, which is how the data reaches other ecosystems. Building the human-readable spec goes through lua and a rock called lcmark: make spec.html for HTML, make spec.pdf for PDF, with xelatex required for the PDF path. The Makefile also defines spec.json, which pipes spec.txt through the dump-tests flag. Nothing in this pipeline parses Markdown itself. It extracts and formats test data.

## Installing and Running Your First Conformance Check

There is no install step for the spec. You clone the repository and run the Python test script against a parser you already have. The README gives this exact invocation, where $PROG is your executable:

```bash
python3 test/spec_tests.py --program $PROG
```

The script reads the examples out of spec.txt, runs each one through your program, and reports which ones disagree with the expected HTML. If you want the raw data instead of a pass or fail, dump it:

```bash
python3 test/spec_tests.py --dump-tests
```

The README states that this prints all the tests in JSON format. JavaScript developers get a shorter path, because the commonmark-spec npm package is published from this repository and exports an array called tests. Each element has the shape shown in the README:

```json
{
  "markdown": "Foo\nBar\n---\n",
  "html": "<h2>Foo\nBar</h2>\n",
  "section": "Setext headings",
  "number": 65
}
```

The markdown field is the input, html is the expected output, section names the part of the spec the example belongs to, and number identifies it. If you want the rendered spec rather than the tests, run make spec.html after installing lua and lcmark via luarocks install lcmark.

## Where the Spec Deliberately Departs From Original Markdown

The README lists the contradictions with Gruber's description, and they are worth reading before you assume your parser is wrong. All punctuation can be backslash-escaped, not just symbols with special meaning, because remembering which ones qualify proved impractical. A backslash at the end of a line is an alternative hard line break, supplementing the two-spaces rule that users kept complaining was invisible. Link syntax became more predictable: single quotes around a title are allowed in both inline and reference links, where Markdown.pl allowed them in only one context. HTML block rules differ, and the README argues the proposal avoids expensive backtracking and makes it easy to include Markdown inside HTML block-level tags. Adjacent blockquotes no longer collapse into one. Changing a bullet character, or switching between bullets and numbers, starts a new list. Ordered list items may use . or ), and changing the delimiter starts a new list. The start number of an ordered list is significant. Fenced code blocks are supported with backticks or tildes.

## What the Spec Refuses to Cover

The scope limitation is explicit. The README says the authors limited themselves to the basic elements in Gruber's description, eschewing extensions like footnotes and definition lists, on the reasoning that the core has to be right first. Tables are not in that list of extensions by accident: they are not part of the core spec, so an implementation that passes every embedded example can still fail on a table, because tables were never defined here. If your documents depend on tables, footnotes, or definition lists, this specification will not settle their behaviour, and the conformance suite will not catch a divergence. The README also notes the spec is written from the point of view of the human writer, not the computer reader. It is a declarative description of what counts as a block quote or a code block, not an algorithm. That choice makes the document readable, but it means implementers still translate prose into a parser, and two correct translations can differ at the edges.

## CommonMark Spec vs Markdown, and the Java Question

The comparison people reach for is CommonMark versus Markdown, and the repository answers it in its own terms: this is a rationalized version of Markdown syntax, meaning it keeps the familiar surface but pins down the undetermined parts. Original Markdown is a syntax description with gaps; CommonMark is the same idea with the gaps closed and a test suite attached. The trade-off is that some documents written against a permissive dialect will render differently here, which is why the README walks through the contradictions one by one rather than claiming compatibility. If you want a different implementation rather than a different specification, the README points to a wiki page listing third-party libraries in a dozen languages, and the two reference implementations live in separate repositories: cmark for C and commonmark.js for JavaScript. A Java implementation such as commonmark-java is not part of this repository. It is one of the third-party libraries, and its conformance depends on the version of the spec it targets, not on anything shipped here.

## Licence, Releases and the Cost of Tracking the Spec

The repository ships two licences with different jobs. The README describes the reference implementations as BSD-licensed, while package.json declares the npm package under CC-BY-SA-4.0. That split matters if you redistribute the spec text or the test data: the attribution and share-alike terms attach to the specification material, not to your parser. This is a description of what the files say, not legal advice. On upgrades, the version string lives in spec.txt and the Makefile reads it with a perl one-liner into SPECVERSION, then the npm target refuses to publish unless package.json carries the same version. So a spec bump and a package bump move together. The cost of tracking releases is the interesting part: the latest listed release is 0.31.2 from 2024-01-28, while the last push to the repository was on 2026-04-27. Long gaps between numbered releases are normal here, so a parser pinned to 0.31.1 or 0.31.0 is not necessarily stale, but it is not automatically current either. Check changelog.txt against the version field before deciding.

## Conclusion

Adopt this repository if you maintain a Markdown parser, write documentation tooling, or need a portable definition of Markdown behaviour; the spec.txt file and the test runner are the two artefacts you actually consume. Do not adopt it expecting a renderer, since the C and JavaScript reference implementations live in separate repositories, and the npm package only exports test data. Before committing, verify which spec version your parser targets by checking the version field in spec.txt against the changelog, then run python3 test/spec_tests.py --program with your own binary and inspect the failures section by section.

## FAQ

### What are the specifications of Markdown?

The canonical syntax description is John Gruber's, which the README notes leaves many aspects of the syntax undetermined. CommonMark is a rationalized version of Markdown syntax with a written spec and BSD-licensed reference implementations in C and JavaScript, and it documents where it contradicts the original description.

### Why would I use Markdown?

The README does not discuss the general case for Markdown. It is written for people implementing or testing it, and states that the spec is written from the point of view of the human writer rather than the computer reader.

### What is Markdown used for?

This repository treats it as a document format with a defined syntax: the spec describes the structural elements that make up a Markdown document, and the embedded examples pair Markdown source with the HTML it should produce.

### Is HTML the same as Markdown?

No, and this repository treats them as different things: the embedded examples pair Markdown source with expected HTML output, and the spec is a declarative description of what counts as a block quote, a code block, and other structural elements, not an HTML specification.

## Sources

- [commonmark/commonmark-spec on GitHub](https://github.com/commonmark/commonmark-spec)
- [Issues](https://github.com/commonmark/commonmark-spec/issues)
- [Project website](http://commonmark.org)
- [README](https://github.com/commonmark/commonmark-spec/blob/master/README.md)
- [Releases](https://github.com/commonmark/commonmark-spec/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/commonmark-commonmark-spec
