Unified
Parse, inspect, transform, and serialize content with syntax trees
Install / Use
/learn @unifiedjs/UnifiedREADME
[![unified][logo]][site]
[![Build][build-badge]][build] [![Coverage][coverage-badge]][coverage] [![Downloads][downloads-badge]][downloads] [![Size][size-badge]][size] [![Sponsors][sponsors-badge]][collective] [![Backers][backers-badge]][collective] [![Chat][chat-badge]][chat]
unified lets you inspect and transform content with plugins.
Contents
- What is this?
- When should I use this?
- Install
- Use
- Overview
- API
processor()processor.compilerprocessor.data([key[, value]])processor.freeze()processor.parse(file)processor.parserprocessor.process(file[, done])processor.processSync(file)processor.run(tree[, file][, done])processor.runSync(tree[, file])processor.stringify(tree[, file])processor.use(plugin[, options])CompileResultMapCompileResultsCompilerDataParserPluggablePluggableListPluginPluginTuplePresetProcessCallbackProcessorRunCallbackSettingsTransformCallbackTransformer
- Types
- Compatibility
- Contribute
- Sponsor
- Acknowledgments
- License
What is this?
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 1.3m+ projects on GH, to process content with plugins
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.
- for more about us, see [
unifiedjs.com][site] - 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), you can 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 16+), install with [npm][]:
npm install unified
In Deno with [esm.sh][esmsh]:
import {unified} from 'https://esm.sh/unified@11'
In browsers with [esm.sh][esmsh]:
<script type="module">
import {unified} from 'https://esm.sh/unified@11?bundle'
</script>
Use
import rehypeDocument from 'rehype-document'
import rehypeFormat from 'rehype-format'
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkRehype from 'remark-rehype'
import {unified} from 'unified'
import {reporter} from 'vfile-reporter'
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeDocument, {title: '👋🌍'})
.use(rehypeFormat)
.use(rehypeStringify)
.process('# Hello world!')
console.error(reporter(file))
console.log(String(file))
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>
<!-- Old name: -->
<a name="description"></a>
Overview
unified is an interface for processing content with syntax trees.
Syntax trees are a representation of content understandable to programs.
Those programs, called [plugins][api-plugin], take these trees and inspect and
modify them.
To get to the syntax tree from text, there is a [parser][api-parser].
To get from that back to text, there is a [compiler][api-compiler].
This is the [process][api-process] of a processor.
| ........................ process ........................... |
| .......... parse ... | ... run ... | ... stringify ..........|
+--------+ +----------+
Input ->- | Parser | ->- Syntax Tree ->- | Compiler | ->- Output
+--------+ | +----------+
X
|
+--------------+
| Transformers |
+--------------+
Processors
Processors process content.
On its own, unified (the root processor) doesn’t work.
It needs to be configured with plugins to work.
For example:
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 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][api-freeze] and they should be called to create
a new processor before they are used.
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.
There are several [utilities][vfile-utilities] for working with these files.
Syntax tree
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:
- [esast][] — JavaScript
- [hast][] — HTML
- [mdast][] — markdown
- [nlcst][] — natural language
- [xast][] — XML
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.
<a name="list-of-processors"></a>
Ecosystems
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.
- [rehype][] (hast) — HTML
- [remark][] (mdast) — markdown
- [retext][] (nlcst) — natural language
<a name="list-of-plugins"></a>
Plugins
Each aforementioned ecosystem comes with a large set of plugins that you can pick and choose from to do all kinds of things.
- [List of remark plugins][remark-plugins] ·
[
remarkjs/awesome-remark][awesome-remark] · [remark-plugintopic][topic-remark-plugin] - [List of rehype plugins][rehype-plugins] ·
[
rehypejs/awesome-rehype][awesome-rehype] · [rehype-plugintopic][topic-rehype-plugin] - [List of retext plugins][retext-plugins] ·
[
retextjs/awesome-retext][awesome-retext] · [retext-plugintopic][topic-retext-plugin]
There are also a few plugins that work in any ecosystem:
unified-diff— ignore unrelated messages in GitHub Actions and Travisunified-infer-git-meta— infer metadata of a document from Gitunified-message-control— enable, disable, and ignore messages from content
Configuration
Processors are configured with [plugins][api-plugin] or with the
[data][api-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 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):
import rehypeStringify from 'rehype-stringify'
import remarkParse from 'remark-parse'
import remarkPresetLintMarkdownStyleGuide from 'remark-preset-lint-markdown
