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] _“An orange cow with scissors, Van Gogh style” - generated +[![An orange cow with scissors, Van Gogh style][8]][7] _“An orange cow with scissors, Van Gogh style” - generated with OpenAI_ -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