small, safe, and great commonmark (optionally gfm, mdx) compliant markdown parser
[![Build][build-badge]][build]
[![Coverage][coverage-badge]][coverage]
[![Downloads][downloads-badge]][downloads]
[![Size][bundle-size-badge]][bundle-size]
[![Sponsors][sponsors-badge]][opencollective]
[![Backers][backers-badge]][opencollective]
[![Chat][chat-badge]][chat]
The smallest CommonMark compliant markdown parser.
With positional info and concrete tokens.
## Feature highlights
* [x] **[compliant][commonmark]** (100% to CommonMark)
* [x] **[extensions][]** (100% [GFM][], 100% [MDX.js][mdxjs], [directives][],
[frontmatter][], [math][])
* [x] **[safe][security]** (by default)
* [x] **[robust][test]** (±2k tests, 100% coverage, fuzz testing)
* [x] **[small][size-debug]** (smallest CM parser at ±14kb)
## Contents
* [When should I use this?](#when-should-i-use-this)
* [What is this?](#what-is-this)
* [Install](#install)
* [Use](#use)
* [API](#api)
* [Extensions](#extensions)
* [List of extensions](#list-of-extensions)
* [`SyntaxExtension`](#syntaxextension)
* [`HtmlExtension`](#htmlextension)
* [Extending markdown](#extending-markdown)
* [Creating a micromark extension](#creating-a-micromark-extension)
* [Architecture](#architecture)
* [Overview](#overview)
* [Preprocess](#preprocess)
* [Parse](#parse)
* [Postprocess](#postprocess)
* [Compile](#compile)
* [Examples](#examples)
* [GitHub flavored markdown (GFM)](#github-flavored-markdown-gfm)
* [Math](#math)
* [Syntax tree](#syntax-tree)
* [Markdown](#markdown)
* [CommonMark](#commonmark)
* [Grammar](#grammar)
* [Project](#project)
* [Comparison](#comparison)
* [Test](#test)
* [Size & debug](#size--debug)
* [Version](#version)
* [Security](#security)
* [Contribute](#contribute)
* [Sponsor](#sponsor)
* [Origin story](#origin-story)
* [License](#license)
## When should I use this?
* If you *just* want to turn markdown into HTML (with maybe a few extensions)
* If you want to do *really complex things* with markdown
See [§ Comparison][comparison] for more info
## What is this?
`micromark` is an open source markdown parser written in JavaScript.
It’s implemented as a state machine that emits concrete tokens, so that every
byte is accounted for, with positional info.
It then compiles those tokens directly to HTML, but other tools can take the
data and for example build an AST which is easier to work with
([`mdast-util-to-markdown`][mdast-util-to-markdown]).
While most markdown parsers work towards compliancy with CommonMark (or GFM),
this project goes further by following how the reference parsers (`cmark`,
`cmark-gfm`) work, which is confirmed with thousands of extra tests.
Other than CommonMark and GFM, micromark also supports common extensions to
markdown such as MDX, math, and frontmatter.
These npm packages have a sibling project in Rust:
[`markdown-rs`][markdown-rs].
* to learn markdown, see this [cheatsheet and tutorial][cheat]
* for more about us, see [`unifiedjs.com`][site]
* for questions, see [Discussions][chat]
* to help, see [contribute][] and [sponsor][] below
## Install
This package is [ESM only][esm].
In Node.js (version 16+), install with [npm][]:
```sh
npm install micromark
```
In Deno with [`esm.sh`][esmsh]:
```js
import {micromark} from 'https://esm.sh/micromark@3'
```
In browsers with [`esm.sh`][esmsh]:
```html
```
## Use
Typical use (buffering):
```js
import {micromark} from 'micromark'
console.log(micromark('## Hello, *world*!'))
```
Yields:
```html
Hello, world!
```
You can pass extensions (in this case [`micromark-extension-gfm`][gfm]):
```js
import {micromark} from 'micromark'
import {gfmHtml, gfm} from 'micromark-extension-gfm'
const value = '* [x]
[email protected] ~~strikethrough~~'
const result = micromark(value, {
extensions: [gfm()],
htmlExtensions: [gfmHtml()]
})
console.log(result)
```
Yields:
```html
```
Streaming interface:
```js
import {createReadStream} from 'node:fs'
import {stream} from 'micromark/stream'
createReadStream('example.md')
.on('error', handleError)
.pipe(stream())
.pipe(process.stdout)
function handleError(error) {
// Handle your error here!
throw error
}
```
## API
See [§ API][api] in the `micromark` readme.
## Extensions
micromark supports extensions.
There are two types of extensions for micromark:
[`SyntaxExtension`][syntax-extension],
which change how markdown is parsed, and [`HtmlExtension`][html-extension],
which change how it compiles.
They can be passed in [`options.extensions`][api-option-extensions] or
[`options.htmlExtensions`][api-option-htmlextensions], respectively.
As a user of extensions, refer to each extension’s readme for more on how to use
them.
As a (potential) author of extensions, refer to
[§ Extending markdown][extending-markdown] and
[§ Creating a micromark extension][create-extension].
### List of extensions
* [`micromark/micromark-extension-directive`][directives]
— support directives (generic extensions)
* [`micromark/micromark-extension-frontmatter`][frontmatter]
— support frontmatter (YAML, TOML, etc)
* [`micromark/micromark-extension-gfm`][gfm]
— support GFM (GitHub Flavored Markdown)
* [`micromark/micromark-extension-gfm-autolink-literal`](https://github.com/micromark/micromark-extension-gfm-autolink-literal)
— support GFM autolink literals
* [`micromark/micromark-extension-gfm-footnote`](https://github.com/micromark/micromark-extension-gfm-footnote)
— support GFM footnotes
* [`micromark/micromark-extension-gfm-strikethrough`](https://github.com/micromark/micromark-extension-gfm-strikethrough)
— support GFM strikethrough
* [`micromark/micromark-extension-gfm-table`](https://github.com/micromark/micromark-extension-gfm-table)
— support GFM tables
* [`micromark/micromark-extension-gfm-tagfilter`](https://github.com/micromark/micromark-extension-gfm-tagfilter)
— support GFM tagfilter
* [`micromark/micromark-extension-gfm-task-list-item`](https://github.com/micromark/micromark-extension-gfm-task-list-item)
— support GFM tasklists
* [`micromark/micromark-extension-math`][math]
— support math
* [`micromark/micromark-extension-mdx`](https://github.com/micromark/micromark-extension-mdx)
— support MDX
* [`micromark/micromark-extension-mdxjs`][mdxjs]
— support MDX.js
* [`micromark/micromark-extension-mdx-expression`][mdx-expression]
— support MDX (or MDX.js) expressions
* [`micromark/micromark-extension-mdx-jsx`](https://github.com/micromark/micromark-extension-mdx-jsx)
— support MDX (or MDX.js) JSX
* [`micromark/micromark-extension-mdx-md`](https://github.com/micromark/micromark-extension-mdx-md)
— support misc MDX changes
* [`micromark/micromark-extension-mdxjs-esm`](https://github.com/micromark/micromark-extension-mdxjs-esm)
— support MDX.js import/exports
#### Community extensions
* [`wataru-chocola/micromark-extension-definition-list`](https://github.com/wataru-chocola/micromark-extension-definition-list)
— support definition lists
### `SyntaxExtension`
A syntax extension is an object whose fields are typically the names of hooks,
referring to where constructs “hook” into.
The fields at such objects are character codes, mapping to constructs as values.
The built in [constructs][] are an example.
See it and [existing extensions][extensions] for inspiration.
### `HtmlExtension`
An HTML extension is an object whose fields are typically `enter` or `exit`
(reflecting whether a token is entered or exited).
The values at such objects are names of tokens mapping to handlers.
See [existing extensions][extensions] for inspiration.
### Extending markdown
micromark lets you change markdown syntax, yes, but there are alternatives.
The alternatives are often better.
Over the years, many micromark and remark users have asked about their unique
goals for markdown.
Some exemplary goals are:
1. I want to add `rel="nofollow"` to external links
2. I want to add links from headings to themselves
3. I want line breaks in paragraphs to become hard breaks
4. I want to support embedded music sheets
5. I want authors to add arbitrary attributes
6. I want authors to mark certain blocks with meaning, such as tip, warning,
etc
7. I want to combine markdown with JS(X)
8. I want to support our legacy flavor of markdown-like syntax
These can be solved in different ways and which solution is best is both
subjective and dependent on unique needs.
Often, there is already a solution in the form of an existing remark or rehype
plugin.
Respectively, their solutions are:
1. [`remark-external-links`](https://github.com/remarkjs/remark-external-links)
2. [`rehype-autolink-headings`](https://github.com/rehypejs/rehype-autolink-headings)
3. [`remark-breaks`](https://github.com/remarkjs/remark-breaks)
4. custom plugin similar to
[`rehype-katex`](https://github.com/remarkjs/remark-math/tree/main/packages/rehype-katex)
but integrating [`abcjs`](https://www.abcjs.net)
5. either [`remark-directive`][remark-directive]
and a custom plugin or with
[`rehype-attr`](https://github.com/jaywcjlove/rehype-attr)
6. [`remark-directive`][remark-directive]
combined with a custom plugin
7. combining the existing micromark MDX extensions however you please, such as
done by [`mdx-js/mdx`][mdx] or
[`xdm`](https://github.com/wooorm/xdm)
8. Writing a micromark extension
Looking at these from a higher level, they can be categorized:
* **Changing the output by transforming syntax trees**
(1 and 2)
This category is nice as the format remains plain markdown that authors are
already familiar with and which will work with existing tools and platforms.
Implementations will deal with the syntax tree
([`mdast`][mdast]) and the ecosystems
**[remark][]** and **[rehype][]**.
There are many existing
[utilities for working with that tree][utilities].
Many [remark plugins][remark-plugins] and
[rehype plugins][rehype-plugins] also exist.
* **Using and abusing markdown to add new meaning**
(3, 4, potentially 5)
This category is similar to *Changing the output by transforming syntax
trees*, but adds a new meaning to certain things which already have
semantics in markdown.
Some examples in pseudocode:
````markdown
* **A list item with the first paragraph bold**
And then more content, is turned into `` / `` / `` elements
Or, the title attributes on links or images is [overloaded](/url 'rel:nofollow')
with a new meaning.
```csv
fenced,code,can,include,data
which,is,turned,into,a,graph
```
```js data can="be" passed=true
// after the code language name
```
HTML, especially comments, could be used as **markers**
````
* **Arbitrary extension mechanism**
(potentially 5; 6)
This category is nice when content should contain embedded “components”.
Often this means it’s required for authors to have some programming
experience.
There are three good ways to solve arbitrary extensions.
**HTML**: Markdown already has an arbitrary extension syntax.
It works in most places and authors are already familiar with the syntax,
but it’s reasonably hard to implement securely.
Certain platforms will remove HTML completely, others sanitize it to varying
degrees.
HTML also supports custom elements.
These could be used and enhanced by client side JavaScript or enhanced when
transforming the syntax tree.
**Generic directives**: although
[a proposal][directive-proposal]
and not supported on most platforms, directives do work with many tools
already.
They’re not the easiest to author compared to, say, a heading, but sometimes
that’s okay.
They do have potential: they nicely solve the need for an infinite number of
potential extensions to markdown in a single