Top Related Projects
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
A markdown parser and compiler. Built for speed.
A bidirectional Markdown to HTML to Markdown converter written in Javascript
Markdown parser, done right. Commonmark support, extensions, syntax plugins, high speed - all in one. Gulp and metalsmith plugins available. Used by Facebook, Docusaurus and many others! Use https://github.com/breakdance/breakdance for HTML-to-markdown conversion. Use https://github.com/jonschlinkert/markdown-toc to generate a table of contents.
Quick Overview
CommonMark.js is a JavaScript implementation of the CommonMark specification for Markdown parsing and rendering. It provides a robust and standardized way to convert Markdown text into HTML, ensuring consistent output across different platforms and applications that adopt the CommonMark standard.
Pros
- Strict adherence to the CommonMark specification, ensuring compatibility and consistency
- High performance and efficiency in parsing and rendering Markdown
- Extensive test suite, covering a wide range of Markdown scenarios
- Well-documented API and easy integration into JavaScript projects
Cons
- Limited support for Markdown extensions beyond the CommonMark specification
- Larger file size compared to some simpler Markdown parsers
- May require additional configuration for specific use cases or custom formatting
Code Examples
- Basic Markdown to HTML conversion:
const commonmark = require('commonmark');
const reader = new commonmark.Parser();
const writer = new commonmark.HtmlRenderer();
const markdown = '# Hello, CommonMark!\n\nThis is **bold** text.';
const parsed = reader.parse(markdown);
const html = writer.render(parsed);
console.log(html);
- Customizing the HTML output:
const commonmark = require('commonmark');
const reader = new commonmark.Parser();
const writer = new commonmark.HtmlRenderer({
softbreak: '<br>',
safe: true
});
const markdown = 'Line 1\nLine 2\n\n<script>alert("XSS");</script>';
const parsed = reader.parse(markdown);
const html = writer.render(parsed);
console.log(html);
- Walking the AST (Abstract Syntax Tree):
const commonmark = require('commonmark');
const reader = new commonmark.Parser();
const markdown = '# Heading\n\nParagraph with *emphasis* and **strong** text.';
const parsed = reader.parse(markdown);
const walker = parsed.walker();
let event;
while ((event = walker.next())) {
if (event.entering) {
console.log(`Entering ${event.node.type}`);
} else {
console.log(`Leaving ${event.node.type}`);
}
}
Getting Started
To use CommonMark.js in your project, follow these steps:
-
Install the package using npm:
npm install commonmark
-
Import and use the library in your JavaScript code:
const commonmark = require('commonmark'); const reader = new commonmark.Parser(); const writer = new commonmark.HtmlRenderer(); const markdown = '# Hello, CommonMark!'; const parsed = reader.parse(markdown); const html = writer.render(parsed); console.log(html);
This will output the HTML representation of the Markdown input.
Competitor Comparisons
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
Pros of markdown-it
- More extensible with a plugin system
- Faster parsing and rendering performance
- Broader feature set beyond CommonMark specification
Cons of markdown-it
- Larger bundle size
- Slightly more complex API
- May introduce non-standard Markdown features
Code Comparison
markdown-it:
const md = require('markdown-it')();
const result = md.render('# Hello, world!');
commonmark.js:
const parser = new commonmark.Parser();
const renderer = new commonmark.HtmlRenderer();
const result = renderer.render(parser.parse('# Hello, world!'));
Additional Notes
Both markdown-it and commonmark.js are popular Markdown parsing libraries for JavaScript. commonmark.js focuses on strict adherence to the CommonMark specification, while markdown-it offers more flexibility and features.
markdown-it provides a simpler API for basic usage but allows for more advanced customization through its plugin system. It's well-suited for applications requiring extended Markdown features or performance optimization.
commonmark.js, being the reference implementation of CommonMark, ensures high compatibility with the specification. It's ideal for projects prioritizing standard compliance and simplicity over extensive features.
The choice between these libraries depends on project requirements, such as needed features, performance considerations, and the importance of strict CommonMark compliance.
A markdown parser and compiler. Built for speed.
Pros of marked
- Faster parsing and rendering speed
- More extensive feature set, including support for GitHub Flavored Markdown
- Larger community and more frequent updates
Cons of marked
- Less strict adherence to CommonMark specification
- Higher complexity, which may lead to more maintenance challenges
- Potentially less consistent output across different versions
Code Comparison
marked:
import { marked } from 'marked';
const html = marked.parse('# Heading\n\nSome **bold** text.');
console.log(html);
commonmark.js:
import { Parser, HtmlRenderer } from 'commonmark';
const parser = new Parser();
const renderer = new HtmlRenderer();
const ast = parser.parse('# Heading\n\nSome **bold** text.');
const html = renderer.render(ast);
console.log(html);
Both libraries aim to convert Markdown to HTML, but marked offers a simpler API with a single function call, while commonmark.js separates parsing and rendering steps. This separation in commonmark.js allows for more flexibility in handling the abstract syntax tree (AST) before rendering, but requires more code for basic usage.
A bidirectional Markdown to HTML to Markdown converter written in Javascript
Pros of Showdown
- More flexible and customizable with a wide range of extensions
- Easier to use and integrate, with a simpler API
- Supports browser-side conversion, making it suitable for client-side applications
Cons of Showdown
- Less strict adherence to CommonMark specification
- May produce inconsistent output across different versions or configurations
- Potentially slower performance for large documents
Code Comparison
Showdown:
var converter = new showdown.Converter();
var html = converter.makeHtml('# Hello, Markdown!');
CommonMark.js:
var reader = new commonmark.Parser();
var writer = new commonmark.HtmlRenderer();
var parsed = reader.parse('# Hello, Markdown!');
var html = writer.render(parsed);
Key Differences
- CommonMark.js focuses on strict compliance with the CommonMark specification, ensuring consistent output across implementations
- Showdown offers more built-in features and extensions, making it more versatile for various use cases
- CommonMark.js uses a separate parsing and rendering step, which can be beneficial for advanced use cases or custom rendering
Use Case Recommendations
- Choose Showdown for quick integration, client-side conversion, and when extensibility is important
- Opt for CommonMark.js when strict adherence to the CommonMark specification is crucial, or when working with large documents where performance is a concern
Markdown parser, done right. Commonmark support, extensions, syntax plugins, high speed - all in one. Gulp and metalsmith plugins available. Used by Facebook, Docusaurus and many others! Use https://github.com/breakdance/breakdance for HTML-to-markdown conversion. Use https://github.com/jonschlinkert/markdown-toc to generate a table of contents.
Pros of Remarkable
- Faster parsing and rendering performance
- More extensive configuration options and customization
- Supports plugins for extended functionality
Cons of Remarkable
- Less strict adherence to CommonMark specification
- May require more setup and configuration for basic usage
- Larger bundle size due to additional features
Code Comparison
Remarkable:
var md = new Remarkable();
var result = md.render('# Hello, world!');
CommonMark.js:
var reader = new commonmark.Parser();
var writer = new commonmark.HtmlRenderer();
var parsed = reader.parse("# Hello, world!");
var result = writer.render(parsed);
Key Differences
- Remarkable offers a simpler API for basic usage
- CommonMark.js provides a more modular approach with separate parser and renderer
- Remarkable includes built-in support for tables and other extensions
- CommonMark.js focuses on strict CommonMark compliance
Use Cases
- Choose Remarkable for projects requiring high performance and extensive customization
- Opt for CommonMark.js when strict CommonMark compliance is essential
Community and Maintenance
- Both projects are well-maintained and have active communities
- Remarkable has a larger user base and more frequent updates
- CommonMark.js is part of the official CommonMark project
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
commonmark.js
CommonMark is a rationalized version of Markdown syntax, with a spec and BSD-licensed reference implementations in C and JavaScript.
For more information, see http://commonmark.org.
This repository contains the JavaScript reference implementation. It provides a library with functions for parsing CommonMark documents to an abstract syntax tree (AST), manipulating the AST, and rendering the document to HTML or to an XML representation of the AST.
To play with this library without installing it, see the live dingus at http://try.commonmark.org/.
Installing
You can install the library using npm
:
npm install commonmark
This package includes the commonmark library and a
command-line executable, commonmark
.
For client-side use, you can use one of the single-file
distributions provided in the dist/
subdirectory
of the node installation (node_modules/commonmark/dist/
).
Use either commonmark.js
(readable source) or
commonmark.min.js
(minimized source).
Alternatively, bower install commonmark
will install
the needed distribution files in
bower_components/commonmark/dist
.
You can also use the version hosted by unpkg: for example, https://unpkg.com/commonmark@0.29.3/dist/commonmark.js for the unminimized version 0.29.3.
Building
Make sure to fetch dependencies with:
npm install
To run tests for the JavaScript library:
npm test
(Running the tests will also rebuild distribution files in
dist/
.)
To run benchmarks against some other JavaScript converters:
make bench
To start an interactive dingus that you can use to try out the library:
make dingus
Usage
Instead of converting Markdown directly to HTML, as most converters
do, commonmark.js
parses Markdown to an AST (abstract syntax tree),
and then renders this AST as HTML. This opens up the possibility of
manipulating the AST between parsing and rendering. For example, one
could transform emphasis into ALL CAPS.
Here's a basic usage example:
var reader = new commonmark.Parser();
var writer = new commonmark.HtmlRenderer();
var parsed = reader.parse("Hello *world*"); // parsed is a 'Node' tree
// transform parsed if you like...
var result = writer.render(parsed); // result is a String
The constructors for Parser
and HtmlRenderer
take an optional
options
parameter:
var reader = new commonmark.Parser({smart: true});
var writer = new commonmark.HtmlRenderer({sourcepos: true});
Parser
currently supports the following:
smart
: iftrue
, straight quotes will be made curly,--
will be changed to an en dash,---
will be changed to an em dash, and...
will be changed to ellipses.
Both HtmlRenderer
and XmlRenderer
(see below) support these options:
sourcepos
: iftrue
, source position information for block-level elements will be rendered in thedata-sourcepos
attribute (for HTML) or thesourcepos
attribute (for XML).safe
: iftrue
, raw HTML will not be passed through to HTML output (it will be replaced by comments), and potentially unsafe URLs in links and images (those beginning withjavascript:
,vbscript:
,file:
, and with a few exceptionsdata:
) will be replaced with empty strings.softbreak
: specify raw string to be used for a softbreak.esc
: specify a function to be used to escape strings. Its argument is the string.
For example, to make soft breaks render as hard breaks in HTML:
var writer = new commonmark.HtmlRenderer({softbreak: "<br />"});
To make them render as spaces:
var writer = new commonmark.HtmlRenderer({softbreak: " "});
XmlRenderer
serves as an alternative to HtmlRenderer
and
will produce an XML representation of the AST:
var writer = new commonmark.XmlRenderer({sourcepos: true});
The parser returns a Node. The following public properties are defined (those marked "read-only" have only a getter, not a setter):
type
(read-only): a String, one oftext
,softbreak
,linebreak
,emph
,strong
,html_inline
,link
,image
,code
,document
,paragraph
,block_quote
,item
,list
,heading
,code_block
,html_block
,thematic_break
.firstChild
(read-only): a Node or null.lastChild
(read-only): a Node or null.next
(read-only): a Node or null.prev
(read-only): a Node or null.parent
(read-only): a Node or null.sourcepos
(read-only): an Array with the following form:[[startline, startcolumn], [endline, endcolumn]]
.isContainer
(read-only):true
if the Node can contain other Nodes as children.literal
: the literal String content of the node or null.destination
: link or image destination (String) or null.title
: link or image title (String) or null.info
: fenced code block info string (String) or null.level
: heading level (Number).listType
: a String, eitherbullet
orordered
.listTight
:true
if list is tight.listStart
: a Number, the starting number of an ordered list.listDelimiter
: a String, either)
or.
for an ordered list.onEnter
,onExit
: Strings, used only forcustom_block
orcustom_inline
.
Nodes have the following public methods:
appendChild(child)
: Append a Nodechild
to the end of the Node's children.prependChild(child)
: Prepend a Nodechild
to the beginning of the Node's children.unlink()
: Remove the Node from the tree, severing its links with siblings and parents, and closing up gaps as needed.insertAfter(sibling)
: Insert a Nodesibling
after the Node.insertBefore(sibling)
: Insert a Nodesibling
before the Node.walker()
: Returns a NodeWalker that can be used to iterate through the Node tree rooted in the Node.
The NodeWalker returned by walker()
has two methods:
next()
: Returns an object with propertiesentering
(a boolean, which istrue
when we enter a Node from a parent or sibling, andfalse
when we reenter it from a child). Returnsnull
when we have finished walking the tree.resumeAt(node, entering)
: Resets the iterator to resume at the specified node and setting forentering
. (Normally this isn't needed unless you do destructive updates to the Node tree.)
Here is an example of the use of a NodeWalker to iterate through
the tree, making transformations. This simple example converts
the contents of all text
nodes to ALL CAPS:
var walker = parsed.walker();
var event, node;
while ((event = walker.next())) {
node = event.node;
if (event.entering && node.type === 'text') {
node.literal = node.literal.toUpperCase();
}
}
This more complex example converts emphasis to ALL CAPS:
var walker = parsed.walker();
var event, node;
var inEmph = false;
while ((event = walker.next())) {
node = event.node;
if (node.type === 'emph') {
if (event.entering) {
inEmph = true;
} else {
inEmph = false;
// add Emph node's children as siblings
while (node.firstChild) {
node.insertBefore(node.firstChild);
}
// remove the empty Emph node
node.unlink()
}
} else if (inEmph && node.type === 'text') {
node.literal = node.literal.toUpperCase();
}
}
Exercises for the reader: write a transform to
- De-linkify a document, transforming links to regular text.
- Remove all raw HTML (
html_inline
andhtml_block
nodes). - Run fenced code blocks marked with a language name through
a syntax highlighting library, replacing them with an
HtmlBlock
containing the highlighted code. - Print warnings to the console for images without image descriptions or titles.
Command line
The command line executable parses CommonMark input from the specified files, or from stdin if no files are specified, and renders the result to stdout as HTML. If multiple input files are specified, their contents are concatenated before parsing, with newlines between them.
commonmark inputfile.md > outputfile.html
commonmark intro.md chapter1.md chapter2.md > book.html
Use commonmark --help
to get a summary of options.
A note on security
The library does not attempt to sanitize link attributes or
raw HTML. If you use this library in applications that accept
untrusted user input, you should either enable the safe
option
(see above) or run the output through an HTML sanitizer to protect against
XSS attacks.
Performance
Performance is excellent, roughly on par with marked
. On a benchmark
converting an 11 MB Markdown file built by concatenating the Markdown
sources of all localizations of the first edition of
Pro Git by Scott
Chacon, the command-line tool, commonmark
is just a bit slower than
the C program discount
, roughly ten times faster than PHP Markdown,
a hundred times faster than Python Markdown, and more than
a thousand times faster than Markdown.pl
.
Here are some focused benchmarks of four JavaScript libraries (using versions available on 24 Jan 2015). They test performance on different kinds of Markdown texts. (Most of these samples are taken from the markdown-it repository.) Results show a ratio of ops/second (higher is better) against showdown (which is usually the slowest implementation). Versions: showdown 1.3.0, marked 0.3.5, commonmark.js 0.22.1, markdown-it 5.0.2, node 5.3.0. Hardware: 1.6GHz Intel Core i5, Mac OSX.
Sample | showdown | commonmark | marked | markdown-it |
---|---|---|---|---|
README.md | 1 | 3.6 | 3.1 | 3.9 |
block-bq-flat.md | 1 | 4.8 | 4.9 | 4.9 |
block-bq-nested.md | 1 | 11.9 | 6.8 | 10.7 |
block-code.md | 1 | 4.7 | 12.1 | 23.0 |
block-fences.md | 1 | 6.2 | 21.2 | 19.1 |
block-heading.md | 1 | 5.0 | 4.8 | 6.5 |
block-hr.md | 1 | 3.5 | 3.3 | 3.5 |
block-html.md | 1 | 2.1 | 0.9 | 3.8 |
block-lheading.md | 1 | 5.1 | 4.9 | 3.9 |
block-list-flat.md | 1 | 4.7 | 4.4 | 7.4 |
block-list-nested.md | 1 | 9.5 | 7.8 | 17.6 |
block-ref-flat.md | 1 | 0.8 | 0.5 | 0.6 |
block-ref-nested.md | 1 | 0.7 | 0.6 | 0.9 |
inline-autolink.md | 1 | 2.3 | 3.4 | 2.5 |
inline-backticks.md | 1 | 7.6 | 5.3 | 8.2 |
inline-em-flat.md | 1 | 1.5 | 1.1 | 1.6 |
inline-em-nested.md | 1 | 1.8 | 1.3 | 1.7 |
inline-em-worst.md | 1 | 2.4 | 1.5 | 2.5 |
inline-entity.md | 1 | 2.0 | 3.8 | 2.7 |
inline-escape.md | 1 | 2.2 | 1.4 | 5.0 |
inline-html.md | 1 | 2.9 | 3.7 | 3.3 |
inline-links-flat.md | 1 | 2.7 | 2.7 | 2.2 |
inline-links-nested.md | 1 | 1.4 | 0.5 | 0.5 |
inline-newlines.md | 1 | 2.3 | 2.0 | 3.5 |
lorem1.md | 1 | 6.0 | 2.9 | 3.3 |
rawtabs.md | 1 | 4.6 | 3.9 | 6.7 |
To generate this table:
make bench-detailed
Authors
John MacFarlane wrote the first version of the JavaScript implementation. The block parsing algorithm was worked out together with David Greenspan. KÄrlis GaÅÄ£is helped work out a better parsing algorithm for links and emphasis, eliminating several worst-case performance issues. Vitaly Puzrin has offered much good advice about optimization and other issues.
Top Related Projects
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
A markdown parser and compiler. Built for speed.
A bidirectional Markdown to HTML to Markdown converter written in Javascript
Markdown parser, done right. Commonmark support, extensions, syntax plugins, high speed - all in one. Gulp and metalsmith plugins available. Used by Facebook, Docusaurus and many others! Use https://github.com/breakdance/breakdance for HTML-to-markdown conversion. Use https://github.com/jonschlinkert/markdown-toc to generate a table of contents.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot