UNPKG

49.4 kBMarkdownView Raw
1# [![unified][logo]][site]
2
3[![Build][build-badge]][build]
4[![Coverage][coverage-badge]][coverage]
5[![Downloads][downloads-badge]][downloads]
6[![Size][size-badge]][size]
7[![Sponsors][sponsors-badge]][collective]
8[![Backers][backers-badge]][collective]
9[![Chat][chat-badge]][chat]
10
11**unified** lets you inspect and transform content with plugins.
12
13## Contents
14
15* [What is this?](#what-is-this)
16* [When should I use this?](#when-should-i-use-this)
17* [Install](#install)
18* [Use](#use)
19* [Overview](#overview)
20* [API](#api)
21 * [`processor()`](#processor)
22 * [`processor.compiler`](#processorcompiler)
23 * [`processor.data([key[, value]])`](#processordatakey-value)
24 * [`processor.freeze()`](#processorfreeze)
25 * [`processor.parse(file)`](#processorparsefile)
26 * [`processor.parser`](#processorparser)
27 * [`processor.process(file[, done])`](#processorprocessfile-done)
28 * [`processor.processSync(file)`](#processorprocesssyncfile)
29 * [`processor.run(tree[, file][, done])`](#processorruntree-file-done)
30 * [`processor.runSync(tree[, file])`](#processorrunsynctree-file)
31 * [`processor.stringify(tree[, file])`](#processorstringifytree-file)
32 * [`processor.use(plugin[, options])`](#processoruseplugin-options)
33 * [`CompileResultMap`](#compileresultmap)
34 * [`CompileResults`](#compileresults)
35 * [`Compiler`](#compiler)
36 * [`Data`](#data)
37 * [`Parser`](#parser)
38 * [`Pluggable`](#pluggable)
39 * [`PluggableList`](#pluggablelist)
40 * [`Plugin`](#plugin)
41 * [`PluginTuple`](#plugintuple)
42 * [`Preset`](#preset)
43 * [`ProcessCallback`](#processcallback)
44 * [`Processor`](#processor-1)
45 * [`RunCallback`](#runcallback)
46 * [`Settings`](#settings)
47 * [`TransformCallback`](#transformcallback)
48 * [`Transformer`](#transformer)
49* [Types](#types)
50* [Compatibility](#compatibility)
51* [Contribute](#contribute)
52* [Sponsor](#sponsor)
53* [Acknowledgments](#acknowledgments)
54* [License](#license)
55
56## What is this?
57
58unified is two things:
59
60* **unified** is a collective of 500+ free and open source packages that work
61 with content as structured data (ASTs)
62* `unified` (this project) is the core package, used in 1.3m+ projects on GH,
63 to process content with plugins
64
65Several ecosystems are built on unified around different kinds of content.
66Notably, [remark][] (markdown), [rehype][] (HTML), and [retext][] (natural
67language).
68These ecosystems can be connected together.
69
70* for more about us, see [`unifiedjs.com`][site]
71* for updates, see [@unifiedjs][twitter] on Twitter
72* for questions, see [support][]
73* to help, see [contribute][] and [sponsor][] below
74
75## When should I use this?
76
77In some cases, you are already using unified.
78For example, it’s used in MDX, Gatsby, Docusaurus, etc.
79In those cases, you don’t need to add `unified` yourself but you can include
80plugins into those projects.
81
82But the real fun (for some) is to get your hands dirty and work with syntax
83trees and build with it yourself.
84You can create those projects, or things like Prettier, or your own site
85generator.
86You can connect utilities together and make your own plugins that check for
87problems and transform from one thing to another.
88
89When you are dealing with one type of content (such as markdown), you can use
90the main package of that ecosystem instead (so `remark`).
91When you are dealing with different kinds of content (such as markdown and
92HTML), it’s recommended to use `unified` itself, and pick and choose the plugins
93you need.
94
95## Install
96
97This package is [ESM only][esm].
98In Node.js (version 16+), install with [npm][]:
99
100```sh
101npm install unified
102```
103
104In Deno with [`esm.sh`][esmsh]:
105
106```js
107import {unified} from 'https://esm.sh/unified@11'
108```
109
110In browsers with [`esm.sh`][esmsh]:
111
112```html
113<script type="module">
114 import {unified} from 'https://esm.sh/unified@11?bundle'
115</script>
116```
117
118## Use
119
120```js
121import rehypeDocument from 'rehype-document'
122import rehypeFormat from 'rehype-format'
123import rehypeStringify from 'rehype-stringify'
124import remarkParse from 'remark-parse'
125import remarkRehype from 'remark-rehype'
126import {unified} from 'unified'
127import {reporter} from 'vfile-reporter'
128
129const file = await unified()
130 .use(remarkParse)
131 .use(remarkRehype)
132 .use(rehypeDocument, {title: '👋🌍'})
133 .use(rehypeFormat)
134 .use(rehypeStringify)
135 .process('# Hello world!')
136
137console.error(reporter(file))
138console.log(String(file))
139```
140
141Yields:
142
143```txt
144no issues found
145```
146
147```html
148<!doctype html>
149<html lang="en">
150 <head>
151 <meta charset="utf-8">
152 <title>👋🌍</title>
153 <meta name="viewport" content="width=device-width, initial-scale=1">
154 </head>
155 <body>
156 <h1>Hello world!</h1>
157 </body>
158</html>
159```
160
161<!-- Old name: -->
162
163<a name="description"></a>
164
165## Overview
166
167`unified` is an interface for processing content with syntax trees.
168Syntax trees are a representation of content understandable to programs.
169Those programs, called *[plugins][api-plugin]*, take these trees and inspect and
170modify them.
171To get to the syntax tree from text, there is a *[parser][api-parser]*.
172To get from that back to text, there is a *[compiler][api-compiler]*.
173This is the *[process][api-process]* of a *processor*.
174
175```ascii
176| ........................ process ........................... |
177| .......... parse ... | ... run ... | ... stringify ..........|
178
179 +--------+ +----------+
180Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
181 +--------+ | +----------+
182 X
183 |
184 +--------------+
185 | Transformers |
186 +--------------+
187```
188
189###### Processors
190
191Processors process content.
192On its own, `unified` (the root processor) doesn’t work.
193It needs to be configured with plugins to work.
194For example:
195
196```js
197const processor = unified()
198 .use(remarkParse)
199 .use(remarkRehype)
200 .use(rehypeDocument, {title: '👋🌍'})
201 .use(rehypeFormat)
202 .use(rehypeStringify)
203```
204
205That processor can do different things.
206It can:
207
208* …parse markdown (`parse`)
209* …turn parsed markdown into HTML and format the HTML (`run`)
210* …compile HTML (`stringify`)
211* …do all of the above (`process`)
212
213Every processor implements another processor.
214To create a processor, call another processor.
215The new processor is configured to work the same as its ancestor.
216But when the descendant processor is configured in the future it does not affect
217the ancestral processor.
218
219When processors are exposed from a module (for example, `unified` itself) they
220should not be configured directly, as that would change their behavior for all
221module users.
222Those processors are *[frozen][api-freeze]* and they should be called to create
223a new processor before they are used.
224
225###### File
226
227When processing a document, metadata is gathered about that document.
228[`vfile`][vfile] is the file format that stores data, metadata, and messages
229about files for unified and plugins.
230
231There are several [utilities][vfile-utilities] for working with these files.
232
233###### Syntax tree
234
235The syntax trees used in unified are [unist][] nodes.
236A tree represents a whole document and each [node][] is a plain JavaScript
237object with a `type` field.
238The semantics of nodes and the format of syntax trees is defined by other
239projects:
240
241* [esast][] — JavaScript
242* [hast][] — HTML
243* [mdast][] — markdown
244* [nlcst][] — natural language
245* [xast][] — XML
246
247There are many utilities for working with trees listed in each aforementioned
248project and maintained in the [`syntax-tree`][syntax-tree] organization.
249These utilities are a level lower than unified itself and are building blocks
250that can be used to make plugins.
251
252<!-- Old name: -->
253
254<a name="list-of-processors"></a>
255
256###### Ecosystems
257
258Around each syntax tree is an ecosystem that focusses on that particular kind
259of content.
260At their core, they parse text to a tree and compile that tree back to text.
261They also provide plugins that work with the syntax tree, without requiring
262that the end user has knowledge about that tree.
263
264* [rehype][] (hast) — HTML
265* [remark][] (mdast) — markdown
266* [retext][] (nlcst) — natural language
267
268<a name="list-of-plugins"></a>
269
270###### Plugins
271
272Each aforementioned ecosystem comes with a large set of plugins that you can
273pick and choose from to do all kinds of things.
274
275* [List of remark plugins][remark-plugins] ·
276 [`remarkjs/awesome-remark`][awesome-remark] ·
277 [`remark-plugin` topic][topic-remark-plugin]
278* [List of rehype plugins][rehype-plugins] ·
279 [`rehypejs/awesome-rehype`][awesome-rehype] ·
280 [`rehype-plugin` topic][topic-rehype-plugin]
281* [List of retext plugins][retext-plugins] ·
282 [`retextjs/awesome-retext`][awesome-retext] ·
283 [`retext-plugin` topic][topic-retext-plugin]
284
285There are also a few plugins that work in any ecosystem:
286
287* [`unified-diff`](https://github.com/unifiedjs/unified-diff)
288 — ignore unrelated messages in GitHub Actions and Travis
289* [`unified-infer-git-meta`](https://github.com/unifiedjs/unified-infer-git-meta)
290 — infer metadata of a document from Git
291* [`unified-message-control`](https://github.com/unifiedjs/unified-message-control)
292 — enable, disable, and ignore messages from content
293
294###### Configuration
295
296Processors are configured with [plugins][api-plugin] or with the
297[`data`][api-data] method.
298Most plugins also accept configuration through options.
299See each plugin’s readme for more info.
300
301###### Integrations
302
303unified can integrate with the file system through
304[`unified-engine`][unified-engine].
305CLI apps can be created with [`unified-args`][unified-args], Gulp plugins with
306[`unified-engine-gulp`][unified-engine-gulp], and language servers with
307[`unified-language-server`][unified-language-server].
308A streaming interface can be created with [`unified-stream`][unified-stream].
309
310###### Programming interface
311
312The [API][] provided by `unified` allows multiple files to be processed and
313gives access to metadata (such as lint messages):
314
315```js
316import rehypeStringify from 'rehype-stringify'
317import remarkParse from 'remark-parse'
318import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown-style-guide'
319import remarkRehype from 'remark-rehype'
320import remarkRetext from 'remark-retext'
321import retextEnglish from 'retext-english'
322import retextEquality from 'retext-equality'
323import {unified} from 'unified'
324import {reporter} from 'vfile-reporter'
325
326const file = await unified()
327 .use(remarkParse)
328 .use(remarkPresetLintMarkdownStyleGuide)
329 .use(remarkRetext, unified().use(retextEnglish).use(retextEquality))
330 .use(remarkRehype)
331 .use(rehypeStringify)
332 .process('*Emphasis* and _stress_, you guys!')
333
334console.error(reporter(file))
335console.log(String(file))
336```
337
338Yields:
339
340```txt
3411:16-1:24 warning Emphasis should use `*` as a marker emphasis-marker remark-lint
3421:30-1:34 warning `guys` may be insensitive, use `people`, `persons`, `folks` instead gals-man retext-equality
343
344⚠ 2 warnings
345```
346
347```html
348<p><em>Emphasis</em> and <em>stress</em>, you guys!</p>
349```
350
351<!-- Old name: -->
352
353<a name="processing-between-syntaxes"></a>
354
355###### Transforming between ecosystems
356
357Ecosystems can be combined in two modes.
358
359**Bridge** mode transforms the tree from one format (*origin*) to another
360(*destination*).
361A different processor runs on the destination tree.
362Afterwards, the original processor continues with the origin tree.
363
364**Mutate** mode also transforms the syntax tree from one format to another.
365But the original processor continues transforming the destination tree.
366
367In the previous example (“Programming interface”), `remark-retext` is used in
368bridge mode: the origin syntax tree is kept after retext is done; whereas
369`remark-rehype` is used in mutate mode: it sets a new syntax tree and discards
370the origin tree.
371
372The following plugins lets you combine ecosystems:
373
374* [`remark-retext`][remark-retext] — turn markdown into natural language
375* [`remark-rehype`][remark-rehype] — turn markdown into HTML
376* [`rehype-retext`][rehype-retext] — turn HTML into natural language
377* [`rehype-remark`][rehype-remark] — turn HTML into markdown
378
379## API
380
381This package exports the identifier `unified` (the root `processor`).
382There is no default export.
383
384### `processor()`
385
386Create a new processor.
387
388###### Returns
389
390New *[unfrozen][api-freeze]* processor ([`processor`][api-processor]).
391
392This processor is configured to work the same as its ancestor.
393When the descendant processor is configured in the future it does not affect
394the ancestral processor.
395
396###### Example
397
398This example shows how a new processor can be created (from `remark`) and linked
399to **stdin**(4) and **stdout**(4).
400
401```js
402import process from 'node:process'
403import concatStream from 'concat-stream'
404import {remark} from 'remark'
405
406process.stdin.pipe(
407 concatStream(function (buf) {
408 process.stdout.write(String(remark().processSync(buf)))
409 })
410)
411```
412
413### `processor.compiler`
414
415Compiler to use ([`Compiler`][api-compiler], optional).
416
417### `processor.data([key[, value]])`
418
419Configure the processor with info available to all plugins.
420Information is stored in an object.
421
422Typically, options can be given to a specific plugin, but sometimes it makes
423sense to have information shared with several plugins.
424For example, a list of HTML elements that are self-closing, which is needed
425during all [phases][overview].
426
427> 👉 **Note**: setting information cannot occur on *[frozen][api-freeze]*
428> processors.
429> Call the processor first to create a new unfrozen processor.
430
431> 👉 **Note**: to register custom data in TypeScript, augment the
432> [`Data`][api-data] interface.
433
434###### Signatures
435
436* `processor = processor.data(key, value)`
437* `processor = processor.data(dataset)`
438* `value = processor.data(key)`
439* `dataset = processor.data()`
440
441###### Parameters
442
443* `key` ([`keyof Data`][api-data], optional) — field to get
444* `value` ([`Data[key]`][api-data]) — value to set
445* `values` ([`Data`][api-data]) — values to set
446
447###### Returns
448
449The current processor when setting ([`processor`][api-processor]), the value at
450`key` when getting ([`Data[key]`][api-data]), or the entire dataset when
451getting without key ([`Data`][api-data]).
452
453###### Example
454
455This example show how to get and set info:
456
457```js
458import {unified} from 'unified'
459
460const processor = unified().data('alpha', 'bravo')
461
462processor.data('alpha') // => 'bravo'
463
464processor.data() // => {alpha: 'bravo'}
465
466processor.data({charlie: 'delta'})
467
468processor.data() // => {charlie: 'delta'}
469```
470
471### `processor.freeze()`
472
473Freeze a processor.
474
475Frozen processors are meant to be extended and not to be configured directly.
476
477When a processor is frozen it cannot be unfrozen.
478New processors working the same way can be created by calling the processor.
479
480It’s possible to freeze processors explicitly by calling `.freeze()`.
481Processors freeze automatically when `.parse()`, `.run()`, `.runSync()`,
482`.stringify()`, `.process()`, or `.processSync()` are called.
483
484###### Returns
485
486The current processor ([`processor`][api-processor]).
487
488###### Example
489
490This example, `index.js`, shows how `rehype` prevents extensions to itself:
491
492```js
493import rehypeParse from 'rehype-parse'
494import rehypeStringify from 'rehype-stringify'
495import {unified} from 'unified'
496
497export const rehype = unified().use(rehypeParse).use(rehypeStringify).freeze()
498```
499
500That processor can be used and configured like so:
501
502```js
503import {rehype} from 'rehype'
504import rehypeFormat from 'rehype-format'
505// …
506
507rehype()
508 .use(rehypeFormat)
509 // …
510```
511
512A similar looking example is broken as operates on the frozen interface.
513If this behavior was allowed it would result in unexpected behavior so an error
514is thrown.
515**This is not valid**:
516
517```js
518import {rehype} from 'rehype'
519import rehypeFormat from 'rehype-format'
520// …
521
522rehype
523 .use(rehypeFormat)
524 // …
525```
526
527Yields:
528
529```txt
530~/node_modules/unified/index.js:426
531 throw new Error(
532 ^
533
534Error: Cannot call `use` on a frozen processor.
535Create a new processor first, by calling it: use `processor()` instead of `processor`.
536 at assertUnfrozen (~/node_modules/unified/index.js:426:11)
537 at Function.use (~/node_modules/unified/index.js:165:5)
538
539```
540
541### `processor.parse(file)`
542
543Parse text to a syntax tree.
544
545> 👉 **Note**: `parse` freezes the processor if not already
546> *[frozen][api-freeze]*.
547
548> 👉 **Note**: `parse` performs the [parse phase][overview], not the run phase
549> or other phases.
550
551###### Parameters
552
553* `file` ([`Compatible`][vfile-compatible]) — file to parse; typically
554 `string` or [`VFile`][vfile]; any value accepted as `x` in `new VFile(x)`
555
556###### Returns
557
558Syntax tree representing `file` ([`Node`][node]).
559
560###### Example
561
562This example shows how `parse` can be used to create a tree from a file.
563
564```js
565import remarkParse from 'remark-parse'
566import {unified} from 'unified'
567
568const tree = unified().use(remarkParse).parse('# Hello world!')
569
570console.log(tree)
571```
572
573Yields:
574
575```js
576{
577 type: 'root',
578 children: [
579 {type: 'heading', depth: 1, children: [Array], position: [Object]}
580 ],
581 position: {
582 start: {line: 1, column: 1, offset: 0},
583 end: {line: 1, column: 15, offset: 14}
584 }
585}
586```
587
588### `processor.parser`
589
590Parser to use ([`Parser`][api-parser], optional).
591
592### `processor.process(file[, done])`
593
594Process the given file as configured on the processor.
595
596> 👉 **Note**: `process` freezes the processor if not already
597> *[frozen][api-freeze]*.
598
599> 👉 **Note**: `process` performs the [parse, run, and stringify
600> phases][overview].
601
602###### Signatures
603
604* `processor.process(file, done)`
605* `Promise<VFile> = processor.process(file?)`
606
607###### Parameters
608
609* `file` ([`Compatible`][vfile-compatible], optional) — file; typically
610 `string` or [`VFile`][vfile]; any value accepted as `x` in `new VFile(x)`
611* `done` ([`ProcessCallback`][api-process-callback], optional) — callback
612
613###### Returns
614
615Nothing if `done` is given (`undefined`).
616Otherwise a promise, rejected with a fatal error or resolved with the
617processed file ([`Promise<VFile>`][vfile]).
618
619The parsed, transformed, and compiled value is available at `file.value` (see
620note).
621
622> 👉 **Note**: unified typically compiles by serializing: most
623> compilers return `string` (or `Uint8Array`).
624> Some compilers, such as the one configured with
625> [`rehype-react`][rehype-react], return other values (in this case, a React
626> tree).
627> If you’re using a compiler that doesn’t serialize, expect different result
628> values.
629>
630> To register custom results in TypeScript, add them to
631> [`CompileResultMap`][api-compile-result-map].
632
633###### Example
634
635This example shows how `process` can be used to process a file:
636
637```js
638import rehypeDocument from 'rehype-document'
639import rehypeFormat from 'rehype-format'
640import rehypeStringify from 'rehype-stringify'
641import remarkParse from 'remark-parse'
642import remarkRehype from 'remark-rehype'
643import {unified} from 'unified'
644
645const file = await unified()
646 .use(remarkParse)
647 .use(remarkRehype)
648 .use(rehypeDocument, {title: '👋🌍'})
649 .use(rehypeFormat)
650 .use(rehypeStringify)
651 .process('# Hello world!')
652
653console.log(String(file))
654```
655
656Yields:
657
658```html
659<!doctype html>
660<html lang="en">
661 <head>
662 <meta charset="utf-8">
663 <title>👋🌍</title>
664 <meta name="viewport" content="width=device-width, initial-scale=1">
665 </head>
666 <body>
667 <h1>Hello world!</h1>
668 </body>
669</html>
670```
671
672### `processor.processSync(file)`
673
674Process the given file as configured on the processor.
675
676An error is thrown if asynchronous transforms are configured.
677
678> 👉 **Note**: `processSync` freezes the processor if not already
679> *[frozen][api-freeze]*.
680
681> 👉 **Note**: `processSync` performs the [parse, run, and stringify
682> phases][overview].
683
684###### Parameters
685
686* `file` ([`Compatible`][vfile-compatible], optional) — file; typically
687 `string` or [`VFile`][vfile]; any value accepted as `x` in `new VFile(x)`
688
689###### Returns
690
691The processed file ([`VFile`][vfile]).
692
693The parsed, transformed, and compiled value is available at `file.value` (see
694note).
695
696> 👉 **Note**: unified typically compiles by serializing: most
697> compilers return `string` (or `Uint8Array`).
698> Some compilers, such as the one configured with
699> [`rehype-react`][rehype-react], return other values (in this case, a React
700> tree).
701> If you’re using a compiler that doesn’t serialize, expect different result
702> values.
703>
704> To register custom results in TypeScript, add them to
705> [`CompileResultMap`][api-compile-result-map].
706
707###### Example
708
709This example shows how `processSync` can be used to process a file, if all
710transformers are synchronous.
711
712```js
713import rehypeDocument from 'rehype-document'
714import rehypeFormat from 'rehype-format'
715import rehypeStringify from 'rehype-stringify'
716import remarkParse from 'remark-parse'
717import remarkRehype from 'remark-rehype'
718import {unified} from 'unified'
719
720const processor = unified()
721 .use(remarkParse)
722 .use(remarkRehype)
723 .use(rehypeDocument, {title: '👋🌍'})
724 .use(rehypeFormat)
725 .use(rehypeStringify)
726
727console.log(String(processor.processSync('# Hello world!')))
728```
729
730Yields:
731
732```html
733<!doctype html>
734<html lang="en">
735 <head>
736 <meta charset="utf-8">
737 <title>👋🌍</title>
738 <meta name="viewport" content="width=device-width, initial-scale=1">
739 </head>
740 <body>
741 <h1>Hello world!</h1>
742 </body>
743</html>
744```
745
746### `processor.run(tree[, file][, done])`
747
748Run *[transformers][api-transformer]* on a syntax tree.
749
750> 👉 **Note**: `run` freezes the processor if not already
751> *[frozen][api-freeze]*.
752
753> 👉 **Note**: `run` performs the [run phase][overview], not other phases.
754
755###### Signatures
756
757* `processor.run(tree, done)`
758* `processor.run(tree, file, done)`
759* `Promise<Node> = processor.run(tree, file?)`
760
761###### Parameters
762
763* `tree` ([`Node`][node]) — tree to transform and inspect
764* `file` ([`Compatible`][vfile-compatible], optional) — file associated
765 with `node`; any value accepted as `x` in `new VFile(x)`
766* `done` ([`RunCallback`][api-run-callback], optional) — callback
767
768###### Returns
769
770Nothing if `done` is given (`undefined`).
771Otherwise, a promise rejected with a fatal error or resolved with the
772transformed tree ([`Promise<Node>`][node]).
773
774###### Example
775
776This example shows how `run` can be used to transform a tree:
777
778```js
779import remarkReferenceLinks from 'remark-reference-links'
780import {unified} from 'unified'
781import {u} from 'unist-builder'
782
783const tree = u('root', [
784 u('paragraph', [
785 u('link', {href: 'https://example.com'}, [u('text', 'Example Domain')])
786 ])
787])
788
789const changedTree = await unified().use(remarkReferenceLinks).run(tree)
790
791console.log(changedTree)
792```
793
794Yields:
795
796```js
797{
798 type: 'root',
799 children: [
800 {type: 'paragraph', children: [Array]},
801 {type: 'definition', identifier: '1', title: '', url: undefined}
802 ]
803}
804```
805
806### `processor.runSync(tree[, file])`
807
808Run *[transformers][api-transformer]* on a syntax tree.
809
810An error is thrown if asynchronous transforms are configured.
811
812> 👉 **Note**: `runSync` freezes the processor if not already
813> *[frozen][api-freeze]*.
814
815> 👉 **Note**: `runSync` performs the [run phase][overview], not other phases.
816
817###### Parameters
818
819* `tree` ([`Node`][node]) — tree to transform and inspect
820* `file` ([`Compatible`][vfile-compatible], optional) — file associated
821 with `node`; any value accepted as `x` in `new VFile(x)`
822
823###### Returns
824
825Transformed tree ([`Node`][node]).
826
827### `processor.stringify(tree[, file])`
828
829Compile a syntax tree.
830
831> 👉 **Note**: `stringify` freezes the processor if not already
832> *[frozen][api-freeze]*.
833
834> 👉 **Note**: `stringify` performs the [stringify phase][overview], not the run
835> phase or other phases.
836
837###### Parameters
838
839* `tree` ([`Node`][node]) — tree to compile
840* `file` ([`Compatible`][vfile-compatible], optional) — file associated
841 with `node`; any value accepted as `x` in `new VFile(x)`
842
843###### Returns
844
845Textual representation of the tree (`Uint8Array` or `string`, see note).
846
847> 👉 **Note**: unified typically compiles by serializing: most compilers
848> return `string` (or `Uint8Array`).
849> Some compilers, such as the one configured with
850> [`rehype-react`][rehype-react], return other values (in this case, a
851> React tree).
852> If you’re using a compiler that doesn’t serialize, expect different
853> result values.
854>
855> To register custom results in TypeScript, add them to
856> [`CompileResultMap`][api-compile-result-map].
857
858###### Example
859
860This example shows how `stringify` can be used to serialize a syntax tree:
861
862```js
863import {h} from 'hastscript'
864import rehypeStringify from 'rehype-stringify'
865import {unified} from 'unified'
866
867const tree = h('h1', 'Hello world!')
868
869const document = unified().use(rehypeStringify).stringify(tree)
870
871console.log(document)
872```
873
874Yields:
875
876```html
877<h1>Hello world!</h1>
878```
879
880### `processor.use(plugin[, options])`
881
882Configure the processor to use a plugin, a list of usable values, or a preset.
883
884If the processor is already using a plugin, the previous plugin configuration
885is changed based on the options that are passed in.
886In other words, the plugin is not added a second time.
887
888> 👉 **Note**: `use` cannot be called on [*frozen*][api-freeze] processors.
889> Call the processor first to create a new unfrozen processor.
890
891###### Signatures
892
893* `processor.use(preset?)`
894* `processor.use(list)`
895* `processor.use(plugin[, ...parameters])`
896
897###### Parameters
898
899* `preset` ([`Preset`][api-preset]) — plugins and settings
900* `list` ([`PluggableList`][api-pluggable-list]) — list of usable things
901* `plugin` ([`Plugin`][api-plugin]) — plugin
902* `parameters` (`Array<unknown>`) — configuration for `plugin`, typically a
903 single options object
904
905###### Returns
906
907Current processor ([`processor`][api-processor]).
908
909###### Example
910
911There are many ways to pass plugins to `.use()`.
912This example gives an overview:
913
914```js
915import {unified} from 'unified'
916
917unified()
918 // Plugin with options:
919 .use(pluginA, {x: true, y: true})
920 // Passing the same plugin again merges configuration (to `{x: true, y: false, z: true}`):
921 .use(pluginA, {y: false, z: true})
922 // Plugins:
923 .use([pluginB, pluginC])
924 // Two plugins, the second with options:
925 .use([pluginD, [pluginE, {}]])
926 // Preset with plugins and settings:
927 .use({plugins: [pluginF, [pluginG, {}]], settings: {position: false}})
928 // Settings only:
929 .use({settings: {position: false}})
930```
931
932### `CompileResultMap`
933
934Interface of known results from compilers (TypeScript type).
935
936Normally, compilers result in text ([`Value`][vfile-value] of `vfile`).
937When you compile to something else, such as a React node (as in,
938`rehype-react`), you can augment this interface to include that type.
939
940```ts
941import type {ReactNode} from 'somewhere'
942
943declare module 'unified' {
944 interface CompileResultMap {
945 // Register a new result (value is used, key should match it).
946 ReactNode: ReactNode
947 }
948}
949
950export {} // You may not need this, but it makes sure the file is a module.
951```
952
953Use [`CompileResults`][api-compile-results] to access the values.
954
955###### Type
956
957```ts
958interface CompileResultMap {
959 // Note: if `Value` from `VFile` is changed, this should too.
960 Uint8Array: Uint8Array
961 string: string
962}
963```
964
965### `CompileResults`
966
967Acceptable results from compilers (TypeScript type).
968
969To register custom results, add them to
970[`CompileResultMap`][api-compile-result-map].
971
972###### Type
973
974```ts
975type CompileResults = CompileResultMap[keyof CompileResultMap]
976```
977
978### `Compiler`
979
980A **compiler** handles the compiling of a syntax tree to something else
981(in most cases, text) (TypeScript type).
982
983It is used in the stringify phase and called with a [`Node`][node]
984and [`VFile`][vfile] representation of the document to compile.
985It should return the textual representation of the given tree (typically
986`string`).
987
988> 👉 **Note**: unified typically compiles by serializing: most compilers
989> return `string` (or `Uint8Array`).
990> Some compilers, such as the one configured with
991> [`rehype-react`][rehype-react], return other values (in this case, a
992> React tree).
993> If you’re using a compiler that doesn’t serialize, expect different
994> result values.
995>
996> To register custom results in TypeScript, add them to
997> [`CompileResultMap`][api-compile-result-map].
998
999###### Type
1000
1001```ts
1002type Compiler<
1003 Tree extends Node = Node,
1004 Result extends CompileResults = CompileResults
1005> = (tree: Tree, file: VFile) => Result
1006```
1007
1008### `Data`
1009
1010Interface of known data that can be supported by all plugins (TypeScript type).
1011
1012Typically, options can be given to a specific plugin, but sometimes it makes
1013sense to have information shared with several plugins.
1014For example, a list of HTML elements that are self-closing, which is needed
1015during all phases.
1016
1017To type this, do something like:
1018
1019```ts
1020declare module 'unified' {
1021 interface Data {
1022 htmlVoidElements?: Array<string> | undefined
1023 }
1024}
1025
1026export {} // You may not need this, but it makes sure the file is a module.
1027```
1028
1029###### Type
1030
1031```ts
1032interface Data {
1033 settings?: Settings | undefined
1034}
1035```
1036
1037See [`Settings`][api-settings] for more info.
1038
1039### `Parser`
1040
1041A **parser** handles the parsing of text to a syntax tree (TypeScript type).
1042
1043It is used in the parse phase and is called with a `string` and
1044[`VFile`][vfile] of the document to parse.
1045It must return the syntax tree representation of the given file
1046([`Node`][node]).
1047
1048###### Type
1049
1050```ts
1051type Parser<Tree extends Node = Node> = (document: string, file: VFile) => Tree
1052```
1053
1054### `Pluggable`
1055
1056Union of the different ways to add plugins and settings (TypeScript type).
1057
1058###### Type
1059
1060```ts
1061type Pluggable =
1062 | Plugin<Array<any>, any, any>
1063 | PluginTuple<Array<any>, any, any>
1064 | Preset
1065```
1066
1067See [`Plugin`][api-plugin], [`PluginTuple`][api-plugin-tuple],
1068and [`Preset`][api-preset] for more info.
1069
1070### `PluggableList`
1071
1072List of plugins and presets (TypeScript type).
1073
1074###### Type
1075
1076```ts
1077type PluggableList = Array<Pluggable>
1078```
1079
1080See [`Pluggable`][api-pluggable] for more info.
1081
1082### `Plugin`
1083
1084Single plugin (TypeScript type).
1085
1086Plugins configure the processors they are applied on in the following ways:
1087
1088* they change the processor, such as the parser, the compiler, or by
1089 configuring data
1090* they specify how to handle trees and files
1091
1092In practice, they are functions that can receive options and configure the
1093processor (`this`).
1094
1095> 👉 **Note**: plugins are called when the processor is *frozen*, not when they
1096> are applied.
1097
1098###### Type
1099
1100```ts
1101type Plugin<
1102 PluginParameters extends unknown[] = [],
1103 Input extends Node | string | undefined = Node,
1104 Output = Input
1105> = (
1106 this: Processor,
1107 ...parameters: PluginParameters
1108) => Input extends string // Parser.
1109 ? Output extends Node | undefined
1110 ? undefined | void
1111 : never
1112 : Output extends CompileResults // Compiler.
1113 ? Input extends Node | undefined
1114 ? undefined | void
1115 : never
1116 : // Inspect/transform.
1117 | Transformer<
1118 Input extends Node ? Input : Node,
1119 Output extends Node ? Output : Node
1120 >
1121 | undefined
1122 | void
1123```
1124
1125See [`Transformer`][api-transformer] for more info.
1126
1127###### Example
1128
1129`move.js`:
1130
1131```js
1132/**
1133 * @typedef Options
1134 * Configuration (required).
1135 * @property {string} extname
1136 * File extension to use (must start with `.`).
1137 */
1138
1139/** @type {import('unified').Plugin<[Options]>} */
1140export function move(options) {
1141 if (!options || !options.extname) {
1142 throw new Error('Missing `options.extname`')
1143 }
1144
1145 return function (_, file) {
1146 if (file.extname && file.extname !== options.extname) {
1147 file.extname = options.extname
1148 }
1149 }
1150}
1151```
1152
1153`example.md`:
1154
1155```markdown
1156# Hello, world!
1157```
1158
1159`example.js`:
1160
1161```js
1162import rehypeStringify from 'rehype-stringify'
1163import remarkParse from 'remark-parse'
1164import remarkRehype from 'remark-rehype'
1165import {read, write} from 'to-vfile'
1166import {unified} from 'unified'
1167import {reporter} from 'vfile-reporter'
1168import {move} from './move.js'
1169
1170const file = await unified()
1171 .use(remarkParse)
1172 .use(remarkRehype)
1173 .use(move, {extname: '.html'})
1174 .use(rehypeStringify)
1175 .process(await read('example.md'))
1176
1177console.error(reporter(file))
1178await write(file) // Written to `example.html`.
1179```
1180
1181Yields:
1182
1183```txt
1184example.md: no issues found
1185```
1186
1187…and in `example.html`:
1188
1189```html
1190<h1>Hello, world!</h1>
1191```
1192
1193### `PluginTuple`
1194
1195Tuple of a plugin and its configuration (TypeScript type).
1196
1197The first item is a plugin, the rest are its parameters.
1198
1199###### Type
1200
1201```ts
1202type PluginTuple<
1203 TupleParameters extends unknown[] = [],
1204 Input extends Node | string | undefined = undefined,
1205 Output = undefined
1206> = [
1207 plugin: Plugin<TupleParameters, Input, Output>,
1208 ...parameters: TupleParameters
1209]
1210```
1211
1212See [`Plugin`][api-plugin] for more info.
1213
1214### `Preset`
1215
1216Sharable configuration (TypeScript type).
1217
1218They can contain plugins and settings.
1219
1220###### Fields
1221
1222* `plugins` ([`PluggableList`][api-pluggable-list], optional)
1223 — list of plugins and presets
1224* `settings` ([`Data`][api-data], optional)
1225 — shared settings for parsers and compilers
1226
1227###### Example
1228
1229`preset.js`:
1230
1231```js
1232import remarkCommentConfig from 'remark-comment-config'
1233import remarkLicense from 'remark-license'
1234import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
1235import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
1236import remarkToc from 'remark-toc'
1237
1238/** @type {import('unified').Preset} */
1239const preset = {
1240 plugins: [
1241 remarkPresetLintRecommended,
1242 remarkPresetLintConsistent,
1243 remarkCommentConfig,
1244 [remarkToc, {maxDepth: 3, tight: true}],
1245 remarkLicense
1246 ]
1247 settings: {bullet: '*', emphasis: '*', fences: true},
1248}
1249
1250export default preset
1251```
1252
1253`example.md`:
1254
1255```markdown
1256# Hello, world!
1257
1258_Emphasis_ and **importance**.
1259
1260## Table of contents
1261
1262## API
1263
1264## License
1265```
1266
1267`example.js`:
1268
1269```js
1270import {remark} from 'remark'
1271import {read, write} from 'to-vfile'
1272import {reporter} from 'vfile-reporter'
1273import preset from './preset.js'
1274
1275const file = await remark()
1276 .use(preset)
1277 .process(await read('example.md'))
1278
1279console.error(reporter(file))
1280await write(file)
1281```
1282
1283Yields:
1284
1285```txt
1286example.md: no issues found
1287```
1288
1289`example.md` now contains:
1290
1291```markdown
1292# Hello, world!
1293
1294*Emphasis* and **importance**.
1295
1296## Table of contents
1297
1298* [API](#api)
1299* [License](#license)
1300
1301## API
1302
1303## License
1304
1305[MIT](license) © [Titus Wormer](https://wooorm.com)
1306```
1307
1308### `ProcessCallback`
1309
1310Callback called when the process is done (TypeScript type).
1311
1312Called with either an error or a result.
1313
1314###### Parameters
1315
1316* `error` (`Error`, optional)
1317 — fatal error
1318* `file` ([`VFile`][vfile], optional)
1319 — processed file
1320
1321###### Returns
1322
1323Nothing (`undefined`).
1324
1325###### Example
1326
1327This example shows how `process` can be used to process a file with a callback.
1328
1329```js
1330import remarkGithub from 'remark-github'
1331import remarkParse from 'remark-parse'
1332import remarkStringify from 'remark-stringify'
1333import {unified} from 'unified'
1334import {reporter} from 'vfile-reporter'
1335
1336unified()
1337 .use(remarkParse)
1338 .use(remarkGithub)
1339 .use(remarkStringify)
1340 .process('@unifiedjs', function (error, file) {
1341 if (error) throw error
1342 if (file) {
1343 console.error(reporter(file))
1344 console.log(String(file))
1345 }
1346 })
1347```
1348
1349Yields:
1350
1351```txt
1352no issues found
1353```
1354
1355```markdown
1356[**@unifiedjs**](https://github.com/unifiedjs)
1357```
1358
1359### `Processor`
1360
1361Type of a [`processor`][api-processor] (TypeScript type).
1362
1363### `RunCallback`
1364
1365Callback called when transformers are done (TypeScript type).
1366
1367Called with either an error or results.
1368
1369###### Parameters
1370
1371* `error` (`Error`, optional)
1372 — fatal error
1373* `tree` ([`Node`][node], optional)
1374 — transformed tree
1375* `file` ([`VFile`][vfile], optional)
1376 — file
1377
1378###### Returns
1379
1380Nothing (`undefined`).
1381
1382### `Settings`
1383
1384Interface of known extra options, that can be supported by parser and
1385compilers.
1386
1387This exists so that users can use packages such as `remark`, which configure
1388both parsers and compilers (in this case `remark-parse` and
1389`remark-stringify`), and still provide options for them.
1390
1391When you make parsers or compilers, that could be packaged up together, you
1392should support `this.data('settings')` as input and merge it with explicitly
1393passed `options`.
1394Then, to type it, using `remark-stringify` as an example, do something like:
1395
1396```ts
1397declare module 'unified' {
1398 interface Settings {
1399 bullet: '*' | '+' | '-'
1400 // …
1401 }
1402}
1403
1404export {} // You may not need this, but it makes sure the file is a module.
1405```
1406
1407###### Type
1408
1409```ts
1410interface Settings {}
1411```
1412
1413### `TransformCallback`
1414
1415Callback passed to transforms (TypeScript type).
1416
1417If the signature of a `transformer` accepts a third argument, the transformer
1418may perform asynchronous operations, and must call it.
1419
1420###### Parameters
1421
1422* `error` (`Error`, optional)
1423 — fatal error to stop the process
1424* `tree` ([`Node`][node], optional)
1425 — new, changed, tree
1426* `file` ([`VFile`][vfile], optional)
1427 — new, changed, file
1428
1429###### Returns
1430
1431Nothing (`undefined`).
1432
1433### `Transformer`
1434
1435Transformers handle syntax trees and files (TypeScript type).
1436
1437They are functions that are called each time a syntax tree and file are
1438passed through the run phase.
1439When an error occurs in them (either because it’s thrown, returned,
1440rejected, or passed to `next`), the process stops.
1441
1442The run phase is handled by [`trough`][trough], see its documentation for
1443the exact semantics of these functions.
1444
1445> 👉 **Note**: you should likely ignore `next`: don’t accept it.
1446> it supports callback-style async work.
1447> But promises are likely easier to reason about.
1448
1449###### Type
1450
1451```ts
1452type Transformer<
1453 Input extends Node = Node,
1454 Output extends Node = Input
1455> = (
1456 tree: Input,
1457 file: VFile,
1458 next: TransformCallback<Output>
1459) =>
1460 | Promise<Output | undefined>
1461 | Output
1462 | Error
1463 | undefined
1464```
1465
1466## Types
1467
1468This package is fully typed with [TypeScript][].
1469It exports the additional types
1470[`CompileResultMap`][api-compile-result-map],
1471[`CompileResults`][api-compile-results],
1472[`Compiler`][api-compiler],
1473[`Data`][api-data],
1474[`Parser`][api-parser],
1475[`Pluggable`][api-pluggable],
1476[`PluggableList`][api-pluggable-list],
1477[`Plugin`][api-plugin],
1478[`PluginTuple`][api-plugin-tuple],
1479[`Preset`][api-preset],
1480[`ProcessCallback`][api-process-callback],
1481[`Processor`][api-processor],
1482[`RunCallback`][api-run-callback],
1483[`Settings`][api-settings],
1484[`TransformCallback`][api-transform-callback],
1485and [`Transformer`][api-transformer]
1486
1487For TypeScript to work, it is particularly important to type your plugins
1488correctly.
1489We strongly recommend using the `Plugin` type with its generics and to use the
1490node types for the syntax trees provided by our packages (as in,
1491[`@types/hast`][types-hast], [`@types/mdast`][types-mdast],
1492[`@types/nlcst`][types-nlcst]).
1493
1494```js
1495/**
1496 * @typedef {import('hast').Root} HastRoot
1497 * @typedef {import('mdast').Root} MdastRoot
1498 */
1499
1500/**
1501 * @typedef Options
1502 * Configuration (optional).
1503 * @property {boolean | null | undefined} [someField]
1504 * Some option (optional).
1505 */
1506
1507// To type options:
1508/** @type {import('unified').Plugin<[(Options | null | undefined)?]>} */
1509export function myPluginAcceptingOptions(options) {
1510 const settings = options || {}
1511 // `settings` is now `Options`.
1512}
1513
1514// To type a plugin that works on a certain tree, without options:
1515/** @type {import('unified').Plugin<[], MdastRoot>} */
1516export function myRemarkPlugin() {
1517 return function (tree, file) {
1518 // `tree` is `MdastRoot`.
1519 }
1520}
1521
1522// To type a plugin that transforms one tree into another:
1523/** @type {import('unified').Plugin<[], MdastRoot, HastRoot>} */
1524export function remarkRehype() {
1525 return function (tree) {
1526 // `tree` is `MdastRoot`.
1527 // Result must be `HastRoot`.
1528 }
1529}
1530
1531// To type a plugin that defines a parser:
1532/** @type {import('unified').Plugin<[], string, MdastRoot>} */
1533export function remarkParse(options) {}
1534
1535// To type a plugin that defines a compiler:
1536/** @type {import('unified').Plugin<[], HastRoot, string>} */
1537export function rehypeStringify(options) {}
1538```
1539
1540## Compatibility
1541
1542Projects maintained by the unified collective are compatible with maintained
1543versions of Node.js.
1544
1545When we cut a new major release, we drop support for unmaintained versions of
1546Node.
1547This means we try to keep the current release line, `unified@^11`, compatible
1548with Node.js 16.
1549
1550## Contribute
1551
1552See [`contributing.md`][contributing] in [`unifiedjs/.github`][health] for ways
1553to get started.
1554See [`support.md`][support] for ways to get help.
1555
1556This project has a [code of conduct][coc].
1557By interacting with this repository, organization, or community you agree to
1558abide by its terms.
1559
1560For info on how to submit a security report, see our
1561[security policy][security].
1562
1563## Sponsor
1564
1565Support this effort and give back by sponsoring on [OpenCollective][collective]!
1566
1567<table>
1568<tr valign="middle">
1569<td width="20%" align="center" rowspan="2" colspan="2">
1570 <a href="https://vercel.com">Vercel</a><br><br>
1571 <a href="https://vercel.com"><img src="https://avatars1.githubusercontent.com/u/14985020?s=256&v=4" width="128"></a>
1572</td>
1573<td width="20%" align="center" rowspan="2" colspan="2">
1574 <a href="https://motif.land">Motif</a><br><br>
1575 <a href="https://motif.land"><img src="https://avatars1.githubusercontent.com/u/74457950?s=256&v=4" width="128"></a>
1576</td>
1577<td width="20%" align="center" rowspan="2" colspan="2">
1578 <a href="https://www.hashicorp.com">HashiCorp</a><br><br>
1579 <a href="https://www.hashicorp.com"><img src="https://avatars1.githubusercontent.com/u/761456?s=256&v=4" width="128"></a>
1580</td>
1581<td width="20%" align="center" rowspan="2" colspan="2">
1582 <a href="https://americanexpress.io">American Express</a><br><br>
1583 <a href="https://americanexpress.io"><img src="https://avatars1.githubusercontent.com/u/3853301?s=256&v=4" width="128"></a>
1584</td>
1585<td width="20%" align="center" rowspan="2" colspan="2">
1586 <a href="https://www.gitbook.com">GitBook</a><br><br>
1587 <a href="https://www.gitbook.com"><img src="https://avatars1.githubusercontent.com/u/7111340?s=256&v=4" width="128"></a>
1588</td>
1589</tr>
1590<tr valign="middle">
1591</tr>
1592<tr valign="middle">
1593<td width="20%" align="center" rowspan="2" colspan="2">
1594 <a href="https://www.gatsbyjs.org">Gatsby</a><br><br>
1595 <a href="https://www.gatsbyjs.org"><img src="https://avatars1.githubusercontent.com/u/12551863?s=256&v=4" width="128"></a>
1596</td>
1597<td width="20%" align="center" rowspan="2" colspan="2">
1598 <a href="https://www.netlify.com">Netlify</a><br><br>
1599 <!--OC has a sharper image-->
1600 <a href="https://www.netlify.com"><img src="https://images.opencollective.com/netlify/4087de2/logo/256.png" width="128"></a>
1601</td>
1602<td width="10%" align="center">
1603 <a href="https://www.coinbase.com">Coinbase</a><br><br>
1604 <a href="https://www.coinbase.com"><img src="https://avatars1.githubusercontent.com/u/1885080?s=256&v=4" width="64"></a>
1605</td>
1606<td width="10%" align="center">
1607 <a href="https://themeisle.com">ThemeIsle</a><br><br>
1608 <a href="https://themeisle.com"><img src="https://avatars1.githubusercontent.com/u/58979018?s=128&v=4" width="64"></a>
1609</td>
1610<td width="10%" align="center">
1611 <a href="https://expo.io">Expo</a><br><br>
1612 <a href="https://expo.io"><img src="https://avatars1.githubusercontent.com/u/12504344?s=128&v=4" width="64"></a>
1613</td>
1614<td width="10%" align="center">
1615 <a href="https://boostnote.io">Boost Note</a><br><br>
1616 <a href="https://boostnote.io"><img src="https://images.opencollective.com/boosthub/6318083/logo/128.png" width="64"></a>
1617</td>
1618<td width="10%" align="center">
1619 <a href="https://markdown.space">Markdown Space</a><br><br>
1620 <a href="https://markdown.space"><img src="https://images.opencollective.com/markdown-space/e1038ed/logo/128.png" width="64"></a>
1621</td>
1622<td width="10%" align="center">
1623 <a href="https://www.holloway.com">Holloway</a><br><br>
1624 <a href="https://www.holloway.com"><img src="https://avatars1.githubusercontent.com/u/35904294?s=128&v=4" width="64"></a>
1625</td>
1626</tr>
1627<tr valign="middle">
1628<td width="100%" align="center" colspan="6">
1629 <br>
1630 <a href="https://opencollective.com/unified"><strong>You?</strong></a>
1631 <br><br>
1632</td>
1633</tr>
1634</table>
1635
1636## Acknowledgments
1637
1638Preliminary work for unified was done [in 2014][preliminary] for
1639**[retext][]** and inspired by [`ware`][ware].
1640Further incubation happened in **[remark][]**.
1641The project was finally [externalised][] in 2015 and [published][] as `unified`.
1642The project was authored by **[@wooorm](https://github.com/wooorm)**.
1643
1644Although `unified` since moved its plugin architecture to [`trough`][trough],
1645thanks to **[@calvinfo](https://github.com/calvinfo)**,
1646**[@ianstormtaylor](https://github.com/ianstormtaylor)**, and others for their
1647work on [`ware`][ware], as it was a huge initial inspiration.
1648
1649## License
1650
1651[MIT][license] © [Titus Wormer][author]
1652
1653<!-- Definitions -->
1654
1655[logo]: https://raw.githubusercontent.com/unifiedjs/unified/93862e5/logo.svg?sanitize=true
1656
1657[build-badge]: https://github.com/unifiedjs/unified/workflows/main/badge.svg
1658
1659[build]: https://github.com/unifiedjs/unified/actions
1660
1661[coverage-badge]: https://img.shields.io/codecov/c/github/unifiedjs/unified.svg
1662
1663[coverage]: https://codecov.io/github/unifiedjs/unified
1664
1665[downloads-badge]: https://img.shields.io/npm/dm/unified.svg
1666
1667[downloads]: https://www.npmjs.com/package/unified
1668
1669[size-badge]: https://img.shields.io/bundlejs/size/unified
1670
1671[size]: https://bundlejs.com/?q=unified
1672
1673[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg
1674
1675[backers-badge]: https://opencollective.com/unified/backers/badge.svg
1676
1677[collective]: https://opencollective.com/unified
1678
1679[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg
1680
1681[chat]: https://github.com/unifiedjs/unified/discussions
1682
1683[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c
1684
1685[esmsh]: https://esm.sh
1686
1687[typescript]: https://www.typescriptlang.org
1688
1689[health]: https://github.com/unifiedjs/.github
1690
1691[contributing]: https://github.com/unifiedjs/.github/blob/main/contributing.md
1692
1693[support]: https://github.com/unifiedjs/.github/blob/main/support.md
1694
1695[coc]: https://github.com/unifiedjs/.github/blob/main/code-of-conduct.md
1696
1697[security]: https://github.com/unifiedjs/.github/blob/main/security.md
1698
1699[license]: license
1700
1701[author]: https://wooorm.com
1702
1703[npm]: https://docs.npmjs.com/cli/install
1704
1705[site]: https://unifiedjs.com
1706
1707[twitter]: https://twitter.com/unifiedjs
1708
1709[rehype]: https://github.com/rehypejs/rehype
1710
1711[remark]: https://github.com/remarkjs/remark
1712
1713[retext]: https://github.com/retextjs/retext
1714
1715[syntax-tree]: https://github.com/syntax-tree
1716
1717[esast]: https://github.com/syntax-tree/esast
1718
1719[hast]: https://github.com/syntax-tree/hast
1720
1721[mdast]: https://github.com/syntax-tree/mdast
1722
1723[nlcst]: https://github.com/syntax-tree/nlcst
1724
1725[unist]: https://github.com/syntax-tree/unist
1726
1727[xast]: https://github.com/syntax-tree/xast
1728
1729[unified-engine]: https://github.com/unifiedjs/unified-engine
1730
1731[unified-args]: https://github.com/unifiedjs/unified-args
1732
1733[unified-engine-gulp]: https://github.com/unifiedjs/unified-engine-gulp
1734
1735[unified-language-server]: https://github.com/unifiedjs/unified-language-server
1736
1737[unified-stream]: https://github.com/unifiedjs/unified-stream
1738
1739[rehype-remark]: https://github.com/rehypejs/rehype-remark
1740
1741[rehype-retext]: https://github.com/rehypejs/rehype-retext
1742
1743[remark-rehype]: https://github.com/remarkjs/remark-rehype
1744
1745[remark-retext]: https://github.com/remarkjs/remark-retext
1746
1747[node]: https://github.com/syntax-tree/unist#node
1748
1749[vfile]: https://github.com/vfile/vfile
1750
1751[vfile-compatible]: https://github.com/vfile/vfile#compatible
1752
1753[vfile-value]: https://github.com/vfile/vfile#value
1754
1755[vfile-utilities]: https://github.com/vfile/vfile#list-of-utilities
1756
1757[rehype-react]: https://github.com/rehypejs/rehype-react
1758
1759[trough]: https://github.com/wooorm/trough#function-fninput-next
1760
1761[rehype-plugins]: https://github.com/rehypejs/rehype/blob/main/doc/plugins.md#list-of-plugins
1762
1763[remark-plugins]: https://github.com/remarkjs/remark/blob/main/doc/plugins.md#list-of-plugins
1764
1765[retext-plugins]: https://github.com/retextjs/retext/blob/main/doc/plugins.md#list-of-plugins
1766
1767[awesome-rehype]: https://github.com/rehypejs/awesome-rehype
1768
1769[awesome-remark]: https://github.com/remarkjs/awesome-remark
1770
1771[awesome-retext]: https://github.com/retextjs/awesome-retext
1772
1773[topic-rehype-plugin]: https://github.com/topics/rehype-plugin
1774
1775[topic-remark-plugin]: https://github.com/topics/remark-plugin
1776
1777[topic-retext-plugin]: https://github.com/topics/retext-plugin
1778
1779[types-hast]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/hast
1780
1781[types-mdast]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/mdast
1782
1783[types-nlcst]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/nlcst
1784
1785[preliminary]: https://github.com/retextjs/retext/commit/8fcb1f
1786
1787[externalised]: https://github.com/remarkjs/remark/commit/9892ec
1788
1789[published]: https://github.com/unifiedjs/unified/commit/2ba1cf
1790
1791[ware]: https://github.com/segmentio/ware
1792
1793[api]: #api
1794
1795[contribute]: #contribute
1796
1797[overview]: #overview
1798
1799[sponsor]: #sponsor
1800
1801[api-compile-result-map]: #compileresultmap
1802
1803[api-compile-results]: #compileresults
1804
1805[api-compiler]: #compiler
1806
1807[api-data]: #data
1808
1809[api-freeze]: #processorfreeze
1810
1811[api-parser]: #parser
1812
1813[api-pluggable]: #pluggable
1814
1815[api-pluggable-list]: #pluggablelist
1816
1817[api-plugin]: #plugin
1818
1819[api-plugin-tuple]: #plugintuple
1820
1821[api-preset]: #preset
1822
1823[api-process]: #processorprocessfile-done
1824
1825[api-process-callback]: #processcallback
1826
1827[api-processor]: #processor
1828
1829[api-run-callback]: #runcallback
1830
1831[api-settings]: #settings
1832
1833[api-transform-callback]: #transformcallback
1834
1835[api-transformer]: #transformer