From 87c50a5884662908cfef15297f109de0102a2c4a Mon Sep 17 00:00:00 2001 From: Titus Date: Thu, 18 Nov 2021 19:14:37 +0100 Subject: [PATCH] Add improved docs Closes GH-900 Reviewed-by: Merlijn Vos Reviewed-by: Christian Murphy Reviewed-by: Remco Haszing Reviewed-by: Morgan Craft --- doc/getting-started.md | 227 +---------- doc/plugins.md | 106 +++-- packages/remark-cli/package.json | 2 +- packages/remark-cli/readme.md | 320 ++++++++++++--- packages/remark-cli/test.js | 2 +- packages/remark-parse/package.json | 2 +- packages/remark-parse/readme.md | 320 ++++++++++++--- packages/remark-stringify/package.json | 2 +- packages/remark-stringify/readme.md | 361 +++++++++++++---- packages/remark/package.json | 2 +- packages/remark/readme.md | 318 ++++++++++----- readme.md | 527 +++++++++++++++++++++---- 12 files changed, 1527 insertions(+), 662 deletions(-) diff --git a/doc/getting-started.md b/doc/getting-started.md index cb86c1e31..ec9a92524 100644 --- a/doc/getting-started.md +++ b/doc/getting-started.md @@ -1,227 +1,6 @@ -![remark][logo] - # Getting started -**remark** transforms markdown. -It’s an ecosystem of [plugins][]. -If you get stuck, [issues][] and [Discussions][] are good places to get help. - -It’s built on [unified][], make sure to read it and its [website][] too. - -## Contents - -* [Intro](#intro) -* [Command line](#command-line) -* [Using remark in a project](#using-remark-in-a-project) -* [Programmatic usage](#programmatic-usage) - -## Intro - -Out of the box, **remark** transforms markdown: markdown is given, reformatted, -and written: - -```md -# Alpha # -Bravo charlie **delta** __echo__. -- Foxtrot -``` - -Yields: - -```md -# Alpha - -Bravo charlie **delta** **echo**. - -* Foxtrot -``` - -But, much more can be done, [through plugins][plugins]. - -## Command line - -**remark**’s CLI is a simple way to process markdown files from the -command line. Its interface is provided by [**unified-args**][unified-args]. - -Install [`remark-cli`][cli] and dependencies (in this case a [linting -preset][preset] and [`remark-html`][html]) with [npm][]: - -```sh -npm install --global remark-cli remark-html remark-preset-lint-markdown-style-guide -``` - -`readme.md` contains: - -```md -_Hello_. -``` - -Now, to process `readme.md`, run the following: - -```sh -remark readme.md --use html --use preset-lint-markdown-style-guide -``` - -Yields: - -```txt -

Hello.

-readme.md.md - 1:1-1:8 warning Emphasis should use `*` as a marker emphasis-marker remark-lint - -⚠ 1 warning -``` - -## Using remark in a project - -In the previous example, `remark-cli` was installed globally. -That’s generally a bad idea. -Here we’re going to use the CLI to lint an npm package. - -Say we have the following `package.json`: - -```json -{ - "name": "my-package", - "version": "1.0.0", - "type": "module", - "scripts": { - "test": "node test.js" - } -} -``` - -And install `remark-cli`, `remark-html`, and -`remark-preset-lint-markdown-style-guide` into it as a dev-dependencies: - -```sh -npm install --save-dev remark-cli remark-html remark-preset-lint-markdown-style-guide -``` - -The `--save-dev` option stores the dependencies in our `package.json`: - -```diff - { - "name": "my-package", - "version": "1.0.0", - "type": "module", -+ "devDependencies": { -+ "remark-cli": "^10.0.0", -+ "remark-html": "^14.0.0", -+ "remark-preset-lint-markdown-style-guide": "^5.0.0" -+ }, - "scripts": { - "test": "node test.js" - } - } -``` - -Then, we change our `test` script to include remark, and add -configuration: - -```diff - { - "name": "my-package", - "version": "1.0.0", - "type": "module", - "devDependencies": { - "remark-cli": "^10.0.0", - "remark-html": "^14.0.0", - "remark-preset-lint-markdown-style-guide": "^5.0.0" - }, - "scripts": { -- "test": "node test.js" -+ "test": "remark . --quiet --frail && node test.js" -+ }, -+ "remarkConfig": { -+ "plugins": [ -+ "preset-lint-markdown-style-guide", -+ "html" -+ ] - } - } -``` - -Now from the command line we can run: - -```sh -npm test -``` - -This will lint all markdown files when we test the project. -[`--frail`][frail] ensures the command fails if a code-style violation -is found, and [`--quiet`][quiet] hides successful files from the report. - -## Programmatic usage - -The programmatic interface of **remark** is provided by -[**unified**][unified]. -In fact, [`remark`][api] is two plugins: [`remark-parse`][parse] and -[`remark-stringify`][stringify]. - -Install [`remark`][api] and dependencies with [npm][]: - -```sh -npm install vfile-reporter remark remark-html remark-preset-lint-markdown-style-guide -``` - -`index.js` contains: - -```js -import {reporter} from 'vfile-reporter' -import {remark} from 'remark' -import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown-style-guide' -import remarkHtml from 'remark-html' - -remark() - .use(remarkPresetLintMarkdownStyleGuide) - .use(remarkHtml) - .process('_Hello_.') - .then((file) => { - console.error(reporter(file)) - console.log(String(file)) - }) -``` - -`node index.js` yields: - -```txt - 1:1-1:8 warning Emphasis should use `*` as a marker emphasis-marker remark-lint - -⚠ 1 warning -

Hello.

-``` - - - -[logo]: https://raw.githubusercontent.com/remarkjs/remark/1f338e72/logo.svg?sanitize=true - -[issues]: https://github.com/remarkjs/remark/issues - -[discussions]: https://github.com/remarkjs/remark/discussions - -[npm]: https://docs.npmjs.com/cli/install - -[api]: https://github.com/remarkjs/remark/tree/main/packages/remark - -[cli]: https://github.com/remarkjs/remark/tree/main/packages/remark-cli - -[plugins]: https://github.com/remarkjs/remark/tree/main/doc/plugins.md - -[unified]: https://github.com/unifiedjs/unified - -[website]: https://unifiedjs.com - -[unified-args]: https://github.com/unifiedjs/unified-args - -[frail]: https://github.com/unifiedjs/unified-args#--frail - -[quiet]: https://github.com/unifiedjs/unified-args#--quiet - -[parse]: https://github.com/remarkjs/remark/tree/main/packages/remark-parse - -[stringify]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify - -[preset]: https://github.com/remarkjs/remark-lint/tree/HEAD/packages/remark-preset-lint-markdown-style-guide +See [the monorepo readme][remark] for what the remark ecosystem is and examples +of how to get started. -[html]: https://github.com/remarkjs/remark-html +[remark]: https://github.com/remarkjs/remark diff --git a/doc/plugins.md b/doc/plugins.md index e81fb9c3c..8da351614 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -2,33 +2,33 @@ # Plugins -**remark** is a markdown processor powered by plugins part of the [unified][] -[collective][]. +**remark** is a tool that transforms markdown with plugins. +See [the monorepo readme][remark] for info on what the remark ecosystem is. +This page lists existing plugins. ## Contents * [List of plugins](#list-of-plugins) * [List of presets](#list-of-presets) * [List of utilities](#list-of-utilities) -* [Using plugins](#using-plugins) -* [Creating plugins](#creating-plugins) +* [Use plugins](#use-plugins) +* [Create plugins](#create-plugins) ## List of plugins -See [awesome remark][awesome] for the most awesome projects in the ecosystem. +See [`awesome-remark`][awesome-remark] for the most awesome projects in the +ecosystem. More plugins can be found on GitHub tagged with the [`remark-plugin` topic][topic]. -Have a good idea for a new plugin? -See [Creating plugins][create] below. +> 👉 **Note**: some plugins don’t work with recent versions of remark due to +> changes in its underlying parser (micromark). +> Plugins that are up to date or unaffected are marked with `🟢` while plugins +> that are **currently broken** are marked with `⚠️`. -Some plugins are affected by the recent switch in the underlying parser of -remark. -Their status is encoded below as: - -* 🟢 This plugin **was not affected** or **a new version is already released** -* ⚠️ This plugin is affected: it’s **currently broken** and maintainers - have been notified +> 💡 **Tip**: remark plugins work with markdown and **rehype** plugins work with +> HTML. +> See rehype’s [List of plugins][rehype-plugins] for more plugins. The list of plugins: @@ -38,7 +38,7 @@ The list of plugins: — new syntax for abbreviations (new node type, rehype compatible) * ⚠️ [`remark-admonitions`](https://github.com/elviswolcott/remark-admonitions) — new syntax for admonitions - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * ⚠️ [`remark-align`](https://github.com/zestedesavoir/zmarkdown/tree/HEAD/packages/remark-align#readme) — new syntax to align text or blocks (new node types, rehype compatible) @@ -72,17 +72,17 @@ The list of plugins: — new syntax to ignore things * ⚠️ [`remark-container`](https://github.com/zWingz/remark-container) — new syntax for containers - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * ⚠️ [`remark-containers`](https://github.com/Nevenall/remark-containers) — new syntax for containers - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * 🟢 [`remark-contributors`](https://github.com/remarkjs/remark-contributors) — add a table of contributors * 🟢 [`remark-copy-linked-files`](https://github.com/sergioramos/remark-copy-linked-files) — find and copy files linked files to a destination directory * ⚠️ [`remark-custom-blocks`](https://github.com/zestedesavoir/zmarkdown/tree/HEAD/packages/remark-custom-blocks#readme) — new syntax for custom blocks (new node types, rehype compatible) - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * 🟢 [`remark-definition-list`](https://github.com/wataru-chocola/remark-definition-list) — support definition lists * 🟢 [`remark-defsplit`](https://github.com/remarkjs/remark-defsplit) @@ -113,7 +113,7 @@ The list of plugins: — better support for Gemoji shortcodes * ⚠️ [`remark-generic-extensions`](https://github.com/medfreeman/remark-generic-extensions) — new syntax for the CommonMark generic directive extension - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * 🟢 [`remark-gfm`](https://github.com/remarkjs/remark-gfm) — support GFM (autolink literals, footnotes, strikethrough, tables, tasklists) @@ -163,6 +163,8 @@ The list of plugins: — serialize markdown as man pages (roff) * 🟢 [`remark-math`](https://github.com/remarkjs/remark-math) — new syntax for math (new node types, rehype compatible) +* 🟢 [`remark-mdx`](https://github.com/mdx-js/mdx/tree/main/packages/remark-mdx) + — support MDX (JSX, expressions, ESM) * 🟢 [`remark-message-control`](https://github.com/remarkjs/remark-message-control) — turn some or all messages on or off * 🟢 [`remark-normalize-headings`](https://github.com/remarkjs/remark-normalize-headings) @@ -206,7 +208,7 @@ The list of plugins: rehype compatible) * ⚠️ [`remark-shortcodes`](https://github.com/djm/remark-shortcodes) — new syntax for Wordpress- and Hugo-like shortcodes (new node type) - (**note: [`remark-directive`][d] is similar and up to date**) + (👉 **note**: [`remark-directive`][d] is similar and up to date) * 🟢 [`remark-simple-plantuml`](https://github.com/akebifiky/remark-simple-plantuml) — turn PlantUML code blocks to images * 🟢 [`remark-slate`](https://github.com/hanford/remark-slate) @@ -274,48 +276,56 @@ The list of plugins: ## List of presets -See [npm search][npm-preset-search] or [github search][github-preset-search] -for available and often inspirational presets. +Use [GitHub search][github-preset-search] to find available and often +inspirational presets. ## List of utilities -See [**mdast**][mdast-util] for a list of utilities for working with the syntax +See [mdast][mdast-util] for a list of utilities that work with the syntax tree. -See [`unist`][unist-util] for other utilities which work with **mdast** -nodes, too. -Finally, see [**vfile**][vfile-util] for a list of utilities working with -virtual files. +See [unist][unist-util] for other utilities which work with **mdast** and other +syntax trees too. +Finally, see [vfile][vfile-util] for a list of utilities working with virtual +files. -## Using plugins +## Use plugins To use a plugin programmatically, call the [`use()`][unified-use] function. - To use plugin with `remark-cli`, pass a [`--use` flag][unified-args-use] or specify it in a [configuration file][config-file-use]. -## Creating plugins - -Have an idea for a plugin? -Post it in [ideas][] and make it happen! +## Create plugins To create a plugin, first read up on the [concept of plugins][unified-plugins]. Then, read the [guide on “Creating a plugin with unified”][guide]. Finally, take one of existing plugins, which looks similar to what you’re about to make, and work from there. -If you get stuck, [ideas][], [issues][], and [discussions][] are good places to -get help. - -You should pick a name prefixed by `'remark-'`, such as `remark-lint`. +If you get stuck, [discussions][] is a good place to get help. +You should pick a name prefixed by `'remark-'` (such as `remark-lint`). **Do not use the `remark-` prefix** if the thing you create doesn’t work with `remark().use()`: it isn’t a “plugin” and will confuse users. If it works with mdast, use `'mdast-util-'`, if it works with any unist tree, use `unist-util-`, and if it works with virtual files, use `vfile-`. +Use default exports to expose plugins from your packages, add `remark-plugin` +keywords in `package.json`, add a `remark-plugin` topic to your repo on GitHub, +and create a pull request to add the plugin here on this page! + [logo]: https://raw.githubusercontent.com/remarkjs/remark/1f338e72/logo.svg?sanitize=true +[d]: https://github.com/remarkjs/remark-directive + +[remark]: https://github.com/remarkjs/remark + +[awesome-remark]: https://github.com/remarkjs/awesome-remark + +[topic]: https://github.com/topics/remark-plugin + +[github-preset-search]: https://github.com/topics/remark-preset + [mdast-util]: https://github.com/syntax-tree/mdast#list-of-utilities [unist-util]: https://github.com/syntax-tree/unist#unist-utilities @@ -330,26 +340,8 @@ use `unist-util-`, and if it works with virtual files, use `vfile-`. [unified-plugins]: https://github.com/unifiedjs/unified#plugin -[issues]: https://github.com/remarkjs/remark/issues - -[discussions]: https://github.com/remarkjs/remark/discussions - [guide]: https://unifiedjs.com/learn/guide/create-a-plugin/ -[npm-preset-search]: https://www.npmjs.com/search?q=remark-preset - -[github-preset-search]: https://github.com/topics/remark-preset - -[awesome]: https://github.com/remarkjs/awesome - -[ideas]: https://github.com/remarkjs/ideas - -[topic]: https://github.com/topics/remark-plugin - -[unified]: https://github.com/unifiedjs/unified - -[collective]: https://opencollective.com/unified - -[create]: #creating-plugins +[discussions]: https://github.com/remarkjs/remark/discussions -[d]: https://github.com/remarkjs/remark-directive +[rehype-plugins]: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins diff --git a/packages/remark-cli/package.json b/packages/remark-cli/package.json index b3b3451b6..d4122972f 100644 --- a/packages/remark-cli/package.json +++ b/packages/remark-cli/package.json @@ -1,7 +1,7 @@ { "name": "remark-cli", "version": "10.0.0", - "description": "CLI to process markdown with remark", + "description": "Command line interface to inspect and change markdown files with remark", "license": "MIT", "keywords": [ "unified", diff --git a/packages/remark-cli/readme.md b/packages/remark-cli/readme.md index aa0472618..5c75b3cda 100644 --- a/packages/remark-cli/readme.md +++ b/packages/remark-cli/readme.md @@ -7,19 +7,47 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -Command line interface for [**remark**][remark]. - -* Interface by [`unified-args`][unified-args] -* Loads [`remark-` plugins][plugins] -* Searches for [markdown extensions][markdown-extensions] -* Ignores paths found in [`.remarkignore` files][ignore-file] -* Loads configuration from [`.remarkrc`, `.remarkrc.js` files][config-file] -* Uses configuration from [`remarkConfig` fields in `package.json` - files][config-file] +Command line interface to inspect and change markdown files with **[remark][]**. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [CLI](#cli) +* [Examples](#examples) + * [Example: checking and formatting markdown on the CLI](#example-checking-and-formatting-markdown-on-the-cli) + * [Example: config files (JSON, YAML, JS)](#example-config-files-json-yaml-js) +* [Compatibility](#compatibility) +* [Security](#security) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [License](#license) + +## What is this? + +This package is a command line interface (CLI) that you can use in your terminal +or in npm scripts and the like to inspect and change markdown files. +This CLI is built around remark, which is a very popular ecosystem of plugins +that work with markdown as structured data, specifically ASTs (abstract syntax +trees). +You can choose from the 150+ plugins that already exist or make your own. + +See [the monorepo readme][remark] for info on what the remark ecosystem is. + +## When should I use this? + +You can use this package when you want to work with the markdown files in your +project from the command line. +`remark-cli` has many options and you can combine it with many plugins, so it +should be possible to do what you want. +If not, you can always use [`remark`][remark-core] itself manually in a script. ## Install -[npm][]: +This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). +In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: ```sh npm install remark-cli @@ -27,19 +55,23 @@ npm install remark-cli ## Use +Add a table of contents with [`remark-toc`][remark-toc] to `readme.md`: + ```sh -# Add a table of contents to `readme.md` -$ remark readme.md --use toc --output +remark readme.md --use remark-toc --output +``` -# Lint markdown files in the current directory -# according to the markdown style guide. -$ remark . --use preset-lint-markdown-style-guide +Lint all markdown files in the current directory according to the markdown style +guide with [`remark-preset-lint-markdown-style-guide`][markdown-style-guide]. + +```sh +remark . --use remark-preset-lint-markdown-style-guide ``` ## CLI -See [`unified-args`][unified-args], which provides the interface, for more -info on all available options. +The interface of `remark-cli` is explained as follows on its help page +(`remark --help`): ```txt Usage: remark [options] [path | glob ...] @@ -86,25 +118,190 @@ Examples: $ remark . -o ``` +More information on all these options is available at +[`unified-args`][unified-args], which does the work. +`remark-cli` is `unified-args` preconfigured to: + +* Load `remark-` plugins +* Search for markdown extensions + ([`.md`, `.markdown`, etc][markdown-extensions]) +* Ignore paths found in [`.remarkignore` files][ignore-file] +* Load configuration from + [`.remarkrc`, `.remarkrc.js`, etc files][config-file] +* Use configuration from + [`remarkConfig` fields in `package.json` files][config-file] + +## Examples + +### Example: checking and formatting markdown on the CLI + +This example checks and formats markdown with `remark-cli`. +It assumes you’re in a Node.js package. + +First, install the CLI and plugins: + +```sh +npm install remark-cli remark-toc remark-preset-lint-consistent remark-preset-lint-recommended --save-dev +``` + +Now, add an npm script in your `package.json`: + +```js + /* … */ + "scripts": { + /* … */ + "format": "remark . --output", + /* … */ + }, + /* … */ +``` + +> 💡 **Tip**: add ESLint and such in the `format` script too. + +Observe that 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: + +```js + /* … */ + "remarkConfig": { + "settings": { + "bullet": "*", // Use `*` for list item bullets (default) + // See 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: + +```sh +npm run format +``` + +### Example: config files (JSON, YAML, JS) + +In the previous example, we saw that `remark-cli` was configured from within a +`package.json` file. +That’s a good place when the configuration is relatively short, when you have a +`package.json`, and when you don’t need comments (which are not allowed in +JSON). + +You can also define configuration in separate files in different languages. +With the `package.json` config as inspiration, here’s a JavaScript version that +can be placed in `.remarkrc.js`: + +```js +import remarkPresetLintConsistent from 'remark-preset-lint-consistent' +import remarkPresetLintRecommended from 'remark-preset-lint-recommended' +import remarkToc from 'remark-toc' + +const remarkConfig = { + settings: { + bullet: '*', // Use `*` for list item bullets (default) + // See for more options. + }, + plugins: [ + remarkPresetLintConsistent, // Check that markdown is consistent. + remarkPresetLintRecommended, // Few recommended rules. + // Generate a table of contents in `## Contents` + [remarkToc, {heading: 'contents'}] + ] +} + +export default remarkConfig +``` + +This is the same configuration in YAML, which can be placed in `.remarkrc.yml`: + +```yml +settings: + bullet: "*" +plugins: + # Check that markdown is consistent. + - remark-preset-lint-consistent + # Few recommended rules. + - remark-preset-lint-recommended + # Generate a table of contents in `## Contents` + - - remark-toc + - heading: contents +``` + +When `remark-cli` is about to process a markdown file it’ll search the file +system upwards for configuration files starting at the folder where that file +exists. +Take the following file structure as an illustration: + +```txt +folder/ +├─ subfolder/ +│ ├─ .remarkrc.json +│ └─ file.md +├─ .remarkrc.js +├─ package.json +└─ readme.md +``` + +When `folder/subfolder/file.md` is processed, the closest config file is +`folder/subfolder/.remarkrc.json`. +For `folder/readme.md`, it’s `folder/.remarkrc.js`. + +The order of precedence is as follows. +Earlier wins (so in the above file structure `folder/.remarkrc.js` wins over +`folder/package.json`): + +1. `.remarkc` (JSON) +2. `.remarkc.json` (JSON) +3. `.remarkc.cjs` (CJS) +4. `.remarkc.mjs` (ESM) +5. `.remarkc.js` (CJS or ESM, depending on `type: 'module'` in `package.json`) +6. `.remarkc.yaml` (YAML) +7. `.remarkc.yml` (YAML) +8. `package.json` with `remarkConfig` field + +## Compatibility + +Projects maintained by the unified collective are compatible with all maintained +versions of Node.js. +As of now, that is Node.js 12.20+, 14.14+, and 16.0+. +Our projects sometimes work with older versions, but this is not guaranteed. + ## Security -As markdown is sometimes used for HTML, and improper use of HTML can open you up -to a [cross-site scripting (XSS)][xss] attack, use of remark can also be unsafe. -When going to HTML, use remark in combination with the [**rehype**][rehype] -ecosystem, and use [`rehype-sanitize`][sanitize] to make the tree safe. +As markdown can be turned into HTML and improper use of HTML can open you up to +[cross-site scripting (XSS)][xss] attacks, use of remark can be unsafe. +When going to HTML, you will likely combine remark with **[rehype][]**, in which +case you should use [`rehype-sanitize`][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][security]. + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways to get started. See [`support.md`][support] for ways to get help. -Ideas for new plugins and tools can be posted in [`remarkjs/ideas`][ideas]. - -A curated list of awesome remark resources can be found in [**awesome -remark**][awesome]. +Join us in [Discussions][chat] to chat with the community and contributors. This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to @@ -118,35 +315,56 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! - - - + + + + + + + + + + + + +
- Gatsby 🥇

- -
- Vercel 🥇

+
+ Vercel

+ + Motif

+ +
+ HashiCorp

+ +
+ Gatsby

+ +
Netlify

- Holloway

- + Coinbase

+
ThemeIsle

+ Expo

+ +
Boost Hub

- Expo

- + Holloway

+
@@ -185,17 +403,15 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [chat]: https://github.com/remarkjs/remark/discussions -[health]: https://github.com/remarkjs/.github - -[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md +[security]: https://github.com/remarkjs/.github/blob/main/security.md -[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md +[health]: https://github.com/remarkjs/.github -[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md +[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md -[ideas]: https://github.com/remarkjs/ideas +[support]: https://github.com/remarkjs/.github/blob/main/support.md -[awesome]: https://github.com/remarkjs/awesome-remark +[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md [license]: https://github.com/remarkjs/remark/blob/main/license @@ -203,20 +419,24 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [npm]: https://docs.npmjs.com/cli/install -[remark]: https://github.com/remarkjs/remark +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting + +[rehype]: https://github.com/rehypejs/rehype -[plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize + +[remark]: https://github.com/remarkjs/remark [markdown-extensions]: https://github.com/sindresorhus/markdown-extensions -[config-file]: https://github.com/unifiedjs/unified-engine/blob/HEAD/doc/configure.md +[config-file]: https://github.com/unifiedjs/unified-engine/blob/main/doc/configure.md -[ignore-file]: https://github.com/unifiedjs/unified-engine/blob/HEAD/doc/ignore.md +[ignore-file]: https://github.com/unifiedjs/unified-engine/blob/main/doc/ignore.md [unified-args]: https://github.com/unifiedjs/unified-args#cli -[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[remark-core]: ../remark -[rehype]: https://github.com/rehypejs/rehype +[remark-toc]: https://github.com/remarkjs/remark-toc -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[markdown-style-guide]: https://github.com/remarkjs/remark-lint/tree/main/packages/remark-preset-lint-markdown-style-guide diff --git a/packages/remark-cli/test.js b/packages/remark-cli/test.js index a2e22e1e5..d12cb439b 100644 --- a/packages/remark-cli/test.js +++ b/packages/remark-cli/test.js @@ -16,7 +16,7 @@ test('remark-cli', (t) => { [ 'Usage: remark [options] [path | glob ...]', '', - ' CLI to process markdown with remark', + ' Command line interface to inspect and change markdown files with remark', '', 'Options:', '', diff --git a/packages/remark-parse/package.json b/packages/remark-parse/package.json index 294f6750a..717d29390 100644 --- a/packages/remark-parse/package.json +++ b/packages/remark-parse/package.json @@ -1,7 +1,7 @@ { "name": "remark-parse", "version": "10.0.0", - "description": "remark plugin to parse markdown", + "description": "remark plugin to add support for parsing markdown input", "license": "MIT", "keywords": [ "unified", diff --git a/packages/remark-parse/readme.md b/packages/remark-parse/readme.md index 2f17387df..cc98e8e28 100644 --- a/packages/remark-parse/readme.md +++ b/packages/remark-parse/readme.md @@ -8,26 +8,93 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[Parser][] for [**unified**][unified]. -Parses markdown to [**mdast**][mdast] syntax trees. -Built on [`micromark`][micromark] and -[`mdast-util-from-markdown`][from-markdown]. -Used in the [**remark** processor][remark] but can be used on its own as well. -Can be [extended][extend] to change how markdown is parsed. +**[remark][]** plugin to add support for parsing markdown input. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(remarkParse)`](#unifieduseremarkparse) +* [Examples](#examples) + * [Example: support GFM and frontmatter](#example-support-gfm-and-frontmatter) + * [Example: turning markdown into a man page](#example-turning-markdown-into-a-man-page) +* [Syntax](#syntax) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [License](#license) + +## What is this? + +This package is a [unified][] ([remark][]) plugin that defines how to take +markdown as input and turn it into a syntax tree. + +This plugin is built on [`mdast-util-from-markdown`][mdast-util-from-markdown], +which in turn uses [`micromark`][micromark] for parsing markdown into tokens and +turns those into [mdast][] syntax trees. +remark focusses on making it easier to transform content by abstracting such +internals away. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**mdast** is the markdown AST that remark uses. +**micromark** is the markdown parser we use. +This is a remark plugin that defines how input markdown is turned into mdast. + +## When should I use this? + +This plugin adds support to unified for parsing markdown. +You can alternatively use [`remark`][remark-core] instead, which combines +unified, this plugin, and [`remark-stringify`][remark-stringify]. + +You can combine this plugin with other plugins to add syntax extensions. +Notable examples that deeply integrate with it are +[`remark-gfm`][remark-gfm], +[`remark-mdx`][remark-mdx], +[`remark-frontmatter`][remark-frontmatter], +[`remark-math`][remark-math], and +[`remark-directive`][remark-directive]. +You can also use any other [remark plugin][plugin] after `remark-parse`. + +If you *just* want to turn markdown into HTML (with maybe a few extensions), +we recommend [`micromark`][micromark] instead. +If you want to handle syntax trees manually, you can use +[`mdast-util-from-markdown`][mdast-util-from-markdown]. ## Install -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. - -[npm][]: +This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). +In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: ```sh npm install remark-parse ``` +In Deno with [Skypack][]: + +```js +import remarkParse from 'https://cdn.skypack.dev/remark-parse@10?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use +Say we have the following module `example.js`: + ```js import {unified} from 'unified' import remarkParse from 'remark-parse' @@ -35,62 +102,152 @@ import remarkGfm from 'remark-gfm' import remarkRehype from 'remark-rehype' import rehypeStringify from 'rehype-stringify' -unified() - .use(remarkParse) - .use(remarkGfm) - .use(remarkRehype) - .use(rehypeStringify) - .process('# Hi\n\n*Hello*, world!') - .then((file) => { - console.log(String(file)) - }) +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkGfm) + .use(remarkRehype) + .use(rehypeStringify) + .process('# Hi\n\n*Hello*, world!') + + console.log(String(file)) +} ``` -Yields: +Running that with `node example.js` yields: ```html

Hi

Hello, world!

``` -[See **unified** for more examples »][unified] - ## API -[See **unified** for API docs »][unified] - This package exports no identifiers. The default export is `remarkParse`. ### `unified().use(remarkParse)` -Configure the `processor` to read markdown as input and process -[**mdast**][mdast] syntax trees. +Add support for parsing markdown input. +There are no options. + +## Examples + +### Example: support GFM and frontmatter + +We support CommonMark by default. +Non-standard markdown extensions can be enabled with plugins. +The following example adds support for GFM features (autolink literals, +footnotes, strikethrough, tables, tasklists) and frontmatter (YAML): + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkFrontmatter from 'remark-frontmatter' +import remarkGfm from 'remark-gfm' +import remarkRehype from 'remark-rehype' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkFrontmatter) + .use(remarkGfm) + .use(remarkRehype) + .use(rehypeStringify) + .process('---\nlayout: home\n---\n\n# Hi ~~Mars~~Venus!') + + console.log(String(file)) +} +``` + +Yields: + +```html +

Hi MarsVenus!

+``` + +### Example: turning markdown into a man page + +Man pages (short for manual pages) are a way to document CLIs (example: type +`man git-log` in your terminal). +They use an old markup format called roff. +There’s a remark plugin, [`remark-man`][remark-man], that can serialize as roff. +The following example turns markdown into man pages by using unified with +`remark-parse` and `remark-man`: + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkMan from 'remark-man' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkMan) + .process('# titan(7) -- largest moon of saturn\n\nTitan is the largest moon…') + + console.log(String(file)) +} +``` + +Yields: + +```roff +.TH "TITAN" "7" "November 2021" "" "" +.SH "NAME" +\fBtitan\fR - largest moon of saturn +.P +Titan is the largest moon… +``` + +## Syntax + +Markdown is parsed according to CommonMark. +Other plugins can add support for syntax extensions. +If you’re interested in extending markdown, +[more information is available in micromark’s readme][micromark-extend]. + +## Syntax tree + +The syntax tree format used in remark is [mdast][]. -## Extending the parser +## Types -See [`micromark`][micromark] and [`mdast-util-from-markdown`][from-markdown]. -Then create a wrapper plugin such as [`remark-gfm`][gfm]. +This package is fully typed with [TypeScript][]. +There are no extra exported types. + +## Compatibility + +Projects maintained by the unified collective are compatible with all maintained +versions of Node.js. +As of now, that is Node.js 12.20+, 14.14+, and 16.0+. +Our projects sometimes work with older versions, but this is not guaranteed. ## Security -As markdown is sometimes used for HTML, and improper use of HTML can open you up -to a [cross-site scripting (XSS)][xss] attack, use of remark can also be unsafe. -When going to HTML, use remark in combination with the [**rehype**][rehype] -ecosystem, and use [`rehype-sanitize`][sanitize] to make the tree safe. +As markdown can be turned into HTML and improper use of HTML can open you up to +[cross-site scripting (XSS)][xss] attacks, use of remark can be unsafe. +When going to HTML, you will likely combine remark with **[rehype][]**, in which +case you should use [`rehype-sanitize`][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][security]. + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways to get started. See [`support.md`][support] for ways to get help. -Ideas for new plugins and tools can be posted in [`remarkjs/ideas`][ideas]. - -A curated list of awesome remark resources can be found in [**awesome -remark**][awesome]. +Join us in [Discussions][chat] to chat with the community and contributors. This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to @@ -104,35 +261,56 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! - - - + + + + + + + + + + + + +
- Gatsby 🥇

- -
- Vercel 🥇

+
+ Vercel

+ + Motif

+ +
+ HashiCorp

+ +
+ Gatsby

+ +
Netlify

- Holloway

- + Coinbase

+
ThemeIsle

+ Expo

+ +
Boost Hub

- Expo

- + Holloway

+
@@ -175,17 +353,15 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [chat]: https://github.com/remarkjs/remark/discussions -[health]: https://github.com/remarkjs/.github - -[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md +[security]: https://github.com/remarkjs/.github/blob/main/security.md -[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md +[health]: https://github.com/remarkjs/.github -[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md +[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md -[ideas]: https://github.com/remarkjs/ideas +[support]: https://github.com/remarkjs/.github/blob/main/support.md -[awesome]: https://github.com/remarkjs/awesome-remark +[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md [license]: https://github.com/remarkjs/remark/blob/main/license @@ -193,24 +369,42 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [unified]: https://github.com/unifiedjs/unified -[remark]: https://github.com/remarkjs/remark/tree/main/packages/remark +[remark]: https://github.com/remarkjs/remark [mdast]: https://github.com/syntax-tree/mdast -[parser]: https://github.com/unifiedjs/unified#processorparser - -[extend]: #extending-the-parser - [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[typescript]: https://www.typescriptlang.org + [rehype]: https://github.com/rehypejs/rehype -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize + +[mdast-util-from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown [micromark]: https://github.com/micromark/micromark -[from-markdown]: https://github.com/syntax-tree/mdast-util-from-markdown +[micromark-extend]: https://github.com/micromark/micromark#extensions + +[remark-gfm]: https://github.com/remarkjs/remark-gfm + +[remark-mdx]: https://github.com/mdx-js/mdx/tree/main/packages/remark-mdx + +[remark-frontmatter]: https://github.com/remarkjs/remark-frontmatter + +[remark-math]: https://github.com/remarkjs/remark-math + +[remark-man]: https://github.com/remarkjs/remark-man + +[remark-directive]: https://github.com/remarkjs/remark-directive + +[remark-stringify]: ../remark-stringify/ + +[remark-core]: ../remark/ -[gfm]: https://github.com/remarkjs/remark-gfm +[plugin]: https://github.com/remarkjs/remark#plugin diff --git a/packages/remark-stringify/package.json b/packages/remark-stringify/package.json index b29b0df16..31eb09b4c 100644 --- a/packages/remark-stringify/package.json +++ b/packages/remark-stringify/package.json @@ -1,7 +1,7 @@ { "name": "remark-stringify", "version": "10.0.1", - "description": "remark plugin to compile markdown", + "description": "remark plugin to add support for serializing markdown", "license": "MIT", "keywords": [ "unified", diff --git a/packages/remark-stringify/readme.md b/packages/remark-stringify/readme.md index 5a31b2773..641854cb8 100644 --- a/packages/remark-stringify/readme.md +++ b/packages/remark-stringify/readme.md @@ -4,108 +4,280 @@ [![Coverage][coverage-badge]][coverage] [![Downloads][downloads-badge]][downloads] [![Size][size-badge]][size] -[![Chat][chat-badge]][chat] [![Sponsors][sponsors-badge]][collective] [![Backers][backers-badge]][collective] +[![Chat][chat-badge]][chat] -[Compiler][] for [**unified**][unified]. -Serializes [**mdast**][mdast] syntax trees to markdown. -Used in the [**remark** processor][remark] but can be used on its own as well. -Can be [extended][extend] to change how markdown is serialized. +**[remark][]** plugin to add support for serializing markdown. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`unified().use(remarkStringify[, options])`](#unifieduseremarkstringify-options) +* [Syntax](#syntax) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Security](#security) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [License](#license) + +## What is this? + +This package is a [unified][] ([remark][]) plugin that defines how to take a +syntax tree as input and turn it into serialized markdown. + +This plugin is built on [`mdast-util-to-markdown`][mdast-util-to-markdown], +which turns [mdast][] syntax trees into a string. +remark focusses on making it easier to transform content by abstracting such +internals away. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**mdast** is the markdown AST that remark uses. +This is a remark plugin that defines how mdast is turned into markdown. + +## When should I use this? + +This plugin adds support to unified for serializing markdown. +You can alternatively use [`remark`][remark-core] instead, which combines +unified, [`remark-parse`][remark-parse], and this plugin. + +You can combine this plugin with other plugins to add syntax extensions. +Notable examples that deeply integrate with it are +[`remark-gfm`][remark-gfm], +[`remark-mdx`][remark-mdx], +[`remark-frontmatter`][remark-frontmatter], +[`remark-math`][remark-math], and +[`remark-directive`][remark-directive]. +You can also use any other [remark plugin][plugin] before `remark-stringify`. + +If you want to handle syntax trees manually, you can use +[`mdast-util-to-markdown`][mdast-util-to-markdown]. ## Install -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. - -[npm][]: +This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). +In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: ```sh npm install remark-stringify ``` +In Deno with [Skypack][]: + +```js +import remarkStringify from 'https://cdn.skypack.dev/remark-stringify@10?dts' +``` + +In browsers with [Skypack][]: + +```html + +``` + ## Use +Say we have the following module `example.js`: + ```js import {unified} from 'unified' import rehypeParse from 'rehype-parse' import rehypeRemark from 'rehype-remark' import remarkStringify from 'remark-stringify' -unified() - .use(rehypeParse) - .use(rehypeRemark) - .use(remarkStringify, { - bullet: '*', - fence: '~', - fences: true, - incrementListMarker: false - }) - .process('

Hello, world!

') - .then((file) => { - console.log(String(file)) - }) +main() + +async function main() { + const file = await unified() + .use(rehypeParse) + .use(rehypeRemark) + .use(remarkStringify, { + bullet: '*', + fence: '~', + fences: true, + incrementListMarker: false + }) + .process('

Hello, world!

') + + console.log(String(file)) +} ``` -Yields: +Running that with `node example.js` yields: ```markdown # Hello, world! ``` -[See **unified** for more examples »][unified] - ## API -[See **unified** for API docs »][unified] - This package exports no identifiers. The default export is `remarkStringify`. ### `unified().use(remarkStringify[, options])` -Configure the `processor` to serialize [**mdast**][mdast] syntax trees to -markdown. +Add support for serializing markdown. +Options are passed to [`mdast-util-to-markdown`][mdast-util-to-markdown]: +all formatting options are supported. -###### `options` +##### `options` -Options can be passed directly or passed later through -[`processor.data()`][data]. +Configuration (optional). -All the formatting options of [`mdast-util-to-markdown`][to-markdown-options] -are supported and will be passed through. +###### `options.bullet` -## Extending the compiler +Marker to use for bullets of items in unordered lists (`'*'`, `'+'`, or `'-'`, +default: `'*'`). -See [`mdast-util-to-markdown`][to-markdown]. -Then create a wrapper plugin such as [`remark-gfm`][remark-gfm]. +###### `options.bulletOther` -## Security +Marker to use in certain cases where the primary bullet doesn’t work (`'*'`, +`'+'`, or `'-'`, default: depends). +See [`mdast-util-to-markdown`][mdast-util-to-markdown] for more information. + +###### `options.bulletOrdered` + +Marker to use for bullets of items in ordered lists (`'.'` or `')'`, default: +`'.'`). + +###### `options.bulletOrderedOther` + +Marker to use in certain cases where the primary bullet for ordered items +doesn’t work (`'.'` or `')'`, default: none). +See [`mdast-util-to-markdown`][mdast-util-to-markdown] for more information. + +###### `options.closeAtx` + +Whether to add the same number of number signs (`#`) at the end of an ATX +heading as the opening sequence (`boolean`, default: `false`). + +###### `options.emphasis` + +Marker to use for emphasis (`'*'` or `'_'`, default: `'*'`). + +###### `options.fence` + +Marker to use for fenced code (``'`'`` or `'~'`, default: ``'`'``). + +###### `options.fences` + +Whether to use fenced code always (`boolean`, default: `false`). +The default is to use fenced code if there is a language defined, if the code is +empty, or if it starts or ends in blank lines. + +###### `options.incrementListMarker` + +Whether to increment the counter of ordered lists items (`boolean`, default: +`true`). + +###### `options.listItemIndent` + +How to indent the content of list items (`'one'`, `'tab'`, or `'mixed'`, +default: `'tab'`). +Either with the size of the bullet plus one space (when `'one'`), a tab stop +(`'tab'`), or depending on the item and its parent list (`'mixed'`, uses `'one'` +if the item and list are tight and `'tab'` otherwise). + +###### `options.quote` + +Marker to use for titles (`'"'` or `"'"`, default: `'"'`). + +###### `options.resourceLink` + +Whether to always use resource links (`boolean`, default: `false`). +The default is to use autolinks (``) when possible +and resource links (`[text](url)`) otherwise. + +###### `options.rule` + +Marker to use for thematic breaks (`'*'`, `'-'`, or `'_'`, default: `'*'`). + +###### `options.ruleRepetition` + +Number of markers to use for thematic breaks (`number`, default: +`3`, min: `3`). + +###### `options.ruleSpaces` + +Whether to add spaces between markers in thematic breaks (`boolean`, default: +`false`). + +###### `options.setext` + +Whether to use setext headings when possible (`boolean`, default: `false`). +The default is to always use ATX headings (`# heading`) instead of setext +headings (`heading\n=======`). +Setext headings can’t be used for empty headings or headings with a rank of +three or more. + +###### `options.strong` + +Marker to use for strong (`'*'` or `'_'`, default: `'*'`). + +###### `options.tightDefinitions` + +Whether to join definitions without a blank line (`boolean`, default: `false`). +The default is to add blank lines between any flow (“block”) construct. + +###### `options.handlers` + +This option is a bit advanced as it requires knowledge of ASTs, so we defer +to the documentation available in +[`mdast-util-to-markdown`][mdast-util-to-markdown]. -`remark-stringify` will do its best to serialize markdown to match the syntax -tree, but there are several cases where that is impossible. -It’ll do its best, but complete roundtripping is impossible given that any -value could be injected into the tree. +###### `options.join` -As markdown is sometimes used for HTML, and improper use of HTML can open you up -to a [cross-site scripting (XSS)][xss] attack, use of `remark-stringify` and -parsing it again later can potentially be unsafe. -When parsing markdown afterwards, use remark in combination with the -[**rehype**][rehype] ecosystem, and use [`rehype-sanitize`][sanitize] to make -the tree safe. +This option is a bit advanced as it requires knowledge of ASTs, so we defer +to the documentation available in +[`mdast-util-to-markdown`][mdast-util-to-markdown]. + +###### `options.unsafe` + +This option is a bit advanced as it requires deep knowledge of markdown, so we +defer to the documentation available in +[`mdast-util-to-markdown`][mdast-util-to-markdown]. + +## Syntax + +Markdown is serialized according to CommonMark but care is taken to format in +such a way that the resulting markdown should work with most markdown parsers. +Other plugins can add support for syntax extensions. + +## Syntax tree + +The syntax tree format used in remark is [mdast][]. + +## Types + +This package is fully typed with [TypeScript][]. +An `Options` type is exported, which models the interface of accepted options. + +## Security + +As markdown can be turned into HTML and improper use of HTML can open you up to +[cross-site scripting (XSS)][xss] attacks, use of remark can be unsafe. +When going to HTML, you will likely combine remark with **[rehype][]**, in which +case you should use [`rehype-sanitize`][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][security]. + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways to get started. See [`support.md`][support] for ways to get help. -Ideas for new plugins and tools can be posted in [`remarkjs/ideas`][ideas]. - -A curated list of awesome remark resources can be found in [**awesome -remark**][awesome]. +Join us in [Discussions][chat] to chat with the community and contributors. This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to @@ -119,35 +291,56 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! - - - + + + + + + + + + + + + +
- Gatsby 🥇

- -
- Vercel 🥇

+
+ Vercel

+ + Motif

+ +
+ HashiCorp

+ +
+ Gatsby

+ +
Netlify

- Holloway

- + Coinbase

+
ThemeIsle

+ Expo

+ +
Boost Hub

- Expo

- + Holloway

+
@@ -190,17 +383,15 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [chat]: https://github.com/remarkjs/remark/discussions -[health]: https://github.com/remarkjs/.github - -[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md +[security]: https://github.com/remarkjs/.github/blob/main/security.md -[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md +[health]: https://github.com/remarkjs/.github -[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md +[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md -[ideas]: https://github.com/remarkjs/ideas +[support]: https://github.com/remarkjs/.github/blob/main/support.md -[awesome]: https://github.com/remarkjs/awesome-remark +[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md [license]: https://github.com/remarkjs/remark/blob/main/license @@ -208,26 +399,36 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [npm]: https://docs.npmjs.com/cli/install -[unified]: https://github.com/unifiedjs/unified - -[data]: https://github.com/unifiedjs/unified#processordatakey-value +[skypack]: https://www.skypack.dev -[remark]: https://github.com/remarkjs/remark/tree/main/packages/remark +[unified]: https://github.com/unifiedjs/unified -[compiler]: https://github.com/unifiedjs/unified#processorcompiler +[remark]: https://github.com/remarkjs/remark [mdast]: https://github.com/syntax-tree/mdast [xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[typescript]: https://www.typescriptlang.org + [rehype]: https://github.com/rehypejs/rehype -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize -[to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown +[mdast-util-to-markdown]: https://github.com/syntax-tree/mdast-util-to-markdown -[to-markdown-options]: https://github.com/syntax-tree/mdast-util-to-markdown#formatting-options +[remark-gfm]: https://github.com/remarkjs/remark-gfm -[extend]: #extending-the-compiler +[remark-mdx]: https://github.com/mdx-js/mdx/tree/main/packages/remark-mdx -[remark-gfm]: https://github.com/remarkjs/remark-gfm +[remark-frontmatter]: https://github.com/remarkjs/remark-frontmatter + +[remark-math]: https://github.com/remarkjs/remark-math + +[remark-directive]: https://github.com/remarkjs/remark-directive + +[remark-parse]: ../remark-parse/ + +[remark-core]: ../remark/ + +[plugin]: https://github.com/remarkjs/remark#plugin diff --git a/packages/remark/package.json b/packages/remark/package.json index 8a31a62cf..d2cc7f9ed 100644 --- a/packages/remark/package.json +++ b/packages/remark/package.json @@ -1,7 +1,7 @@ { "name": "remark", "version": "14.0.1", - "description": "Markdown processor powered by plugins part of the unified collective", + "description": "unified processor with support for parsing markdown input and serializing markdown as output", "license": "MIT", "keywords": [ "unified", diff --git a/packages/remark/readme.md b/packages/remark/readme.md index ede5c929a..fd9a05ab8 100644 --- a/packages/remark/readme.md +++ b/packages/remark/readme.md @@ -8,138 +8,231 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -[**unified**][unified] processor to parse and serialize markdown. -Built on [micromark][]. -Powered by [plugins][]. -Part of the [unified][] collective. - -* API by [**unified**][unified] -* Parses markdown to a syntax tree with [`remark-parse`][parse] -* [**mdast**][mdast] syntax tree -* [Plugins][] transform the tree -* Serializes syntax trees to markdown with [`remark-stringify`][stringify] - -Don’t need the parser? -Or compiler? -[That’s OK: use **unified** directly][unified-usage]. +**[unified][]** processor with support for parsing markdown input and +serializing markdown as output. + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [API](#api) + * [`remark()`](#remark-1) +* [Examples](#examples) + * [Example: checking markdown](#example-checking-markdown) + * [Example: passing options to `remark-stringify`](#example-passing-options-to-remark-stringify) +* [Syntax](#syntax) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [License](#license) + +## What is this? + +This package is a [unified][] processor with support for parsing markdown input +and serializing markdown as output by using unified with +[`remark-parse`][remark-parse] and [`remark-stringify`][remark-stringify]. + +**unified** is a project that transforms content with abstract syntax trees +(ASTs). +**remark** adds support for markdown to unified. +**mdast** is the markdown AST that remark uses. +Please see [the monorepo readme][remark] for what the remark ecosystem is. + +## When should I use this? + +You can use this package when you want to use unified, have markdown as input, +and want markdown as output. +This package is a shortcut for +`unified().use(remarkParse).use(remarkStringify)`. +When the input isn’t markdown (meaning you don’t need `remark-parse`) or the +output is not markdown (you don’t need `remark-stringify`), it’s recommended to +use unified directly. + +When you want to inspect and format markdown files in a project on the command +line, you can use [`remark-cli`][remark-cli]. ## Install -This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c): -Node 12+ is needed to use it and it must be `import`ed instead of `require`d. - -[npm][]: +This package is [ESM only](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c). +In Node.js (version 12.20+, 14.14+, or 16.0+), install with [npm][]: ```sh npm install remark ``` -## Use +In Deno with [Skypack][]: -[See **unified** for more examples »][unified] +```js +import {remark} from 'https://cdn.skypack.dev/remark@14?dts' +``` -###### Common example +In browsers with [Skypack][]: + +```html + +``` + +## Use -This example lints markdown and turns it into HTML. +Say we have the following module `example.js`: ```js -import {reporter} from 'vfile-reporter' import {remark} from 'remark' -import remarkPresetLintRecommended from 'remark-preset-lint-recommended' -import remarkHtml from 'remark-html' - -remark() - .use(remarkPresetLintRecommended) - .use(remarkHtml) - .process('## Hello world!') - .then((file) => { - console.error(reporter(file)) - console.log(String(file)) - }) -``` +import remarkGfm from 'remark-gfm' +import remarkToc from 'remark-toc' -Yields: +main() -```txt - 1:1 warning Missing newline character at end of file final-newline remark-lint +async function main() { + const file = await remark() + .use(remarkGfm) + .use(remarkToc) + .process('# Hi\n\n## Table of contents\n\n## Hello\n\n*Some* ~more~ _things_.') -⚠ 1 warning + console.error(String(file)) +} ``` -```html -

Hello world!

+Running that with `node example.js` yields: + +```markdown +# Hi + +## Table of contents + +* [Hello](#hello) + +## Hello + +*Some* ~~more~~ *things*. ``` -###### Settings through data +## API + +This package exports the following identifier: `remark`. +There is no default export. + +### `remark()` + +Create a new (unfrozen) unified processor that already uses `remark-parse` and +`remark-stringify` and you can add more plugins to. +See [`unified`][unified] for more information. + +## Examples + +### Example: checking markdown -This example prettifies markdown and configures [`remark-stringify`][stringify] -through [data][]. +The following example checks that markdown code style is consistent and follows +some best practices: ```js +import {reporter} from 'vfile-reporter' import {remark} from 'remark' +import remarkPresetLintConsistent from 'remark-preset-lint-consistent' +import remarkPresetLintRecommended from 'remark-preset-lint-recommended' + +main() -remark() - .data('settings', {emphasis: '*', strong: '*'}) - .process('_Emphasis_ and __importance__') - .then((file) => { - console.log(String(file)) - }) +async function main() { + const file = await remark() + .use(remarkPresetLintConsistent) + .use(remarkPresetLintRecommended) + .process('1) Hello, _Jupiter_ and *Neptune*!') + + console.error(reporter(file)) +} ``` Yields: -```markdown -*Emphasis* and **importance** +```txt + 1:1 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 ``` -###### Settings through a preset +### Example: passing options to `remark-stringify` -This example prettifies markdown and configures [`remark-parse`][parse] and -[`remark-stringify`][stringify] through a [preset][]. +When you use `remark-stringify` manually you can pass options to `use`. +Because `remark-stringify` is already used in `remark`, that’s not possible. +To define options for `remark-stringify`, you can instead pass options to +`data`: ```js import {remark} from 'remark' -remark() - .use({settings: {emphasis: '*', strong: '*'}}) - .process('_Emphasis_ and __importance__') - .then((file) => { - console.log(String(file)) - }) +main() + +async function main() { + const file = await remark() + .data('settings', {bullet: '*', setext: true, listItemIndent: 'one'}) + .process('# Moons of Neptune\n\n- Naiad\n- Thalassa\n- Despine\n- …') + + console.log(String(file)) +} ``` Yields: ```markdown -*Emphasis* and **importance** +Moons of Neptune +================ + +* Naiad +* Thalassa +* Despine +* … ``` -## API +## Syntax -[See **unified** for API docs »][unified] +Markdown is parsed and serialized according to CommonMark. +Other plugins can add support for syntax extensions. -This package exports the following identifier: `remark`. -There is no default export. +## Syntax tree + +The syntax tree format used in remark is [mdast][]. + +## Types + +This package is fully typed with [TypeScript][]. +There are no extra exported types. + +## Compatibility + +Projects maintained by the unified collective are compatible with all maintained +versions of Node.js. +As of now, that is Node.js 12.20+, 14.14+, and 16.0+. +Our projects sometimes work with older versions, but this is not guaranteed. ## Security -As markdown is sometimes used for HTML, and improper use of HTML can open you up -to a [cross-site scripting (XSS)][xss] attack, use of remark can also be unsafe. -When going to HTML, use remark in combination with the [**rehype**][rehype] -ecosystem, and use [`rehype-sanitize`][sanitize] to make the tree safe. +As markdown can be turned into HTML and improper use of HTML can open you up to +[cross-site scripting (XSS)][xss] attacks, use of remark can be unsafe. +When going to HTML, you will likely combine remark with **[rehype][]**, in which +case you should use [`rehype-sanitize`][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][security]. + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways to get started. See [`support.md`][support] for ways to get help. -Ideas for new plugins and tools can be posted in [`remarkjs/ideas`][ideas]. - -A curated list of awesome remark resources can be found in [**awesome -remark**][awesome]. +Join us in [Discussions][chat] to chat with the community and contributors. This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to @@ -153,35 +246,56 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! - - - + + + + + + + + + + + + +
- Gatsby 🥇

- -
- Vercel 🥇

+
+ Vercel

+ + Motif

+ +
+ HashiCorp

+ +
+ Gatsby

+ +
Netlify

- Holloway

- + Coinbase

+
ThemeIsle

+ Expo

+ +
Boost Hub

- Expo

- + Holloway

+
@@ -224,17 +338,15 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [chat]: https://github.com/remarkjs/remark/discussions -[health]: https://github.com/remarkjs/.github - -[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md +[security]: https://github.com/remarkjs/.github/blob/main/security.md -[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md +[health]: https://github.com/remarkjs/.github -[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md +[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md -[ideas]: https://github.com/remarkjs/ideas +[support]: https://github.com/remarkjs/.github/blob/main/support.md -[awesome]: https://github.com/remarkjs/awesome-remark +[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md [license]: https://github.com/remarkjs/remark/blob/main/license @@ -242,26 +354,24 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [npm]: https://docs.npmjs.com/cli/install +[skypack]: https://www.skypack.dev + [unified]: https://github.com/unifiedjs/unified [mdast]: https://github.com/syntax-tree/mdast -[parse]: https://github.com/remarkjs/remark/blob/main/packages/remark-parse - -[stringify]: https://github.com/remarkjs/remark/blob/main/packages/remark-stringify +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting -[plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md +[typescript]: https://www.typescriptlang.org -[unified-usage]: https://github.com/unifiedjs/unified#usage +[rehype]: https://github.com/rehypejs/rehype -[preset]: https://github.com/unifiedjs/unified#preset +[remark]: https://github.com/remarkjs/remark -[data]: https://github.com/unifiedjs/unified#processordatakey-value +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize -[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting - -[rehype]: https://github.com/rehypejs/rehype +[remark-parse]: ../remark-parse -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[remark-stringify]: ../remark-stringify -[micromark]: https://github.com/micromark/micromark +[remark-cli]: ../remark-cli diff --git a/readme.md b/readme.md index 8b0457906..50e5566dc 100644 --- a/readme.md +++ b/readme.md @@ -8,65 +8,399 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -**remark** is a markdown processor built on [micromark][] powered by -[plugins][] part of the [unified][] collective. +**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. -## Intro - -**remark** is [the world’s most popular markdown parser][popular]! -And it does so much more than parse: it inspects (check, lint) and transforms -(generate, compile) markdown too! - -Everything is possible with plugins, such as [checking markdown code -style (`remark-lint`)][remark-lint], [transforming safely to React -(`remark-react`)][remark-react], [adding a table of -contents (`remark-toc`)][remark-toc], or [compiling to man pages -(`remark-man`)][remark-man]. - -Internally, remark now uses [micromark][], a new, fast, and tiny CommonMark -compliant markdown tokenizer. -It can be GFM compliant with [`remark-gfm`][remark-gfm]. +## Feature highlights -Finally, remark is part of the [unified][website] [collective][governance]. -Learn more about us: +* [x] **[popular][]** (world’s most popular markdown parser) +* [x] **[compliant][syntax]** (100% to CommonMark, 100% to GFM with a plugin) +* [x] **[plugins][]** (150+ plugins you can pick and choose from) +* [x] **[ASTs][syntax-tree]** (inspecting and changing content made easy) -* Visit [`unifiedjs.com`][website] and peruse its [Learn][] section for an - overview -* Read [unified][]’s readme for a technical intro -* Browse [awesome remark][awesome] to find out more about the ecosystem -* Follow us on [Twitter][] to see what we’re up to -* Check out [Contribute][] below to find out how to help out - -## Packages - -This repository contains the following packages: +## Intro -* [`remark-parse`][parse] — Parse markdown to syntax trees -* [`remark-stringify`][stringify] — Serialize syntax trees to markdown -* [`remark`][api] — Programmatic interface with both `remark-parse` and `remark-stringify` -* [`remark-cli`][cli] — Command line interface wrapping `remark` +remark is a very popular 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][cheat] +* for more about us, see [`unifiedjs.com`][site] +* for updates, see [Twitter][] +* for questions, see [support][] +* to help, see [contribute][] or [sponsor][] below + +## Contents + +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Plugins](#plugins) +* [Examples](#examples) + * [Example: turning markdown into HTML](#example-turning-markdown-into-html) + * [Example: support for GFM and frontmatter](#example-support-for-gfm-and-frontmatter) + * [Example: checking markdown](#example-checking-markdown) + * [Example: checking and formatting markdown on the CLI](#example-checking-and-formatting-markdown-on-the-cli) +* [Syntax](#syntax) +* [Syntax tree](#syntax-tree) +* [Types](#types) +* [Compatibility](#compatibility) +* [Security](#security) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [License](#license) + +## What is this? + +You can use plugins to turn markdown into HTML. +**In**: + +```markdown +# Hello, *Mercury*! +``` + +**Out**: + +```html +

Hello, Mercury!

+``` + +You can use plugins to change markdown. +**In**: + +```markdown +# Hi, Saturn! +``` + +**Plugin**: + +```js +import {visit} from 'unist-util-visit' + +/** @type {import('unified').Plugin<[], import('mdast').Root>} */ +function myRemarkPluginToIncreaseHeadings() { + return (tree) => { + visit(tree, (node) => { + if (node.type === 'heading') { + node.depth++ + } + }) + } +} +``` + +**Out**: + +```markdown +## Hi, Saturn! +``` + +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`][remark-parse] + — plugin to take markdown as input and turn it into a syntax tree (mdast) +* [`remark-stringify`][remark-stringify] + — plugin to take a syntax tree (mdast) and turn it into markdown as output +* [`remark`][remark-core] + — unified, `remark-parse`, and `remark-stringify`, useful when input and + output are markdown +* [`remark-cli`][remark-cli] + — CLI around `remark` to inspect and format markdown in scripts + +## When should I use this? + +If you *just* want to turn markdown into HTML (with maybe a few extensions), +we recommend [`micromark`][micromark] instead. +remark can also do that but it focusses on ASTs and providing an interface for +plugins to transform them. + +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`. + +## Plugins + +remark plugins deal with markdown. +Some popular examples are: + +* [`remark-gfm`][remark-gfm] + — add support for GFM (GitHub flavored markdown) +* [`remark-lint`][remark-lint] + — inspect markdown and warns about inconsistencies +* [`remark-toc`][remark-toc] + — generate a table of contents +* [`remark-html`][remark-html] + — turn the syntax tree into serialized 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 define other output formats. + +You can choose from the 150+ plugins that already exist. +Here are three good ways to find plugins: + +* [`awesome-remark`][awesome-remark] + — selection of the most awesome projects +* [List of plugins][list-of-plugins] + — list of all plugins +* [`remark-plugin` topic][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`][remark-rehype]: + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkRehype from 'remark-rehype' +import rehypeSanitize from 'rehype-sanitize' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkRehype) + .use(rehypeSanitize) + .use(rehypeStringify) + .process('# Hello, Neptune!') + + console.log(String(file)) +} +``` + +Yields: + +```html +

Hello, Neptune!

+``` + +### 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): + +```js +import {unified} from 'unified' +import remarkParse from 'remark-parse' +import remarkFrontmatter from 'remark-frontmatter' +import remarkGfm from 'remark-gfm' +import remarkRehype from 'remark-rehype' +import rehypeStringify from 'rehype-stringify' + +main() + +async function main() { + const file = await unified() + .use(remarkParse) + .use(remarkFrontmatter) + .use(remarkGfm) + .use(remarkRehype) + .use(rehypeStringify) + .process('---\nlayout: home\n---\n\n# Hi ~~Mars~~Venus!') + + console.log(String(file)) +} +``` + +Yields: + +```html +

Hi MarsVenus!

+``` + +### Example: checking markdown + +The following example checks that markdown code style is consistent and follows +recommended best practices: + +```js +import {reporter} from 'vfile-reporter' +import {remark} from 'remark' +import remarkPresetLintConsistent from 'remark-preset-lint-consistent' +import remarkPresetLintRecommended from 'remark-preset-lint-recommended' + +main() + +async function main() { + const file = await remark() + .use(remarkPresetLintConsistent) + .use(remarkPresetLintRecommended) + .process('1) Hello, _Jupiter_ and *Neptune*!') + + console.error(reporter(file)) +} +``` + +Yields: + +```txt + 1:1 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: + +```sh +npm install remark-cli remark-toc remark-preset-lint-consistent remark-preset-lint-recommended --save-dev +``` + +Now, add an npm script in your `package.json`: + +```js + /* … */ + "scripts": { + /* … */ + "format": "remark . --output", + /* … */ + }, + /* … */ +``` + +> 💡 **Tip**: add ESLint and such in the `format` script too. + +Observe that 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: + +```js + /* … */ + "remarkConfig": { + "settings": { + "bullet": "*", // Use `*` for list item bullets (default) + // See 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: + +```sh +npm run format +``` + +## Syntax + +remark follows CommonMark, which standardizes the differences between markdown +implementations, by default. +Some syntax extensions are supported through plugins. + +We use [`micromark`][micromark] for our parsing. +See its documentation for more information on markdown, CommonMark, and +extensions. + +## Syntax tree + +The syntax tree format used in remark is [mdast][]. +It represents markdown constructs as JSON objects. +**In**: + +```markdown +## Hello *Pluto*! +``` + +**Out**: + +```js +{ + 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`][types-mdast]. + +## Compatibility + +Projects maintained by the unified collective are compatible with all maintained +versions of Node.js. +As of now, that is Node.js 12.20+, 14.14+, and 16.0+. +Our projects sometimes work with older versions, but this is not guaranteed. ## Security -As markdown is sometimes used for HTML, and improper use of HTML can open you up -to a [cross-site scripting (XSS)][xss] attack, use of remark can also be unsafe. -When going to HTML, use remark in combination with the [**rehype**][rehype] -ecosystem, and use [`rehype-sanitize`][sanitize] to make the tree safe. +As markdown can be turned into HTML and improper use of HTML can open you up to +[cross-site scripting (XSS)][xss] attacks, use of remark can be unsafe. +When going to HTML, you will likely combine remark with **[rehype][]**, in which +case you should use [`rehype-sanitize`][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][security]. + ## Contribute See [`contributing.md`][contributing] in [`remarkjs/.github`][health] for ways to get started. See [`support.md`][support] for ways to get help. -Ideas for new plugins and tools can be posted in [`remarkjs/ideas`][ideas]. Join us in [Discussions][chat] to chat with the community and contributors. -A curated list of awesome resources can be found in [**awesome -remark**][awesome]. - This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to abide by its terms. @@ -79,35 +413,56 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! - - - + + + + + + + + + + + + +
- Gatsby 🥇

- -
- Vercel 🥇

+
+ Vercel

+ + Motif

+ +
+ HashiCorp

+ +
+ Gatsby

+ +
Netlify

- Holloway

- + Coinbase

+
ThemeIsle

+ Expo

+ +
Boost Hub

- Expo

- + Holloway

+
@@ -150,58 +505,72 @@ Support this effort and give back by sponsoring on [OpenCollective][collective]! [backers-badge]: https://opencollective.com/unified/backers/badge.svg -[popular]: https://www.npmtrends.com/remark-parse-vs-marked-vs-markdown-it +[security]: https://github.com/remarkjs/.github/blob/main/security.md -[api]: https://github.com/remarkjs/remark/tree/main/packages/remark +[health]: https://github.com/remarkjs/.github -[parse]: https://github.com/remarkjs/remark/tree/main/packages/remark-parse +[contributing]: https://github.com/remarkjs/.github/blob/main/contributing.md -[stringify]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify +[support]: https://github.com/remarkjs/.github/blob/main/support.md -[cli]: https://github.com/remarkjs/remark/tree/main/packages/remark-cli +[coc]: https://github.com/remarkjs/.github/blob/main/code-of-conduct.md -[plugins]: https://github.com/remarkjs/remark/tree/main/doc/plugins.md +[collective]: https://opencollective.com/unified -[remark-lint]: https://github.com/remarkjs/remark-lint +[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting -[remark-react]: https://github.com/mapbox/remark-react +[typescript]: https://www.typescriptlang.org -[remark-toc]: https://github.com/remarkjs/remark-toc +[cheat]: https://commonmark.org/help/ + +[twitter]: https://twitter.com/unifiedjs + +[site]: https://unifiedjs.com + +[topic]: https://github.com/topics/remark-plugin + +[popular]: https://www.npmtrends.com/remark-parse-vs-marked-vs-micromark-vs-markdown-it -[remark-man]: https://github.com/remarkjs/remark-man +[types-mdast]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mdast [unified]: https://github.com/unifiedjs/unified -[website]: https://unifiedjs.com +[remark-gfm]: https://github.com/remarkjs/remark-gfm -[learn]: https://unifiedjs.com/learn/ +[remark-toc]: https://github.com/remarkjs/remark-toc -[contribute]: #contribute +[remark-rehype]: https://github.com/remarkjs/remark-rehype -[health]: https://github.com/remarkjs/.github +[remark-html]: https://github.com/remarkjs/remark-html -[contributing]: https://github.com/remarkjs/.github/blob/HEAD/contributing.md +[remark-lint]: https://github.com/remarkjs/remark-lint -[support]: https://github.com/remarkjs/.github/blob/HEAD/support.md +[awesome-remark]: https://github.com/remarkjs/awesome-remark -[coc]: https://github.com/remarkjs/.github/blob/HEAD/code-of-conduct.md +[rehype]: https://github.com/rehypejs/rehype -[ideas]: https://github.com/remarkjs/ideas +[rehype-sanitize]: https://github.com/rehypejs/rehype-sanitize -[awesome]: https://github.com/remarkjs/awesome-remark +[mdast]: https://github.com/syntax-tree/mdast -[collective]: https://opencollective.com/unified +[micromark]: https://github.com/micromark/micromark -[governance]: https://github.com/unifiedjs/governance +[remark-parse]: packages/remark-parse/ -[twitter]: https://twitter.com/unifiedjs +[remark-stringify]: packages/remark-stringify/ -[xss]: https://en.wikipedia.org/wiki/Cross-site_scripting +[remark-core]: packages/remark/ -[rehype]: https://github.com/rehypejs/rehype +[remark-cli]: packages/remark-cli/ -[sanitize]: https://github.com/rehypejs/rehype-sanitize +[list-of-plugins]: doc/plugins.md#list-of-plugins -[micromark]: https://github.com/micromark/micromark +[syntax]: #syntax -[remark-gfm]: https://github.com/remarkjs/remark-gfm +[syntax-tree]: #syntax-tree + +[plugins]: #plugins + +[contribute]: #contribute + +[sponsor]: #sponsor