Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/remarkjs/remark/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through installing remark and running your first markdown transformation. You will start with a markdown-to-markdown pipeline (using remark directly) and then extend it to output HTML by adding remark-rehype and rehype-stringify. Every code snippet here is taken directly from the remark source and is ready to run.
1
Install remark
2
Make sure you are inside a Node.js project (Node.js 16 or later is required). Install the remark package, which bundles unified, remark-parse, and remark-stringify together.
3
npm
npm install remark
yarn
yarn add remark
pnpm
pnpm add remark
4
All remark packages are ESM only. Your project must either use "type": "module" in package.json, or use .mjs file extensions. CommonJS require() is not supported.
5
For the next step you also need a plugin. Install remark-toc, which generates a table of contents:
6
npm
npm install remark-toc
yarn
yarn add remark-toc
pnpm
pnpm add remark-toc
7
Process markdown with a plugin
8
Create a file called example.js and paste the following code. It uses remark together with remark-toc to automatically fill in the ## Contents section of a document:
9
import {remark} from 'remark'
import remarkToc from 'remark-toc'

const value = `
# Pluto

Pluto is a dwarf planet in the Kuiper belt.

## Contents

## History

### Discovery

In the 1840s, Urbain Le Verrier used Newtonian mechanics to predict the position of…

### Name and symbol

The name Pluto is for the Roman god of the underworld, from a Greek epithet for Hades…

### Planet X disproved

Once Pluto was found, its faintness and lack of a viewable disc cast doubt…

## Orbit

Pluto's orbital period is about 248 years…
`

const file = await remark().use(remarkToc).process(value)

console.error(String(file))
10
The remark() call creates a unified processor that already has remark-parse and remark-stringify wired up. Calling .use(remarkToc) registers the table-of-contents plugin. .process(value) parses the markdown, runs all plugins, and serializes the result back to a markdown string.
11
Run the script and see the output
12
Run the script from your terminal:
13
node example.js
14
The ## Contents section is now populated with a list of links to every heading that follows it:
15
# Pluto

Pluto is a dwarf planet in the Kuiper belt.

## Contents

* [History](#history)
  * [Discovery](#discovery)
  * [Name and symbol](#name-and-symbol)
  * [Planet X disproved](#planet-x-disproved)
* [Orbit](#orbit)

## History

### Discovery

In the 1840s, Urbain Le Verrier used Newtonian mechanics to predict the position of…

### Name and symbol

The name Pluto is for the Roman god of the underworld, from a Greek epithet for Hades…

### Planet X disproved

Once Pluto was found, its faintness and lack of a viewable disc cast doubt…

## Orbit

Pluto's orbital period is about 248 years…
16
remark-toc walked the mdast tree, found the heading named “Contents”, and inserted a list of links as its next sibling. The rest of the document was untouched. This is exactly how all remark plugins work — they receive the full AST and can read or mutate any node.
17
Convert markdown to HTML
18
Markdown-to-markdown is useful for formatting, but many projects need HTML output. For that you combine remark-parse with remark-rehype (which converts the mdast tree into an HTML AST) and rehype-stringify (which serializes the HTML AST to a string).
19
Install the additional packages:
20
npm
npm install unified remark-parse remark-rehype rehype-stringify
yarn
yarn add unified remark-parse remark-rehype rehype-stringify
pnpm
pnpm add unified remark-parse remark-rehype rehype-stringify
21
Create a new file html.js:
22
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'

const file = await unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeStringify)
  .process('# Hello, *Mercury*!')

console.log(String(file)) // => '<h1>Hello, <em>Mercury</em>!</h1>'
23
Run it:
24
node html.js
25
Output:
26
<h1>Hello, <em>Mercury</em>!</h1>
27
Notice that this pipeline uses unified() directly rather than remark(). When the output is not markdown you only need remark-parse for parsing — there is no need to include remark-stringify. You compose exactly the plugins you need, nothing more.
28
Add rehype-sanitize between remarkRehype and rehypeStringify when processing untrusted user-supplied markdown. Without sanitization, raw HTML in the markdown source is passed through to the output unchanged, which can expose XSS vulnerabilities.

Next steps

Now that you have a working pipeline, here are some directions to explore:
  • Installation — detailed install instructions for all four packages, including Deno and browser usage.
  • Add GFM support — install remark-gfm and add .use(remarkGfm) to enable GitHub Flavored Markdown features like tables, strikethrough, and task lists.
  • Lint your markdown — use remark-preset-lint-recommended with remark-cli to enforce style rules across your whole project.
  • Browse plugins — over 150 remark plugins are available. Explore the list of plugins or the awesome-remark collection to find tools for syntax highlighting, math rendering, directives, and more.

Build docs developers (and LLMs) love