From 239814c3d1d91f42336bb63a1dc7dde66cac4329 Mon Sep 17 00:00:00 2001
From: Lars Kappert <lars@webpro.nl>
Date: Wed, 30 Aug 2023 07:11:18 +0200
Subject: [PATCH] Update docs

---
 .vscode/settings.json               |   3 +-
 README.md                           | 276 ++++++++++++++--------------
 docs/custom-reporters.md            |  82 ---------
 docs/reporters-and-preprocessors.md |  99 ++++++++++
 4 files changed, 241 insertions(+), 219 deletions(-)
 delete mode 100644 docs/custom-reporters.md
 create mode 100644 docs/reporters-and-preprocessors.md

diff --git a/.vscode/settings.json b/.vscode/settings.json
index 293e9260a..a10007f24 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -2,6 +2,7 @@
   "prettier.withNodeModules": true,
   "markdown.extension.toc.levels": "2..3",
   "markdown.extension.toc.omittedFromToc": {
-    "README.md": ["## Contents"]
+    "README.md": ["## Contents"],
+    "docs/reporters-and-preprocessors.md": ["## Contents"]
   }
 }
diff --git a/README.md b/README.md
index 143a1516e..37ffc721e 100644
--- a/README.md
+++ b/README.md
@@ -24,55 +24,55 @@ The dots don't connect themselves. This is where Knip comes in:
 - [x] Finds unused members of classes and enums
 - [x] Finds duplicate exports
 - [x] Supports any combination of JavaScript and TypeScript
-- [x] Features multiple [reporters][4] and supports [custom reporters][5]
+- [x] Multiple built-in [reporters][4] (or use [custom reporters][5] and [preprocessors][6])
 - [x] Run Knip as part of your CI environment to detect issues and prevent regressions
 
 Knip shines in both small and large projects. It's a fresh take on keeping your projects clean & tidy!
 
-[![An orange cow with scissors, Van Gogh style][7]][6] <sup>_“An orange cow with scissors, Van Gogh style” - generated
+[![An orange cow with scissors, Van Gogh style][8]][7] <sup>_“An orange cow with scissors, Van Gogh style” - generated
 with OpenAI_</sup>
 
-For updates or questions, come hang out in [The Knip Barn (Discord)][8], or follow [@webprolific (Twitter)][9] or
-[@webpro (fosstodon.org)][10]. Please use GitHub to [report issues][11].
+For updates or questions, come hang out in [The Knip Barn (Discord)][9], or follow [@webprolific (Twitter)][10] or
+[@webpro (fosstodon.org)][11]. Please use GitHub to [report issues][12].
 
 ## Contents
 
-- [Getting Started][12]
-  - [Installation][13]
-  - [Default Configuration][14]
-  - [Let's Go!][15]
-- [Configuration][16]
-  - [Entry Files][17]
+- [Getting Started][13]
+  - [Installation][14]
+  - [Default Configuration][15]
+  - [Let's Go!][16]
+- [Configuration][17]
+  - [Entry Files][18]
   - [Workspaces][1]
   - [Plugins][2]
   - [Compilers][3]
-  - [Ignore files, binaries, dependencies and workspaces][18]
-  - [Public exports][19]
-  - [Ignore exports used in file][20]
-  - [Include exports in entry files][21]
-  - [Paths][22]
-- [Production Mode][23]
-  - [Strict][24]
-  - [Ignore `@internal` exports][25]
-  - [Plugins][26]
-- [Output][27]
-  - [Screenshots][28]
-  - [Reading the report][29]
-  - [Rules & Filters][30]
+  - [Ignore files, binaries, dependencies and workspaces][19]
+  - [Public exports][20]
+  - [Ignore exports used in file][21]
+  - [Include exports in entry files][22]
+  - [Paths][23]
+- [Production Mode][24]
+  - [Strict][25]
+  - [Ignore `@internal` exports][26]
+  - [Plugins][27]
+- [Output][28]
+  - [Screenshots][29]
+  - [Reading the report][30]
+  - [Rules & Filters][31]
   - [Reporters][4]
-- [Fixing Issues][31]
-- [Command Line Options][32]
-- [Potential boost with `--no-gitignore`][33]
-- [Comparison & Migration][34]
-  - [depcheck][35]
-  - [unimported][36]
-  - [ts-unused-exports][37]
-  - [ts-prune][38]
-- [Projects using Knip][39]
-- [Articles, etc.][40]
-- [Why "Knip"?][41]
-- [Really, another unused file/dependency/export finder?][42]
-- [Contributors][43]
+- [Fixing Issues][32]
+- [Command Line Options][33]
+- [Potential boost with `--no-gitignore`][34]
+- [Comparison & Migration][35]
+  - [depcheck][36]
+  - [unimported][37]
+  - [ts-unused-exports][38]
+  - [ts-prune][39]
+- [Projects using Knip][40]
+- [Articles, etc.][41]
+- [Why "Knip"?][42]
+- [Really, another unused file/dependency/export finder?][43]
+- [Contributors][44]
 
 ## Getting Started
 
@@ -93,7 +93,7 @@ Knip has good defaults and you can run it without any configuration. The (simpli
 }
 ```
 
-There's more, jump to [Entry Files][17] for details.
+There's more, jump to [Entry Files][18] for details.
 
 Places where Knip looks for configuration (ordered by priority):
 
@@ -135,7 +135,7 @@ Run the checks with `npx knip`. Or first add this script to `package.json`:
 Then use `npm run knip` to analyze the project and output unused files, dependencies and exports. Knip works just fine
 with `yarn` or `pnpm` as well.
 
-See [Command Line Options][32] for an overview of available CLI options.
+See [Command Line Options][33] for an overview of available CLI options.
 
 ## Configuration
 
@@ -198,7 +198,7 @@ Here's an example `knip.json` configuration with some custom `entry` and `projec
 ```
 
 It might be useful to run Knip first with no or little configuration to see where it needs custom `entry` and/or
-`project` files. Each workspace has the same [default configuration][16].
+`project` files. Each workspace has the same [default configuration][17].
 
 The root workspace is named `"."` under `workspaces` (like in the example).
 
@@ -321,7 +321,7 @@ has them at `e2e-tests/*.spec.ts`. Here's how to configure this:
 #### Multi-project repositories
 
 Some repositories have a single `package.json`, but consist of multiple projects with configuration files across the
-repository (such as the [Nx "intregrated repo" style][44]). Let's assume some of these projects are apps and have their
+repository (such as the [Nx "intregrated repo" style][45]). Let's assume some of these projects are apps and have their
 own Cypress configuration and test files. In that case, we could configure the Cypress plugin like this:
 
 ```json
@@ -338,7 +338,7 @@ In case a plugin causes issues, it can be disabled by using `false` as its value
 
 #### Create a new plugin
 
-Getting false positives because a plugin is missing? Want to help out? Please read more at [writing a plugin][45]. This
+Getting false positives because a plugin is missing? Want to help out? Please read more at [writing a plugin][46]. This
 guide also contains more details if you want to learn more about plugins and why they are useful.
 
 ### Compilers
@@ -361,7 +361,7 @@ export default {
 };
 ```
 
-Read [Compilers][46] for more details and examples.
+Read [Compilers][47] for more details and examples.
 
 ### Ignore files, binaries, dependencies and workspaces
 
@@ -528,7 +528,7 @@ The report contains the following types of issues:
 
 When an issue type has zero issues, it is not shown.
 
-Getting too many reported issues and false positives? Read more about [handling issues][47].
+Getting too many reported issues and false positives? Read more about [handling issues][48].
 
 ### Rules & Filters
 
@@ -555,7 +555,7 @@ Example:
 }
 ```
 
-See [reading the report][29] for the list of issue types.
+See [reading the report][30] for the list of issue types.
 
 The rules are modeled after the ESLint `rules` configuration, and could be extended in the future. For instance, to
 apply filters or configurations only to a specific issue type.
@@ -576,7 +576,7 @@ Use `--exclude` to ignore reports you're not interested in:
 
 Use `--dependencies` or `--exports` as shortcuts to combine groups of related types.
 
-See [reading the report][29] for the list of issue types.
+See [reading the report][30] for the list of issue types.
 
 #### When to use rules or filters
 
@@ -600,10 +600,13 @@ Knip provides the following built-in reporters:
 
 When the provided built-in reporters are not sufficient, a custom reporter can be implemented.
 
-Pass something like `--reporter ./my-reporter` from the command line. The results are passed to the function from its
-default export and can be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
+Find more details in [reporters and preprocessors][49].
 
-Find more details and ideas in [custom reporters][48].
+#### Preprocessers
+
+Use preprocessers to modify the results before they're passed to the reporter(s).
+
+Find more details in [reporters and preprocessors][49].
 
 ## Fixing Issues
 
@@ -621,7 +624,7 @@ Tip: back up files or use an VCS like Git before deleting files or making change
 
 Repeat the process to reveal new unused files and exports. It's so liberating to remove unused things!
 
-Getting too many reported issues and false positives? Read more about [handling issues][49] describing potential causes
+Getting too many reported issues and false positives? Read more about [handling issues][50] describing potential causes
 for false positives, and how to handle them.
 
 ## Command Line Options
@@ -672,13 +675,13 @@ for false positives, and how to handle them.
 
 ## Potential boost with `--no-gitignore`
 
-To increase performance in a large monorepo, check out [Potential boost with `--no-gitignore`][50].
+To increase performance in a large monorepo, check out [Potential boost with `--no-gitignore`][51].
 
 ## Comparison & Migration
 
 This table is an ongoing comparison. Based on their docs (please report any mistakes):
 
-| Feature                 | **knip** | [depcheck][51] | [unimported][52] | [ts-unused-exports][53] | [ts-prune][54] |
+| Feature                 | **knip** | [depcheck][52] | [unimported][53] | [ts-unused-exports][54] | [ts-prune][55] |
 | :---------------------- | :------: | :------------: | :--------------: | :---------------------: | :------------: |
 | Unused files            |    ✅    |       -        |        ✅        |            -            |       -        |
 | Unused dependencies     |    ✅    |       ✅       |        ✅        |            -            |       -        |
@@ -714,7 +717,7 @@ The following commands are similar:
     unimported
     knip --production --dependencies --include files
 
-Also see [production mode][23].
+Also see [production mode][24].
 
 ### ts-unused-exports
 
@@ -736,25 +739,25 @@ The following commands are similar:
 
 Many thanks to some of the early adopters of Knip:
 
-- [Block Protocol][55]
-- [DeepmergeTS][56]
-- [eslint-plugin-functional][57]
-- [freeCodeCamp.org][58]
-- [is-immutable-type][59]
-- [IsaacScript][60]
-- [Nuxt][61]
-- [Owncast][62]
-- [release-it][63]
-- [Template TypeScript Node Package][64]
-- [Tipi][65]
+- [Block Protocol][56]
+- [DeepmergeTS][57]
+- [eslint-plugin-functional][58]
+- [freeCodeCamp.org][59]
+- [is-immutable-type][60]
+- [IsaacScript][61]
+- [Nuxt][62]
+- [Owncast][63]
+- [release-it][64]
+- [Template TypeScript Node Package][65]
+- [Tipi][66]
 
 ## Articles, etc.
 
-- Discord: hang out in [The Knip Barn][8]
-- Ask your questions in the [Knip knowledge base][66] (powered by OpenAI and [7-docs][67], experimental!)
-- Smashing Magazine: [Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies][68]
-- Effective TypeScript: [Recommendation Update: ✂️ Use knip to detect dead code and types][69]
-- Josh Goldberg: [Speeding Up Centered Part 4: Unused Code Bloat][70]
+- Discord: hang out in [The Knip Barn][9]
+- Ask your questions in the [Knip knowledge base][67] (powered by OpenAI and [7-docs][68], experimental!)
+- Smashing Magazine: [Knip: An Automated Tool For Finding Unused Files, Exports, And Dependencies][69]
+- Effective TypeScript: [Recommendation Update: ✂️ Use knip to detect dead code and types][70]
+- Josh Goldberg: [Speeding Up Centered Part 4: Unused Code Bloat][71]
 
 ## Why "Knip"?
 
@@ -772,80 +775,81 @@ each file, and traversing all of this, why not collect the various issues in one
 
 Special thanks to the wonderful people who have contributed to this project:
 
-[![Contributors][72]][71]
+[![Contributors][73]][72]
 
 [1]: #workspaces
 [2]: #plugins
 [3]: #compilers
 [4]: #reporters
 [5]: #custom-reporters
-[6]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
-[7]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
-[8]: https://discord.gg/ya5yktTq
-[9]: https://twitter.com/webprolific
-[10]: https://fosstodon.org/@webpro
-[11]: https://github.com/webpro/knip/issues
-[12]: #getting-started
-[13]: #installation
-[14]: #default-configuration
-[15]: #lets-go
-[16]: #configuration
-[17]: #entry-files
-[18]: #ignore-files-binaries-dependencies-and-workspaces
-[19]: #public-exports
-[20]: #ignore-exports-used-in-file
-[21]: #include-exports-in-entry-files
-[22]: #paths
-[23]: #production-mode
-[24]: #strict
-[25]: #ignore-internal-exports
-[26]: #plugins-1
-[27]: #output
-[28]: #screenshots
-[29]: #reading-the-report
-[30]: #rules--filters
-[31]: #fixing-issues
-[32]: #command-line-options
-[33]: #potential-boost-with---no-gitignore
-[34]: #comparison--migration
-[35]: #depcheck
-[36]: #unimported
-[37]: #ts-unused-exports
-[38]: #ts-prune
-[39]: #projects-using-knip
-[40]: #articles-etc
-[41]: #why-knip
-[42]: #really-another-unused-filedependencyexport-finder
-[43]: #contributors
-[44]: https://nx.dev/concepts/integrated-vs-package-based
-[45]: ./docs/writing-a-plugin.md
-[46]: ./docs/compilers.md
-[47]: #handling-issues
-[48]: ./docs/custom-reporters.md
-[49]: ./docs/handling-issues.md
-[50]: ./docs/perf-boost-with-no-gitignore.md
-[51]: https://github.com/depcheck/depcheck
-[52]: https://github.com/smeijer/unimported
-[53]: https://github.com/pzavolinsky/ts-unused-exports
-[54]: https://github.com/nadeesha/ts-prune
-[55]: https://github.com/blockprotocol/blockprotocol
-[56]: https://github.com/RebeccaStevens/deepmerge-ts
-[57]: https://github.com/eslint-functional/eslint-plugin-functional
-[58]: https://github.com/freeCodeCamp/freeCodeCamp
-[59]: https://github.com/RebeccaStevens/is-immutable-type
-[60]: https://github.com/IsaacScript/isaacscript
-[61]: https://github.com/nuxt/nuxt
-[62]: https://github.com/owncast/owncast
-[63]: https://github.com/release-it/release-it
-[64]: https://github.com/JoshuaKGoldberg/template-typescript-node-package
-[65]: https://github.com/meienberger/runtipi
-[66]: https://knip.deno.dev
-[67]: https://github.com/7-docs/7-docs
-[68]: https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/
-[69]: https://effectivetypescript.com/2023/07/29/knip/
-[70]: https://www.joshuakgoldberg.com/blog/speeding-up-centered-part-4-unused-code-bloat/
-[71]: https://github.com/webpro/knip/graphs/contributors
-[72]: https://contrib.rocks/image?repo=webpro/knip
+[6]: #preprocessers
+[7]: https://labs.openai.com/s/xZQACaLepaKya0PRUPtIN5dC
+[8]: ./assets/cow-with-orange-scissors-van-gogh-style.webp
+[9]: https://discord.gg/ya5yktTq
+[10]: https://twitter.com/webprolific
+[11]: https://fosstodon.org/@webpro
+[12]: https://github.com/webpro/knip/issues
+[13]: #getting-started
+[14]: #installation
+[15]: #default-configuration
+[16]: #lets-go
+[17]: #configuration
+[18]: #entry-files
+[19]: #ignore-files-binaries-dependencies-and-workspaces
+[20]: #public-exports
+[21]: #ignore-exports-used-in-file
+[22]: #include-exports-in-entry-files
+[23]: #paths
+[24]: #production-mode
+[25]: #strict
+[26]: #ignore-internal-exports
+[27]: #plugins-1
+[28]: #output
+[29]: #screenshots
+[30]: #reading-the-report
+[31]: #rules--filters
+[32]: #fixing-issues
+[33]: #command-line-options
+[34]: #potential-boost-with---no-gitignore
+[35]: #comparison--migration
+[36]: #depcheck
+[37]: #unimported
+[38]: #ts-unused-exports
+[39]: #ts-prune
+[40]: #projects-using-knip
+[41]: #articles-etc
+[42]: #why-knip
+[43]: #really-another-unused-filedependencyexport-finder
+[44]: #contributors
+[45]: https://nx.dev/concepts/integrated-vs-package-based
+[46]: ./docs/writing-a-plugin.md
+[47]: ./docs/compilers.md
+[48]: #handling-issues
+[49]: ./docs/reporters-and-preprocessors.md
+[50]: ./docs/handling-issues.md
+[51]: ./docs/perf-boost-with-no-gitignore.md
+[52]: https://github.com/depcheck/depcheck
+[53]: https://github.com/smeijer/unimported
+[54]: https://github.com/pzavolinsky/ts-unused-exports
+[55]: https://github.com/nadeesha/ts-prune
+[56]: https://github.com/blockprotocol/blockprotocol
+[57]: https://github.com/RebeccaStevens/deepmerge-ts
+[58]: https://github.com/eslint-functional/eslint-plugin-functional
+[59]: https://github.com/freeCodeCamp/freeCodeCamp
+[60]: https://github.com/RebeccaStevens/is-immutable-type
+[61]: https://github.com/IsaacScript/isaacscript
+[62]: https://github.com/nuxt/nuxt
+[63]: https://github.com/owncast/owncast
+[64]: https://github.com/release-it/release-it
+[65]: https://github.com/JoshuaKGoldberg/template-typescript-node-package
+[66]: https://github.com/meienberger/runtipi
+[67]: https://knip.deno.dev
+[68]: https://github.com/7-docs/7-docs
+[69]: https://www.smashingmagazine.com/2023/08/knip-automated-tool-find-unused-files-exports-dependencies/
+[70]: https://effectivetypescript.com/2023/07/29/knip/
+[71]: https://www.joshuakgoldberg.com/blog/speeding-up-centered-part-4-unused-code-bloat/
+[72]: https://github.com/webpro/knip/graphs/contributors
+[73]: https://contrib.rocks/image?repo=webpro/knip
 [plugin-ava]: ./src/plugins/ava
 [plugin-babel]: ./src/plugins/babel
 [plugin-capacitor]: ./src/plugins/capacitor
diff --git a/docs/custom-reporters.md b/docs/custom-reporters.md
deleted file mode 100644
index 35fda78e1..000000000
--- a/docs/custom-reporters.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# Custom Reporters
-
-When the provided built-in reporters are not quite sufficient, a custom reporter can be implemented.
-
-Pass `--reporter ./my-reporter`, with the default export of that module having this interface:
-
-```ts
-type Reporter = (options: ReporterOptions) => void;
-
-type ReporterOptions = {
-  report: Report;
-  issues: Issues;
-  cwd: string;
-  workingDir: string;
-  isProduction: boolean;
-  options: string;
-};
-```
-
-The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
-
-## JSON
-
-The `json` reporter output is meant to be consumed by other tools. It reports in JSON format as an array with one object
-per file like this:
-
-```json
-[
-  {
-    "file": "package.json",
-    "owners": ["@org/admin"],
-    "files": false,
-    "dependencies": ["jquery", "moment"],
-    "devDependencies": [],
-    "unlisted": [],
-    "exports": [],
-    "types": [],
-    "duplicates": []
-  },
-  {
-    "file": "src/Registration.tsx",
-    "owners": ["@org/owner"],
-    "files": true,
-    "dependencies": [],
-    "devDependencies": [],
-    "unlisted": ["react"],
-    "exports": ["lowercaseFirstLetter", "RegistrationBox"],
-    "types": ["RegistrationServices", "RegistrationAction"],
-    "duplicates": ["Registration", "default"]
-  }
-]
-```
-
-The keys match the [reported issue types][1]
-
-## Usage Ideas
-
-Use tools like [miller][2] or [jtbl][3] to consume the JSON and render a table in the terminal.
-
-### Table
-
-    $ npx knip --reporter json | mlr --ijson --opprint --no-auto-flatten cat
-    file                  owners      files  unlisted  exports                                types                                     duplicates
-    src/Registration.tsx  @org/owner  true   react     lowercaseFirstLetter, RegistrationBox  RegistrationServices, RegistrationAction  Registration, default
-    src/ProductsList.tsx  @org/team   false  -         -                                      ProductDetail                             -
-
-### Markdown Table
-
-    $ npx knip --reporter json | mlr --ijson --omd --no-auto-flatten cat
-    | file | owners | files | duplicates |
-    | --- | --- | --- | --- |
-    | src/Registration.tsx | @org/owner | true | Registration, default |
-    | src/ProductsList.tsx | @org/team | false |  |
-
-Include specific issue types and/or replace the `cat` command with `put` for clean output:
-
-    npx knip --include files,duplicates --reporter json | mlr --ijson --opprint --no-auto-flatten put 'for (e in $*) { if(is_array($[e])) { $[e] = joinv($[e], ", ") } }'
-    npx knip --reporter json | mlr --ijson --omd --no-auto-flatten put 'for (e in $*) { if(is_array($[e])) { $[e] = joinv($[e], ", ") } }'
-
-[1]: ../README.md#reading-the-report
-[2]: https://miller.readthedocs.io
-[3]: https://github.com/kellyjonbrazil/jtbl
diff --git a/docs/reporters-and-preprocessors.md b/docs/reporters-and-preprocessors.md
new file mode 100644
index 000000000..cc9f95310
--- /dev/null
+++ b/docs/reporters-and-preprocessors.md
@@ -0,0 +1,99 @@
+# Reporters and Preprocessors
+
+## Contents
+
+- [Reporters][1]
+  - [Local][2]
+  - [External][3]
+  - [JSON][4]
+- [Preprocessors][5]
+
+## Reporters
+
+When the provided built-in reporters are not quite sufficient, a custom local reporter can be implemented or an external
+reporter can be used. Multiple reporters can be used at once by repeating the `--reporter` argument.
+
+Pass something like `--reporter ./my-reporter` from the command line. The results are passed to the function from its
+default export and can be used to write issues to `stdout`, a JSON or CSV file, or sent to a service. It supports
+TypeScript or an external dependency such as `--reporter ./my-reporter.ts` or `--reporter [pgk-name]`.
+
+### Local
+
+Pass `--reporter ./my-reporter`, with the default export of that module having this interface:
+
+```ts
+type Reporter = async (options: ReporterOptions) => void;
+
+type ReporterOptions = {
+  report: Report;
+  issues: Issues;
+  configurationHints: ConfigurationHints;
+  noConfigHints: boolean;
+  cwd: string;
+  isProduction: boolean;
+  isShowProgress: boolean;
+  options: string;
+};
+```
+
+The data can then be used to write issues to `stdout`, a JSON or CSV file, or sent to a service.
+
+### External
+
+Pass `--reporter [pkg-name]` to use an external reporter. The default exported function of the `main` script (default:
+`index.js`) will be invoked with the `ReporterOptions`, just like a local reporter.
+
+### JSON
+
+The built-in `json` reporter output is meant to be consumed by other tools. It reports in JSON format as an array with
+one object per file like this:
+
+```json
+[
+  {
+    "file": "package.json",
+    "owners": ["@org/admin"],
+    "files": false,
+    "dependencies": ["jquery", "moment"],
+    "devDependencies": [],
+    "unlisted": [],
+    "exports": [],
+    "types": [],
+    "duplicates": []
+  },
+  {
+    "file": "src/Registration.tsx",
+    "owners": ["@org/owner"],
+    "files": true,
+    "dependencies": [],
+    "devDependencies": [],
+    "unlisted": ["react"],
+    "exports": ["lowercaseFirstLetter", "RegistrationBox"],
+    "types": ["RegistrationServices", "RegistrationAction"],
+    "duplicates": ["Registration", "default"]
+  }
+]
+```
+
+The keys match the [reported issue types][6]
+
+## Preprocessors
+
+A preprocessor is a function that receives the results and should return data in the same shape/structure (unless you
+pass it to only your own reporter). Just like reporters, use e.g. `--preprocessor ./my-preprocessor` from the command
+line (can be repeated).
+
+The default export of that module having this interface:
+
+```ts
+type Preprocessor = async (options: ReporterOptions) => ReporterOptions;
+```
+
+Like reporters, you can use JavaScript, TypeScript, and external npm packages as preprocessors.
+
+[1]: #reporters
+[2]: #local
+[3]: #external
+[4]: #json
+[5]: #preprocessors
+[6]: ../README.md#reading-the-report