@knip/mcp 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/docs/blog/brief-history.md +30 -0
- package/docs/docs/blog/for-editors-and-agents.md +127 -0
- package/docs/docs/blog/knip-v3.mdx +88 -0
- package/docs/docs/blog/knip-v4.mdx +149 -0
- package/docs/docs/blog/knip-v5.mdx +190 -0
- package/docs/docs/blog/migration-to-v1.md +65 -0
- package/docs/docs/blog/release-notes-v2.md +46 -0
- package/docs/docs/blog/slim-down-to-speed-up.md +269 -0
- package/docs/docs/blog/state-of-knip.md +191 -0
- package/docs/docs/blog/two-years.mdx +107 -0
- package/docs/docs/explanations/comparison-and-migration.md +129 -0
- package/docs/docs/explanations/entry-files.md +70 -0
- package/docs/docs/explanations/plugins.md +319 -0
- package/docs/docs/explanations/why-use-knip.md +128 -0
- package/docs/docs/features/auto-fix.mdx +333 -0
- package/docs/docs/features/compilers.md +172 -0
- package/docs/docs/features/integrated-monorepos.md +61 -0
- package/docs/docs/features/monorepos-and-workspaces.md +134 -0
- package/docs/docs/features/production-mode.md +95 -0
- package/docs/docs/features/reporters.md +302 -0
- package/docs/docs/features/rules-and-filters.md +102 -0
- package/docs/docs/features/script-parser.md +156 -0
- package/docs/docs/features/source-mapping.md +100 -0
- package/docs/docs/guides/configuring-project-files.md +205 -0
- package/docs/docs/guides/contributing.md +24 -0
- package/docs/docs/guides/handling-issues.mdx +646 -0
- package/docs/docs/guides/issue-reproduction.md +94 -0
- package/docs/docs/guides/namespace-imports.md +125 -0
- package/docs/docs/guides/performance.md +97 -0
- package/docs/docs/guides/troubleshooting.md +136 -0
- package/docs/docs/guides/using-knip-in-ci.md +54 -0
- package/docs/docs/guides/working-with-commonjs.md +72 -0
- package/docs/docs/index.mdx +160 -0
- package/docs/docs/overview/configuration.md +104 -0
- package/docs/docs/overview/features.md +66 -0
- package/docs/docs/overview/getting-started.mdx +195 -0
- package/docs/docs/overview/screenshots-videos.md +42 -0
- package/docs/docs/playground.mdx +38 -0
- package/docs/docs/reference/cli.md +485 -0
- package/docs/docs/reference/configuration.md +413 -0
- package/docs/docs/reference/dynamic-configuration.mdx +72 -0
- package/docs/docs/reference/faq.md +441 -0
- package/docs/docs/reference/issue-types.md +43 -0
- package/docs/docs/reference/jsdoc-tsdoc-tags.md +122 -0
- package/docs/docs/reference/known-issues.md +64 -0
- package/docs/docs/reference/plugins/.gitkeep +0 -0
- package/docs/docs/reference/plugins.md +238 -0
- package/docs/docs/reference/related-tooling.md +46 -0
- package/docs/docs/sponsors.mdx +65 -0
- package/docs/docs/typescript/unused-dependencies.md +86 -0
- package/docs/docs/typescript/unused-exports.md +87 -0
- package/docs/docs/writing-a-plugin/argument-parsing.md +202 -0
- package/docs/docs/writing-a-plugin/index.md +376 -0
- package/docs/docs/writing-a-plugin/inputs.md +162 -0
- package/package.json +5 -3
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Auto-fix
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
import { Tabs, TabItem } from '@astrojs/starlight/components';
|
|
6
|
+
import { Badge } from '@astrojs/starlight/components';
|
|
7
|
+
|
|
8
|
+
Run Knip as you normally would, and if the report looks good then run it again
|
|
9
|
+
with the `--fix` flag to let Knip automatically apply fixes. It fixes the
|
|
10
|
+
following [issue types][1]:
|
|
11
|
+
|
|
12
|
+
- Remove `export` keyword for unused exports and exported types
|
|
13
|
+
- Remove `export default` keywords for unused default exports
|
|
14
|
+
- Remove exports, re-exports and exported types
|
|
15
|
+
- Remove unused enum members
|
|
16
|
+
- Remove unused class members (disabled by default)
|
|
17
|
+
- Remove unused `dependencies` and `devDependencies` from `package.json`
|
|
18
|
+
- Remove unused files
|
|
19
|
+
|
|
20
|
+
:::caution
|
|
21
|
+
|
|
22
|
+
Use a VCS (version control system) like Git to review and undo changes as
|
|
23
|
+
necessary.
|
|
24
|
+
|
|
25
|
+
:::
|
|
26
|
+
|
|
27
|
+
## Flags
|
|
28
|
+
|
|
29
|
+
### Fix
|
|
30
|
+
|
|
31
|
+
Add the `--fix` flag to remove unused exports and dependencies:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
knip --fix
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Add `--allow-remove-files` to allow Knip to remove unused files:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
knip --fix --allow-remove-files
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Use `--fix-type` to fix only specific issue types:
|
|
44
|
+
|
|
45
|
+
- `files`
|
|
46
|
+
- `exports`
|
|
47
|
+
- `types`
|
|
48
|
+
- `dependencies`
|
|
49
|
+
- `catalog`
|
|
50
|
+
|
|
51
|
+
Example:
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
knip --fix-type exports,types
|
|
55
|
+
knip --fix-type exports --fix-type types # same as above
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Format
|
|
59
|
+
|
|
60
|
+
Add `--format` to format the modified files using the formatter and
|
|
61
|
+
configuration in your project. Supports Biome, deno fmt, dprint and Prettier
|
|
62
|
+
(using [Formatly][2]):
|
|
63
|
+
|
|
64
|
+
```sh
|
|
65
|
+
knip --fix --format
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Demo
|
|
69
|
+
|
|
70
|
+
<video controls width="500">
|
|
71
|
+
<source src="/screenshots/fix.mp4" type="video/mp4" />
|
|
72
|
+
|
|
73
|
+
<source src="/screenshots/fix.webm" type="video/webm" />
|
|
74
|
+
</video>
|
|
75
|
+
|
|
76
|
+
## Post-fix
|
|
77
|
+
|
|
78
|
+
After Knip has fixed issues, there are four things to consider:
|
|
79
|
+
|
|
80
|
+
### 1. Use a formatter
|
|
81
|
+
|
|
82
|
+
Use a tool like Prettier or Biome if the code needs formatting. Knip removes the
|
|
83
|
+
minimum amount of code while leaving it in a working state.
|
|
84
|
+
|
|
85
|
+
:::tip
|
|
86
|
+
|
|
87
|
+
Add the `--format` flag to format the modified files using the formatter and
|
|
88
|
+
configuration in your project.
|
|
89
|
+
|
|
90
|
+
:::
|
|
91
|
+
|
|
92
|
+
### 2. Unused variables
|
|
93
|
+
|
|
94
|
+
Use a tool like ESLint or Biome to find and remove unused variables inside
|
|
95
|
+
files. Even better, try [remove-unused-vars][3] to remove unused variables
|
|
96
|
+
within files.
|
|
97
|
+
|
|
98
|
+
This may result in more deleted code, and Knip may then find more unused code.
|
|
99
|
+
Rinse and repeat!
|
|
100
|
+
|
|
101
|
+
### 3. Unused dependencies
|
|
102
|
+
|
|
103
|
+
Verify changes in `package.json` and update dependencies using your package
|
|
104
|
+
manager.
|
|
105
|
+
|
|
106
|
+
<Tabs syncKey="pm">
|
|
107
|
+
<TabItem label="npm">
|
|
108
|
+
```shell
|
|
109
|
+
npm install
|
|
110
|
+
```
|
|
111
|
+
</TabItem>
|
|
112
|
+
|
|
113
|
+
<TabItem label="pnpm">
|
|
114
|
+
```shell
|
|
115
|
+
pnpm install
|
|
116
|
+
```
|
|
117
|
+
</TabItem>
|
|
118
|
+
|
|
119
|
+
<TabItem label="bun">
|
|
120
|
+
```shell
|
|
121
|
+
bun install
|
|
122
|
+
```
|
|
123
|
+
</TabItem>
|
|
124
|
+
|
|
125
|
+
<TabItem label="yarn">
|
|
126
|
+
```shell
|
|
127
|
+
yarn
|
|
128
|
+
```
|
|
129
|
+
</TabItem>
|
|
130
|
+
</Tabs>
|
|
131
|
+
|
|
132
|
+
### 4. Install unlisted dependencies
|
|
133
|
+
|
|
134
|
+
If Knip reports unlisted dependencies or binaries, they should be installed
|
|
135
|
+
using the package manager in the project, for example:
|
|
136
|
+
|
|
137
|
+
<Tabs syncKey="pm">
|
|
138
|
+
<TabItem label="npm">
|
|
139
|
+
```shell
|
|
140
|
+
npm install unlisted-package
|
|
141
|
+
```
|
|
142
|
+
</TabItem>
|
|
143
|
+
|
|
144
|
+
<TabItem label="pnpm">
|
|
145
|
+
```shell
|
|
146
|
+
pnpm add unlisted-package
|
|
147
|
+
```
|
|
148
|
+
</TabItem>
|
|
149
|
+
|
|
150
|
+
<TabItem label="bun">
|
|
151
|
+
```shell
|
|
152
|
+
bun add unlisted-package
|
|
153
|
+
```
|
|
154
|
+
</TabItem>
|
|
155
|
+
|
|
156
|
+
<TabItem label="yarn">
|
|
157
|
+
```shell
|
|
158
|
+
yarn add unlisted-package
|
|
159
|
+
```
|
|
160
|
+
</TabItem>
|
|
161
|
+
</Tabs>
|
|
162
|
+
|
|
163
|
+
## Example results
|
|
164
|
+
|
|
165
|
+
### Exports
|
|
166
|
+
|
|
167
|
+
The `export` keyword for unused exports is removed:
|
|
168
|
+
|
|
169
|
+
```diff title="module.ts"
|
|
170
|
+
-export const unused = 1;
|
|
171
|
+
-export default class MyClass {}
|
|
172
|
+
+const unused = 1;
|
|
173
|
+
+class MyClass {}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The `default` keyword was also removed here.
|
|
177
|
+
|
|
178
|
+
Knip removes the whole or part of export declarations:
|
|
179
|
+
|
|
180
|
+
```diff title="module.ts"
|
|
181
|
+
type Snake = 'python' | 'anaconda';
|
|
182
|
+
const Owl = 'Hedwig';
|
|
183
|
+
const Hawk = 'Tony';
|
|
184
|
+
-export type { Snake };
|
|
185
|
+
-export { Owl, Hawk };
|
|
186
|
+
+;
|
|
187
|
+
+;
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Re-exports
|
|
191
|
+
|
|
192
|
+
Knip removes the whole or part of re-exports:
|
|
193
|
+
|
|
194
|
+
```diff title="file.js"
|
|
195
|
+
-export { Cat, Dog } from './pets';
|
|
196
|
+
-export { Lion, Elephant } from './jungle';
|
|
197
|
+
+export { Elephant } from './jungle'
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Also across any chain of re-exports:
|
|
201
|
+
|
|
202
|
+
<Tabs>
|
|
203
|
+
<TabItem label="module.ts">
|
|
204
|
+
```diff
|
|
205
|
+
export const Hawk = 'Tony';
|
|
206
|
+
-export const Owl = 'Hedwig';
|
|
207
|
+
+const Owl = 'Hedwig';
|
|
208
|
+
```
|
|
209
|
+
</TabItem>
|
|
210
|
+
|
|
211
|
+
<TabItem label="barrel.ts">
|
|
212
|
+
```diff
|
|
213
|
+
export * from './module.js';
|
|
214
|
+
```
|
|
215
|
+
</TabItem>
|
|
216
|
+
|
|
217
|
+
<TabItem label="index.ts">
|
|
218
|
+
```diff
|
|
219
|
+
-export { Hawk, Owl } from './barrel.js';
|
|
220
|
+
+export { Hawk } from './barrel.js'
|
|
221
|
+
```
|
|
222
|
+
</TabItem>
|
|
223
|
+
</Tabs>
|
|
224
|
+
|
|
225
|
+
### Export assignments
|
|
226
|
+
|
|
227
|
+
Knip removes individual exported items in "export assignments", but does not
|
|
228
|
+
remove the entire export declaration if it's empty:
|
|
229
|
+
|
|
230
|
+
```diff title="file.js"
|
|
231
|
+
-export const { a, b } = fn();
|
|
232
|
+
+export const { } = fn();
|
|
233
|
+
|
|
234
|
+
-export const [c, d] = [c, d];
|
|
235
|
+
+export const [, ] = [c, d];
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Reason: the right-hand side of the assignment might have side-effects. It's not
|
|
239
|
+
safe to always remove the whole declaration. This could be improved in the
|
|
240
|
+
future (feel free to open an issue/RFC).
|
|
241
|
+
|
|
242
|
+
### Enum members
|
|
243
|
+
|
|
244
|
+
Unused members of enums are removed:
|
|
245
|
+
|
|
246
|
+
```diff title="file.ts"
|
|
247
|
+
export enum Directions {
|
|
248
|
+
North = 1,
|
|
249
|
+
East = 2,
|
|
250
|
+
- South = 3,
|
|
251
|
+
West = 4,
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### CommonJS
|
|
256
|
+
|
|
257
|
+
Knip supports CommonJS and removes unused exports:
|
|
258
|
+
|
|
259
|
+
```diff title="common.js"
|
|
260
|
+
-module.exports = { identifier, unused };
|
|
261
|
+
+module.exports = { identifier, };
|
|
262
|
+
|
|
263
|
+
-module.exports.UNUSED = 1;
|
|
264
|
+
-module.exports['ACCESS'] = 1;
|
|
265
|
+
+
|
|
266
|
+
+
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Warning: the right-hand side of such an assignment might have side-effects. Knip
|
|
270
|
+
currently removes the whole declaration (feel free to open an issue/RFC).
|
|
271
|
+
|
|
272
|
+
### Dependencies
|
|
273
|
+
|
|
274
|
+
Unused dependencies are removed from `package.json`:
|
|
275
|
+
|
|
276
|
+
```diff title="package.json"
|
|
277
|
+
{
|
|
278
|
+
"name": "my-package",
|
|
279
|
+
"dependencies": {
|
|
280
|
+
- "rimraf": "*",
|
|
281
|
+
- "unused-dependency": "*"
|
|
282
|
+
+ "rimraf": "*"
|
|
283
|
+
},
|
|
284
|
+
- "devDependencies": {
|
|
285
|
+
- "unreferenced-package": "5.3.3"
|
|
286
|
+
- }
|
|
287
|
+
+ "devDependencies": {}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
### Class members <Badge text="experimental" variant="caution" />
|
|
292
|
+
|
|
293
|
+
Unused members of classes can be removed:
|
|
294
|
+
|
|
295
|
+
```diff title="file.ts"
|
|
296
|
+
export class Rectangle {
|
|
297
|
+
constructor(public width: number, public height: number) {}
|
|
298
|
+
|
|
299
|
+
- static Key = 1;
|
|
300
|
+
+
|
|
301
|
+
|
|
302
|
+
area() {
|
|
303
|
+
return this.width * this.height;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
- public get unusedGetter(): string {
|
|
307
|
+
- return 'unusedGetter';
|
|
308
|
+
- }
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Currently Knip might be too eager removing class members when they're not
|
|
313
|
+
referenced internally but meant to be called by an external library. For
|
|
314
|
+
instance, Knip might think `componentDidMount` and `render` in React class
|
|
315
|
+
component are unused and will remove those.
|
|
316
|
+
|
|
317
|
+
Note that [`classMembers` aren't included by default][4].
|
|
318
|
+
|
|
319
|
+
## What's not included
|
|
320
|
+
|
|
321
|
+
Operations that auto-fix does not (yet) perform and why:
|
|
322
|
+
|
|
323
|
+
- Add unlisted (dev) dependencies to `package.json` (should it go into
|
|
324
|
+
`dependencies` or `devDependencies`? For monorepos in current workspace or
|
|
325
|
+
root?)
|
|
326
|
+
- Add unlisted binaries (which package and package version contains the used
|
|
327
|
+
binary?)
|
|
328
|
+
- Fix duplicate exports (which one should be removed?)
|
|
329
|
+
|
|
330
|
+
[1]: ../reference/issue-types.md
|
|
331
|
+
[2]: https://github.com/JoshuaKGoldberg/formatly
|
|
332
|
+
[3]: https://github.com/webpro-nl/remove-unused-vars
|
|
333
|
+
[4]: ../guides/handling-issues.mdx#class-members
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Compilers
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
Projects may have source files that are not JavaScript or TypeScript, and thus
|
|
6
|
+
require compilation (or transpilation, or pre-processing, you name it). Files
|
|
7
|
+
like `.mdx`, `.astro`, `.vue` and `.svelte` may also import other source files
|
|
8
|
+
and external dependencies. So ideally, these files are included when linting the
|
|
9
|
+
project. That's why Knip supports compilers.
|
|
10
|
+
|
|
11
|
+
## Built-in compilers
|
|
12
|
+
|
|
13
|
+
Knip has built-in "compilers" for the following file extensions:
|
|
14
|
+
|
|
15
|
+
- `.astro`
|
|
16
|
+
- `.css` (only enabled by `tailwindcss`)
|
|
17
|
+
- `.mdx`
|
|
18
|
+
- `.prisma`
|
|
19
|
+
- `.sass` + `.scss`
|
|
20
|
+
- `.svelte`
|
|
21
|
+
- `.vue`
|
|
22
|
+
|
|
23
|
+
Knip does not include real compilers for those files, but regular expressions to
|
|
24
|
+
collect `import` statements. This is fast, requires no dependencies, and enough
|
|
25
|
+
for Knip to build the module graph.
|
|
26
|
+
|
|
27
|
+
On the other hand, real compilers may expose their own challenges in the context
|
|
28
|
+
of Knip. For instance, the Svelte compiler keeps `exports` intact, while they
|
|
29
|
+
might represent component properties. This results in those exports being
|
|
30
|
+
reported as unused by Knip.
|
|
31
|
+
|
|
32
|
+
The built-in functions seem to do a decent job, but override them however you
|
|
33
|
+
like.
|
|
34
|
+
|
|
35
|
+
Compilers are enabled only if certain dependencies are found. If that's not
|
|
36
|
+
working for your project, set `true` and enable any compiler manually:
|
|
37
|
+
|
|
38
|
+
```ts title="knip.ts"
|
|
39
|
+
export default {
|
|
40
|
+
compilers: {
|
|
41
|
+
mdx: true,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Custom compilers
|
|
47
|
+
|
|
48
|
+
Built-in compilers can be overridden, and additional compilers can be added.
|
|
49
|
+
Since compilers are functions, the Knip configuration file must be a dynamic
|
|
50
|
+
`.js` or `.ts` file.
|
|
51
|
+
|
|
52
|
+
### Interface
|
|
53
|
+
|
|
54
|
+
The compiler function interface is straightforward. Text in, text out:
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
(source: string, filename: string) => string;
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
This may also be an `async` function.
|
|
61
|
+
|
|
62
|
+
:::tip[Note]
|
|
63
|
+
|
|
64
|
+
Compilers will automatically have their extension added as a default extension
|
|
65
|
+
to Knip. This means you don't need to add something like `**/*.{ts,vue}` to the
|
|
66
|
+
`entry` or `project` file patterns manually.
|
|
67
|
+
|
|
68
|
+
:::
|
|
69
|
+
|
|
70
|
+
### Examples
|
|
71
|
+
|
|
72
|
+
- [CSS][1]
|
|
73
|
+
- [MDX][2]
|
|
74
|
+
- [Svelte][3]
|
|
75
|
+
- [Vue][4]
|
|
76
|
+
|
|
77
|
+
#### CSS
|
|
78
|
+
|
|
79
|
+
Here's an example, minimal compiler for CSS files:
|
|
80
|
+
|
|
81
|
+
```ts title="knip.ts"
|
|
82
|
+
export default {
|
|
83
|
+
compilers: {
|
|
84
|
+
css: (text: string) => [...text.matchAll(/(?<=@)import[^;]+/g)].join('\n'),
|
|
85
|
+
},
|
|
86
|
+
};
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You may wonder why the CSS compiler is not included by default. It's currently
|
|
90
|
+
not clear if it should be included. And if so, what would be the best way to
|
|
91
|
+
determine it should be enabled, and what syntax(es) it should support. Note that
|
|
92
|
+
Tailwind CSS and SASS/SCSS compilers are included.
|
|
93
|
+
|
|
94
|
+
#### MDX
|
|
95
|
+
|
|
96
|
+
Another example, in case the built-in MDX compiler is not enough:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { compile } from '@mdx-js/mdx';
|
|
100
|
+
|
|
101
|
+
export default {
|
|
102
|
+
compilers: {
|
|
103
|
+
mdx: async text => (await compile(text)).toString(),
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Svelte
|
|
109
|
+
|
|
110
|
+
In a Svelte project, the compiler is automatically enabled. Override and use
|
|
111
|
+
Svelte's compiler for better results if the built-in "compiler" is not enough:
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
import type { KnipConfig } from 'knip';
|
|
115
|
+
import { compile } from 'svelte/compiler';
|
|
116
|
+
|
|
117
|
+
export default {
|
|
118
|
+
compilers: {
|
|
119
|
+
svelte: (source: string) => compile(source, {}).js.code,
|
|
120
|
+
},
|
|
121
|
+
} satisfies KnipConfig;
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
#### Vue
|
|
125
|
+
|
|
126
|
+
In a Vue project, the compiler is automatically enabled. Override and use Vue's
|
|
127
|
+
parser for better results if the built-in "compiler" is not enough:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import type { KnipConfig } from 'knip';
|
|
131
|
+
import {
|
|
132
|
+
parse,
|
|
133
|
+
type SFCScriptBlock,
|
|
134
|
+
type SFCStyleBlock,
|
|
135
|
+
} from 'vue/compiler-sfc';
|
|
136
|
+
|
|
137
|
+
function getScriptBlockContent(block: SFCScriptBlock | null): string[] {
|
|
138
|
+
if (!block) return [];
|
|
139
|
+
if (block.src) return [`import '${block.src}'`];
|
|
140
|
+
return [block.content];
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function getStyleBlockContent(block: SFCStyleBlock | null): string[] {
|
|
144
|
+
if (!block) return [];
|
|
145
|
+
if (block.src) return [`@import '${block.src}';`];
|
|
146
|
+
return [block.content];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function getStyleImports(content: string): string {
|
|
150
|
+
return [...content.matchAll(/(?<=@)import[^;]+/g)].join('\n');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const config = {
|
|
154
|
+
compilers: {
|
|
155
|
+
vue: (text: string, filename: string) => {
|
|
156
|
+
const { descriptor } = parse(text, { filename, sourceMap: false });
|
|
157
|
+
return [
|
|
158
|
+
...getScriptBlockContent(descriptor.script),
|
|
159
|
+
...getScriptBlockContent(descriptor.scriptSetup),
|
|
160
|
+
...descriptor.styles.flatMap(getStyleBlockContent).map(getStyleImports),
|
|
161
|
+
].join('\n');
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
} satisfies KnipConfig;
|
|
165
|
+
|
|
166
|
+
export default config;
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
[1]: #css
|
|
170
|
+
[2]: #mdx
|
|
171
|
+
[3]: #svelte
|
|
172
|
+
[4]: #vue
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Integrated Monorepos
|
|
3
|
+
sidebar:
|
|
4
|
+
order: 3
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Some repositories have a single `package.json`, but consist of multiple projects
|
|
8
|
+
with configuration files across the repository. A good example is the [Nx
|
|
9
|
+
integrated monorepo style][1].
|
|
10
|
+
|
|
11
|
+
:::tip
|
|
12
|
+
|
|
13
|
+
An integrated monorepo is a single workspace.
|
|
14
|
+
|
|
15
|
+
:::
|
|
16
|
+
|
|
17
|
+
## Entry Files
|
|
18
|
+
|
|
19
|
+
The default entrypoints files might not be enough. Here's an idea that might fit
|
|
20
|
+
this type of monorepo:
|
|
21
|
+
|
|
22
|
+
```json title="knip.json"
|
|
23
|
+
{
|
|
24
|
+
"entry": ["{apps,libs}/**/src/index.{ts,tsx}"],
|
|
25
|
+
"project": ["{apps,libs}/**/src/**/*.{ts,tsx}"]
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Plugins
|
|
30
|
+
|
|
31
|
+
Let's assume some of these projects are applications ("apps") which have their
|
|
32
|
+
own ESLint configuration files and Cypress configuration and test files. This
|
|
33
|
+
may result in those files getting reported as unused, and consequently also the
|
|
34
|
+
dependencies they import and refer to.
|
|
35
|
+
|
|
36
|
+
In that case, we could configure the ESLint and Cypress plugins like this:
|
|
37
|
+
|
|
38
|
+
```json title="knip.json"
|
|
39
|
+
{
|
|
40
|
+
"eslint": {
|
|
41
|
+
"config": ["{apps,libs}/**/.eslintrc.json"]
|
|
42
|
+
},
|
|
43
|
+
"cypress": {
|
|
44
|
+
"entry": ["apps/**/cypress.config.ts", "apps/**/cypress/e2e/*.spec.ts"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Adapt the file patterns to your project, and the relevant `config` and `entry`
|
|
50
|
+
files and dependencies should no longer be reported as unused.
|
|
51
|
+
|
|
52
|
+
## Internal Workspace Dependencies
|
|
53
|
+
|
|
54
|
+
A note about repositories with multiple `package.json` files and **internal**
|
|
55
|
+
workspace packages: it is recommended to list all dependencies in each consuming
|
|
56
|
+
`package.json`, allowing Knip to do fine-grained reporting of both unused and
|
|
57
|
+
unlisted dependencies.
|
|
58
|
+
|
|
59
|
+
An alternative is to `ignoreDependencies: ["@internal/*"]`.
|
|
60
|
+
|
|
61
|
+
[1]: https://nx.dev/getting-started/tutorials/integrated-repo-tutorial
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Monorepos & Workspaces
|
|
3
|
+
sidebar:
|
|
4
|
+
order: 2
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Workspaces are handled out-of-the-box by Knip.
|
|
8
|
+
|
|
9
|
+
Workspaces are sometimes also referred to as package-based monorepos, or as
|
|
10
|
+
packages in a monorepo. Knip uses the term workspace exclusively to indicate a
|
|
11
|
+
directory that has a `package.json`.
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
Here's example configuration with custom `entry` and `project` patterns:
|
|
16
|
+
|
|
17
|
+
```json title="knip.json"
|
|
18
|
+
{
|
|
19
|
+
"workspaces": {
|
|
20
|
+
".": {
|
|
21
|
+
"entry": "scripts/*.js",
|
|
22
|
+
"project": "scripts/**/*.js"
|
|
23
|
+
},
|
|
24
|
+
"packages/*": {
|
|
25
|
+
"entry": "{index,cli}.ts",
|
|
26
|
+
"project": "**/*.ts"
|
|
27
|
+
},
|
|
28
|
+
"packages/cli": {
|
|
29
|
+
"entry": "bin/cli.js"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
:::tip
|
|
36
|
+
|
|
37
|
+
Run Knip without any configuration to see if and where custom `entry` and/or
|
|
38
|
+
`project` files are necessary per workspace.
|
|
39
|
+
|
|
40
|
+
:::
|
|
41
|
+
|
|
42
|
+
Each workspace has the same [default configuration][1].
|
|
43
|
+
|
|
44
|
+
The root workspace is named `"."` under `workspaces` (like in the example
|
|
45
|
+
above).
|
|
46
|
+
|
|
47
|
+
:::caution
|
|
48
|
+
|
|
49
|
+
In a project with workspaces, the `entry` and `project` options at the root
|
|
50
|
+
level are ignored. Use the workspace named `"."` for those (like in the example
|
|
51
|
+
above).
|
|
52
|
+
|
|
53
|
+
:::
|
|
54
|
+
|
|
55
|
+
## Workspaces
|
|
56
|
+
|
|
57
|
+
Knip reads workspaces from four possible locations:
|
|
58
|
+
|
|
59
|
+
1. The `workspaces` array in `package.json` (npm, Bun, Yarn, Lerna)
|
|
60
|
+
2. The `packages` array in `pnpm-workspace.yaml` (pnpm)
|
|
61
|
+
3. The `workspaces.packages` array in `package.json` (legacy)
|
|
62
|
+
4. The `workspaces` object in Knip configuration
|
|
63
|
+
|
|
64
|
+
The `workspaces` in Knip configuration (4) not already defined in the root
|
|
65
|
+
`package.json` or `pnpm-workspace.yaml` (1, 2, 3) are added to the analysis.
|
|
66
|
+
|
|
67
|
+
:::caution
|
|
68
|
+
|
|
69
|
+
A workspace must have a `package.json` file.
|
|
70
|
+
|
|
71
|
+
:::
|
|
72
|
+
|
|
73
|
+
For projects with only a root `package.json`, please see [integrated
|
|
74
|
+
monorepos][2].
|
|
75
|
+
|
|
76
|
+
## Additional workspaces
|
|
77
|
+
|
|
78
|
+
If a workspaces is not configured as such in `package.json#workspaces` (or
|
|
79
|
+
`pnpm-workspace.yaml`) it can be added to the Knip configuration manually. Add
|
|
80
|
+
their path to the `workspaces` configuration object the same way as
|
|
81
|
+
`"packages/cli": {}` in the example above.
|
|
82
|
+
|
|
83
|
+
## Source mapping
|
|
84
|
+
|
|
85
|
+
See [Source Mapping][3].
|
|
86
|
+
|
|
87
|
+
## Additional options
|
|
88
|
+
|
|
89
|
+
The following options are available inside workspace configurations:
|
|
90
|
+
|
|
91
|
+
- [ignore][4]
|
|
92
|
+
- [ignoreBinaries][5]
|
|
93
|
+
- [ignoreDependencies][6]
|
|
94
|
+
- [ignoreMembers][7]
|
|
95
|
+
- [ignoreUnresolved][8]
|
|
96
|
+
- [includeEntryExports][9]
|
|
97
|
+
|
|
98
|
+
[Plugins][10] can be configured separately per workspace.
|
|
99
|
+
|
|
100
|
+
Use `--debug` for verbose output and see the workspaces Knip includes, their
|
|
101
|
+
configurations, enabled plugins, glob options and resolved files.
|
|
102
|
+
|
|
103
|
+
## Lint a single workspace
|
|
104
|
+
|
|
105
|
+
Use the `--workspace` (or `-W`) argument to focus on a single workspace (and let
|
|
106
|
+
Knip run faster). Example:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
knip --workspace packages/my-lib
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
This will include the target workspace, but also ancestor and dependent
|
|
113
|
+
workspaces. For two reasons:
|
|
114
|
+
|
|
115
|
+
- Ancestor workspaces may list dependencies in `package.json` the linted
|
|
116
|
+
workspace uses.
|
|
117
|
+
- Dependent workspaces may reference exports from the linted workspace.
|
|
118
|
+
|
|
119
|
+
To lint the workspace in isolation, there are two options:
|
|
120
|
+
|
|
121
|
+
- Combine the `workspace` argument with [strict production mode][11].
|
|
122
|
+
- Run Knip from inside the workspace directory.
|
|
123
|
+
|
|
124
|
+
[1]: ../overview/configuration.md#defaults
|
|
125
|
+
[2]: ./integrated-monorepos.md
|
|
126
|
+
[3]: ./source-mapping.md
|
|
127
|
+
[4]: ../reference/configuration.md#ignore
|
|
128
|
+
[5]: ../reference/configuration.md#ignorebinaries
|
|
129
|
+
[6]: ../reference/configuration.md#ignoredependencies
|
|
130
|
+
[7]: ../reference/configuration.md#ignoremembers
|
|
131
|
+
[8]: ../reference/configuration.md#ignoreunresolved
|
|
132
|
+
[9]: ../reference/configuration.md#includeentryexports
|
|
133
|
+
[10]: ../reference/configuration.md#plugins
|
|
134
|
+
[11]: ./production-mode.md#strict-mode
|