{"id":13739365,"url":"https://github.com/unifiedjs/unified-engine","last_synced_at":"2025-05-16T03:02:19.470Z","repository":{"id":9069461,"uuid":"60716014","full_name":"unifiedjs/unified-engine","owner":"unifiedjs","description":"Engine to process multiple files with unified","archived":false,"fork":false,"pushed_at":"2025-04-09T12:25:08.000Z","size":910,"stargazers_count":58,"open_issues_count":4,"forks_count":23,"subscribers_count":9,"default_branch":"main","last_synced_at":"2025-05-07T06:31:12.305Z","etag":null,"topics":["engine","unified","unifiedjs","vfile"],"latest_commit_sha":null,"homepage":"https://unifiedjs.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unifiedjs.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"license","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"unifiedjs","open_collective":"unified","thanks_dev":"u/gh/unifiedjs"}},"created_at":"2016-06-08T17:16:23.000Z","updated_at":"2025-05-02T16:55:05.000Z","dependencies_parsed_at":"2023-01-13T15:09:05.181Z","dependency_job_id":"4d963d8a-6c08-4604-9e61-42228dc0b552","html_url":"https://github.com/unifiedjs/unified-engine","commit_stats":{"total_commits":282,"total_committers":11,"mean_commits":"25.636363636363637","dds":"0.046099290780141855","last_synced_commit":"0266c1abe3c54b736bae3f73b9f235083b466736"},"previous_names":[],"tags_count":45,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unifiedjs%2Funified-engine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unifiedjs%2Funified-engine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unifiedjs%2Funified-engine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unifiedjs%2Funified-engine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unifiedjs","download_url":"https://codeload.github.com/unifiedjs/unified-engine/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254453862,"owners_count":22073668,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["engine","unified","unifiedjs","vfile"],"created_at":"2024-08-03T04:00:33.177Z","updated_at":"2025-05-16T03:02:19.389Z","avatar_url":"https://github.com/unifiedjs.png","language":"JavaScript","readme":"# unified-engine\n\n[![Build][build-badge]][build]\n[![Coverage][coverage-badge]][coverage]\n[![Downloads][downloads-badge]][downloads]\n[![Sponsors][sponsors-badge]][collective]\n[![Backers][backers-badge]][collective]\n[![Chat][chat-badge]][chat]\n\n**[unified][]** engine to process multiple files, lettings users\n[configure][config-files] from the file system.\n\n## Contents\n\n* [What is this?](#what-is-this)\n* [When should I use this?](#when-should-i-use-this)\n* [Install](#install)\n* [Use](#use)\n* [API](#api)\n  * [`engine(options, callback?)`](#engineoptions-callback)\n  * [`Configuration`](#configuration)\n  * [`Completer`](#completer)\n  * [`Callback`](#callback)\n  * [`ConfigResult`](#configresult)\n  * [`ConfigTransform`](#configtransform)\n  * [`ContextWithCode`](#contextwithcode)\n  * [`Context`](#context)\n  * [`FileSet`](#fileset)\n  * [`Options`](#options)\n  * [`Preset`](#preset)\n  * [`ResolveFrom`](#resolvefrom)\n  * [`VFileReporter`](#vfilereporter)\n* [Config files](#config-files)\n  * [Explicit configuration](#explicit-configuration)\n  * [Implicit configuration](#implicit-configuration)\n  * [Examples](#examples)\n* [Ignore files](#ignore-files)\n  * [Explicit ignoring](#explicit-ignoring)\n  * [Implicit ignoring](#implicit-ignoring)\n  * [Extra ignoring](#extra-ignoring)\n  * [Ignoring](#ignoring)\n  * [Examples](#examples-1)\n* [Plugins](#plugins)\n* [Examples](#examples-2)\n  * [`options.alwaysStringify`](#optionsalwaysstringify)\n  * [`options.configTransform`](#optionsconfigtransform)\n  * [`options.defaultConfig`](#optionsdefaultconfig)\n  * [`options.detectConfig`](#optionsdetectconfig)\n  * [`options.detectIgnore`](#optionsdetectignore)\n  * [`options.extensions`](#optionsextensions)\n  * [`options.filePath`](#optionsfilepath)\n  * [`options.files`](#optionsfiles)\n  * [`options.frail`](#optionsfrail)\n  * [`options.ignoreName`](#optionsignorename)\n  * [`options.ignorePath`](#optionsignorepath)\n  * [`options.ignorePathResolveFrom`](#optionsignorepathresolvefrom)\n  * [`options.ignorePatterns`](#optionsignorepatterns)\n  * [`options.ignoreUnconfigured`](#optionsignoreunconfigured)\n  * [`options.inspect`](#optionsinspect)\n  * [`options.out`](#optionsout)\n  * [`options.output`](#optionsoutput)\n  * [`options.packageField`](#optionspackagefield)\n  * [`options.pluginPrefix`](#optionspluginprefix)\n  * [`options.plugins`](#optionsplugins)\n  * [`options.processor`](#optionsprocessor)\n  * [`options.quiet`](#optionsquiet)\n  * [`options.rcName`](#optionsrcname)\n  * [`options.rcPath`](#optionsrcpath)\n  * [`options.reporter` and `options.reporterOptions`](#optionsreporter-and-optionsreporteroptions)\n  * [`options.settings`](#optionssettings)\n  * [`options.silent`](#optionssilent)\n  * [`options.streamError`](#optionsstreamerror)\n  * [`options.streamIn`](#optionsstreamin)\n  * [`options.streamOut`](#optionsstreamout)\n  * [`options.tree`](#optionstree)\n  * [`options.treeIn`](#optionstreein)\n  * [`options.treeOut`](#optionstreeout)\n* [Types](#types)\n* [Compatibility](#compatibility)\n* [Security](#security)\n* [Contribute](#contribute)\n* [License](#license)\n\n## What is this?\n\nThis package is the engine.\nIt’s what you use underneath when you use [`remark-cli`][remark-cli] or a\nlanguage server.\nCompared to unified, this deals with multiple files, often from the file\nsystem, and with [configuration files][config-files] and\n[ignore files][ignore-files].\n\n## When should I use this?\n\nYou typically use something that wraps this, such as:\n\n* [`unified-args`][unified-args]\n  — create CLIs\n* [`unified-engine-gulp`][unified-engine-gulp]\n  — create Gulp plugins\n* [`unified-language-server`][unified-language-server]\n  — create language servers\n\nYou can use this to make such things.\n\n## Install\n\nThis package is [ESM only][esm].\nIn Node.js (version 16+), install with [npm][]:\n\n```sh\nnpm install unified-engine\n```\n\n## Use\n\nThe following example processes all files in the current folder with a\nmarkdown extension with **[remark][]**, allows [configuration][config-files]\nfrom `.remarkrc` and `package.json` files, ignoring files from `.remarkignore`\nfiles, and more.\n\n```js\n/**\n * @import {Callback} from 'unified-engine'\n */\n\nimport process from 'node:process'\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    color: true,\n    extensions: ['md', 'markdown', 'mkd', 'mkdn', 'mkdown'],\n    files: ['.'],\n    ignoreName: '.remarkignore',\n    packageField: 'remarkConfig',\n    pluginPrefix: 'remark',\n    processor: remark,\n    rcName: '.remarkrc'\n  },\n  done\n)\n\n/** @type {Callback} */\nfunction done(error, code) {\n  if (error) throw error\n  process.exitCode = code\n}\n```\n\n## API\n\nThis package exports the identifiers [`Configuration`][api-configuration] and\n[`engine`][api-engine].\nThere is no default export.\n\n### `engine(options, callback?)`\n\nProcess.\n\n###### Parameters\n\n* `options` ([`Options`][api-options], required)\n  — configuration\n* `callback` ([`Callback`][api-callback], optional)\n  — callback\n\n###### Returns\n\nIf a callback is given, nothing (`undefined`).\nOtherwise [`Promise\u003cContextWithCode\u003e`][api-context-with-code].\n\n### `Configuration`\n\nInternal class to load configuration files.\n\nExposed to build more complex integrations.\n\n###### Parameters\n\n* `options` (subset of [`Options`][api-options], required)\n  — configuration (`cwd` is required)\n\n###### Fields\n\n* `load(string, (Error?[, ConfigResult?]): undefined): undefined`\n  — get the config for a file\n\n### `Completer`\n\nCompleter (TypeScript type).\n\n###### Type\n\n```ts\ntype Completer = (CompleterCallback | CompleterRegular) \u0026 {\n    pluginId?: string | symbol | undefined\n}\n\ntype CompleterCallback = (set: FileSet, next: CompleterCallbackNext) =\u003e undefined\ntype CompleterCallbackNext = (error?: Error | null | undefined) =\u003e undefined\ntype CompleterRegular = (set: FileSet) =\u003e Promise\u003cundefined\u003e | undefined\n```\n\n### `Callback`\n\nCallback called when done (TypeScript type).\n\nCalled with a fatal error if things went horribly wrong (probably due to\nincorrect configuration), or a status code and the processing context.\n\n###### Parameters\n\n* `error` (`Error`, optional)\n  — error\n* `code` (`0` or `1`, optional)\n  — exit code, `0` if successful or `1` if unsuccessful\n* `context` ([`Context`][api-context], optional)\n  — processing context\n\n###### Returns\n\nNothing (`undefined`).\n\n### `ConfigResult`\n\nResolved configuration from [`Configuration`][api-configuration] (TypeScript\ntype).\n\n###### Fields\n\n* `filePath` (`string`)\n  — file path of found configuration\n* `plugins` (`Array\u003cPluginTuple\u003e` from `unified`)\n  — resolved plugins\n* `settings` ([`Settings` from `unified`][unified-settings])\n  — resolved settings\n\n### `ConfigTransform`\n\nTransform arbitrary configs to our format (TypeScript type).\n\n###### Parameters\n\n* `config` (`unknown`)\n  — arbitrary config\n* `filePath` (`string`)\n  — file path of config file\n\n###### Returns\n\nOur config format ([`Preset`][api-preset]).\n\n### `ContextWithCode`\n\nProcessing context with code (TypeScript type).\n\n###### Extends\n\n* [`Context`][api-context]\n\n###### Fields\n\n* `code` (`0` or `1`)\n  — exit code,\n  `0` if successful or `1` if unsuccessful\n\n### `Context`\n\nProcessing context (TypeScript type).\n\n###### Fields\n\n* `fileSet` ([`FileSet`][api-file-set])\n  — internally used info\n* `files` ([`Array\u003cVFile\u003e`][vfile])\n  — processed files\n\n### `FileSet`\n\nA FileSet is created to process multiple files through unified processors\n(TypeScript type).\n\nThis set, containing all files, is exposed to plugins as the second parameter.\n\n###### Parameters\n\nNone.\n\n###### Fields\n\n* `valueOf(): Array\u003cVFile\u003e`\n  — get files in a set\n* `use(completer: Completer): this`\n  — add middleware to be called when done (see: [`Completer`][api-completer])\n* `add(file: VFile | string): this`\n  — add a file; the given file is processed like other files with a few\n  differences: it’s ignored when their file path is already added, never\n  written to the file system or `streamOut`, and not included in the  report\n\n### `Options`\n\nConfiguration (TypeScript type).\n\n\u003e 👉 **Note**: `options.processor` is required.\n\n###### Fields\n\n* `alwaysStringify` (`boolean`, default: `false`)\n  — whether to always serialize successfully processed files\n* `color` (`boolean`, default: `false`)\n  — whether to report with ANSI color sequences; given to the reporter\n* `configTransform` ([`ConfigTransform`][api-config-transform], optional)\n  — transform config files from a different schema\n* `cwd` (`URL` or `string`, default: `process.cwd()`)\n  — folder to search files in, load plugins from, and more\n* `defaultConfig` ([`Preset`][api-preset], optional)\n  — default configuration to use if no config file is given or found\n* `detectConfig` (`boolean`, default: `true` if `options.packageField` or\n  `options.rcName`)\n  — whether to search for configuration files\n* `detectIgnore` (`boolean`, default: `true` if `options.ignoreName`)\n  — whether to search for ignore files\n* `extensions` (`Array\u003cstring\u003e`, optional)\n  — search for files with these extensions, when folders are passed;\n  generated files are also given the first extension if `treeIn` is on and\n  `output` is on or points to a folder\n* `filePath` (`URL` or `string`, optional)\n  — file path to process the given file on `streamIn` as\n* `files` (`Array\u003cURL | VFile | string\u003e`, optional)\n  — paths or [globs][node-glob] to files and folder, or virtual files, to\n  process\n* `frail` (`boolean`, default: `false`)\n  — call back with an unsuccessful (`1`) code on warnings as well as errors\n* `ignoreName` (`string`, optional)\n  — name of ignore files to load\n* `ignorePath` (`URL` or `string`, optional)\n  — filepath to an ignore file to load\n* `ignorePathResolveFrom` ([`ResolveFrom`][api-resolve-from], default:\n  `'dir'`)\n  — resolve patterns in `ignorePath` from the current working folder\n  (`'cwd'`) or the ignore file’s folder (`'dir'`)\n* `ignorePatterns` (optional)\n  — patterns to ignore in addition to ignore files\n* `ignoreUnconfigured` (`boolean`, default: `false`)\n  — ignore files that do not have an associated detected configuration file;\n  either `rcName` or `packageField` must be defined too; cannot be combined\n  with `rcPath` or `detectConfig: false`\n* `inspect` (`boolean`, default: `false`)\n  — whether to output a formatted syntax tree for debugging\n* `out` (`boolean`, default: `false`)\n  — whether to write the processed file to `streamOut`\n* `output` (`URL`, `boolean` or `string`, default: `false`)\n  — whether to write successfully processed files, and where to; when `true`,\n  overwrites the given files, when `false`, does not write to the file system;\n  when pointing to an existing folder, files are written to that folder and\n  keep their original basenames; when the parent folder of the given path\n  exists and one file is processed, the file is written to the given path\n* `packageField` (`string`, optional)\n  — field where configuration can be found in `package.json` files\n* `pluginPrefix` (`string`, optional)\n  — prefix to use when searching for plugins\n* `plugins` ([`Preset['plugins']`][api-preset], optional)\n  — plugins to use\n* `processor` ([`Processor`][unified-processor], **required**)\n  — unified processor to transform files\n* `quiet` (`boolean`, default: `false`)\n  — do not report successful files; given to the reporter\n* `rcName` (`string`, optional)\n  — name of configuration files to load\n* `rcPath` (`URL` or `string`, optional)\n  — filepath to a configuration file to load\n* `reporter` ([`VFileReporter`][api-vfile-reporter] or `string`, default:\n  `vfile-reporter`)\n  — reporter to use; if a `string` is passed, it’s loaded from `cwd`, and\n  `'vfile-reporter-'` can be omitted\n* `reporterOptions` ([`Options`][vfile-reporter-options] from\n  `vfile-reporter`, optional)\n  — config to pass to the used reporter\n* `settings` ([`Settings`][unified-settings] from `unified`, optional)\n  — configuration for the parser and compiler of the processor\n* `silent` (`boolean`, default: `false`)\n  — report only fatal errors; given to the reporter\n* `silentlyIgnore` (`boolean`, default: `false`)\n  — skip given files if they are ignored\n* `streamError` ([`WritableStream`][node-writable-stream] from Node.js,\n  default: `process.stderr`)\n  — stream to write the report (if any) to\n* `streamIn` ([`ReadableStream`][node-readable-stream] from Node.js,\n  default: `process.stdin`)\n  — stream to read from if no files are found or given\n* `streamOut` ([`WritableStream`][node-writable-stream] from Node.js,\n  default: `process.stdout`)\n  — stream to write processed files to, nothing is streamed if either `out`\n  is `false`, `output` is not `false`, multiple files are processed, or a\n  fatal error occurred while processing a file\n* `tree` (`boolean`, default: `false`)\n  — whether to treat both input and output as a syntax tree\n* `treeIn` (`boolean`, default: `options.tree`)\n  — whether to treat input as a syntax tree\n* `treeOut` (`boolean`, default: `options.tree`)\n  — whether to output as a syntax tree\n* `verbose` (`boolean`, default: `false`)\n  — report extra info; given to the reporter\n\n### `Preset`\n\nSharable configuration, with support for specifiers (TypeScript type).\n\nSpecifiers should *not* be used in actual presets (because they can’t be\nused by regular unified), but they can be used in config files locally,\nas those are only for the engine.\n\nThey can contain plugins and settings.\n\n###### Type\n\n```ts\nimport type {\n  Plugin as UnifiedPlugin,\n  PluginTuple as UnifiedPluginTuple,\n  Preset as UnifiedPreset,\n  Settings\n} from 'unified'\n\ntype Preset = {\n  plugins?: PluggableList | PluggableMap | undefined\n  settings?: Settings | undefined\n}\n\ntype Pluggable = Plugin | PluginTuple | UnifiedPreset\ntype PluggableList = Array\u003cPluggable\u003e\ntype PluggableMap = Record\u003cstring, unknown\u003e\ntype Plugin = UnifiedPlugin | string\ntype PluginTupleSupportingSpecifiers =\n  | [plugin: string, ...parameters: Array\u003cunknown\u003e]\n  | UnifiedPluginTuple\n```\n\n### `ResolveFrom`\n\nHow to resolve (TypeScript type).\n\n###### Type\n\n```ts\ntype ResolveFrom = 'cwd' | 'dir';\n```\n\n### `VFileReporter`\n\nTransform arbitrary configs to our format (TypeScript type).\n\nThis is essentially the interface of [`vfile-reporter`][vfile-reporter], with\nadded support for unknown fields in options and async support.\n\n###### Parameters\n\n* `files` ([`Array\u003cVFile\u003e`][vfile])\n  — files\n* `options` ([`Options`][vfile-reporter-options] from `vfile-reporter`,\n  optional)\n  — configuration\n\n###### Returns\n\nReport (`Promise\u003cstring\u003e` or `string`).\n\n## Config files\n\n`unified-engine` accepts configuration through options and through\nconfiguration files (*rc files*).\n\n### Explicit configuration\n\nOne configuration file can be given through `options.rcPath`, this is loaded\nregardless of `options.detectConfig` and `options.rcName`.\n\n### Implicit configuration\n\nOtherwise, configuration files are detected if `options.detectConfig` is turned\non, depending on the following options:\n\n* if `options.rcName` is given, `$rcName` (JSON), `$rcName.js` (CommonJS or\n  ESM depending on the `type` field of the closest `package.json`),\n  `$rcName.cjs` (CommonJS), `$rcName.mjs` (ESM), `$rcName.yml` (YAML),\n  and `$rcName.yaml` (YAML) are loaded\n* if `options.packageField` is given, `package.json` (JSON) files are loaded\n  and the configuration at their `$packageField` field is used\n\nThe first file that is searched for in a folder is used as the configuration.\nIf no file is found, the parent folder is searched, and so on.\n\nThe schema (type) of rc files is [`Preset`][api-preset].\n\n### Examples\n\nAn example **rc** file could look as follows:\n\n```json\n{\n  \"plugins\": [\n    \"remark-inline-links\",\n    \"remark-lint-recommended\"\n  ],\n  \"settings\": {\n    \"bullet\": \"*\",\n    \"ruleRepetition\": 3,\n    \"fences\": true\n  }\n}\n```\n\nAnother example, **rc.js**, could look as follows:\n\n```js\nexports.plugins = [\n  './script/natural-language.js',\n  'remark-lint-recommended',\n  'remark-license'\n]\n\nexports.settings = {bullet: '*'}\n```\n\nWhen using ESM (ECMAScript modules), **rc.mjs** could look as folows:\n\n```js\nexport default {\n  plugins: [\n    './script/natural-language.js',\n    'remark-lint-recommended',\n    'remark-license'\n  ],\n  settings: {bullet: '*'}\n}\n```\n\nAnother example, **rc.yaml**, could look as follows:\n\n```js\nplugins:\n  - 'rehype-document'\n  - 'rehype-preset-minify'\nsettings:\n  preferUnquoted: true\n  quote: \"'\"\n  quoteSmart: true\n  verbose: true\n```\n\n## Ignore files\n\n`unified-engine` accepts patterns to ignore when searching for files to process\nthrough ignore files.\n\n### Explicit ignoring\n\nOne ignore file can be given through `options.ignorePath`, this is loaded\nregardless of `options.detectIgnore` and `options.ignoreName`.\n\n### Implicit ignoring\n\nOtherwise, ignore files are detected if `options.detectIgnore` is turned on and\n`options.ignoreName` is given.\n\nThe first file named `$ignoreName` in the parent folder of a checked file is\nused.\nOr, if no file is found, the parent folder if searched, and so on.\n\n### Extra ignoring\n\nIn addition to explicit and implicit ignore files, other patterns can be given\nwith `options.ignorePatterns`.\nThe format of each pattern in `ignorePatterns` is the same as a line in an\nignore file.\nPatterns and files are resolved based on the current working folder.\n\nIt is also possible to ignore files that do not have an associated detected\nconfiguration file by turning on `options.ignoreUnconfigured`.\n\n### Ignoring\n\nIgnoring is used when searching for files in folders.\nIf paths (including those expanded from [globs][node-glob]) are passed in that\nare ignored, an error is thrown.\nThese files can be silently ignored by turning on `options.silentlyIgnore`.\n\nNormally, files are ignored based on the path of the found ignore file and the\npatterns inside it.\nPatterns passed with `options.ignorePatterns` are resolved based on the current\nworking directory.\n\nPatterns in an explicit ignore file passed in with `options.ignorePath` can be\nresolved from the current working directory instead, by setting\n`options.ignorePathResolveFrom` to `'cwd'` instead of `'dir'` (default).\n\nIf paths or globs to folders are given to the engine, they will be searched\nfor matching files, but `node_modules` are normally not searched.\nPass paths (or globs) to the `node_modules` you want to include in\n`options.files` to search them.\n\nThe format for ignore files is the same as [`.gitignore`][gitignore], so it’s\npossible to pass a `.gitignore` in as `options.ignorePath`.\n\n[`node-ignore`][node-ignore] is used under the hood, see its documentation\nfor more information.\n\n### Examples\n\nAn example **ignore** file could look as follows:\n\n```ini\n# Ignore files in `.github`.\n.github/\n\n# Bower.\nbower_components/\n# Duo dependencies.\ncomponents/\n\n# Fixtures.\ntest/{input,tree}/\n```\n\nIf we had an ignore file `folder/.remarkignore`, with the value: `index.txt`,\nand our file system looked as follows:\n\n```text\nfolder/.remarkignore\nfolder/index.txt\nindex.txt\n```\n\nThen `folder/index.txt` would be ignored but `index.txt` would not be.\n\n## Plugins\n\nNormally, **unified** plugins receive a single `options` argument upon attaching\n(an `Object` users can provide to configure the plugin).\n\nIf a plugin is attached by **unified-engine**, a second argument is given:\n[`FileSet`][api-file-set].\n\n## Examples\n\n`unified-engine` can be configured extensively by engine authors.\n\n### `options.alwaysStringify`\n\nThis example shows how you can use `options.alwaysStringify` when you don’t\nwant the engine to write to the file system, but still want to get the compiled\nresults.\nOne example that does this is `unified-engine-gulp`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\nimport {VFile} from 'vfile'\n\nconst file = new VFile({path: 'example.md', value: '_hi_'})\n\nengine(\n  {alwaysStringify: true, files: [file], processor: remark},\n  function (error, code, context) {\n    if (error) throw error\n    console.log(context?.files.map((d) =\u003e String(d)))\n  }\n)\n```\n\nYields:\n\n```text\nexample.md: no issues found\n```\n\n```js\n[ '*hi*\\n' ]\n```\n\n### `options.configTransform`\n\nTo support custom rc files, that have a different format than what the engine\nsupports, pass as [`ConfigTransform`][api-config-transform].\n\nThis example processes `readme.md` and loads options from `custom` (from a\n`package.json`).\n`configTransform` is called with those options and transforms it to\nconfiguration `unified-engine` understands.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    configTransform,\n    files: ['readme.md'],\n    packageField: 'custom',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n\nfunction configTransform(config) {\n  return {settings: (config || {}).options}\n}\n```\n\nWhere `package.json` contains:\n\n```json\n{\n  \"name\": \"foo\",\n  \"private\": true,\n  \"custom\": {\n    \"options\": {\n      \"bullet\": \"+\"\n    }\n  }\n}\n```\n\n### `options.defaultConfig`\n\nThis example processes `readme.md`.\nIf `package.json` exists, that config is used, otherwise the configuration at\n`defaultConfig` is used.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    defaultConfig: {settings: {bullet: '+'}},\n    files: ['readme.md'],\n    packageField: 'remarkConfig',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nWhere `package.json` contains:\n\n```json\n{\n  \"name\": \"foo\",\n  \"private\": true,\n  \"remarkConfig\": {\n    \"settings\": {\n      \"bullet\": \"-\"\n    }\n  }\n}\n```\n\n### `options.detectConfig`\n\nThis example processes `readme.md` but does **not** allow configuration from\n`.remarkrc` or `package.json` files, as `detectConfig` is `false`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    detectConfig: false,\n    files: ['readme.md'],\n    processor: remark(),\n    packageField: 'remarkConfig',\n    rcName: '.remarkrc'\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.detectIgnore`\n\nThis example processes files in the current working directory with an `md`\nextension but does **not** ignore file paths from the closest `.remarkignore`\nfile, because `detectIgnore` is `false`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    detectIgnore: false,\n    extensions: ['md'],\n    files: ['.'],\n    ignoreName: '.remarkignore',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.extensions`\n\nThis example reformats all files with `md`, `markdown`, and `mkd`\nextensions in the current folder.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md', 'mkd', 'markdown'],\n    files: ['.'],\n    output: true,\n    processor: remark\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.filePath`\n\nThis example shows that `streamIn` is named as `filePath`:\n\n```js\nimport {PassThrough} from 'node:stream'\nimport {remark} from 'remark'\nimport remarkPresetLintRecommended from 'remark-preset-lint-recommended'\nimport {engine} from 'unified-engine'\n\nconst streamIn = new PassThrough()\n\nstreamIn.write('doc')\n\nsetImmediate(function () {\n  streamIn.end('ument')\n})\n\nengine(\n  {\n    filePath: '~/alpha/bravo/charlie.md',\n    out: false,\n    plugins: [remarkPresetLintRecommended],\n    processor: remark(),\n    streamIn\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nYields:\n\n```text\n~/alpha/bravo/charlie.md\n  1:1  warning  Missing newline character at end of file  final-newline  remark-lint\n\n⚠ 1 warning\n```\n\n### `options.files`\n\nThis example processes `LICENSE` and all files with an `md` extension in `doc`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['LICENSE', 'doc/'],\n    processor: remark\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.frail`\n\nThis example uses [`remark-lint`][remark-lint] to lint `readme.md` and exits\nwith the given exit code.\nNormally, only errors turn the `code` to `1`, but in `frail` mode lint warnings\nresult in the same.\n\n```js\nimport process from 'node:process'\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    frail: true,\n    plugins: ['remark-preset-lint-recommended'],\n    processor: remark()\n  },\n  function (error, code) {\n    process.exitCode = error ? 1 : code\n  }\n)\n```\n\n### `options.ignoreName`\n\nThis example processes files in the current working directory with an `md`\nextension, and is configured to ignore file paths from the closest\n`.remarkignore` file.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['.'],\n    ignoreName: '.remarkignore',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.ignorePath`\n\nThis example processes files in the current working directory with an `md`\nextension and ignores file paths specified in `.gitignore`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['.'],\n    ignorePath: '.gitignore',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.ignorePathResolveFrom`\n\nThis example processes files in the current working directory with an `md`\nextension and takes a reusable configuration file from a dependency.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['.'],\n    ignorePath: 'node_modules/my-config/my-ignore',\n    ignorePathResolveFrom: 'cwd',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.ignorePatterns`\n\nThis example processes files in the current working directory with an `md`\nextension, except for `readme.md`:\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['.'],\n    ignorePatterns: ['readme.md'],\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.ignoreUnconfigured`\n\nThis example processes files in the current working directory with an\n`md` extension, but only if there is an explicit `.remarkrc` config file near\n(upwards) to them:\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['.'],\n    ignoreUnconfigured: true,\n    processor: remark(),\n    rcName: '.remarkrc'\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.inspect`\n\nThis example shows a module which reads and parses `doc.md`, then\n[`remark-unlink`][remark-unlink] transforms the syntax tree, the tree is\nformatted with [`unist-util-inspect`][unist-util-inspect], and finally written\nto **stdout**(4).\n\n```js\nimport {remark} from 'remark'\nimport remarkUnlink from 'remark-unlink'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['doc.md'],\n    inspect: true,\n    plugins: [remarkUnlink],\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nWhere `doc.md` looks as follows:\n\n```markdown\n[foo](https://example.com)\n```\n\nYields:\n\n```text\nroot[1] (1:1-2:1, 0-27)\n└─ paragraph[1] (1:1-1:27, 0-26)\n   └─ text: \"foo\" (1:2-1:5, 1-4)\n```\n\n### `options.out`\n\nThis example uses [`remark-lint`][remark-lint] to lint `readme.md`, writes the\nreport, and ignores the serialized document.\n\n```js\nimport {remark} from 'remark'\nimport remarkPresetLintRecommended from 'remark-preset-lint-recommended'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    out: false,\n    plugins: [remarkPresetLintRecommended],\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.output`\n\nThis example writes all files in `src/` with an `md` extension compiled to\n`dest/`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['md'],\n    files: ['src/'],\n    output: 'dest/',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.packageField`\n\nThis example processes `readme.md`, and allows configuration from\n`remarkConfig` fields in `package.json` files.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    packageField: 'remarkConfig',\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.pluginPrefix`\n\nThis example processes `readme.md` and loads the\n`preset-lint-recommended` plugin.\nBecause `pluginPrefix` is given, this resolves to\n[`remark-preset-lint-recommended`][remark-preset-lint-recommended] (from\n`node_modules/`) if available.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    pluginPrefix: 'remark',\n    plugins: ['preset-lint-recommended'],\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.plugins`\n\nThis example processes `readme.md` and loads the\n[`remark-preset-lint-recommended`][remark-preset-lint-recommended]\npreset.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    plugins: ['remark-preset-lint-recommended'],\n    processor: remark()\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.processor`\n\nThis example reformats **stdin**(4) using [remark][], writes the report\nto **stderr**(4), and formatted document to **stdout**(4).\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine({processor: remark}, function (error) {\n  if (error) throw error\n})\n```\n\n### `options.quiet`\n\nThis example uses [`remark-lint`][remark-lint] to lint `readme.md`.\nNothing is reported if the file processed successfully.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    plugins: ['remark-preset-lint-recommended'],\n    processor: remark(),\n    quiet: true\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.rcName`\n\nThis example processes `readme.md` and allows configuration from `.remarkrc`,\n`.remarkrc.json`, `.remarkrc.yml`, `.remarkrc.yaml`, `.remarkrc.js`,\n`.remarkrc.cjs`, and `.remarkrc.mjs` files.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {files: ['readme.md'], processor: remark(), rcName: '.remarkrc'},\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.rcPath`\n\nThis example processes `readme.md` and loads configuration from `config.json`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {files: ['readme.md'], processor: remark(), rcPath: 'config.json'},\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.reporter` and `options.reporterOptions`\n\nThis example processes all HTML files in the current folder with rehype,\nconfigures the processor with `.rehyperc` files, and prints a report in\nJSON using [`vfile-reporter-json`][vfile-reporter-json] with\n[reporter options][vfile-reporter-options].\n\n```js\nimport {rehype} from 'rehype'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    extensions: ['html'],\n    files: ['.'],\n    processor: rehype(),\n    rcName: '.rehyperc',\n    reporter: 'json',\n    reporterOptions: {pretty: true}\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.settings`\n\nThis example processes `readme.md` and configures the compiler\n([`remark-stringify`][remark-stringify]) with `bullet: '+'`.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {files: ['readme.md'], processor: remark(), settings: {bullet: '+'}},\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.silent`\n\nThis example uses [`remark-lint`][remark-lint] to lint `readme.md` but does not\nreport any warnings or success messages, only fatal errors, if they occur.\n\n```js\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    plugins: ['remark-preset-lint-recommended'],\n    processor: remark(),\n    silent: true\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.streamError`\n\nThis example uses [`remark-lint`][remark-lint] to lint `readme.md` and writes\nthe report to `report.txt`.\n\n```js\nimport fs from 'node:fs'\nimport {remark} from 'remark'\nimport remarkPresetLintRecommended from 'remark-preset-lint-recommended'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['readme.md'],\n    out: false,\n    plugins: [remarkPresetLintRecommended],\n    processor: remark(),\n    streamErr: fs.createWriteStream('report.txt')\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.streamIn`\n\nThis example uses [`remark-lint`][remark-lint] to lint an incoming\nstream.\n\n```js\nimport {PassThrough} from 'node:stream'\nimport {remark} from 'remark'\nimport remarkPresetLintRecommended from 'remark-preset-lint-recommended'\nimport {engine} from 'unified-engine'\n\nconst streamIn = new PassThrough()\n\nstreamIn.write('doc')\n\nsetImmediate(function () {\n  streamIn.end('ument')\n})\n\nengine(\n  {\n    out: false,\n    plugins: [remarkPresetLintRecommended],\n    processor: remark(),\n    streamIn\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nYields:\n\n```text\n\u003cstdin\u003e\n  1:1  warning  Missing newline character at end of file  final-newline  remark-lint\n\n⚠ 1 warning\n```\n\n### `options.streamOut`\n\nThis example reads `readme.md` and writes the serialized document to\n`readme-two.md`.\nThis can also be achieved by passing `output: 'readme-two.md'` instead of\n`streamOut`.\n\n```js\nimport fs from 'node:fs'\nimport {remark} from 'remark'\nimport {engine} from 'unified-engine'\n\nconst streamOut = fs.createWriteStream('readme-two.md')\n\nengine(\n  {files: ['readme.md'], processor: remark(), streamOut},\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\n### `options.tree`\n\nThis example reads `tree.json`, then [`remark-unlink`][remark-unlink]\ntransforms the syntax tree, and the transformed tree is written to\n**stdout**(4).\n\n```js\nimport {remark} from 'remark'\nimport remarkUnlink from 'remark-unlink'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['tree.json'],\n    plugins: [remarkUnlink],\n    processor: remark(),\n    tree: true\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nWhere `tree.json` looks as follows:\n\n```json\n{\n  \"type\": \"paragraph\",\n  \"children\": [{\n    \"type\": \"link\",\n    \"url\": \"https://example.com\",\n    \"children\": [{\n      \"type\": \"text\",\n      \"value\": \"foo\"\n    }]\n  }]\n}\n```\n\nYields:\n\n```json\n{\n  \"type\": \"paragraph\",\n  \"children\": [{\n    \"type\": \"text\",\n    \"value\": \"foo\"\n  }]\n}\n```\n\n### `options.treeIn`\n\nThis example reads `tree.json`, then [`remark-unlink`][remark-unlink]\ntransforms the syntax tree, the tree is serialized, and the resulting document\nis written to **stdout**(4).\n\n```js\nimport {remark} from 'remark'\nimport remarkUnlink from 'remark-unlink'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['tree.json'],\n    plugins: [remarkUnlink],\n    processor: remark(),\n    treeIn: true\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nWhere `tree.json` looks as follows:\n\n```json\n{\n  \"type\": \"paragraph\",\n  \"children\": [{\n    \"type\": \"link\",\n    \"url\": \"https://example.com\",\n    \"children\": [{\n      \"type\": \"text\",\n      \"value\": \"foo\"\n    }]\n  }]\n}\n```\n\nYields:\n\n```markdown\nfoo\n```\n\n### `options.treeOut`\n\nThis example shows a module which reads and parses `doc.md`, then\n[`remark-unlink`][remark-unlink] transforms the syntax tree, and the tree is\nwritten to **stdout**(4).\n\n```js\nimport {remark} from 'remark'\nimport remarkUnlink from 'remark-unlink'\nimport {engine} from 'unified-engine'\n\nengine(\n  {\n    files: ['doc.md'],\n    plugins: [remarkUnlink],\n    processor: remark(),\n    treeOut: true\n  },\n  function (error) {\n    if (error) throw error\n  }\n)\n```\n\nWhere `doc.md` looks as follows:\n\n```markdown\n[foo](https://example.com)\n```\n\nYields:\n\n```json\n{\n  \"type\": \"paragraph\",\n  \"children\": [{\n    \"type\": \"text\",\n    \"value\": \"foo\"\n  }]\n}\n```\n\n## Types\n\nThis package is fully typed with [TypeScript][].\nIt exports the additional types\n[`Completer`][api-completer],\n[`Callback`][api-callback],\n[`ConfigResult`][api-config-result],\n[`ConfigTransform`][api-config-transform],\n[`ContextWithCode`][api-context-with-code],\n[`Context`][api-context],\n[`FileSet`][api-file-set],\n[`Options`][api-options],\n[`Preset`][api-preset],\n[`ResolveFrom`][api-resolve-from], and\n[`VFileReporter`][api-vfile-reporter].\n\n## Compatibility\n\nProjects maintained by the unified collective are compatible with maintained\nversions of Node.js.\n\nWhen we cut a new major release, we drop support for unmaintained versions of\nNode.\nThis means we try to keep the current release line, `unified-engine@^11`,\ncompatible with Node.js 16.\n\n## Security\n\n`unified-engine` loads and evaluates configuration files, plugins, and presets\nfrom the file system (often from `node_modules/`).\nThat means code that is on your file system runs.\nMake sure you trust the workspace where you run `unified-engine` and be careful\nwith packages from npm and changes made by contributors.\n\n## Contribute\n\nSee [`contributing.md`][contributing] in [`unifiedjs/.github`][health] for ways\nto get started.\nSee [`support.md`][support] for ways to get help.\n\nThis project has a [code of conduct][coc].\nBy interacting with this repository, organization, or community you agree to\nabide by its terms.\n\n## License\n\n[MIT][license] © [Titus Wormer][author]\n\n\u003c!-- Definitions --\u003e\n\n[api-callback]: #callback\n\n[api-completer]: #completer\n\n[api-config-result]: #configresult\n\n[api-config-transform]: #configtransform\n\n[api-configuration]: #configuration\n\n[api-context]: #context\n\n[api-context-with-code]: #contextwithcode\n\n[api-engine]: #engineoptions-callback\n\n[api-file-set]: #fileset\n\n[api-options]: #options\n\n[api-preset]: #preset\n\n[api-resolve-from]: #resolvefrom\n\n[api-vfile-reporter]: #vfilereporter\n\n[author]: https://wooorm.com\n\n[backers-badge]: https://opencollective.com/unified/backers/badge.svg\n\n[build]: https://github.com/unifiedjs/unified-engine/actions\n\n[build-badge]: https://github.com/unifiedjs/unified-engine/workflows/main/badge.svg\n\n[chat]: https://github.com/unifiedjs/unified/discussions\n\n[chat-badge]: https://img.shields.io/badge/chat-discussions-success.svg\n\n[coc]: https://github.com/unifiedjs/.github/blob/main/code-of-conduct.md\n\n[collective]: https://opencollective.com/unified\n\n[config-files]: #config-files\n\n[contributing]: https://github.com/unifiedjs/.github/blob/main/contributing.md\n\n[coverage]: https://codecov.io/github/unifiedjs/unified-engine\n\n[coverage-badge]: https://img.shields.io/codecov/c/github/unifiedjs/unified-engine.svg\n\n[downloads]: https://www.npmjs.com/package/unified-engine\n\n[downloads-badge]: https://img.shields.io/npm/dm/unified-engine.svg\n\n[esm]: https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c\n\n[gitignore]: https://git-scm.com/docs/gitignore\n\n[health]: https://github.com/unifiedjs/.github\n\n[ignore-files]: #ignore-files\n\n[license]: license\n\n[node-glob]: https://github.com/isaacs/node-glob#glob-primer\n\n[node-ignore]: https://github.com/kaelzhang/node-ignore\n\n[node-readable-stream]: https://nodejs.org/api/stream.html#readable-streams\n\n[node-writable-stream]: https://nodejs.org/api/stream.html#writable-streams\n\n[npm]: https://docs.npmjs.com/cli/install\n\n[remark]: https://github.com/remarkjs/remark\n\n[remark-cli]: https://github.com/remarkjs/remark/tree/main/packages/remark-cli#readme\n\n[remark-lint]: https://github.com/remarkjs/remark-lint\n\n[remark-preset-lint-recommended]: https://github.com/remarkjs/remark-lint/tree/main/packages/remark-preset-lint-recommended\n\n[remark-stringify]: https://github.com/remarkjs/remark/tree/main/packages/remark-stringify\n\n[remark-unlink]: https://github.com/remarkjs/remark-unlink\n\n[sponsors-badge]: https://opencollective.com/unified/sponsors/badge.svg\n\n[support]: https://github.com/unifiedjs/.github/blob/main/support.md\n\n[typescript]: https://www.typescriptlang.org\n\n[unified]: https://github.com/unifiedjs/unified\n\n[unified-args]: https://github.com/unifiedjs/unified-args\n\n[unified-engine-gulp]: https://github.com/unifiedjs/unified-engine-gulp\n\n[unified-language-server]: https://github.com/unifiedjs/unified-language-server\n\n[unified-processor]: https://github.com/unifiedjs/unified#processor-1\n\n[unified-settings]: https://github.com/unifiedjs/unified#settings\n\n[unist-util-inspect]: https://github.com/syntax-tree/unist-util-inspect\n\n[vfile]: https://github.com/vfile/vfile\n\n[vfile-reporter]: https://github.com/vfile/vfile-reporter\n\n[vfile-reporter-json]: https://github.com/vfile/vfile-reporter-json\n\n[vfile-reporter-options]: https://github.com/vfile/vfile-reporter#options\n","funding_links":["https://github.com/sponsors/unifiedjs","https://opencollective.com/unified","https://thanks.dev/u/gh/unifiedjs"],"categories":["Projects","JavaScript","others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funifiedjs%2Funified-engine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funifiedjs%2Funified-engine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funifiedjs%2Funified-engine/lists"}