Skip to content

Commit

Permalink
Update docs for writing a plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
webpro committed Jan 28, 2025
1 parent 3815fae commit c1de2ba
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 76 deletions.
120 changes: 59 additions & 61 deletions packages/docs/src/content/docs/guides/handling-issues.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Let's go over common causes for having to add `entry` patterns manually:
- [Build artifacts and ignored files][7]
- [Auto-mocking or auto-imports][8]

Use `--files` to [filter the report][10] and focus only on unused files:
Use `--files` to [filter the report][9] and focus only on unused files:

```sh
knip --files
Expand All @@ -51,7 +51,7 @@ exports.
:::caution

Don't add unused files to the `ignore` option before reading [configuring
project files][9]. Learn why and when to use `entry`, `project` and `ignore`
project files][10]. Learn why and when to use `entry`, `project` and `ignore`
patterns for better results and performance.

:::
Expand Down Expand Up @@ -118,15 +118,14 @@ examples:

**Solution**: [create a new plugin][13] for the tool or framework that's not [in
the list][14] yet. Or work around it and add `entry` patterns and maybe ignore a
dependency or two (using
[`ignoreDependencies`](../reference/configuration.md#ignoredependencies)).
dependency or two (using [`ignoreDependencies`][15]).

### Incomplete plugin

Files may be reported as unused if existing plugins do not include that entry
file pattern yet. See the [plugins section of entry files][15] for more details.
file pattern yet. See the [plugins section of entry files][16] for more details.

**Solution**: [override plugin configuration][16] to customize default patterns
**Solution**: [override plugin configuration][17] to customize default patterns
for existing plugins. Or even better: send a pull request to improve the plugin.

### Integrated monorepos
Expand All @@ -135,7 +134,7 @@ Multiple instances of configuration files like `.eslintrc` and
`jest.config.json` across the repository may be reported as unused when working
in a (mono)repo with a single `package.json`.

**Solution**: see [integrated monorepos][17] for more details and how to
**Solution**: see [integrated monorepos][18] for more details and how to
configure plugins to target those configuration files.

### Build artifacts and ignored files
Expand Down Expand Up @@ -174,17 +173,17 @@ negated `project` patterns:
## Unused dependencies

Dependencies imported in unused files are reported as unused dependencies.
That's why it's strongly recommended to try and remedy [unused files][18] first.
That's why it's strongly recommended to try and remedy [unused files][19] first.
Better `entry` and `project` file coverage will solve many cases of reported
unused dependencies.

The most common causes for unused dependencies include:

- [Missing or incomplete plugin][19]
- [Unrecognized reference][20]
- [Type Definition Packages](#type-definition-packages)
- [Missing or incomplete plugin][20]
- [Unrecognized reference][21]
- [Type Definition Packages][22]

Use `--dependencies` to [filter the report][10] and focus only on issues related
Use `--dependencies` to [filter the report][9] and focus only on issues related
to dependencies:

```sh
Expand Down Expand Up @@ -215,11 +214,10 @@ Sometimes a reference to a dependency is unrecognizable or unreachable to Knip,
so it's a false positive and incorrectly reported as unused.

**Solution**: add a new plugin or improve an existing one. If you don't feel
like a plugin could solve it, a last resort is to use
[ignoreDependencies](../reference/configuration.md#ignoredependencies).
like a plugin could solve it, a last resort is to use [ignoreDependencies][15].

If a binary (or "executable") is referenced you'll want to use `ignoreBinaries`
instead. See [unlisted binaries][21].
instead. See [unlisted binaries][23].

### Type Definition Packages

Expand Down Expand Up @@ -264,7 +262,7 @@ reported as an unlisted binary as there is no package listed that contains it.

Binaries that are installed on the OS already and not thus likely not meant to
be installed from npm are not reported as unlisted (details: [list of ignored
binaries in source][23]).
binaries in source][24]).

### Missing binaries

Expand All @@ -275,7 +273,7 @@ dependencies and binaries, or by not running Knip from the root of the
repository.

**Solution**: run Knip from the project root. From there you can [lint
individual workspaces][24].
individual workspaces][25].

Sometimes binaries and how they're reported can be a bit confusing. See this
example:
Expand Down Expand Up @@ -303,29 +301,27 @@ This technically works, as `commitlint` is a transitive dependency of

Knip may be unable to resolve an import specifier or dependency reference.

**Solution**: First look for solutions such as [paths][25] or try relative
imports. Otherwise, use
[`ignoreUnresolved`](../reference/configuration.md#ignoreunresolved) as a last
resort.
**Solution**: First look for solutions such as [paths][26] or try relative
imports. Otherwise, use [`ignoreUnresolved`][27] as a last resort.

## Unused exports

By default, Knip does not report unused exports of `entry` files.

The most common causes for unused exports include:

- [Enumerations][26]
- [External libraries][27]
- [Enumerations][28]
- [External libraries][29]

Use the `--exports` flag to [filter][10] and focus only on issues related to
Use the `--exports` flag to [filter][9] and focus only on issues related to
exports:

```sh
knip --exports
```

Use [includeEntryExports](../reference/configuration.md#includeentryexports) to
report unused exports of entry files as well. This can be set per workspace.
Use [includeEntryExports][30] to report unused exports of entry files as well.
This can be set per workspace.

### Enumerations

Expand All @@ -336,7 +332,7 @@ Individual exports are then **not** reported.
**Solution**: include the `nsExports` issue type to turn off the heuristic and
always consider exports on a imported namespaces individually.

See [namepace imports][28] to see all related patterns.
See [namepace imports][31] to see all related patterns.

### External libraries

Expand Down Expand Up @@ -376,22 +372,22 @@ Knip does not include external type definitions by default so it won't see the
export being referenced.

**Solution**: include the type definitions of external libraries with the
[--include-libs][29] flag:
[--include-libs][32] flag:

```shell
knip --include-libs
```

This comes at a performance and memory penalty, but should give better results
if you need it. This flag is implied when [classMembers][30] are included (that
if you need it. This flag is implied when [classMembers][33] are included (that
feature comes with roughly the same performance penalty).

### Exclude exports from the report

To exclude false positives from the report, there are a few options:

- [Ignore exports used in file][31] for exports used internally.
- Individual exports can be [tagged using JSDoc syntax][32].
- [Ignore exports used in file][34] for exports used internally.
- Individual exports can be [tagged using JSDoc syntax][35].
- Have the export in an entry file:
- Add the file to the `entry` file patterns array in the configuration.
- Move the export(s) to an entry file.
Expand All @@ -401,7 +397,7 @@ To exclude false positives from the report, there are a few options:
### Missing unused exports?

Did you expect certain exports in the report, but are they missing? They might
be exported from an entry file. In that case, use [--include-entry-exports][33]
be exported from an entry file. In that case, use [--include-entry-exports][30]
to make Knip also report unused exports in entry files.

The exports of non-standard extensions like `.astro`, `.mdx`, `.vue` or
Expand All @@ -420,10 +416,10 @@ knip --include classMembers
This option is also available in the Knip configuration file. Note that this
feature comes at a cost: linting will take more time and more memory.

Individual class members can be [tagged using JSDoc syntax][32].
Individual class members can be [tagged using JSDoc syntax][35].

Classes exported from entry files are ignored, and so are their members. Use
[--include-entry-exports][33] to make Knip also report members of unused exports
[--include-entry-exports][30] to make Knip also report members of unused exports
in entry files.

## Enum members
Expand All @@ -435,18 +431,18 @@ Reporting such members can be disabled:
knip --exclude enumMembers
```

Individual enum members can be [tagged using JSDoc syntax][32].
Individual enum members can be [tagged using JSDoc syntax][35].

Enums exported from entry files are ignored, and so are their members. Use
[--include-entry-exports][33] to make Knip also report members of unused exports
[--include-entry-exports][30] to make Knip also report members of unused exports
in entry files.

## Feedback or false positives?

If you believe Knip incorrectly reports something as unused (i.e. there's a
false positive), feel free to create a [minimal reproduction][34] and open an
false positive), feel free to create a [minimal reproduction][36] and open an
issue on GitHub. It'll make Knip better for everyone! Join the [Discord
channel][35] to discuss any feedback or questions you may have.
channel][37] to discuss any feedback or questions you may have.

[1]: #dynamic-import-specifiers
[2]: #unsupported-arguments-in-scripts
Expand All @@ -456,31 +452,33 @@ channel][35] to discuss any feedback or questions you may have.
[6]: #integrated-monorepos
[7]: #build-artifacts-and-ignored-files
[8]: #auto-mocking-or-auto-imports
[9]: ./configuring-project-files.md
[10]: ../features/rules-and-filters.md#filters
[9]: ../features/rules-and-filters.md#filters
[10]: ./configuring-project-files.md
[11]: ../features/script-parser.md
[12]: ../features/compilers.md
[13]: ./writing-a-plugin.md
[14]: ../reference/plugins.md
[15]: ../explanations/plugins.md#entry-files
[16]: ../explanations/entry-files.md#plugins
[17]: ../features/integrated-monorepos.md
[18]: #unused-files
[19]: #missing-or-incomplete-plugin
[20]: #unrecognized-reference
[21]: #unlisted-binaries
[22]: https://eslint.org/docs/latest/use/configure/configuration
[23]:
[15]: ../reference/configuration.md#ignoredependencies
[16]: ../explanations/plugins.md#entry-files
[17]: ../explanations/entry-files.md#plugins
[18]: ../features/integrated-monorepos.md
[19]: #unused-files
[20]: #missing-or-incomplete-plugin
[21]: #unrecognized-reference
[22]: #type-definition-packages
[23]: #unlisted-binaries
[24]:
https://github.com/webpro-nl/knip/blob/b70958a58ea255ee7a7831e404786da807ca93d7/packages/knip/src/constants.ts#L37-L139
[24]: ../features/monorepos-and-workspaces.md#lint-a-single-workspace
[25]: ../reference/configuration.md#paths
[26]: #enumerations
[27]: #external-libraries
[28]: ../guides/namespace-imports.md
[29]: ../reference/cli#--include-libs
[30]: #class-members
[31]: ../reference/configuration.md#ignoreexportsusedinfile
[32]: ../reference/jsdoc-tsdoc-tags.md
[33]: ../reference/configuration.md#includeentryexports
[34]: ../guides/issue-reproduction
[35]: https://discord.gg/r5uXTtbTpc
[25]: ../features/monorepos-and-workspaces.md#lint-a-single-workspace
[26]: ../reference/configuration.md#paths
[27]: ../reference/configuration.md#ignoreunresolved
[28]: #enumerations
[29]: #external-libraries
[30]: ../reference/configuration.md#includeentryexports
[31]: ../guides/namespace-imports.md
[32]: ../reference/cli#--include-libs
[33]: #class-members
[34]: ../reference/configuration.md#ignoreexportsusedinfile
[35]: ../reference/jsdoc-tsdoc-tags.md
[36]: ../guides/issue-reproduction
[37]: https://discord.gg/r5uXTtbTpc
67 changes: 53 additions & 14 deletions packages/docs/src/content/docs/guides/writing-a-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ without an extension are provided as plain text strings.
You should implement `resolveConfig` if any of these are true:

- The tool supports a `config` file in JSON or YAML format
- The `config` file references dependencies as strings
- The `config` file references dependencies by strings (not import statements)

:::

Expand Down Expand Up @@ -188,8 +188,8 @@ both the tool (e.g. Preconstruct) and Knip.

:::tip[Should I implement resolveEntryPaths?]

You should implement `resolveEntryPaths` if the configuration object contains
file patterns that override the plugin's default `entry` patterns.
Plugins should have `resolveEntryPaths` implemented if the configuration file
contains one or more options that represent [entry points][2].

:::

Expand Down Expand Up @@ -224,12 +224,12 @@ expected to be listed in `"dependencies"`.

The `deferResolve` input type is used to defer the resolution of a specifier.
This could be resolved to a dependency or an entry file. For instance, the
specifier `"input"` could be resolved to `"input.js"`, `"input/index.js"` or the
`"input"` package name (dependency). If it's a local file, it will be added as
an entry file, otherwise it's an external dependency.
specifier `"input"` could be resolved to `"input.js"`, `"input.tsx"`,
`"input/index.js"` or the `"input"` package name. Local files are added as entry
files, package names are external dependencies.

If this does not lead to a resolution, the specifier will be listed under
"unresolved imports"
If this does not lead to a resolution, the specifier will be reported under
"unresolved imports".

### toDeferResolveEntry

Expand All @@ -254,11 +254,45 @@ parser (through the `getInputsFromScripts` helper). Think of GitHub Actions
worfklow YAML files or husky scripts. Using this input type, a binary is
"assigned" to the dependency that has it as a `"bin"` in their `package.json`.

### Input options
### Options

When creating inputs from specifiers, extra `options` can be provided. Most
notably, the optional `dir` argument to indicate something belongs to a
different workspace.
When creating inputs from specifiers, extra `options` can be provided.

#### dir

The optional `dir` argument assigns the input to a different workspace. For
instance, GitHub Action workflows are always stored in the root workspace, and
support `working-directory` in job steps. For example:

```yaml
jobs:
stylelint:
runs-on: ubuntu-latest
steps:
- run: npx esbuild
working-directory: packages/app
```
The GitHub Action plugin understands `working-directory` and adds this `dir` to
the input:

```ts
toDependency('esbuild', { dir: 'packages/app' });
```

Knip now understands `esbuild` is a dependency of the workspace in the
`packages/app` directory.

## Argument parsing

As part of the [script parser][3], Knip parses command-line arguments. Plugins
can implement the `arg` object to add custom argument parsing tailored to the
executables of the tool.

For now, there are two resources available to learn more:

- [The documented `Args` type in source code][4]
- [Implemented `args` in existing plugins][5]

## Create a new plugin

Expand Down Expand Up @@ -290,7 +324,12 @@ individual plugin pages][1] from the exported plugin values.

Thanks for reading. If you have been following this guide to create a new
plugin, this might be the right time to open a pull request! Feel free to join
[the Knip Discord channel][2] if you have any questions.
[the Knip Discord channel][6] if you have any questions.

[1]: ../reference/plugins.md
[2]: https://discord.gg/r5uXTtbTpc
[2]: ../explanations/plugins.md#entry-files-from-config-files
[3]: ../features/script-parser.md
[4]: https://github.com/webpro-nl/knip/blob/main/packages/knip/src/types/args.ts
[5]:
https://github.com/search?q=repo%3Awebpro-nl%2Fknip++path%3Apackages%2Fknip%2Fsrc%2Fplugins+%22const+args+%3D%22&type=code
[6]: https://discord.gg/r5uXTtbTpc
2 changes: 1 addition & 1 deletion packages/docs/src/content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Enjoying Knip? [Support it!][2]

<Card title="Plugins" icon="open-book">

Knip comes with [over 80 plugins][3] for tools and frameworks like Astro,
Knip comes with [over 90 plugins][3] for tools and frameworks like Astro,
Cypress, ESLint, Jest, GitHub Actions, Next.js, Nx, Remix, Storybook,
Svelte, Vite, Vitest, Webpack and many many more.

Expand Down

0 comments on commit c1de2ba

Please sign in to comment.