Top Related Projects
☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees
A markdown parser and compiler. Built for speed.
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
A bidirectional Markdown to HTML to Markdown converter written in Javascript
CommonMark parser and renderer in JavaScript
Quick Overview
Remark is a powerful Markdown processor powered by plugins. It's part of the unified collective and can be used to parse, inspect, transform, and serialize Markdown. Remark is highly extensible and can be used to build various tools for working with Markdown content.
Pros
- Highly extensible with a rich plugin ecosystem
- Part of the unified collective, allowing seamless integration with other text processing tools
- Supports both CommonMark and GitHub Flavored Markdown
- Fast and efficient processing of Markdown content
Cons
- Learning curve can be steep for complex transformations
- Documentation can be overwhelming for beginners
- Some plugins may have compatibility issues with each other
- Setting up a custom workflow might require significant configuration
Code Examples
- Parsing Markdown to AST:
import { remark } from 'remark';
const markdown = '# Hello, world!';
const ast = remark().parse(markdown);
console.log(ast);
- Converting Markdown to HTML:
import { remark } from 'remark';
import html from 'remark-html';
const markdown = '# Hello, world!';
remark()
.use(html)
.process(markdown)
.then((file) => console.log(String(file)));
- Using a plugin to add syntax highlighting:
import { remark } from 'remark';
import html from 'remark-html';
import highlight from 'remark-highlight.js';
const markdown = '```js\nconsole.log("Hello, world!");\n```';
remark()
.use(highlight)
.use(html)
.process(markdown)
.then((file) => console.log(String(file)));
Getting Started
To get started with Remark, first install it and any necessary plugins:
npm install remark remark-html
Then, create a simple script to process Markdown:
import { remark } from 'remark';
import html from 'remark-html';
const markdown = '# Hello, Remark!';
remark()
.use(html)
.process(markdown)
.then((file) => console.log(String(file)))
.catch((error) => console.error(error));
This script will convert the Markdown to HTML. You can run it using Node.js with ES modules enabled.
Competitor Comparisons
☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees
Pros of unified
- More versatile, supporting multiple syntax trees (not just Markdown)
- Provides a unified interface for processing content
- Offers a plugin system for extending functionality
Cons of unified
- Steeper learning curve due to its more abstract nature
- May be overkill for simple Markdown processing tasks
- Requires additional plugins for specific syntax support
Code Comparison
unified:
import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkHtml from 'remark-html'
unified()
.use(remarkParse)
.use(remarkHtml)
.process('# Hello, world!')
remark:
import { remark } from 'remark'
import html from 'remark-html'
remark()
.use(html)
.process('# Hello, world!')
Summary
unified is a more comprehensive toolkit for content processing, offering greater flexibility and extensibility. It's ideal for complex projects dealing with multiple content types. remark, on the other hand, is more focused on Markdown processing, making it simpler to use for straightforward Markdown tasks. The choice between the two depends on the specific requirements of your project and the level of complexity you're willing to manage.
A markdown parser and compiler. Built for speed.
Pros of marked
- Lightweight and fast, with minimal dependencies
- Simple API and easy to use out of the box
- Widely adopted and battle-tested in production environments
Cons of marked
- Less extensible and customizable compared to remark
- Limited support for advanced Markdown features and extensions
- Fewer plugins and ecosystem tools available
Code comparison
marked:
import marked from 'marked';
const html = marked('# Hello, world!');
console.log(html);
remark:
import { remark } from 'remark';
import html from 'remark-html';
const processor = remark().use(html);
const result = await processor.process('# Hello, world!');
console.log(String(result));
Key differences
- marked is more straightforward to use for basic Markdown parsing
- remark offers a plugin-based architecture for greater flexibility
- remark supports a wider range of Markdown flavors and extensions
- marked focuses on speed and simplicity, while remark prioritizes extensibility
Use cases
- Choose marked for quick and simple Markdown-to-HTML conversion
- Opt for remark when you need advanced parsing, custom syntax, or extensive transformations
Both libraries have their strengths, and the choice depends on your specific requirements and project complexity.
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
Pros of markdown-it
- Faster parsing and rendering performance
- Extensive plugin ecosystem with many ready-to-use extensions
- Simpler API and easier to get started for basic use cases
Cons of markdown-it
- Less flexible architecture for complex transformations
- Limited support for abstract syntax tree (AST) manipulations
- Fewer built-in features for advanced use cases like syntax highlighting
Code Comparison
markdown-it:
const md = require('markdown-it')();
const result = md.render('# Hello, world!');
remark:
const remark = require('remark');
const html = require('remark-html');
remark()
.use(html)
.process('# Hello, world!', (err, file) => console.log(String(file)));
Key Differences
- remark uses a plugin-based architecture, allowing for more complex transformations
- markdown-it focuses on speed and simplicity for common use cases
- remark provides better support for working with ASTs and custom syntax
- markdown-it has a larger collection of ready-made plugins for common extensions
- remark is part of a larger ecosystem (unified) for processing various content types
Use Cases
- Choose markdown-it for simpler projects requiring fast parsing and rendering
- Opt for remark when working with complex transformations or custom syntax
- Consider remark for projects that may expand to handle multiple content types
A bidirectional Markdown to HTML to Markdown converter written in Javascript
Pros of Showdown
- Simpler API and easier to get started with for basic Markdown conversion
- Supports browser-side conversion without additional setup
- Extensive configuration options for customizing output
Cons of Showdown
- Less modular and extensible compared to Remark
- Not as actively maintained or updated as Remark
- Limited support for advanced Markdown features and custom syntax
Code Comparison
Showdown:
var converter = new showdown.Converter();
var html = converter.makeHtml('# Hello, Markdown!');
Remark:
import { remark } from 'remark';
import html from 'remark-html';
const result = await remark()
.use(html)
.process('# Hello, Markdown!');
Key Differences
- Remark uses a plugin-based architecture, allowing for more flexibility and customization
- Showdown is more focused on straightforward Markdown-to-HTML conversion
- Remark has better support for parsing and manipulating abstract syntax trees (ASTs)
- Showdown is easier to integrate into browser-based applications without additional build steps
- Remark has a larger ecosystem of plugins and extensions for advanced use cases
Both libraries serve their purposes well, with Showdown being more suitable for simple conversion tasks and Remark offering greater extensibility for complex Markdown processing needs.
CommonMark parser and renderer in JavaScript
Pros of commonmark.js
- Strictly adheres to the CommonMark specification
- Lightweight and focused solely on parsing and rendering CommonMark
- Provides a reference implementation for the CommonMark spec
Cons of commonmark.js
- Limited extensibility compared to remark's plugin ecosystem
- Lacks support for additional Markdown flavors or extensions
- Smaller community and fewer resources available
Code Comparison
commonmark.js:
var reader = new commonmark.Parser();
var writer = new commonmark.HtmlRenderer();
var parsed = reader.parse("Hello *world*");
var result = writer.render(parsed);
remark:
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkHtml from 'remark-html';
const result = unified()
.use(remarkParse)
.use(remarkHtml)
.processSync("Hello *world*");
Key Differences
- remark offers a more modular and extensible architecture
- commonmark.js focuses on strict CommonMark compliance
- remark supports various Markdown flavors and custom extensions
- commonmark.js provides a simpler API for basic parsing and rendering
- remark has a larger ecosystem and community support
Use Cases
commonmark.js
- Projects requiring strict CommonMark compliance
- Lightweight Markdown parsing in browser environments
- Reference implementation for CommonMark spec
remark
- Complex document processing pipelines
- Projects needing custom Markdown extensions
- Integration with other unified ecosystem tools
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
remark is a tool that transforms markdown with plugins. These plugins can inspect and change your markup. You can use remark on the server, the client, CLIs, deno, etc.
Feature highlights
- compliant â 100% to CommonMark, 100% to GFM or MDX with a plugin
- ASTs â inspecting and changing content made easy
- popular â worldâs most popular markdown parser
- plugins â 150+ plugins you can pick and choose from
Intro
remark is an ecosystem of plugins that work with markdown as structured data, specifically ASTs (abstract syntax trees). ASTs make it easy for programs to deal with markdown. We call those programs plugins. Plugins inspect and change trees. You can use the many existing plugins or you can make your own.
- to learn markdown, see this cheatsheet and tutorial
- for more about us, see
unifiedjs.com
- for updates, see Twitter
- for questions, see support
- to help, see contribute or sponsor below
Contents
- What is this?
- When should I use this?
- Plugins
- Examples
- Syntax
- Syntax tree
- Types
- Compatibility
- Security
- Contribute
- Sponsor
- License
What is this?
With this project and a plugin, you can turn this markdown:
# Hello, *Mercury*!
â¦into the following HTML:
<h1>Hello, <em>Mercury</em>!</h1>
Show example code
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>'
With another plugin, you can turn this markdown:
# Hi, Saturn!
â¦into the following markdown:
## Hi, Saturn!
Show example code
/**
* @import {Root} from 'mdast'
*/
import remarkParse from 'remark-parse'
import remarkStringify from 'remark-stringify'
import {unified} from 'unified'
import {visit} from 'unist-util-visit'
const file = await unified()
.use(remarkParse)
.use(myRemarkPluginToIncreaseHeadings)
.use(remarkStringify)
.process('# Hi, Saturn!')
console.log(String(file)) // => '## Hi, Saturn!'
function myRemarkPluginToIncreaseHeadings() {
/**
* @param {Root} tree
*/
return function (tree) {
visit(tree, function (node) {
if (node.type === 'heading') {
node.depth++
}
})
}
}
You can use remark for many different things. unified is the core project that transforms content with ASTs. remark adds support for markdown to unified. mdast is the markdown AST that remark uses.
This GitHub repository is a monorepo that contains the following packages:
remark-parse
â plugin to take markdown as input and turn it into a syntax tree (mdast)remark-stringify
â plugin to take a syntax tree (mdast) and turn it into markdown as outputremark
âunified
,remark-parse
, andremark-stringify
, useful when input and output are markdownremark-cli
â CLI aroundremark
to inspect and format markdown in scripts
When should I use this?
Depending on the input you have and output you want, you can use different
parts of remark.
If the input is markdown, you can use remark-parse
with unified
.
If the output is markdown, you can use remark-stringify
with unified
.
If both the input and output are markdown, you can use remark
on its own.
When you want to inspect and format markdown files in a project, you can use
remark-cli
.
If you just want to turn markdown into HTML (with maybe a few extensions),
we recommend micromark
instead.
If you donât use plugins and want to deal with syntax trees manually, you can
use mdast-util-from-markdown
and
mdast-util-to-markdown
.
Plugins
remark plugins deal with markdown. Some popular examples are:
remark-gfm
â add support for GFM (GitHub flavored markdown)remark-lint
â inspect markdown and warn about inconsistenciesremark-toc
â generate a table of contentsremark-rehype
â turn markdown into HTML
These plugins are exemplary because what they do and how they do it is quite different, respectively to extend markdown syntax, inspect trees, change trees, and transform to other syntax trees.
You can choose from the 150+ plugins that already exist. Here are three good ways to find plugins:
awesome-remark
â selection of the most awesome projects- List of plugins â list of all plugins
remark-plugin
topic â any tagged repo on GitHub
Some plugins are maintained by us here in the @remarkjs
organization while
others are maintained by folks elsewhere.
Anyone can make remark plugins, so as always when choosing whether to include
dependencies in your project, make sure to carefully assess the quality of
remark plugins too.
Examples
Example: turning markdown into HTML
remark is an ecosystem around markdown.
A different ecosystem is for HTML: rehype.
The following example turns markdown into HTML by combining both ecosystems with
remark-rehype
:
import rehypeSanitize from 'rehype-sanitize'
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(rehypeSanitize)
.use(rehypeStringify)
.process('# Hello, Neptune!')
console.log(String(file))
Yields:
<h1>Hello, Neptune!</h1>
Example: support for GFM and frontmatter
remark supports CommonMark by default. Non-standard markdown extensions can be enabled with plugins. The following example adds support for GFM (autolink literals, footnotes, strikethrough, tables, tasklists) and frontmatter (YAML):
import rehypeStringify from 'rehype-stringify'
import remarkFrontmatter from 'remark-frontmatter'
import remarkGfm from 'remark-gfm'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'
const doc = `---
layout: solar-system
---
# Hi ~~Mars~~Venus!
`
const file = await unified()
.use(remarkParse)
.use(remarkFrontmatter)
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeStringify)
.process(doc)
console.log(String(file))
Yields:
<h1>Hi <del>Mars</del>Venus!</h1>
Example: checking markdown
The following example checks that markdown code style is consistent and follows recommended best practices:
import {remark} from 'remark'
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
import {reporter} from 'vfile-reporter'
const file = await remark()
.use(remarkPresetLintConsistent)
.use(remarkPresetLintRecommended)
.process('1) Hello, _Jupiter_ and *Neptune*!')
console.error(reporter(file))
Yields:
warning Missing newline character at end of file final-newline remark-lint
1:1-1:35 warning Marker style should be `.` ordered-list-marker-style remark-lint
1:4 warning Incorrect list-item indent: add 1 space list-item-indent remark-lint
1:25-1:34 warning Emphasis should use `_` as a marker emphasis-marker remark-lint
â 4 warnings
Example: checking and formatting markdown on the CLI
The following example checks and formats markdown with remark-cli
, which is
the CLI (command line interface) of remark that you can use in your terminal.
This example assumes youâre in a Node.js package.
First, install the CLI and plugins:
npm install remark-cli remark-preset-lint-consistent remark-preset-lint-recommended remark-toc --save-dev
â¦then add an npm script in your package.json
:
/* ⦠*/
"scripts": {
/* ⦠*/
"format": "remark . --output",
/* ⦠*/
},
/* ⦠*/
ð¡ Tip: add ESLint and such in the
format
script too.
The above change adds a format
script, which can be run with
npm run format
.
It runs remark on all markdown files (.
) and rewrites them (--output
).
Run ./node_modules/.bin/remark --help
for more info on the CLI.
Then, add a remarkConfig
to your package.json
to configure remark:
/* ⦠*/
"remarkConfig": {
"settings": {
"bullet": "*", // Use `*` for list item bullets (default)
// See <https://github.com/remarkjs/remark/tree/main/packages/remark-stringify> for more options.
},
"plugins": [
"remark-preset-lint-consistent", // Check that markdown is consistent.
"remark-preset-lint-recommended", // Few recommended rules.
[
// Generate a table of contents in `## Contents`
"remark-toc",
{
"heading": "contents"
}
]
]
},
/* ⦠*/
ð Note: you must remove the comments in the above examples when copy/pasting them as comments are not supported in
package.json
files.
Finally, you can run the npm script to check and format markdown files in your project:
npm run format
Syntax
Markdown is parsed and serialized according to CommonMark. Other plugins can add support for syntax extensions.
We use micromark
for our parsing.
See its documentation for more information on markdown, CommonMark, and
extensions.
Syntax tree
The syntax tree used in remark is mdast. It represents markdown constructs as JSON objects.
This markdown:
## Hello *Pluto*!
â¦yields the following tree (positional info remove for brevity):
{
type: 'heading',
depth: 2,
children: [
{type: 'text', value: 'Hello '},
{type: 'emphasis', children: [{type: 'text', value: 'Pluto'}]}
{type: 'text', value: '!'}
]
}
Types
The remark organization and the unified collective as a whole is fully typed
with TypeScript.
Types for mdast are available in @types/mdast
.
For TypeScript to work, it is important to type your plugins. For example:
/**
* @import {Root} from 'mdast'
* @import {VFile} from 'vfile'
*/
/**
* @typedef Options
* Configuration.
* @property {boolean | null | undefined} [someField]
* Some option (optional).
*/
/**
* My plugin.
*
* @param {Options | null | undefined} [options]
* Configuration (optional).
* @returns
* Transform.
*/
export function myRemarkPluginAcceptingOptions(options) {
/**
* Transform.
*
* @param {Root} tree
* Tree.
* @param {VFile} file
* File
* @returns {undefined}
* Nothing.
*/
return function (tree, file) {
// Do things.
}
}
Compatibility
Projects maintained by the unified collective are compatible with maintained versions of Node.js.
When we cut a new major release, we drop support for unmaintained versions of Node. This means we try to keep the current release line compatible with Node.js 16.
Security
As markdown can be turned into HTML and improper use of HTML can open you up to
cross-site scripting (XSS) attacks, use of remark can be unsafe.
When going to HTML, you will combine remark with rehype, in which case
you should use rehype-sanitize
.
Use of remark plugins could also open you up to other attacks. Carefully assess each plugin and the risks involved in using them.
For info on how to submit a report, see our security policy.
Contribute
See contributing.md
in remarkjs/.github
for ways
to get started.
See support.md
for ways to get help.
Join us in Discussions to chat with the community and contributors.
This project has a code of conduct. By interacting with this repository, organization, or community you agree to abide by its terms.
Sponsor
Support this effort and give back by sponsoring on OpenCollective!
Vercel |
Motif |
HashiCorp |
GitBook |
Gatsby |
|||||
Netlify |
Coinbase |
ThemeIsle |
Expo |
Boost Note |
Markdown Space |
Holloway |
|||
You? |
License
MIT © Titus Wormer
Top Related Projects
☔️ interface for parsing, inspecting, transforming, and serializing content through syntax trees
A markdown parser and compiler. Built for speed.
Markdown parser, done right. 100% CommonMark support, extensions, syntax plugins & high speed
A bidirectional Markdown to HTML to Markdown converter written in Javascript
CommonMark parser and renderer in JavaScript
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