!Buildbuild-badgebuild
!Coveragecoverage-badgecoverage
!Downloadsdownloads-badgedownloads
!Sizesize-badgesize
!Sponsorssponsors-badgecollective
!Backersbackers-badgecollective
!Chatchat-badgechat
unified is an interface for processing text using syntax trees. Itβs what powers remarkremark (Markdown), retextretext (natural language), and rehyperehype (HTML), and allows for processing between formats.
npm install unified
Yields:
When processors are exposed from a module (for example,
There are several utilitiesunist-utilities for working with nodes.
There are several utilitiesvfile-utilities for working with these files.
Yields:
Bridge mode transforms the syntax treesyntax-tree from one format (origin) to another (destination). Another processor runs on the destination tree. Finally, the original processor continues transforming 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β),
Processorprocessors describing how to process text.
Configureconfiguration the processor to use a pluginplugin and
optionally configure that plugin with options.
If the processor is already using this plugin, the previous plugin configuration is changed based on the options that are passed in. The plugin is not added a second time.
Parse text to a syntax treesyntax-tree.
Yields:
A parser handles the parsing of text to a syntax treesyntax-tree.
Used in the parse phasedescription and called with a
Compile a syntax treesyntax-tree.
unified typically compiles by serializing: most compilercompilers return
Yields:
A compiler handles the compiling of a syntax treesyntax-tree to text.
Used in the stringify phasedescription and called with a
Run transformerstransformer on a syntax treesyntax-tree.
Callback called when transformerstransformer are done.
Called with either an error or results.
Yields:
Run transformerstransformer on a syntax treesyntax-tree.
An error is thrown if asynchronous pluginplugins are configured.
Processdescription the given filefile as configured on the
processor.
The parsed, transformed, and compiled value is exposed on
unified typically compiles by serializing: most compilercompilers return
Yields:
Callback called when the processdescription is done.
Called with a fatal error, if any, and a filefile.
Yields:
Processdescription the given filefile as configured on the
processor.
An error is thrown if asynchronous pluginplugins are configured.
The parsed, transformed, and compiled value is exposed on
unified typically compiles by serializing: most compilercompilers return
Yields:
Configureconfiguration the processor with information available to all
pluginplugins.
Information is stored in an in-memory key-value store.
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 phasesdescription of the process.
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. New processors working the same way can be created by calling the processor.
Itβs possible to freeze processors explicitly by calling
The below example,
The below example,
Yields:
Plugins configureconfiguration the processors they are applied on in
the following ways:
Plugins are a concept. They materialize as
Yields:
β¦and in
Attachers are materialized pluginplugins.
An attacher is a function that can receive options and
configuresconfiguration the processor.
Attachers change the processor, such as the parserparser, the compilercompiler, configuring datadata, or by specifying how the syntax treesyntax-tree or filefile are handled.
Transformers handle syntax treesyntax-trees and filefiles.
A transformer is a function that is called each time a syntax tree and file are
passed through the run phasedescription.
If an error occurs (either because itβs thrown, returned, rejected, or passed to
The run phase is handled by
If the signature of a transformertransformer includes
Presets are sharable configurationconfiguration.
They can contain pluginsplugin and settings.
Yields:
A curated list of awesome unified resources can be found in awesome unifiedawesome.
This project has a code of conductcoc. By interacting with this repository, organization, or community you agree to abide by its terms.
Although
unified is an interface for processing text using syntax trees. Itβs what powers remarkremark (Markdown), retextretext (natural language), and rehyperehype (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 unifiedawesome 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
Support this effort and give back by sponsoring on OpenCollectivecollective!
Vercel |
Motif |
HashiCorp |
American Express |
GitBook |
|||
Gatsby |
Netlify![]() |
Coinbase |
ThemeIsle |
Expo |
Boost Note![]() |
Holloway |
|
You? |
Install
This package is ESM only: Node 12+ is needed to use it and it must beimport
ed instead of require
d.npm install unified
## Use
```js
import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
import {reporter} from 'vfile-reporter'
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
}
)
Yields:
no issues found
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ππ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
Contents
* [`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)
* [`function attacher([options])`](#function-attacheroptions)
* [`function transformer(node, file[, next])`](#function-transformernode-file-next)
Description
unified is an interface for processing text using syntax trees. Syntax trees are a representation of text understandable to programs. Those programs, called pluginplugins, take these trees and inspect and modify them. To get to the syntax tree from text, there is a parserparser. To get from that back to text, there is a compilercompiler. This is the processprocess of a processor.| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|
+--------+ +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
+--------+ | +----------+
X
|
+--------------+
| Transformers |
+--------------+
Processors
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 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 frozenfreeze and they should be called to create a
new processor before they are used.Syntax trees
The syntax trees used in unified are unistunist nodes. A nodenode is a plain JavaScript objects with atype
field.
The semantics of nodes and format of syntax trees is defined by other projects.There are several utilitiesunist-utilities for working with nodes.
- esastesast β JS
- hasthast β HTML
- mdastmdast β Markdown
- nlcstnlcst β Natural language
- xastxast β XML
List of processors
The following projects process different syntax treesyntax-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.- rehyperehype (hasthast) β HTML
- remarkremark (mdastmdast) β Markdown
- retextretext (nlcstnlcst) β Natural language
List of plugins
The below pluginsplugin work with unified, on all syntax treesyntax-tree formats:β Ignore messages for unchanged lines in Travis
β Enable, disable, and ignore messages
See remarkremark-plugins, rehyperehype-plugins, and
retextretext-plugins for their lists of plugins.File
When processing a document, metadata is often gathered about that document. vfilevfile is a virtual file format that stores data, metadata, and messages about files for unified and its plugins.There are several utilitiesvfile-utilities for working with these files.
Configuration
Processorsprocessors are configured with pluginplugins or with thedata
data method.Integrations
unified can integrate with the file system withunified-engine
engine.
CLI apps can be created with unified-args
args, Gulp plugins with
unified-engine-gulp
gulp, and Atom Linters with
unified-engine-atom
atom.unified-stream
stream provides a streaming interface.Programming interface
The API provided by unified allows multiple files to be processed and gives access to metadata (such as lint messages):import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown-style-guide'
import remarkRetext from 'remark-retext'
import retextEnglish from 'retext-english'
import retextEquality from 'retext-equality'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'
import {reporter} from 'vfile-reporter'
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
}
)
Yields:
1:16-1:24 warning Emphasis should use `*` as a marker emphasis-marker remark-lint
1:30-1:34 warning `guys` may be insensitive, use `people`, `persons`, `folks` instead gals-man retext-equality
β 2 warnings
<p><em>Emphasis</em> and <em>stress</em>, you guys!</p>
Processing between syntaxes
Processorsprocessors can be combined in two modes.Bridge mode transforms the syntax treesyntax-tree from one format (origin) to another (destination). Another processor runs on the destination tree. Finally, the original processor continues transforming 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 retextretext is
done; whereas remark-rehype
is used in mutate mode: it sets a new syntax
tree and discards the origin tree.remark-retext
remark-retextremark-rehype
remark-rehyperehype-retext
rehype-retextrehype-remark
rehype-remark
API
This package exports the following identifiers:unified
.
There is no default export.processor()
Processorprocessors describing how to process text.Returns
Function
β New unfrozenfreeze 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).import {remark} from 'remark'
import concatStream from 'concat-stream'
process.stdin.pipe(
concatStream((buf) => {
process.stdout.write(remark().processSync(buf).toString())
})
)
processor.use(plugin[, options])
Configureconfiguration the processor to use a pluginplugin and
optionally configure that plugin with options.If the processor is already using this plugin, the previous plugin configuration is changed based on the options that are passed in. The plugin is not added a second time.
Signatures
processor.use(plugin[, options])
processor.use(preset)
processor.use(list)
Parameters
plugin
(Attacher
plugin)options
(*
, optional) β Configuration forplugin
preset
(Object
) β Object with an optionalplugins
(set tolist
),
and/or an optional `settings` object
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 frozenfreeze processors.
Call the processor first to create a new unfrozen processor.Example
There are many ways to pass plugins to.use()
.
The below example gives an overview.import {unified} from 'unified'
unified()
// Plugin with options:
.use(pluginA, {x: true, y: true})
// Passing the same plugin again merges configuration (to `{x: true, y: false, z: true}`):
.use(pluginA, {y: false, z: true})
// Plugins:
.use([pluginB, pluginC])
// Two plugins, the second with options:
.use([pluginD, [pluginE, {}]])
// Preset with plugins and settings:
.use({plugins: [pluginF, [pluginG, {}]], settings: {position: false}})
// Settings only:
.use({settings: {position: false}})
processor.parse(file)
Parse text to a syntax treesyntax-tree.Parameters
Returns
Node
node β Parsed syntax treesyntax-tree representing file
.Note
parse
freezes the processor if not already frozenfreeze.parse
performs the parse phasedescription, not the run phase or other
phases.Example
The below example shows howparse
can be used to create a syntax tree from a
file.import {unified} from 'unified'
import remarkParse from 'remark-parse'
const tree = unified().use(remarkParse).parse('# Hello world!')
console.log(tree)
Yields:
{
type: 'root',
children: [
{type: 'heading', depth: 1, children: [Array], position: [Position]}
],
position: {
start: {line: 1, column: 1, offset: 0},
end: {line: 1, column: 15, offset: 14}
}
}
processor.Parser
A parser handles the parsing of text to a syntax treesyntax-tree.
Used in the parse phasedescription and called with a string
and
VFile
vfile representation of the text 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 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
.
Instances must have a parse
method that is called without arguments and must
return a Node
node.processor.stringify(node[, file])
Compile a syntax treesyntax-tree.Parameters
node
(Node
node) β Syntax treesyntax-tree to compilefile
(VFile
vfile, optional) β Filefile, any value accepted by
`vfile()`
Returns
string
or Buffer
(see notes) β Textual representation of the syntax
treesyntax-treeNote
stringify
freezes the processor if not already frozenfreeze.stringify
performs the stringify phasedescription, not the run phase
or other phases.unified typically compiles by serializing: most compilercompilers 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.Example
The below example shows howstringify
can be used to serialize a syntax tree.import {unified} from 'unified'
import rehypeStringify from 'rehype-stringify'
import {h} from 'hastscript'
const tree = h('h1', 'Hello world!')
const doc = unified().use(rehypeStringify).stringify(tree)
console.log(doc)
Yields:
<h1>Hello world!</h1>
processor.Compiler
A compiler handles the compiling of a syntax treesyntax-tree to text.
Used in the stringify phasedescription and called with a Node
node
and VFile
file representation of syntax tree to compile.Compiler
can be a function, in which case it should return a string
: the
textual representation of the syntax tree.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
.
Instances must have a compile
method that is called without arguments and
should return a string
.processor.run(node[, file][, done])
Run transformerstransformer on a syntax treesyntax-tree.Parameters
node
(Node
node) β Syntax treesyntax-tree to run onfile
(VFile
vfile, optional) β Filefile, any value accepted by
`vfile()`
Returns
Promise
promise if done
is not given.
The returned promise is rejected with a fatal error, or resolved with the
transformed syntax treesyntax-tree.Note
run
freezes the processor if not already frozenfreeze.run
performs the run phasedescription, not other phases.function done(err[, node, file])
Callback called when transformerstransformer are done.
Called with either an error or results.Parameters
err
(Error
, optional) β Fatal errornode
(Node
node, optional) β Transformed syntax treesyntax-treefile
(VFile
vfile, optional) β Filefile
Example
The below example shows howrun
can be used to transform a syntax tree.import {unified} from 'unified'
import remarkReferenceLinks from 'remark-reference-links'
import {u} from 'unist-builder'
const tree = u('root', [
u('paragraph', [
u('link', {href: 'https://example.com'}, [u('text', 'Example Domain')])
])
])
unified()
.use(remarkReferenceLinks)
.run(tree)
.then(
(changedTree) => console.log(changedTree),
(error) => {
// Handle your error here!
throw error
}
)
Yields:
{
type: 'root',
children: [
{type: 'paragraph', children: [Array]},
{type: 'definition', identifier: '1', title: undefined, url: undefined}
]
}
processor.runSync(node[, file])
Run transformerstransformer on a syntax treesyntax-tree.An error is thrown if asynchronous pluginplugins are configured.
Parameters
node
(Node
node) β Syntax treesyntax-tree to run onfile
(VFile
vfile, optional) β Filefile, any value accepted by
`vfile()`
Returns
Node
node β Transformed syntax treesyntax-tree.Note
runSync
freezes the processor if not already frozenfreeze.runSync
performs the run phasedescription, not other phases.processor.process(file[, done])
Processdescription the given filefile as configured on the
processor.Parameters
file
(VFile
vfile) β Filefile, any value accepted byvfile()
done
(Function
process-done, optional) β Callback
Returns
Promise
promise if done
is not given.
The returned promise is rejected with a fatal error, or resolved with the
processed filefile.The parsed, transformed, and compiled value is exposed on
file.value
vfile-value or file.result
(see notes).Note
process
freezes the processor if not already frozenfreeze.process
performs the parse, run, and stringify phasesdescription.unified typically compiles by serializing: most compilercompilers 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
.Example
The below example shows howprocess
can be used to process a file, whether
transformers are asynchronous or not, with promises.import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
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
}
)
Yields:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ππ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
function done(err, file)
Callback called when the processdescription is done.
Called with a fatal error, if any, and a filefile.Parameters
Example
The below example shows howprocess
can be used to process a file, whether
transformers are asynchronous or not, with a callback.import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkGithub from 'remark-github'
import remarkStringify from 'remark-stringify'
import {reporter} from 'vfile-reporter'
unified()
.use(remarkParse)
.use(remarkGithub)
.use(remarkStringify)
.process('@unifiedjs')
.then(
(file) => {
console.error(reporter(file))
console.log(String(file))
},
(error) => {
// Handle your error here!
throw error
}
)
Yields:
no issues found
[**@unifiedjs**](https://github.com/unifiedjs)
processor.processSync(file|value)
Processdescription the given filefile as configured on the
processor.An error is thrown if asynchronous pluginplugins are configured.
Parameters
Returns
(VFile
vfile) β Processed filefileThe 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 frozenfreeze.processSync
performs the parse, run, and stringify
phasesdescription.unified typically compiles by serializing: most compilercompilers 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
.Example
The below example shows howprocessSync
can be used to process a file, if all
transformers are synchronous.import {unified} from 'unified'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
const processor = unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeDocument, {title: 'ππ'})
.use(rehypeFormat)
.use(rehypeStringify)
console.log(processor.processSync('# Hello world!').toString())
Yields:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ππ</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<h1>Hello world!</h1>
</body>
</html>
processor.data([key[, value]])
Configureconfiguration the processor with information available to all
pluginplugins.
Information is stored in an in-memory key-value store.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 phasesdescription of the process.
Signatures
processor = processor.data(key, value)
processor = processor.data(values)
value = processor.data(key)
info = processor.data()
Parameters
key
(string
, optional) β Identifiervalue
(*
, optional) β Value to setvalues
(Object
, optional) β Values to set
Returns
processor
β If setting, the processor thatdata
is called onvalue
(*
) β If getting, the value atkey
info
(Object
) β Without arguments, the key-value store
Note
Setting information cannot occur on frozenfreeze processors. Call the processor first to create a new unfrozen processor.Example
The following example show how to get and set information:import {unified} from 'unified'
const processor = unified().data('alpha', 'bravo')
processor.data('alpha') // => 'bravo'
processor.data() // => {alpha: 'bravo'}
processor.data({charlie: 'delta'})
processor.data() // => {charlie: 'delta'}
processor.freeze()
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. 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,
.runSync()
run-sync, .stringify()
stringify, .process()
process,
or .processSync()
process-sync are called.Returns
processor
β The processor that freeze
was called on.Example
The following example,index.js
, shows how rehype prevents extensions to
itself:import {unified} from 'unified'
import remarkParse from 'rehype-parse'
import remarkStringify from 'rehype-stringify'
export const rehype = unified().use(remarkParse).use(remarkStringify).freeze()
The below example,
a.js
, shows how that processor can be used and configured.import {rehype} from 'rehype'
import rehypeFormat from 'rehype-format'
// β¦
rehype()
.use(rehypeFormat)
// β¦
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:import {rehype} from 'rehype'
import rehypeFormat from 'rehype-format'
// β¦
rehype
.use(rehypeFormat)
// β¦
Yields:
~/node_modules/unified/index.js:426
throw new Error(
^
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 configureconfiguration the processors they are applied on in
the following ways:[*compiler*][compiler], or configuring [*data*][data]
- They specify how to handle syntax treessyntax-tree and filesfile
Plugins are a concept. They materialize as
attacher
attachers.Example
move.js
:export function move(options = {}) {
const {extname} = options
if (!extname) {
throw new Error('Missing `extname` in options')
}
return transformer
function transformer(tree, file) {
if (file.extname && file.extname !== extname) {
file.extname = extname
}
}
}
index.md
:# Hello, world!
index.js
: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()
.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
}
)
Yields:
index.md: no issues found
β¦and in
index.html
:<h1>Hello, world!</h1>
function attacher([options])
Attachers are materialized pluginplugins.
An attacher is a function that can receive options and
configuresconfiguration the processor.Attachers change the processor, such as the parserparser, the compilercompiler, configuring datadata, or by specifying how the syntax treesyntax-tree or filefile are handled.
Context
The context object (this
) is set to the processor the attacher is applied on.Parameters
options
(*
, optional) β Configuration
Returns
transformer
transformer β Optional.Note
Attachers are called when the processor is frozenfreeze, not when they are applied.function transformer(node, file[, next])
Transformers handle syntax treesyntax-trees and filefiles.
A transformer is a function that is called each time a syntax tree and file are
passed through the run phasedescription.
If an error occurs (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
exact semantics of these functions.Parameters
node
(Node
node) β Syntax treesyntax-tree to handlefile
(VFile
vfile) β Filefile to handlenext
(Function
next, optional)
Returns
void
β If nothing is returned, the next transformer keeps using same tree.Error
β Fatal error to stop the processnode
(Node
node) β New syntax treesyntax-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`)
function next(err[, tree[, file]])
If the signature of a transformertransformer includes next
(the third
argument), the transformer may perform asynchronous operations, and must
call next()
.Parameters
err
(Error
, optional) β Fatal error to stop the processnode
(Node
node, optional) β New syntax treesyntax-tree.
If given, the next transformer is given this new tree
If given, the next transformer is given this new file
Preset
Presets are sharable configurationconfiguration.
They can contain pluginsplugin and settings.Example
preset.js
:import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
import remarkPresetLintConsistent from 'remark-preset-lint-consistent'
import remarkCommentConfig from 'remark-comment-config'
import remarkToc from 'remark-toc'
import remarkLicense from 'remark-license'
export const preset = {
settings: {bullet: '*', emphasis: '*', fences: true},
plugins: [
remarkPresetLintRecommended,
remarkPresetLintConsistent,
remarkCommentConfig,
[remarkToc, {maxDepth: 3, tight: true}],
remarkLicense
]
}
example.md
:# Hello, world!
_Emphasis_ and **importance**.
## Table of contents
## API
## License
index.js
:import {remark} from 'remark'
import {toVFile} from 'to-vfile'
import {reporter} from 'vfile-reporter'
import {preset} from './preset.js'
remark()
.use(preset)
.process(toVFile.readSync('example.md'))
.then(
(file) => {
console.error(reporter(file))
toVFile.writeSync(file)
},
(error) => {
// Handle your error here!
throw error
}
)
Yields:
example.md: no issues found
example.md
now contains:# Hello, world!
*Emphasis* and **importance**.
## Table of contents
* [API](#api)
* [License](#license)
## API
## License
[MIT](license) Β© [Titus Wormer](https://wooorm.com)
Contribute
Seecontributing.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 unifiedawesome.
This project has a code of conductcoc. By interacting with this repository, organization, or community you agree to abide by its terms.
Acknowledgments
Preliminary work for unified was done in 2014preliminary for retextretext and inspired byware
ware.
Further incubation happened in remarkremark.
The project was finally externalised in 2015 and published as unified
.
The project was authored by @wooorm.Although
unified
since moved its plugin architecture to trough
trough,
thanks to @calvinfo,
@ianstormtaylor, and others for their
work on ware
ware, as it was a huge initial inspiration.