From 144eec01b0e1faa23655359d61c3749ad2af99e7 Mon Sep 17 00:00:00 2001 From: Titus Wormer Date: Sun, 19 Jun 2022 17:21:19 +0200 Subject: [PATCH] Add improved docs --- package.json | 6 +- readme.md | 1260 +++++++++++++++++++++++++++----------------------- 2 files changed, 699 insertions(+), 567 deletions(-) diff --git a/package.json b/package.json index 5da980f8..797e32ec 100644 --- a/package.json +++ b/package.json @@ -95,7 +95,11 @@ }, "remarkConfig": { "plugins": [ - "preset-wooorm" + "preset-wooorm", + [ + "remark-lint-no-html", + false + ] ] }, "typeCoverage": { diff --git a/readme.md b/readme.md index c1311510..987cfdc3 100644 --- a/readme.md +++ b/readme.md @@ -8,112 +8,99 @@ [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat] -**unified** is an interface for processing text using syntax trees. -It’s what powers [**remark**][remark] (Markdown), [**retext**][retext] (natural -language), and [**rehype**][rehype] (HTML), and allows for processing between -formats. - -## Intro - -**unified** enables new exciting projects like [Gatsby][] to pull in Markdown, -[MDX][] to embed [JSX][], and [Prettier][] to format it. -It’s used in about 700k projects on GitHub and has about 35m downloads each -month on npm: you’re probably using it. -Some notable users are [Node.js][], [Vercel][], [Netlify][], [GitHub][], -[Mozilla][], [WordPress][], [Adobe][], [Facebook][], [Google][], and many more. - -* To read about what we are up to, follow us [Twitter][] -* For a less technical and more practical introduction to unified, visit - [`unifiedjs.com`][site] and peruse its [Learn][] section -* Browse [awesome unified][awesome] to find out more about the ecosystem -* Questions? - Get help on [Discussions][chat]! -* Check out [Contribute][] below to find out how to help out, or become a - backer or sponsor on [OpenCollective][collective] - -## Sponsors +**unified** lets you inspect and transform content with plugins. -Support this effort and give back by sponsoring on [OpenCollective][collective]! +## Contents - +* [What is this?](#what-is-this) +* [When should I use this?](#when-should-i-use-this) +* [Install](#install) +* [Use](#use) +* [Overview](#overview) +* [API](#api) + * [`processor()`](#processor) + * [`processor.use(plugin[, options])`](#processoruseplugin-options) + * [`processor.parse(file)`](#processorparsefile) + * [`processor.stringify(tree[, file])`](#processorstringifytree-file) + * [`processor.run(tree[, file][, done])`](#processorruntree-file-done) + * [`processor.runSync(tree[, file])`](#processorrunsynctree-file) + * [`processor.process(file[, done])`](#processorprocessfile-done) + * [`processor.processSync(file)`](#processorprocesssyncfile) + * [`processor.data([key[, value]])`](#processordatakey-value) + * [`processor.freeze()`](#processorfreeze) +* [`Plugin`](#plugin) + * [`function attacher(options?)`](#function-attacheroptions) + * [`function transformer(tree, file[, next])`](#function-transformertree-file-next) +* [`Preset`](#preset) +* [Types](#types) +* [Compatibility](#compatibility) +* [Contribute](#contribute) +* [Sponsor](#sponsor) +* [Acknowledgments](#acknowledgments) +* [License](#license) - - - - - - - - - - - - - - - - - - - - - - - -
- Vercel

- -
- Motif

- -
- HashiCorp

- -
- American Express

- -
- GitBook

- -
- Gatsby

- -
- Netlify

- - -
- Coinbase

- -
- ThemeIsle

- -
- Expo

- -
- Boost Note

- -
- Holloway

- -
-
- You? -

-
+## What is this? -## Install +unified is two things: + +* **unified** is a collective of 500+ free and open source packages that work + with content as structured data (ASTs) +* `unified` (this project) is the core package, used in 800k+ projects on GH, + to process content with plugins -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. +Several ecosystems are built on unified around different kinds of content. +Notably, [remark][] (markdown), [rehype][] (HTML), and [retext][] (natural +language). +These ecosystems can be connected together. -[npm][]: +* for more about us, see [`unifiedjs.com`][site] +* for updates, see [@unifiedjs][twitter] on Twitter +* for questions, see [support][] +* to help, see [contribute][] and [sponsor][] below + +## When should I use this? + +In some cases, you are already using unified. +For example, it’s used in MDX, Gatsby, Docusaurus, etc. +In those cases, you don’t need to add `unified` yourself but you can include +plugins into those projects. + +But the real fun (for some) is to get your hands dirty and work with syntax +trees and build with it yourself. +You can create those projects, or things like Prettier, or your own site +generator. +You can connect utilities together and make your own plugins that check for +problems and transform from one thing to another. + +When you are dealing with one type of content (such as markdown), it’s +recommended to use the main package of that ecosystem instead (so `remark`). +When you are dealing with different kinds of content (such as markdown and +HTML), it’s recommended to use `unified` itself, and pick and choose the plugins +you need. + +## Install + +This package is [ESM only][esm]. +In Node.js (version 12.20+, 14.14+, 16.0+, 18.0+), install with [npm][]: ```sh npm install unified ``` +In Deno with [`esm.sh`][esmsh]: + +```js +import {unified} from 'https://esm.sh/unified@10' +``` + +In browsers with [`esm.sh`][esmsh]: + +```html + +``` + ## Use ```js @@ -125,23 +112,16 @@ import rehypeFormat from 'rehype-format' import rehypeStringify from 'rehype-stringify' import {reporter} from 'vfile-reporter' -unified() +const file = await unified() .use(remarkParse) .use(remarkRehype) .use(rehypeDocument, {title: '👋🌍'}) .use(rehypeFormat) .use(rehypeStringify) .process('# Hello world!') - .then( - (file) => { - console.error(reporter(file)) - console.log(String(file)) - }, - (error) => { - // Handle your error here! - throw error - } - ) + +console.error(reporter(file)) +console.log(String(file)) ``` Yields: @@ -164,37 +144,19 @@ no issues found ``` -## Contents + -* [Description](#description) -* [API](#api) - * [`processor()`](#processor) - * [`processor.use(plugin[, options])`](#processoruseplugin-options) - * [`processor.parse(file)`](#processorparsefile) - * [`processor.stringify(node[, file])`](#processorstringifynode-file) - * [`processor.run(node[, file][, done])`](#processorrunnode-file-done) - * [`processor.runSync(node[, file])`](#processorrunsyncnode-file) - * [`processor.process(file[, done])`](#processorprocessfile-done) - * [`processor.processSync(file|value)`](#processorprocesssyncfilevalue) - * [`processor.data([key[, value]])`](#processordatakey-value) - * [`processor.freeze()`](#processorfreeze) -* [`Plugin`](#plugin) - * [`function attacher([options])`](#function-attacheroptions) - * [`function transformer(node, file[, next])`](#function-transformernode-file-next) -* [`Preset`](#preset) -* [Contribute](#contribute) -* [Acknowledgments](#acknowledgments) -* [License](#license) + -## Description +## Overview -**unified** is an interface for processing text using syntax trees. -Syntax trees are a representation of text understandable to programs. -Those programs, called [*plugin*][plugin]s, take these trees and inspect and +`unified` is an interface for processing content with syntax trees. +Syntax trees are a representation of content understandable to programs. +Those programs, called *[plugins][plugin]*, take these trees and inspect and modify them. -To get to the syntax tree from text, there is a [*parser*][parser]. -To get from that back to text, there is a [*compiler*][compiler]. -This is the [*process*][process] of a *processor*. +To get to the syntax tree from text, there is a *[parser][]*. +To get from that back to text, there is a *[compiler][]*. +This is the *[process][]* of a *processor*. ```ascii | ........................ process ........................... | @@ -212,7 +174,29 @@ Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output ###### Processors -Every **processor** implements another processor. +Processors process content. +On its own, `unified` (the root processor) doesn’t work. +It needs to be configured with plugins to work. +For example: + +```js +const processor = unified() + .use(remarkParse) + .use(remarkRehype) + .use(rehypeDocument, {title: '👋🌍'}) + .use(rehypeFormat) + .use(rehypeStringify) +``` + +That processor can do different things. +It can: + +* …parse markdown (`parse`) +* …turn parsed markdown into HTML and format the HTML (`run`) +* …compile HTML (`stringify`) +* …do all of the above (`process`) + +Every processor implements another processor. To create a processor, call another processor. The new processor is configured to work the same as its ancestor. But when the descendant processor is configured in the future it does not affect @@ -221,72 +205,98 @@ the ancestral processor. When processors are exposed from a module (for example, `unified` itself) they should not be configured directly, as that would change their behavior for all module users. -Those processors are [*frozen*][freeze] and they should be called to create a +Those processors are *[frozen][freeze]* and they should be called to create a new processor before they are used. -###### Syntax trees +###### File + +When processing a document, metadata is gathered about that document. +[`vfile`][vfile] is the file format that stores data, metadata, and messages +about files for unified and plugins. -The **syntax trees** used in **unified** are [**unist**][unist] nodes. -A [**node**][node] is a plain JavaScript objects with a `type` field. -The semantics of nodes and format of syntax trees is defined by other projects. +There are several [utilities][vfile-utilities] for working with these files. -There are several [*utilities*][unist-utilities] for working with nodes. +###### Syntax tree -* [**esast**][esast] — JS -* [**hast**][hast] — HTML -* [**mdast**][mdast] — Markdown -* [**nlcst**][nlcst] — Natural language -* [**xast**][xast] — XML +The syntax trees used in unified are [unist][] nodes. +A tree represents a whole document and each [node][] is a plain JavaScript +object with a `type` field. +The semantics of nodes and the format of syntax trees is defined by other +projects: -###### List of processors +* [esast][] — JavaScript +* [hast][] — HTML +* [mdast][] — markdown +* [nlcst][] — natural language +* [xast][] — XML -The following projects process different [*syntax tree*][syntax-tree] formats. -They parse text to a syntax tree and compile that back to text. -These processors can be used as is, or their parser and compiler can be mixed -and matched with **unified** and plugins to process between different syntaxes. +There are many utilities for working with trees listed in each aforementioned +project and maintained in the [`syntax-tree`][syntax-tree] organization. +These utilities are a level lower than unified itself and are building blocks +that can be used to make plugins. -* [**rehype**][rehype] ([*hast*][hast]) — HTML -* [**remark**][remark] ([*mdast*][mdast]) — Markdown -* [**retext**][retext] ([*nlcst*][nlcst]) — Natural language + -###### List of plugins + -The below [**plugins**][plugin] work with **unified**, on all [*syntax -tree*][syntax-tree] formats: +###### Ecosystems -* [`unified-diff`](https://github.com/unifiedjs/unified-diff) - — Ignore messages for unchanged lines in Travis -* [`unified-message-control`](https://github.com/unifiedjs/unified-message-control) - — Enable, disable, and ignore messages +Around each syntax tree is an ecosystem that focusses on that particular kind +of content. +At their core, they parse text to a tree and compile that tree back to text. +They also provide plugins that work with the syntax tree, without requiring +that the end user has knowledge about that tree. -See [**remark**][remark-plugins], [**rehype**][rehype-plugins], and -[**retext**][retext-plugins] for their lists of plugins. +* [rehype][] (hast) — HTML +* [remark][] (mdast) — markdown +* [retext][] (nlcst) — natural language -###### File + + +###### Plugins -When processing a document, **metadata** is often gathered about that document. -[**vfile**][vfile] is a virtual file format that stores data, metadata, and -messages about files for **unified** and its plugins. +Each aforementioned ecosystem comes with a large set of plugins that you can +pick and choose from to do all kinds of things. -There are several [*utilities*][vfile-utilities] for working with these files. +* [List of remark plugins][remark-plugins] · + [`remarkjs/awesome-remark`][awesome-remark] · + [`remark-plugin` topic][topic-remark-plugin] +* [List of rehype plugins][rehype-plugins] · + [`rehypejs/awesome-rehype`][awesome-rehype] · + [`rehype-plugin` topic][topic-rehype-plugin] +* [List of retext plugins][retext-plugins] · + [`retextjs/awesome-retext`][awesome-retext] · + [`retext-plugin` topic][topic-retext-plugin] + +There are also a few plugins that work in any ecosystem: + +* [`unified-diff`](https://github.com/unifiedjs/unified-diff) + — ignore unrelated messages in GitHub Actions and Travis +* [`unified-infer-git-meta`](https://github.com/unifiedjs/unified-infer-git-meta) + — infer metadata of a document from Git +* [`unified-message-control`](https://github.com/unifiedjs/unified-message-control) + — enable, disable, and ignore messages from content ###### Configuration -[*Processors*][processors] are configured with [*plugin*][plugin]s or -with the [`data`][data] method. +Processors are configured with [plugins][plugin] or with the [`data`][data] +method. +Most plugins also accept configuration through options. +See each plugin’s readme for more info. ###### Integrations -**unified** can integrate with the file system with [`unified-engine`][engine]. -CLI apps can be created with [`unified-args`][args], Gulp plugins with -[`unified-engine-gulp`][gulp]. - -[`unified-stream`][stream] provides a streaming interface. +unified can integrate with the file system through +[`unified-engine`][unified-engine]. +CLI apps can be created with [`unified-args`][unified-args], Gulp plugins with +[`unified-engine-gulp`][unified-engine-gulp], and language servers with +[`unified-language-server`][unified-language-server]. +A streaming interface can be created with [`unified-stream`][unified-stream]. ###### Programming interface -The API provided by **unified** allows multiple files to be processed and gives -access to *metadata* (such as lint messages): +The [API][] provided by `unified` allows multiple files to be processed and +gives access to metadata (such as lint messages): ```js import {unified} from 'unified' @@ -299,23 +309,16 @@ import remarkRehype from 'remark-rehype' import rehypeStringify from 'rehype-stringify' import {reporter} from 'vfile-reporter' -unified() +const file = await unified() .use(remarkParse) .use(remarkPresetLintMarkdownStyleGuide) .use(remarkRetext, unified().use(retextEnglish).use(retextEquality)) .use(remarkRehype) .use(rehypeStringify) .process('*Emphasis* and _stress_, you guys!') - .then( - (file) => { - console.error(reporter(file)) - console.log(String(file)) - }, - (error) => { - // Handle your error here! - throw error - } - ) + +console.error(reporter(file)) +console.log(String(file)) ``` Yields: @@ -331,68 +334,78 @@ Yields:

Emphasis and stress, you guys!

``` -###### Processing between syntaxes + + + -[*Processors*][processors] can be combined in two modes. +###### Transforming between ecosystems -**Bridge** mode transforms the [*syntax tree*][syntax-tree] from one format -(*origin*) to another (*destination*). -Another processor runs on the destination tree. -Finally, the original processor continues transforming the origin tree. +Ecosystems can be combined in two modes. + +**Bridge** mode transforms the tree from one format (*origin*) to another +(*destination*). +A different processor runs on the destination tree. +Afterwards, the original processor continues with the origin tree. **Mutate** mode also transforms the syntax tree from one format to another. But the original processor continues transforming the destination tree. In the previous example (“Programming interface”), `remark-retext` is used in -*bridge* mode: the origin syntax tree is kept after [**retext**][retext] is -done; whereas `remark-rehype` is used in *mutate* mode: it sets a new syntax -tree and discards the origin tree. +bridge mode: the origin syntax tree is kept after retext is done; whereas +`remark-rehype` is used in mutate mode: it sets a new syntax tree and discards +the origin tree. + +The following plugins lets you combine ecosystems: -* [`remark-retext`][remark-retext] -* [`remark-rehype`][remark-rehype] -* [`rehype-retext`][rehype-retext] -* [`rehype-remark`][rehype-remark] +* [`remark-retext`][remark-retext] — turn markdown into natural language +* [`remark-rehype`][remark-rehype] — turn markdown into HTML +* [`rehype-retext`][rehype-retext] — turn HTML into natural language +* [`rehype-remark`][rehype-remark] — turn HTML into markdown ## API -This package exports the following identifiers: `unified`. +This package exports the identifier `unified` (the root `processor`). There is no default export. ### `processor()` -[*Processor*][processors] describing how to *process* text. +Create a processor. ###### Returns -`Function` — New [*unfrozen*][freeze] processor that is configured to work the +New *[unfrozen][freeze]* processor (`processor`) that is configured to work the same as its ancestor. When the descendant processor is configured in the future it does not affect the ancestral processor. ###### Example -The following example shows how a new processor can be created (from the remark -processor) and linked to **stdin**(4) and **stdout**(4). +This example shows how a new processor can be created (from `remark`) and linked +to **stdin**(4) and **stdout**(4). ```js -import {remark} from 'remark' +import process from 'node:process' import concatStream from 'concat-stream' +import {remark} from 'remark' process.stdin.pipe( concatStream((buf) => { - process.stdout.write(remark().processSync(buf).toString()) + process.stdout.write(String(remark().processSync(buf))) }) ) ``` ### `processor.use(plugin[, options])` -[*Configure*][configuration] the processor to use a [*plugin*][plugin] and -optionally configure that plugin with options. +Configure the processor to use a plugin and optionally configure that plugin +with options. -If the processor is already using this plugin, the previous plugin configuration +If the processor is already using a plugin, the previous plugin configuration is changed based on the options that are passed in. -The plugin is not added a second time. +In other words, the plugin is not added a second time. + +> 👉 **Note**: `use` cannot be called on *[frozen][freeze]* processors. +> Call the processor first to create a new unfrozen processor. ###### Signatures @@ -403,25 +416,20 @@ The plugin is not added a second time. ###### Parameters * `plugin` ([`Attacher`][plugin]) -* `options` (`*`, optional) — Configuration for `plugin` -* `preset` (`Object`) — Object with an optional `plugins` (set to `list`), +* `options` (`*`, optional) — configuration for `plugin` +* `preset` (`Object`) — object with an optional `plugins` (set to `list`), and/or an optional `settings` object -* `list` (`Array`) — List of plugins, presets, and pairs (`plugin` and +* `list` (`Array`) — list of plugins, presets, and pairs (`plugin` and `options` in an array) ###### Returns -`processor` — The processor that `use` was called on. - -###### Note - -`use` cannot be called on [*frozen*][freeze] processors. -Call the processor first to create a new unfrozen processor. +The processor that `use` was called on (`processor`). ###### Example There are many ways to pass plugins to `.use()`. -The below example gives an overview. +This example gives an overview: ```js import {unified} from 'unified' @@ -443,27 +451,24 @@ unified() ### `processor.parse(file)` -Parse text to a [*syntax tree*][syntax-tree]. +Parse text to a syntax tree. -###### Parameters +> 👉 **Note**: `parse` freezes the processor if not already *[frozen][freeze]*. -* `file` ([`VFile`][vfile]) — [*File*][file], any value accepted by `vfile()` - -###### Returns +> 👉 **Note**: `parse` performs the [parse phase][overview], not the run phase +> or other phases. -[`Node`][node] — Parsed [*syntax tree*][syntax-tree] representing `file`. +###### Parameters -###### Note +* `file` ([`VFile`][vfile]) — any value accepted as `x` in `new VFile(x)` -`parse` freezes the processor if not already [*frozen*][freeze]. +###### Returns -`parse` performs the [*parse phase*][description], not the *run phase* or other -phases. +Syntax tree representing `file` ([`Node`][node]). ###### Example -The below example shows how `parse` can be used to create a syntax tree from a -file. +This example shows how `parse` can be used to create a tree from a file. ```js import {unified} from 'unified' @@ -491,50 +496,49 @@ Yields: #### `processor.Parser` -A **parser** handles the parsing of text to a [*syntax tree*][syntax-tree]. -Used in the [*parse phase*][description] and called with a `string` and -[`VFile`][vfile] representation of the text to parse. +A **parser** handles the parsing of text to a syntax tree. +It is used in the [parse phase][overview] and is called with a `string` and +[`VFile`][vfile] of the document to parse. -`Parser` can be a function, in which case it must return a [`Node`][node]: the -syntax tree representation of the given file. +`Parser` can be a normal function, in which case it must return the syntax +tree representation of the given file ([`Node`][node]). `Parser` can also be a constructor function (a function with a `parse` field, or -other fields, in its `prototype`), in which case it’s constructed with `new`. +other fields, in its `prototype`), in which case it is constructed with `new`. Instances must have a `parse` method that is called without arguments and must return a [`Node`][node]. -### `processor.stringify(node[, file])` +### `processor.stringify(tree[, file])` -Compile a [*syntax tree*][syntax-tree]. +Compile a syntax tree. -###### Parameters +> 👉 **Note**: `stringify` freezes the processor if not already +> *[frozen][freeze]*. -* `node` ([`Node`][node]) — [*Syntax tree*][syntax-tree] to compile -* `file` ([`VFile`][vfile], optional) — [*File*][file], any value accepted by - `vfile()` - -###### Returns +> 👉 **Note**: `stringify` performs the [stringify phase][overview], not the run +> phase or other phases. -`string` or `Buffer` (see notes) — Textual representation of the [*syntax -tree*][syntax-tree] +###### Parameters -###### Note +* `tree` ([`Node`][node]) — tree to compile +* `file` ([`VFile`][vfile], optional) — any value accepted as `x` in + `new VFile(x)` -`stringify` freezes the processor if not already [*frozen*][freeze]. +###### Returns -`stringify` performs the [*stringify phase*][description], not the *run phase* -or other phases. +Textual representation of the tree (`string` or `Buffer`, see note). -unified typically compiles by serializing: most [*compiler*][compiler]s return -`string` (or `Buffer`). -Some compilers, such as the one configured with [`rehype-react`][rehype-react], -return other values (in this case, a React tree). -If you’re using a compiler doesn’t serialize, expect different result values. -When using TypeScript, cast the type on your side. +> 👉 **Note**: unified typically compiles by serializing: most +> [compilers][compiler] return `string` (or `Buffer`). +> Some compilers, such as the one configured with +> [`rehype-react`][rehype-react], return other values (in this case, a React +> tree). +> If you’re using a compiler that doesn’t serialize, expect different result +> values. ###### Example -The below example shows how `stringify` can be used to serialize a syntax tree. +This example shows how `stringify` can be used to serialize a syntax tree: ```js import {unified} from 'unified' @@ -556,56 +560,53 @@ Yields: #### `processor.Compiler` -A **compiler** handles the compiling of a [*syntax tree*][syntax-tree] to text. -Used in the [*stringify phase*][description] and called with a [`Node`][node] -and [`VFile`][file] representation of syntax tree to compile. +A **compiler** handles the compiling of a syntax tree to something else (in +most cases, text). +It is used in the [stringify phase][overview] and called with a [`Node`][node] +and [`VFile`][file] representation of the document to compile. -`Compiler` can be a function, in which case it should return a `string`: the -textual representation of the syntax tree. +`Compiler` can be a normal function, in which case it should return the textual +representation of the given tree (`string`). `Compiler` can also be a constructor function (a function with a `compile` -field, or other fields, in its `prototype`), in which case it’s constructed with -`new`. +field, or other fields, in its `prototype`), in which case it is constructed +with `new`. Instances must have a `compile` method that is called without arguments and should return a `string`. -### `processor.run(node[, file][, done])` - -Run [*transformers*][transformer] on a [*syntax tree*][syntax-tree]. - -###### Parameters - -* `node` ([`Node`][node]) — [*Syntax tree*][syntax-tree] to run on -* `file` ([`VFile`][vfile], optional) — [*File*][file], any value accepted by - `vfile()` -* `done` ([`Function`][run-done], optional) — Callback - -###### Returns +> 👉 **Note**: unified typically compiles by serializing: most compilers +> return `string` (or `Buffer`). +> Some compilers, such as the one configured with +> [`rehype-react`][rehype-react], return other values (in this case, a React +> tree). +> If you’re using a compiler that doesn’t serialize, expect different result +> values. -[`Promise`][promise] if `done` is not given. -The returned promise is rejected with a fatal error, or resolved with the -transformed [*syntax tree*][syntax-tree]. +### `processor.run(tree[, file][, done])` -###### Note +Run *[transformers][transformer]* on a syntax tree. -`run` freezes the processor if not already [*frozen*][freeze]. +> 👉 **Note**: `run` freezes the processor if not already *[frozen][freeze]*. -`run` performs the [*run phase*][description], not other phases. +> 👉 **Note**: `run` performs the [run phase][overview], not other phases. -#### `function done(err[, node, file])` +###### Parameters -Callback called when [*transformers*][transformer] are done. -Called with either an error or results. +* `tree` ([`Node`][node]) — tree to transform and inspect +* `file` ([`VFile`][vfile], optional) — any value accepted as `x` in + `new VFile(x)` +* `done` ([`Function`][run-done], optional) — callback -###### Parameters +###### Returns -* `err` (`Error`, optional) — Fatal error -* `node` ([`Node`][node], optional) — Transformed [*syntax tree*][syntax-tree] -* `file` ([`VFile`][vfile], optional) — [*File*][file] +Nothing if `done` is given (`void`). +A [`Promise`][promise] otherwise. +The promise is rejected with a fatal error or resolved with the transformed +tree ([`Node`][node]). ###### Example -The below example shows how `run` can be used to transform a syntax tree. +This example shows how `run` can be used to transform a tree: ```js import {unified} from 'unified' @@ -618,16 +619,9 @@ const tree = u('root', [ ]) ]) -unified() - .use(remarkReferenceLinks) - .run(tree) - .then( - (changedTree) => console.log(changedTree), - (error) => { - // Handle your error here! - throw error - } - ) +const changedTree = await unified().use(remarkReferenceLinks).run(tree) + +console.log(changedTree) ``` Yields: @@ -642,65 +636,73 @@ Yields: } ``` -### `processor.runSync(node[, file])` - -Run [*transformers*][transformer] on a [*syntax tree*][syntax-tree]. +#### `function done(err[, tree, file])` -An error is thrown if asynchronous [*plugin*][plugin]s are configured. +Callback called when transformers are done. +Called with either an error or results. ###### Parameters -* `node` ([`Node`][node]) — [*Syntax tree*][syntax-tree] to run on -* `file` ([`VFile`][vfile], optional) — [*File*][file], any value accepted by - `vfile()` +* `err` (`Error`, optional) — fatal error +* `tree` ([`Node`][node], optional) — transformed tree +* `file` ([`VFile`][vfile], optional) — file -###### Returns +### `processor.runSync(tree[, file])` -[`Node`][node] — Transformed [*syntax tree*][syntax-tree]. +Run *[transformers][transformer]* on a syntax tree. +An error is thrown if asynchronous transforms are configured. -###### Note +> 👉 **Note**: `runSync` freezes the processor if not already +> *[frozen][freeze]*. -`runSync` freezes the processor if not already [*frozen*][freeze]. +> 👉 **Note**: `runSync` performs the [run phase][overview], not other phases. -`runSync` performs the [*run phase*][description], not other phases. +###### Parameters -### `processor.process(file[, done])` +* `tree` ([`Node`][node]) — tree to transform and inspect +* `file` ([`VFile`][vfile], optional) — any value accepted as `x` in + `new VFile(x)` -[*Process*][description] the given [*file*][file] as configured on the -processor. +###### Returns -###### Parameters +Transformed tree ([`Node`][node]). -* `file` ([`VFile`][vfile]) — [*File*][file], any value accepted by `vfile()` -* `done` ([`Function`][process-done], optional) — Callback +### `processor.process(file[, done])` -###### Returns +Process the given file as configured on the processor. -[`Promise`][promise] if `done` is not given. -The returned promise is rejected with a fatal error, or resolved with the -processed [*file*][file]. +> 👉 **Note**: `process` freezes the processor if not already +> *[frozen][freeze]*. -The parsed, transformed, and compiled value is exposed on -[`file.value`][vfile-value] or `file.result` (see notes). +> 👉 **Note**: `process` performs the [parse, run, and stringify +> phases][overview]. -###### Note +###### Parameters -`process` freezes the processor if not already [*frozen*][freeze]. +* `file` ([`VFile`][vfile]) — any value accepted as `x` in `new VFile(x)` +* `done` ([`Function`][process-done], optional) — callback -`process` performs the [*parse*, *run*, and *stringify* phases][description]. +###### Returns -unified typically compiles by serializing: most [*compiler*][compiler]s return -`string` (or `Buffer`). -Some compilers, such as the one configured with [`rehype-react`][rehype-react], -return other values (in this case, a React tree). -If you’re using a compiler that serializes, the result is available at -`file.value`. -Otherwise, the result is available at `file.result`. +Nothing if `done` is given (`void`). +A [`Promise`][promise] otherwise. +The promise is rejected with a fatal error or resolved with the processed +file ([`VFile`][vfile]). + +The parsed, transformed, and compiled value is available at +[`file.value`][vfile-value] (see note). + +> 👉 **Note**: unified typically compiles by serializing: most +> [compilers][compiler] return `string` (or `Buffer`). +> Some compilers, such as the one configured with +> [`rehype-react`][rehype-react], result in other values (in this case, a React +> tree). +> If you’re using a compiler that does not serialize, the result is available +> at `file.result`. ###### Example -The below example shows how `process` can be used to process a file, whether -transformers are asynchronous or not, with promises. +This example shows how `process` can be used to process a file: ```js import {unified} from 'unified' @@ -710,20 +712,15 @@ import rehypeDocument from 'rehype-document' import rehypeFormat from 'rehype-format' import rehypeStringify from 'rehype-stringify' -unified() +const file = await unified() .use(remarkParse) .use(remarkRehype) .use(rehypeDocument, {title: '👋🌍'}) .use(rehypeFormat) .use(rehypeStringify) .process('# Hello world!') - .then( - (file) => console.log(String(file)), - (error) => { - // Handle your error here! - throw error - } - ) + +console.log(String(file)) ``` Yields: @@ -744,18 +741,17 @@ Yields: #### `function done(err, file)` -Callback called when the [*process*][description] is done. -Called with a fatal error, if any, and a [*file*][file]. +Callback called when the process is done. +Called with either an error or a result. ###### Parameters -* `err` (`Error`, optional) — Fatal error -* `file` ([`VFile`][vfile]) — Processed [*file*][file] +* `err` (`Error`, optional) — fatal error +* `file` ([`VFile`][vfile]) — processed file ###### Example -The below example shows how `process` can be used to process a file, whether -transformers are asynchronous or not, with a callback. +This example shows how `process` can be used to process a file with a callback. ```js import {unified} from 'unified' @@ -768,17 +764,12 @@ unified() .use(remarkParse) .use(remarkGithub) .use(remarkStringify) - .process('@unifiedjs') - .then( - (file) => { - console.error(reporter(file)) + .process('@unifiedjs', function (error, file) { + console.error(reporter(error || file)) + if (file) { console.log(String(file)) - }, - (error) => { - // Handle your error here! - throw error } - ) + }) ``` Yields: @@ -791,42 +782,39 @@ no issues found [**@unifiedjs**](https://github.com/unifiedjs) ``` -### `processor.processSync(file|value)` +### `processor.processSync(file)` + +Process the given file as configured on the processor. +An error is thrown if asynchronous transforms are configured. -[*Process*][description] the given [*file*][file] as configured on the -processor. +> 👉 **Note**: `processSync` freezes the processor if not already +> *[frozen][freeze]*. -An error is thrown if asynchronous [*plugin*][plugin]s are configured. +> 👉 **Note**: `processSync` performs the [parse, run, and stringify +> phases][overview]. ###### Parameters -* `file` ([`VFile`][vfile]) — [*File*][file], any value accepted by `vfile()` +* `file` ([`VFile`][vfile]) — any value accepted as `x` in `new VFile(x)` ###### Returns -([`VFile`][vfile]) — Processed [*file*][file] - -The parsed, transformed, and compiled value is exposed on -[`file.value`][vfile-value] or `file.result` (see notes). - -###### Note - -`processSync` freezes the processor if not already [*frozen*][freeze]. +The processed file ([`VFile`][vfile]). -`processSync` performs the [*parse*, *run*, and *stringify* -phases][description]. +The parsed, transformed, and compiled value is available at +[`file.value`][vfile-value] (see note). -unified typically compiles by serializing: most [*compiler*][compiler]s return -`string` (or `Buffer`). -Some compilers, such as the one configured with [`rehype-react`][rehype-react], -return other values (in this case, a React tree). -If you’re using a compiler that serializes, the result is available at -`file.value`. -Otherwise, the result is available at `file.result`. +> 👉 **Note**: unified typically compiles by serializing: most +> [compilers][compiler] return `string` (or `Buffer`). +> Some compilers, such as the one configured with +> [`rehype-react`][rehype-react], result in other values (in this case, a React +> tree). +> If you’re using a compiler that does not serialize, the result is available +> at `file.result`. ###### Example -The below example shows how `processSync` can be used to process a file, if all +This example shows how `processSync` can be used to process a file, if all transformers are synchronous. ```js @@ -844,7 +832,7 @@ const processor = unified() .use(rehypeFormat) .use(rehypeStringify) -console.log(processor.processSync('# Hello world!').toString()) +console.log(String(processor.processSync('# Hello world!'))) ``` Yields: @@ -865,14 +853,17 @@ Yields: ### `processor.data([key[, value]])` -[*Configure*][configuration] the processor with information available to all -[*plugin*][plugin]s. -Information is stored in an in-memory key-value store. +Configure the processor with info available to all plugins. +Information is stored in an object. Typically, options can be given to a specific plugin, but sometimes it makes sense to have information shared with several plugins. For example, a list of HTML elements that are self-closing, which is needed -during all [*phases*][description] of the *process*. +during all [phases][overview]. + +> 👉 **Note**: setting information cannot occur on *[frozen][freeze]* +> processors. +> Call the processor first to create a new unfrozen processor. ###### Signatures @@ -883,24 +874,19 @@ during all [*phases*][description] of the *process*. ###### Parameters -* `key` (`string`, optional) — Identifier -* `value` (`*`, optional) — Value to set -* `values` (`Object`, optional) — Values to set +* `key` (`string`, optional) — identifier +* `value` (`*`, optional) — value to set +* `values` (`Object`, optional) — values to set ###### Returns -* `processor` — If setting, the processor that `data` is called on -* `value` (`*`) — If getting, the value at `key` -* `info` (`Object`) — Without arguments, the key-value store - -###### Note - -Setting information cannot occur on [*frozen*][freeze] processors. -Call the processor first to create a new unfrozen processor. +* `processor` — when setting, the processor that `data` is called on +* `value` (`*`) — when getting, the value at `key` +* `info` (`Object`) — without arguments, the key-value store ###### Example -The following example show how to get and set information: +This example show how to get and set info: ```js import {unified} from 'unified' @@ -918,35 +904,34 @@ processor.data() // => {charlie: 'delta'} ### `processor.freeze()` -**Freeze** a processor. -*Frozen* processors are meant to be extended and not to be configured directly. +Freeze a processor. +Frozen processors are meant to be extended and not to be configured directly. -Once a processor is frozen it cannot be *unfrozen*. +When a processor is frozen it cannot be unfrozen. New processors working the same way can be created by calling the processor. It’s possible to freeze processors explicitly by calling `.freeze()`. -Processors freeze implicitly when [`.parse()`][parse], [`.run()`][run], +Processors freeze automatically when [`.parse()`][parse], [`.run()`][run], [`.runSync()`][run-sync], [`.stringify()`][stringify], [`.process()`][process], or [`.processSync()`][process-sync] are called. ###### Returns -`processor` — The processor that `freeze` was called on. +The processor that `freeze` was called on (`processor`). ###### Example -The following example, `index.js`, shows how rehype prevents extensions to -itself: +This example, `index.js`, shows how `rehype` prevents extensions to itself: ```js import {unified} from 'unified' -import remarkParse from 'rehype-parse' -import remarkStringify from 'rehype-stringify' +import rehypeParse from 'rehype-parse' +import rehypeStringify from 'rehype-stringify' -export const rehype = unified().use(remarkParse).use(remarkStringify).freeze() +export const rehype = unified().use(rehypeParse).use(rehypeStringify).freeze() ``` -The below example, `a.js`, shows how that processor can be used and configured. +That processor can be used and configured like so: ```js import {rehype} from 'rehype' @@ -958,11 +943,10 @@ rehype() // … ``` -The below example, `b.js`, shows a similar looking example that operates on the -frozen rehype interface because it does not call `rehype`. -If this behavior was allowed it would result in unexpected behavior so an -error is thrown. -**This is invalid**: +A similar looking example is broken as operates on the frozen interface. +If this behavior was allowed it would result in unexpected behavior so an error +is thrown. +**This is not valid**: ```js import {rehype} from 'rehype' @@ -985,38 +969,41 @@ Error: Cannot call `use` on a frozen processor. Create a new processor first, by calling it: use `processor()` instead of `processor`. at assertUnfrozen (~/node_modules/unified/index.js:426:11) at Function.use (~/node_modules/unified/index.js:165:5) - at ~/b.js:6:4 + … ``` ## `Plugin` -**Plugins** [*configure*][configuration] the processors they are applied on in -the following ways: +**Plugins** configure the processors they are applied on in the following ways: -* They change the processor: such as the [*parser*][parser], the - [*compiler*][compiler], or configuring [*data*][data] -* They specify how to handle [*syntax trees*][syntax-tree] and [*files*][file] +* they change the processor, such as the [parser][], the [compiler][], or by + configuring [data][] +* they specify how to handle trees and files Plugins are a concept. -They materialize as [`attacher`][attacher]s. +They materialize as [`Attacher`s][attacher]. ###### Example `move.js`: ```js -export function move(options = {}) { - const {extname} = options - - if (!extname) { - throw new Error('Missing `extname` in options') +/** + * @typedef Options + * Configuration (required). + * @property {string} extname + * File extension to use (must start with `.`). + */ + +/** @type {import('unified').Plugin<[Options]>} */ +export function move(options) { + if (!options || !options.extname) { + throw new Error('Missing `options.extname`') } - return transformer - - function transformer(tree, file) { - if (file.extname && file.extname !== extname) { - file.extname = extname + return function (tree, file) { + if (file.extname && file.extname !== options.extname) { + file.extname = options.extname } } } @@ -1031,30 +1018,24 @@ export function move(options = {}) { `index.js`: ```js +import {read, write} from 'to-vfile' +import {reporter} from 'vfile-reporter' import {unified} from 'unified' import remarkParse from 'remark-parse' import remarkRehype from 'remark-rehype' import rehypeStringify from 'rehype-stringify' -import {toVFile} from 'to-vfile' -import {reporter} from 'vfile-reporter' import {move} from './move.js' -unified() +const file = await unified() .use(remarkParse) .use(remarkRehype) .use(move, {extname: '.html'}) .use(rehypeStringify) - .process(toVFile.readSync('index.md')) - .then( - (file) => { - console.error(reporter(file)) - toVFile.writeSync(file) // Written to `index.html`. - }, - (error) => { - // Handle your error here! - throw error - } - ) + .process(await read('index.md')) + +console.error(reporter(file)) +await write(file) // Written to `index.html`. + ``` Yields: @@ -1069,78 +1050,66 @@ index.md: no issues found

Hello, world!

``` -### `function attacher([options])` - -**Attachers** are materialized [*plugin*][plugin]s. -An attacher is a function that can receive options and -[*configures*][configuration] the processor. +### `function attacher(options?)` -Attachers change the processor, such as the [*parser*][parser], the -[*compiler*][compiler], configuring [*data*][data], or by specifying how the -[*syntax tree*][syntax-tree] or [*file*][file] are handled. +Attachers are materialized plugins. +They are functions that can receive options and configure the processor. -###### Context +Attachers change the processor, such as the [parser][], the [compiler][], +by configuring [data][], or by specifying how the tree and file are handled. -The context object (`this`) is set to the processor the attacher is applied on. +> 👉 **Note**: attachers are called when the processor is *[frozen][freeze]*, +> not when they are applied. ###### Parameters -* `options` (`*`, optional) — Configuration +* `this` (`processor`) — processor the attacher is applied to +* `options` (`*`, optional) — configuration ###### Returns -[`transformer`][transformer] — Optional. - -###### Note - -Attachers are called when the processor is [*frozen*][freeze], not when they are -applied. +Optional transform ([`Transformer`][transformer]). -### `function transformer(node, file[, next])` +### `function transformer(tree, file[, next])` -**Transformers** handle [*syntax tree*][syntax-tree]s and [*file*][file]s. -A transformer is a function that is called each time a syntax tree and file are -passed through the [*run phase*][description]. -If an error occurs (either because it’s thrown, returned, rejected, or passed to -[`next`][next]), the process stops. +Transformers handle syntax trees and files. +They are functions that are called each time a syntax tree and file are passed +through the [run phase][overview]. +When an error occurs in them (either because it’s thrown, returned, rejected, +or passed to [`next`][next]), the process stops. -The *run phase* is handled by [`trough`][trough], see its documentation for the +The run phase is handled by [`trough`][trough], see its documentation for the exact semantics of these functions. ###### Parameters -* `node` ([`Node`][node]) — [*Syntax tree*][syntax-tree] to handle -* `file` ([`VFile`][vfile]) — [*File*][file] to handle +* `tree` ([`Node`][node]) — tree to handle +* `file` ([`VFile`][vfile]) —file to handle * `next` ([`Function`][next], optional) ###### Returns -* `void` — If nothing is returned, the next transformer keeps using same tree. -* `Error` — Fatal error to stop the process -* `node` ([`Node`][node]) — New [*syntax tree*][syntax-tree]. - If returned, the next transformer is given this new tree -* `Promise` — Returned to perform an asynchronous operation. - The promise **must** be resolved (optionally with a [`Node`][node]) or - rejected (optionally with an `Error`) +* `void` — the next transformer keeps using same tree +* `Error` — fatal error to stop the process +* [`Node`][node] — new, changed, tree +* `Promise` — resolved with a new, changed, tree or rejected with an + `Error` #### `function next(err[, tree[, file]])` -If the signature of a [*transformer*][transformer] includes `next` (the third -argument), the transformer **may** perform asynchronous operations, and **must** -call `next()`. +If the signature of a `transformer` accepts a third argument, the transformer +may perform asynchronous operations, and must call `next()`. ###### Parameters -* `err` (`Error`, optional) — Fatal error to stop the process -* `node` ([`Node`][node], optional) — New [*syntax tree*][syntax-tree]. - If given, the next transformer is given this new tree -* `file` ([`VFile`][vfile], optional) — New [*file*][file]. - If given, the next transformer is given this new file +* `err` (`Error`, optional) — fatal error to stop the process +* `tree` ([`Node`][node], optional) — new, changed, tree +* `file` ([`VFile`][vfile], optional) — new, changed, file ## `Preset` -**Presets** are sharable [*configuration*][configuration]. -They can contain [*plugins*][plugin] and settings. +Presets are sharable configuration. +They can contain plugins and settings. ###### Example @@ -1182,24 +1151,17 @@ _Emphasis_ and **importance**. `index.js`: ```js +import {read, write} from 'to-vfile' import {remark} from 'remark' -import {toVFile} from 'to-vfile' import {reporter} from 'vfile-reporter' import {preset} from './preset.js' -remark() +const file = await remark() .use(preset) - .process(toVFile.readSync('example.md')) - .then( - (file) => { - console.error(reporter(file)) - toVFile.writeSync(file) - }, - (error) => { - // Handle your error here! - throw error - } - ) + .process(await read('example.md')) + +console.error(reporter(file)) +await write(file) ``` Yields: @@ -1227,31 +1189,203 @@ example.md: no issues found [MIT](license) © [Titus Wormer](https://wooorm.com) ``` +## Types + +This package is fully typed with [TypeScript][]. +It exports the following additional types: + +* `Processor` + — processor, where `ParseTree` is the tree that the parser creates, + `CurrentTree` the tree that the current plugin yields, `CompileTree` the + tree that the compiler accepts, and `CompileResult` the thing that the + compiler yields +* `FrozenProcessor` + — like `Processor` but frozen +* `Plugin` + — plugin, where `PluginParameters` are the accepted arguments, `Input` the + input value, and `Output` the output value (see below) +* `Pluggable` +* `Preset` + — preset +* `PluginTuple` + — plugin tuple +* `Pluggable` + — any usable value, where `PluginParameters` are the accepted arguments +* `PluggableList` + — list of plugins and presets +* `Transformer` + — transformer, where `Input` and `Output` are the input/output trees +* `TransformCallback` + — third argument of a transformer +* `Parser` + — parser as a class or normal function, where `Tree` is the resulting tree +* `ParserClass` + — parser class +* `ParserFunction` + — parser function +* `Compiler` + — compiler as a class or normal function, where `Tree` is the accepted tree + and `Result` the thing that the compiler yields +* `CompilerClass` + — compiler class +* `CompilerFunction` + — compiler function +* `RunCallback` + — callback to `run`, where `Tree` is the resulting tree +* `ProcessCallback` + — callback to `process`, where `File` is the resulting file + +For TypeScript to work, it is particularly important to type your plugins +correctly. +We strongly recommend using the `Plugin` type with its generics and to use the +node types for the syntax trees provided by our packages (as in, +[`@types/hast`][types-hast], [`@types/mdast`][types-mdast], +[`@types/nlcst`][types-nlcst]). + +```js +/** + * @typedef {import('mdast').Root} MdastRoot + * @typedef {import('hast').Root} HastRoot + * + * @typedef Options + * Configuration (optional). + * @property {boolean} [someField] + * Some option. + */ + +// To type options: +/** @type {import('unified').Plugin<[Options?]>} */ +export function myPluginAcceptingOptions(options) { + // `options` is `Options?`. +} + +// To type a plugin that works on a certain tree: +/** @type {import('unified').Plugin<[], MdastRoot>} */ +export function myRemarkPlugin() { + return function (tree, file) { + // `tree` is `MdastRoot`. + } +} + +// To type a plugin that transforms one tree into another: +/** @type {import('unified').Plugin<[], MdastRoot, HastRoot>} */ +export function remarkRehype() { + return function (tree) { + // `tree` is `MdastRoot`. + // Result must be `HastRoot`. + } +} + +// To type a plugin that defines a parser: +/** @type {import('unified').Plugin<[], string, MdastRoot>} */ +export function remarkParse(options) {} + +// To type a plugin that defines a compiler: +/** @type {import('unified').Plugin<[], HastRoot, string>} */ +export function rehypeStringify(options) {} +``` + +## 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+, 16.0+, and 18.0+. +Our projects sometimes work with older versions, but this is not guaranteed. + ## Contribute See [`contributing.md`][contributing] in [`unifiedjs/.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 [`unifiedjs/ideas`][ideas]. - -A curated list of awesome unified resources can be found in [**awesome -unified**][awesome]. This project has a [code of conduct][coc]. By interacting with this repository, organization, or community you agree to abide by its terms. +For info on how to submit a security report, see our +[security policy][security]. + +## Sponsor + +Support this effort and give back by sponsoring on [OpenCollective][collective]! + + + + + + + + + + + + + + + + + + + + + + + + +
+ Vercel

+ +
+ Motif

+ +
+ HashiCorp

+ +
+ American Express

+ +
+ GitBook

+ +
+ Gatsby

+ +
+ Netlify

+ + +
+ Coinbase

+ +
+ ThemeIsle

+ +
+ Expo

+ +
+ Boost Note

+ +
+ Holloway

+ +
+
+ You? +

+
+ ## Acknowledgments Preliminary work for unified was done [in 2014][preliminary] for -[**retext**][retext] and inspired by [`ware`][ware]. -Further incubation happened in [**remark**][remark]. +**[retext][]** and inspired by [`ware`][ware]. +Further incubation happened in **[remark][]**. The project was finally [externalised][] in 2015 and [published][] as `unified`. -The project was authored by [**@wooorm**](https://github.com/wooorm). +The project was authored by **[@wooorm](https://github.com/wooorm)**. Although `unified` since moved its plugin architecture to [`trough`][trough], -thanks to [**@calvinfo**](https://github.com/calvinfo), -[**@ianstormtaylor**](https://github.com/ianstormtaylor), and others for their +thanks to **[@calvinfo](https://github.com/calvinfo)**, +**[@ianstormtaylor](https://github.com/ianstormtaylor)**, and others for their work on [`ware`][ware], as it was a huge initial inspiration. ## License @@ -1288,15 +1422,21 @@ work on [`ware`][ware], as it was a huge initial inspiration. [chat]: https://github.com/unifiedjs/unified/discussions +[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c + +[esmsh]: https://esm.sh + +[typescript]: https://www.typescriptlang.org + [health]: https://github.com/unifiedjs/.github -[contributing]: https://github.com/unifiedjs/.github/blob/HEAD/contributing.md +[contributing]: https://github.com/unifiedjs/.github/blob/main/contributing.md -[support]: https://github.com/unifiedjs/.github/blob/HEAD/support.md +[support]: https://github.com/unifiedjs/.github/blob/main/support.md -[coc]: https://github.com/unifiedjs/.github/blob/HEAD/code-of-conduct.md +[coc]: https://github.com/unifiedjs/.github/blob/main/code-of-conduct.md -[awesome]: https://github.com/unifiedjs/awesome-unified +[security]: https://github.com/unifiedjs/.github/blob/main/security.md [license]: license @@ -1308,14 +1448,14 @@ work on [`ware`][ware], as it was a huge initial inspiration. [twitter]: https://twitter.com/unifiedjs -[learn]: https://unifiedjs.com/learn/ - [rehype]: https://github.com/rehypejs/rehype [remark]: https://github.com/remarkjs/remark [retext]: https://github.com/retextjs/retext +[syntax-tree]: https://github.com/syntax-tree + [esast]: https://github.com/syntax-tree/esast [hast]: https://github.com/syntax-tree/hast @@ -1328,11 +1468,15 @@ work on [`ware`][ware], as it was a huge initial inspiration. [unist]: https://github.com/syntax-tree/unist -[engine]: https://github.com/unifiedjs/unified-engine +[unified-engine]: https://github.com/unifiedjs/unified-engine + +[unified-args]: https://github.com/unifiedjs/unified-args + +[unified-engine-gulp]: https://github.com/unifiedjs/unified-engine-gulp -[args]: https://github.com/unifiedjs/unified-args +[unified-language-server]: https://github.com/unifiedjs/unified-language-server -[gulp]: https://github.com/unifiedjs/unified-engine-gulp +[unified-stream]: https://github.com/unifiedjs/unified-stream [remark-rehype]: https://github.com/remarkjs/remark-rehype @@ -1342,7 +1486,7 @@ work on [`ware`][ware], as it was a huge initial inspiration. [rehype-remark]: https://github.com/rehypejs/rehype-remark -[unist-utilities]: https://github.com/syntax-tree/unist#list-of-utilities +[node]: https://github.com/syntax-tree/unist#node [vfile]: https://github.com/vfile/vfile @@ -1350,31 +1494,25 @@ work on [`ware`][ware], as it was a huge initial inspiration. [vfile-utilities]: https://github.com/vfile/vfile#list-of-utilities -[node]: https://github.com/syntax-tree/unist#node - -[description]: #description - -[syntax-tree]: #syntax-trees - -[configuration]: #configuration +[overview]: #overview [file]: #file -[processors]: #processors +[api]: #api [process]: #processorprocessfile-done -[process-sync]: #processorprocesssyncfilevalue +[process-sync]: #processorprocesssyncfile [parse]: #processorparsefile [parser]: #processorparser -[stringify]: #processorstringifynode-file +[stringify]: #processorstringifytree-file -[run]: #processorrunnode-file-done +[run]: #processorruntree-file-done -[run-sync]: #processorrunsyncnode-file +[run-sync]: #processorrunsynctree-file [compiler]: #processorcompiler @@ -1382,7 +1520,7 @@ work on [`ware`][ware], as it was a huge initial inspiration. [attacher]: #function-attacheroptions -[transformer]: #function-transformernode-file-next +[transformer]: #function-transformertree-file-next [next]: #function-nexterr-tree-file @@ -1390,58 +1528,48 @@ work on [`ware`][ware], as it was a huge initial inspiration. [plugin]: #plugin -[run-done]: #function-doneerr-node-file +[run-done]: #function-doneerr-tree-file [process-done]: #function-doneerr-file [contribute]: #contribute +[sponsor]: #sponsor + [rehype-react]: https://github.com/rehypejs/rehype-react [trough]: https://github.com/wooorm/trough#function-fninput-next [promise]: https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise -[remark-plugins]: https://github.com/remarkjs/remark/blob/HEAD/doc/plugins.md#list-of-plugins - -[rehype-plugins]: https://github.com/rehypejs/rehype/blob/HEAD/doc/plugins.md#list-of-plugins - -[retext-plugins]: https://github.com/retextjs/retext/blob/HEAD/doc/plugins.md#list-of-plugins - -[stream]: https://github.com/unifiedjs/unified-stream - -[ideas]: https://github.com/unifiedjs/ideas +[remark-plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins -[preliminary]: https://github.com/retextjs/retext/commit/8fcb1f#diff-168726dbe96b3ce427e7fedce31bb0bc - -[externalised]: https://github.com/remarkjs/remark/commit/9892ec#diff-168726dbe96b3ce427e7fedce31bb0bc - -[published]: https://github.com/unifiedjs/unified/commit/2ba1cf +[rehype-plugins]: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins -[ware]: https://github.com/segmentio/ware +[retext-plugins]: https://github.com/retextjs/retext/blob/main/doc/plugins.md#list-of-plugins -[gatsby]: https://www.gatsbyjs.org +[awesome-remark]: https://github.com/remarkjs/awesome-remark -[mdx]: https://mdxjs.com +[awesome-rehype]: https://github.com/rehypejs/awesome-rehype -[jsx]: https://reactjs.org/docs/jsx-in-depth.html +[awesome-retext]: https://github.com/retextjs/awesome-retext -[prettier]: https://prettier.io +[topic-remark-plugin]: https://github.com/topics/remark-plugin -[node.js]: https://nodejs.org +[topic-rehype-plugin]: https://github.com/topics/rehype-plugin -[vercel]: https://vercel.com +[topic-retext-plugin]: https://github.com/topics/retext-plugin -[netlify]: https://www.netlify.com +[types-hast]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/hast -[github]: https://github.com +[types-mdast]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mdast -[mozilla]: https://www.mozilla.org +[types-nlcst]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nlcst -[wordpress]: https://wordpress.com +[preliminary]: https://github.com/retextjs/retext/commit/8fcb1f#diff-168726dbe96b3ce427e7fedce31bb0bc -[adobe]: https://www.adobe.com +[externalised]: https://github.com/remarkjs/remark/commit/9892ec#diff-168726dbe96b3ce427e7fedce31bb0bc -[facebook]: https://www.facebook.com +[published]: https://github.com/unifiedjs/unified/commit/2ba1cf -[google]: https://www.google.com +[ware]: https://github.com/segmentio/ware