Open-source project
micromark/micromark avatar
micromark/micromark

micromark: a CommonMark parser built as a state machine that accounts for every byte

small, safe, and great commonmark (optionally gfm, mdx) compliant markdown parser

2,232 stars97 forksJavaScriptMIT

At a glance

What is it?
The smallest fully compliant CommonMark parser in JavaScript, emitting positional concrete tokens so other tools can build an AST, plus extension packages for GFM, MDX, math and frontmatter.
Who is it for?
micromark makes sense when you need something other than HTML out of your markdown, or when you need the CommonMark specification followed exactly rather than approximately. The token output with positional info is what makes it composable: feed the same stream into an AST builder, a linter, a syntax highlighter or a renderer and every consumer agrees on where everything was.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 16 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 11, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two ways to use it, and when each one applies

The README answers the suitability question before describing the API, which is unusual and helpful. It says to use micromark if you just want to turn markdown into HTML with maybe a few extensions, and separately if you want to do really complex things with markdown, with a pointer to a comparison section. Those two cases have very different shapes, and the second one is the reason the project exists in its current form.

The basic call is a single function:

js
import {micromark} from 'micromark'

console.log(micromark('## Hello, *world*!'))

That returns `<h2>Hello, <em>world</em>!</h2>`, which is the whole API surface for the simple case. What makes the library different is stated immediately after: it is 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. That sentence is the design decision. Most parsers go straight to HTML or to a tree; this one goes to a positioned token stream first, and HTML is just one consumer of it.

Extensions split into syntax and HTML phases

Extensions come as separate npm packages, and the README explains that there are two kinds. A `SyntaxExtension` changes how markdown is parsed, and an `HtmlExtension` changes how it compiles, and they are passed in `options.extensions` and `options.htmlExtensions` respectively. Keeping those two phases separate is what lets a downstream tool reuse the parse phase and ignore the compile phase entirely, which is precisely the case when you are building something other than HTML.

The extension example in the README shows both halves used together, which is the pattern to copy:

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()]
})

The feature highlights list claims 100 percent coverage for GFM and for MDX.js, plus directives, frontmatter and math, so this is not a case of one extension and a hope. The repository topics back that up with separate entries for commonmark, gfm and markdown, and the sibling projects section names dedicated repositories for the extension packages, including `micromark/micromark-extension-mdxjs` and `micromark/micromark-extension-mdx`.

If you are writing an extension yourself rather than using one, the README points to two separate sections, one on extending markdown and one on creating a micromark extension, which tells you the extension authoring path is treated as a first class use case rather than an afterthought.

Compliant, safe, tested against fuzzing

The feature highlights are a checklist of five claims, and the wording is specific enough to be worth reading closely. Compliance is 100 percent to CommonMark, and extensions are 100 percent for GFM, MDX.js, directives, frontmatter and math. Safety is by default. Robustness is listed as roughly 2k tests, 100 percent coverage and fuzz testing. Size is called the smallest CommonMark parser at around 14kb.

The compliance claim is stronger than the usual one, and the README explains why: while most markdown parsers work toward compliance with CommonMark or GFM, this project goes further by following how the reference parsers `cmark` and `cmark-gfm` work, confirmed with thousands of extra tests. That is the difference between passing the spec examples and matching the behaviour of the implementations everyone actually uses, and it is why the test count is larger than you would expect from a parser this small.

The size number is the other claim that deserves context. A parser that accounts for every byte and emits positioned tokens could plausibly be large; around 14kb is what the state machine approach buys you. The repository is a monorepo, with a `packages/` directory holding each package, and the release history shows the granularity: version 4.0.3 and a separate `micromark-util-types` package and a brand new `micromark-util-edit-map` package were all released within seconds of each other in September 2026. That is the unified ecosystem in practice, where one parser release and its utilities ship together.

The 4.0.3 notes are worth reading as a signal about what the project considers important. Alongside a fix for attention flanking next to other tokens, they add a list of start tokens for performance and add the edit map package, also for performance. A parser that has been tuned for flanking rules and start token lookup has been profiled against real workloads.

ESM only, with a streaming interface for large files

The install section leads with a constraint that will decide the question for some projects immediately: this package is ESM only. On Node.js 16 or newer you install with `npm install micromark`, and there is no CommonJS build to fall back on. If you are working in Deno or directly in a browser, the documented route is esm.sh, importing `micromark` from an esm.sh URL for Deno and as a module script for the browser.

The `package.json` at the repository root is marked private and named `micromark-mono` at version 0.0.1, which is the monorepo root rather than a publishable package. The actual library lives under `packages/`, and the root also carries `rollup.config.js`, `xo.config.js` for linting, `tsconfig.json`, and a `todo.txt`. A `readme.md` in lowercase at the root is where the reference API documentation lives, with the section marked as needing to stay in sync with the `micromark` package readme, a comment that appears repeatedly in the file. That sync requirement is a small maintenance tax of the monorepo layout and explains why some sections in the package readme defer to it.

For anything larger than a string, there is a streaming interface, which matters when you are processing files rather than form fields:

js
import {createReadStream} from 'node:fs'
import {stream} from 'micromark/stream'

createReadStream('example.md')
  .on('error', handleError)
  .pipe(stream())
  .pipe(process.stdout)

That pipeline shape, a file read stream piped through the parser stream and onward, is what you would want for generating HTML from a directory of documentation. The parser is also MIT licensed, with the `license` file present in the tree and GitHub reporting MIT, and funding is handled through GitHub Sponsors and OpenCollective under the unifiedjs and unified organisations.

Editorial conclusion

micromark makes sense when you need something other than HTML out of your markdown, or when you need the CommonMark specification followed exactly rather than approximately. The token output with positional info is what makes it composable: feed the same stream into an AST builder, a linter, a syntax highlighter or a renderer and every consumer agrees on where everything was. The state machine design also explains the small size, since the parser holds no document model and just tracks where it is. Against that, it is ESM only, which rules out CommonJS consumers without a bundler, and the extension set is split across separate packages you have to find deliberately. If you only want markdown to HTML with an extension or two, most projects reach for something friendlier first and micromark arrives later when the requirements harden.

Frequently asked questions

What is micromark used for?

micromark is a CommonMark compliant markdown parser for JavaScript. It compiles markdown to HTML, and because it emits positioned tokens rather than HTML directly, other tools can consume the same parse and build an AST, lint output or a custom renderer instead.

Is micromark CommonMark compliant?

The README claims 100 percent compliance to CommonMark and to GFM, and says the project additionally follows the behaviour of the cmark and cmark-gfm reference parsers, confirmed with thousands of extra tests.

How do I install and use micromark?

The package is ESM only and requires Node.js 16 or newer. Install with npm install micromark, then call the exported micromark function with your markdown string to get HTML back.

Can micromark parse markdown without converting it to HTML?

Yes. It is built as a state machine that emits concrete tokens with positional info, and HTML is compiled from those tokens. Other tools can take the token data and build an AST, which is easier to work with, and a streaming interface is available at micromark/stream.

Official sources

  1. License: MIT
  2. micromark/micromark on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/micromark-micromark.svg)](https://hysenlabs.com/projects/micromark-micromark)