unified-engine
can be configured extensively by engine authors.
options.processor
options.cwd
options.files
options.extensions
options.streamIn
options.filePath
options.streamOut
options.streamError
options.out
options.output
options.alwaysStringify
options.tree
options.treeIn
options.treeOut
options.inspect
options.rcName
options.packageField
options.detectConfig
options.rcPath
options.settings
options.ignoreName
options.detectIgnore
options.ignorePath
options.ignorePathResolveFrom
options.ignorePatterns
options.ignoreUnconfigured
options.silentlyIgnore
options.plugins
options.pluginPrefix
options.defaultConfig
options.configTransform
options.reporter
options.reporterOptions
options.color
options.silent
options.quiet
options.frail
unified processor to transform files.
- Type:
Processor
The following example reformats stdin(4) using remark, writes the report to stderr(4), and formatted document to stdout(4).
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine({processor: remark}, done)
function done(error) {
if (error) throw error
}
Directory to search files in, load plugins from, and more.
- Type:
string
orURL
- Default:
process.cwd()
The following example reformats readme.md
. The doc
directory is used to
process from.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
cwd: new URL('doc/', import.meta.url),
files: ['readme.md'],
output: true
},
done
)
function done(error) {
if (error) throw error
}
Paths or globs, or vfiles or URL
s to files and directories to
process.
Fileglobs (for example, *.md
) can be given to add all matching files.
Directories and globs to directories can be given alongside
extensions
to search directories for files matching an extension
(for example, dir
to add dir/readme.txt
and dir/sub/history.text
if
extensions
is ['txt', 'text']
).
This searching will not include node_modules
or hidden directories (those
starting with a dot, .
, like .git
).
- Type:
Array<string|URL|VFile>
- Default:
[]
The following example processes README
and all files with an md
extension in
doc
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark,
files: ['README', 'doc'],
extensions: ['md']
},
done
)
function done(error) {
if (error) throw error
}
If files
matches directories, those directories are searched for
files whose extension matches the given extensions
.
In addition, if treeIn
is turned on and output
is
true
or points to a directory, generated files are given the first extension.
- Type:
Array<string>
- Default:
[]
The following example reformats all files with md
, markdown
, and mkd
extensions in the current directory.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark,
files: ['.'],
extensions: ['md', 'mkd', 'markdown'],
output: true
},
done
)
function done(error) {
if (error) throw error
}
Stream to read from if no files are found or given.
If streamIn
is the only possible source of input but it’s a TTY, an error
is thrown.
- Type:
ReadableStream
- Default:
process.stdin
The following example uses remark-lint
to lint an incoming
stream.
import {PassThrough} from 'stream'
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
const streamIn = new PassThrough()
engine(
{
processor: remark(),
plugins: [remarkPresetLintRecommended],
streamIn: streamIn,
out: false
},
done
)
streamIn.write('doc')
setTimeout(delayed, 100)
function delayed() {
streamIn.end('ument')
}
function done(error) {
if (error) throw error
}
Yields:
<stdin>
1:1 warning Missing newline character at end of file final-newline remark-lint
⚠ 1 warning
File path to process the given file on streamIn
as, if any.
- Type:
string
(optional)
The following example shows the same as before, with a filePath
added, which
is shown in the report:
import {PassThrough} from 'stream'
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
const streamIn = new PassThrough()
engine(
{
processor: remark(),
plugins: [remarkPresetLintRecommended],
filePath: '~/alpha/bravo/charlie.md',
streamIn: streamIn,
out: false
},
done
)
streamIn.write('doc')
setTimeout(() => {
streamIn.end('ument')
}, 100)
function done(error) {
if (error) throw error
}
Yields:
~/alpha/bravo/charlie.md
1:1 warning Missing newline character at end of file final-newline remark-lint
⚠ 1 warning
Stream to write processed files to. This behavior is suppressed if:
out
isfalse
output
is notfalse
- multiple files are processed
- a fatal error occurred while processing a file
- Type:
WritableStream
- Default:
process.stdout
The following example reads readme.md
and writes the serialized document to
readme-two.md
.
Note that this can also be achieved by passing output: 'readme-two.md'
instead
of streamOut
.
import fs from 'node:fs'
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
streamOut: fs.createWriteStream('readme-two.md')
},
done
)
function done(error) {
if (error) throw error
}
Stream to write the report (if any) to.
- Type:
WritableStream
- Default:
process.stderr
The following example uses remark-lint
to lint readme.md
and
writes the report to report.txt
.
import fs from 'node:fs'
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: [remarkPresetLintRecommended],
out: false,
streamErr: fs.createWriteStream('report.txt')
},
done
)
function done(error) {
if (error) throw error
}
Whether to write the processed file to streamOut
.
The default behavior is to only write under some conditions, as specified in
the section on streamOut
, but if out
is false
nothing will
be written to streamOut
.
- Type:
boolean
- Default: depends (see above)
The following example uses remark-lint
to lint readme.md
,
writes the report, and ignores the serialized document.
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkPresetLintRecommended from 'remark-preset-lint-recommended'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: [remarkPresetLintRecommended],
out: false
},
done
)
function done(error) {
if (error) throw error
}
Whether to write successfully processed files and where to.
- When
true
, overwrites the given files - When
false
, does not write to the file system - When pointing to an existing directory, files are written to that directory and keep their original basenames
- When the parent directory of the given path exists and one file is processed, the file is written to the given path
- Otherwise, a fatal error is thrown
Note that if treeIn
is turned on, generated files get the first
defined extensions
.
If treeOut
is turned on, generated files receive the 'json'
extension.
If inspect
is turned on, generated files receive the 'txt'
extension.
- Type:
string
orboolean
- Default:
false
The following example writes all files in src/
with an md
extension,
compiled, to dest/
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['src/'],
extensions: ['md'],
output: 'dest/'
},
done
)
function done(error) {
if (error) throw error
}
Whether to always serialize successful documents.
By default, documents are serialized when it’s detected that a file is to be
written to stdout(4) or the file system.
If files are handled and possibly written somewhere later, set this option to
true
.
- Type:
boolean
- Default:
false
Whether to treat both input and output as a syntax tree.
If given, specifies the default value for both treeIn
and
treeOut
.
- Type:
boolean
, optional - Default:
false
The following example reads tree.json
, then remark-unlink
transforms the syntax tree, and the transformed tree is written to
stdout(4).
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkUnlink from 'remark-unlink'
engine(
{
processor: remark(),
plugins: [remarkUnlink],
files: ['tree.json'],
tree: true
},
done
)
function done(error) {
if (error) throw error
}
Where tree.json
looks as follows:
{
"type": "paragraph",
"children": [{
"type": "link",
"url": "https://example.com",
"children": [{
"type": "text",
"value": "foo"
}]
}]
}
Yields:
{
"type": "paragraph",
"children": [{
"type": "text",
"value": "foo"
}]
}
Treat input as a JSON.stringify
d syntax tree, thus skipping
the parsing phase and passing the syntax tree right
through to transformers.
If extensions
are given, sets the extension of processed files
to the first one.
- Type:
boolean
, optional - Default:
options.tree
The following example reads tree.json
, then remark-unlink
transforms the syntax tree, the tree is serialized, and the resulting document
is written to stdout(4).
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkUnlink from 'remark-unlink'
engine(
{
processor: remark(),
plugins: [remarkUnlink],
files: ['tree.json'],
treeIn: true
},
done
)
function done(error) {
if (error) throw error
}
Where tree.json
looks as follows:
{
"type": "paragraph",
"children": [{
"type": "link",
"url": "https://example.com",
"children": [{
"type": "text",
"value": "foo"
}]
}]
}
Yields:
foo
Skip the compilation phase and serialize the transformed syntax tree to JSON.
Sets the extension of processed files to json
, if possible.
- Type:
boolean
, optional - Default:
options.tree
The following example shows a module which reads and parses doc.md
, then
remark-unlink
transforms the syntax tree, and the tree is
written to stdout(4).
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkUnlink from 'remark-unlink'
engine(
{
processor: remark(),
plugins: [remarkUnlink],
files: ['doc.md'],
treeOut: true
},
done
)
function done(error) {
if (error) throw error
}
Where doc.md
looks as follows:
[foo](https://example.com)
Yields:
{
"type": "paragraph",
"children": [{
"type": "text",
"value": "foo"
}]
}
Skip the compilation phase and output a syntax tree
formatted with unist-util-inspect
.
Sets the extension of processed files to txt
if possible.
Uses ANSI color sequences in the formatted syntax tree if color
is turned on.
- Type:
boolean
, optional - Default:
false
The following example shows a module which reads and parses doc.md
, then
remark-unlink
transforms the syntax tree, the tree is
formatted with unist-util-inspect
, and finally written
to stdout(4).
import {engine} from 'unified-engine'
import {remark} from 'remark'
import remarkUnlink from 'remark-unlink'
engine(
{
processor: remark(),
plugins: [remarkUnlink],
files: ['doc.md'],
inspect: true
},
done
)
function done(error) {
if (error) throw error
}
Where doc.md
looks as follows:
[foo](https://example.com)
Yields:
root[1] (1:1-2:1, 0-27)
└─ paragraph[1] (1:1-1:27, 0-26)
└─ text: "foo" (1:2-1:5, 1-4)
File path of configuration file to load.
If given and detectConfig
is not false
, then:
$rcName
and$rcName.json
are loaded and parsed as JSON$rcName.yml
and$rcName.yaml
are loaded withyaml
$rcName.js
are eitherrequire
d orimport
ed$rcName.cjs
arerequire
d$rcName.mjs
areimport
ed
- Type:
string
, optional
The following example processes readme.md
and allows configuration from
.remarkrc
, .remarkrc.json
, .remarkrc.yml
, .remarkrc.yaml
,
.remarkrc.js
, .remarkrc.cjs
, and .remarkrc.mjs
files.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
rcName: '.remarkrc',
files: ['readme.md']
},
done
)
function done(error) {
if (error) throw error
}
Property at which configuration can live in package.json
files.
If given and detectConfig
is not false
, package.json
files are loaded and parsed as JSON and their $packageField
property is used
for configuration.
- Type:
string
, optional
The following example processes readme.md
, and allows configuration from
remarkConfig
fields in package.json
files.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
packageField: 'remarkConfig',
files: ['readme.md']
},
done
)
function done(error) {
if (error) throw error
}
Whether to search for configuration files ($rcName
,
$rcName.json
, $rcName.cjs
, $rcName.mjs
, $rcName.js
, $rcName.yaml
,
$rcName.yml
, and package.json
with $packageField
).
- Type:
boolean
, optional - Default:
true
ifrcName
orpackageField
are given
The following example processes readme.md
but does not allow configuration
from .remarkrc
or package.json
files, as detectConfig
is false
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
detectConfig: false,
rcName: '.remarkrc',
packageField: 'remarkConfig',
files: ['readme.md']
},
done
)
function done(error) {
if (error) throw error
}
File path to a config file to load, regardless of
detectConfig
or rcName
.
If the file’s extension is yml
or yaml
, it’s loaded as YAML.
If it’s js
, it’s either require
d or import
ed.
If it’s cjs
, it’s require
d.
If it’s mjs
, it’s import
ed.
If the file’s basename is package.json
, the value at
packageField
is used.
Otherwise, the file is parsed as JSON.
- Type:
string
, optional
The following example processes readme.md
and loads configuration from
config.json
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
rcPath: 'config.json',
files: ['readme.md']
},
done
)
function done(error) {
if (error) throw error
}
Configuration for the parser and compiler of the processor.
- Type:
Object
, optional
The following example processes readme.md
and configures the parser and
compiler with position: false
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
settings: {position: false}
},
done
)
function done(error) {
if (error) throw error
}
Name of ignore file to load.
If given and detectIgnore
is not false
, $ignoreName
files
are loaded.
The patterns in found ignore file are resolved based on the file’s directory.
If we had an ignore file folder/.remarkignore
, with the value: index.txt
,
and our file system looked as follows:
folder/.remarkignore
folder/index.txt
index.txt
Then folder/index.txt
would be ignored but index.txt
would not be.
- Type:
string
, optional
The following example processes files in the current working directory with an
md
extension, and is configured to ignore file paths from the closest
.remarkignore
file.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
ignoreName: '.remarkignore'
},
done
)
function done(error) {
if (error) throw error
}
Whether to search for ignore files ($ignoreName
).
- Type:
boolean
, optional - Default:
true
ifignoreName
is given
The following example processes files in the current working directory with an
md
extension but does not ignore file paths from the closest
.remarkignore
file, because detectIgnore
is false
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
ignoreName: '.remarkignore',
detectIgnore: false
},
done
)
function done(error) {
if (error) throw error
}
File path to ignore file to load, regardless of
detectIgnore
or ignoreName
.
The patterns in the ignore file are resolved based the setting of
ignorePathResolveFrom
, which when 'dir'
(default) means to resolve from the
ignore file’s directory, or when 'cwd'
means to resolve from the current
working directory.
If we had an ignore file folder/ignore
, with the value: index.txt
, and our
file system looked as follows:
folder/ignore
folder/index.txt
index.txt
Then folder/index.txt
would be ignored but index.txt
would not be.
- Type:
string
, optional
The following example processes files in the current working directory with an
md
extension and ignores file paths specified in .gitignore
.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
ignorePath: '.gitignore'
},
done
)
function done(error) {
if (error) throw error
}
Enum of either dir
(default) or cwd
, which defines whether the patterns
found in the ignore file at ignorePath
are resolved from that
file’s directory or the current working directory.
If we had an ignore file config/ignore
, with the value: index.txt
, and our
file system looked as follows:
config/ignore
folder/index.txt
index.txt
Normally, no index.txt
files would be ignored, but when given
ignorePathResolveFrom: 'cwd'
, both would be.
- Type:
string
, optional
The following example processes files in the current working directory with an
md
extension and takes a reusable configuration file from a dependency.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
ignorePath: 'node_modules/my-config/my-ignore',
ignorePathResolveFrom: 'cwd'
},
done
)
function done(error) {
if (error) throw error
}
Additional patterns to use to ignore files.
- Type:
Array<string>
, optional
The following example processes files in the current working directory with an
md
extension, except for readme.md
:
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
ignorePatterns: ['readme.md']
},
done
)
function done(error) {
if (error) throw error
}
Ignore files that do not have an associated detected configuration file.
- Type:
boolean
, default:false
👉 Note: this option cannot be turned on in combination with
rcPath
ordetectConfig: false
. Additionally, at least one ofrcName
orpackageField
must be defined.
The following example processes files in the current working directory with an
md
extension, but only if there is an explicit .remarkrc
config file near
(upwards) to them:
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['.'],
extensions: ['md'],
rcName: '.remarkrc'
},
done
)
function done(error) {
if (error) throw error
}
Skip given files
which are ignored by ignore files, instead
of warning about them.
- Type:
boolean
, default:false
Plugins to load and attach with options to the processor for every processed file.
- Type:
Object
,Array
, optional. Same format asplugins
in config files
The following example processes readme.md
and loads the
remark-preset-lint-recommended
plugin.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: ['remark-preset-lint-recommended']
},
done
)
function done(error) {
if (error) throw error
}
Allow plugins to be specified without a prefix.
For example, if a plugin is specified with a name of foo
, and pluginPrefix
is bar
, both bar-foo
and foo
are checked in node_modules/
directories.
Note: If a prefix is specified, plugins with that prefix are preferred over plugins without that prefix.
- Type:
string
, optional
The following example processes readme.md
and loads the
preset-lint-recommended
plugin.
Because pluginPrefix
is given, this resolves to
remark-preset-lint-recommended
from node_modules/
if available.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
pluginPrefix: 'remark',
plugins: ['preset-lint-recommended']
},
done
)
function done(error) {
if (error) throw error
}
Optional object with plugins
and/or settings
to use if no config file is
supplied by the user.
- Type:
Object
, optional
The following example processes readme.md
. If package.json
exists, that
config is used, otherwise the configuration at defaultConfig
is used.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
packageField: 'remarkConfig',
defaultConfig: {settings: {commonmark: true}}
},
done
)
function done(error) {
if (error) throw error
}
Where package.json
contains:
{
"name": "foo",
"private": true,
"remarkConfig": {
"settings": {
"footnotes": true
}
}
}
Want configuration files in a different format? Pass a configTransform
function.
It will be called with the parsed value from configuration files and the file
path to the found file, and should return a config object (with plugins
and/or
settings
).
- Type:
Function
, optional
The following example processes readme.md
and loads options from custom
(from a package.json
).
configTransform
is called with those options and transforms it to
configuration unified-engine
understands.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
packageField: 'custom',
configTransform: configTransform
},
done
)
function done(error) {
if (error) throw error
}
function configTransform(config) {
return {settings: (config || {}).options}
}
Where package.json
contains:
{
"name": "foo",
"private": true,
"custom": {
"options": {
"position": false
}
}
}
Reporter to use.
Reporters must be loadable from the cwd
(such as by installing them
from that directory with npm).
Reporters must be VFile reporters.
- Type:
string
orfunction
, optional, default:import('vfile-reporter').reporter
. Ifstring
, the reporter’s prefix (vfile-reporter-
) can be omitted, so ifjson
is given,vfile-reporter-json
is loaded if it exists, and otherwise thejson
module itself is loaded (which in this example will not work as it’s not a reporter)
The quiet
, silent
, and color
options may not
work with the used reporter.
The following example processes all HTML files in the current directory with
rehype, configures the processor with .rehyperc
files, and prints a report in
json, with reporter options.
import {engine} from 'unified-engine'
import {rehype} from 'rehype'
engine(
{
processor: rehype(),
files: ['.'],
extensions: ['html'],
rcName: '.rehyperc',
reporter: 'json',
reporterOptions: {pretty: true}
},
done
)
function done(error) {
if (error) throw error
}
Options to pass to the reporter.
- Type:
Object
, optional
The quiet
, silent
, and color
options are
preferred over reporterOptions
(and passed too).
See options.reporter
for an example.
Whether to report or inspect with ANSI color sequences.
- Type:
boolean
, default:false
This option may not work with the used reporter.
The following example processes readme.md
and uses color in the report.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
color: true,
out: false
},
done
)
function done(error) {
if (error) throw error
}
Yields:
�[4m�[32mreadme.md�[39m�[24m: no issues found
Show only fatal errors in the report.
- Type:
boolean
, default:false
This option may not work with the used reporter.
The following example uses remark-lint
to lint readme.md
but
does not report any warnings or success messages, only fatal errors, if they
occur.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: ['remark-preset-lint-recommended'],
silent: true
},
done
)
function done(error) {
if (error) throw error
}
Whether to ignore processed files without any messages in the report. The default behavior is to show a success message.
- Type:
boolean
, default:options.silent
This option may not work with the used reporter.
The following example uses remark-lint
to lint readme.md
.
Nothing is reported if the file processed successfully.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: ['remark-preset-lint-recommended'],
quiet: true
},
done
)
function done(error) {
if (error) throw error
}
Count warnings as errors when calculating if the process succeeded.
- Type:
boolean
, default:false
The following example uses remark-lint
to lint readme.md
and
logs the exit code.
Normally, only errors turn the code
to 1
, but in frail
mode lint warnings
result in the same.
import {engine} from 'unified-engine'
import {remark} from 'remark'
engine(
{
processor: remark(),
files: ['readme.md'],
plugins: ['remark-preset-lint-recommended'],
frail: true
},
done
)
function done(error, code) {
process.exit(error ? 1 : code)
}