CommonMark Specification and Test Cases
The `commonmark-spec` package provides the official CommonMark specification (`spec.txt`) and a comprehensive suite of over 500 conformance test cases in a machine-readable JSON format. It is a crucial resource for developers building or testing Markdown parsers and renderers that aim for CommonMark compatibility. This package primarily serves as a data source, not a Markdown processor itself; for implementations, refer to `commonmark.js` (JavaScript) or `cmark` (C). The current stable version is 0.31.2, released January 28, 2024. Releases generally occur with updates to the CommonMark specification, which includes clarifications, corrections, and sometimes minor syntactic adjustments. The package's core differentiator is its direct provision of the authoritative spec and its associated, extensive test suite, making it the definitive reference for CommonMark conformance testing.
Common errors
-
TypeError: Cannot destructure property 'tests' of 'commonmark-spec' as it is undefined.
cause Attempting to use `require('commonmark-spec')` with ES module destructuring syntax in a CommonJS environment, or in an environment where the package is treated as a default export rather than a named export.fixUse `const { tests } = require('commonmark-spec');` for CommonJS environments, or `import { tests } from 'commonmark-spec';` for ES Modules. Ensure your build configuration correctly handles ES modules if mixing syntax. -
Cannot read properties of undefined (reading 'markdown')
cause Accessing `tests[i].markdown` or similar where `tests[i]` might be `undefined` or the structure of a specific test object is unexpected, possibly due to filtering or out-of-bounds access.fixAlways add checks for array bounds (`i < tests.length`) and object property existence (e.g., `if (test && test.markdown)`) before accessing properties, especially if working with filtered or externally sourced test data.
Warnings
- breaking The format for embedded spec examples within `spec.txt` significantly changed in version 0.24. This affects users who directly parse `spec.txt` or use `spec_tests.py --dump-tests` from older versions, as the delimiters and overall structure for examples were revised. The `tests` array exported by the npm package, however, consistently uses the new JSON structure as shown in the README, so direct consumers of the `tests` array were primarily impacted by the *content* changes reflecting the new spec.
- breaking Starting with version 0.31.0, the `commonmark-spec` npm package (and the CommonMark spec itself) was relicensed under the Creative Commons Attribution-ShareAlike 4.0 International License (CC-BY-SA 4.0). Previous versions used a BSD license. This is a significant legal change that may require review for projects integrating this package.
- gotcha Terminology within the CommonMark specification has evolved. For example, 'horizontal rule' was renamed to 'thematic break' and 'header' to 'heading' in version 0.23. While this package primarily provides the spec and tests, these changes affect how properties or sections might be named or referenced within the `tests` array (e.g., `section` property in test objects).
- gotcha The `commonmark-spec` package exports the `tests` array directly from its main entry point, and the raw `spec.txt` file is not a direct named export. Attempting `import { spec } from 'commonmark-spec'` will fail. To access `spec.txt` content, a bundler-specific raw loader or direct file system access (in Node.js) is typically required.
Install
-
npm install commonmark-spec -
yarn add commonmark-spec -
pnpm add commonmark-spec
Imports
- tests
const tests = require('commonmark-spec');import { tests } from 'commonmark-spec'; - spec
import { spec } from 'commonmark-spec';import spec from 'commonmark-spec/spec.txt?raw';
- CommonMarkTest
import type { CommonMarkTest } from 'commonmark-spec/dist/types';
Quickstart
import { tests } from 'commonmark-spec';
console.log(`Total CommonMark test cases: ${tests.length}`);
// Display the first few test cases
for (let i = 0; i < Math.min(3, tests.length); i++) {
const test = tests[i];
console.log(`\n--- Test Case ${test.number} (${test.section}) ---\n`);
console.log('Markdown Input:\n' + test.markdown.trim());
console.log('Expected HTML Output:\n' + test.html.trim());
}
// Example of how to filter tests for a specific section
const emphasisTests = tests.filter(test => test.section === 'Emphasis and strong emphasis');
console.log(`\nNumber of emphasis tests: ${emphasisTests.length}`);