knip 1.0.0-beta.2 → 1.0.0-beta.3

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/README.md CHANGED
@@ -61,14 +61,14 @@ Create a configuration file, let's give it the default name `knip.json` with the
61
61
 
62
62
  ```json
63
63
  {
64
- "$schema": "https://unpkg.com/knip@alpha/schema.json",
64
+ "$schema": "https://unpkg.com/knip@next/schema.json",
65
65
  "entry": ["src/index.ts"],
66
66
  "project": ["src/**/*.ts"]
67
67
  }
68
68
  ```
69
69
 
70
- The `entry` files target the starting point(s) to resolve code dependencies. The `project` files should contain all
71
- files it should match them against, including potentially unused files.
70
+ The `entry` files target the starting point(s) to resolve the rest of the imported code. The `project` files should
71
+ contain all files to match against the files resolved from the entry files, including potentially unused files.
72
72
 
73
73
  Then run the checks:
74
74
 
@@ -184,7 +184,7 @@ be part of the analysis. Here's a simple example:
184
184
  ```jsonc
185
185
  {
186
186
  "ignore": "**/fixtures/**",
187
- "ignoreBinaries": ["deno", "git"],
187
+ "ignoreBinaries": ["rm", "docker-compose"],
188
188
  "ignoreWorkspaces": ["packages/ignore-me"],
189
189
  "workspaces": {
190
190
  "packages/*": {
@@ -262,7 +262,7 @@ idea of how they work and why they are needed:
262
262
  - Static configuration files such as JSON and YAML always require a custom dependency resolver.
263
263
 
264
264
  Custom dependency resolvers return all referenced dependencies for the configuration files it is given. Knip handles the
265
- rest.
265
+ rest to find which of those dependencies are unused or missing.
266
266
 
267
267
  ### `entry`
268
268
 
@@ -15,6 +15,7 @@ export default class ConfigurationChief {
15
15
  config: Configuration;
16
16
  manifestPath: undefined | string;
17
17
  manifest: undefined | PackageJson;
18
+ manifestWorkspaces: undefined | string[];
18
19
  constructor({ cwd, isStrict, isProduction }: ConfigurationManagerOptions);
19
20
  loadLocalConfig(): Promise<void>;
20
21
  normalize(rawLocalConfig: z.infer<typeof ConfigurationValidator>): {
@@ -35,7 +36,8 @@ export default class ConfigurationChief {
35
36
  config: WorkspaceConfiguration;
36
37
  ancestors: string[];
37
38
  }[]>;
38
- getNegatedWorkspacePatterns(): Promise<string[]>;
39
+ getDescendentWorkspaces(name: string): Promise<string[]>;
40
+ getNegatedWorkspacePatterns(name: string): Promise<string[]>;
39
41
  private getConfigKeyForWorkspace;
40
42
  private hasConfigForWorkspace;
41
43
  getConfigForWorkspace(workspaceName: string): WorkspaceConfiguration;
@@ -8,12 +8,12 @@ import { arrayify } from './util/array.js';
8
8
  import { ConfigurationError } from './util/errors.js';
9
9
  import { findFile, loadJSON } from './util/fs.js';
10
10
  import parsedArgs from './util/parseArgs.js';
11
- import { resolveIncludedIssueTypes } from './util/resolveIncludedIssueTypes.js';
11
+ import { resolveIncludedIssueTypes } from './util/resolve-included-issue-types.js';
12
12
  import { byPathDepth } from './util/workspace.js';
13
13
  const { values: { config: rawConfigArg, workspace: rawWorkspaceArg, include = [], exclude = [] }, } = parsedArgs;
14
14
  const defaultWorkspaceConfig = {
15
- entry: ['index.{js,ts,tsx}', 'src/index.{js,ts,tsx}'],
16
- project: ['**/*.{js,ts,tsx}'],
15
+ entry: ['index.{js,ts,tsx}!', 'src/index.{js,ts,tsx}!'],
16
+ project: ['**/*.{js,ts,tsx}!'],
17
17
  ignore: [],
18
18
  };
19
19
  const defaultConfig = {
@@ -35,6 +35,7 @@ export default class ConfigurationChief {
35
35
  config;
36
36
  manifestPath;
37
37
  manifest;
38
+ manifestWorkspaces;
38
39
  constructor({ cwd, isStrict, isProduction }) {
39
40
  this.cwd = cwd ?? this.cwd;
40
41
  this.isStrict = isStrict;
@@ -115,6 +116,8 @@ export default class ConfigurationChief {
115
116
  };
116
117
  }
117
118
  async getManifestWorkspaces() {
119
+ if (this.manifestWorkspaces)
120
+ return this.manifestWorkspaces;
118
121
  if (this.manifest) {
119
122
  const workspaces = await mapWorkspaces({
120
123
  pkg: this.manifest,
@@ -122,7 +125,8 @@ export default class ConfigurationChief {
122
125
  ignore: this.config.ignoreWorkspaces,
123
126
  absolute: false,
124
127
  });
125
- return Array.from(workspaces.values()).map(workspaceDir => path.relative(this.cwd, workspaceDir));
128
+ this.manifestWorkspaces = Array.from(workspaces.values()).map(dir => path.relative(this.cwd, dir));
129
+ return this.manifestWorkspaces;
126
130
  }
127
131
  return [];
128
132
  }
@@ -172,11 +176,17 @@ export default class ConfigurationChief {
172
176
  }, []),
173
177
  }));
174
178
  }
175
- async getNegatedWorkspacePatterns() {
179
+ async getDescendentWorkspaces(name) {
176
180
  const manifestWorkspaces = await this.getManifestWorkspaces();
177
181
  const additionalWorkspaces = this.getAdditionalWorkspaces(manifestWorkspaces);
178
182
  return [...manifestWorkspaces, ...additionalWorkspaces]
179
- .filter(workspaceName => workspaceName !== ROOT_WORKSPACE_NAME)
183
+ .filter(workspaceName => workspaceName !== name)
184
+ .filter(workspaceName => name === ROOT_WORKSPACE_NAME || workspaceName.startsWith(name));
185
+ }
186
+ async getNegatedWorkspacePatterns(name) {
187
+ const descendentWorkspaces = await this.getDescendentWorkspaces(name);
188
+ return descendentWorkspaces
189
+ .map(workspaceName => path.relative(path.join(this.cwd, name), workspaceName))
180
190
  .map(workspaceName => `!${workspaceName}`);
181
191
  }
182
192
  getConfigKeyForWorkspace(workspaceName) {
@@ -191,9 +201,8 @@ export default class ConfigurationChief {
191
201
  }
192
202
  getConfigForWorkspace(workspaceName) {
193
203
  const key = this.getConfigKeyForWorkspace(workspaceName);
194
- if (key) {
195
- return this.config?.workspaces?.[key] ?? { entry: [], project: [], ignore: [] };
196
- }
204
+ if (key && this.config?.workspaces?.[key])
205
+ return this.config.workspaces[key];
197
206
  return { entry: [], project: [], ignore: [] };
198
207
  }
199
208
  resolveIncludedIssueTypes() {
package/dist/index.js CHANGED
@@ -7,7 +7,7 @@ import ProjectPrincipal from './project-principal.js';
7
7
  import SourceLab from './source-lab.js';
8
8
  import { compact } from './util/array.js';
9
9
  import { debugLogObject, debugLogFiles } from './util/debug.js';
10
- import { _findImportModuleSpecifiers } from './util/externalImports.js';
10
+ import { _findImportModuleSpecifiers } from './util/find-import-specifiers.js';
11
11
  import { findFile, loadJSON } from './util/fs.js';
12
12
  import { _glob } from './util/glob.js';
13
13
  import { getPackageNameFromModuleSpecifier } from './util/modules.js';
@@ -24,7 +24,6 @@ export const main = async (unresolvedConfiguration) => {
24
24
  await chief.loadLocalConfig();
25
25
  const deputy = new DependencyDeputy({ ignoreDependencies: chief.config.ignoreDependencies });
26
26
  const workspaces = await chief.getActiveWorkspaces();
27
- const negatedWorkspacePatterns = await chief.getNegatedWorkspacePatterns();
28
27
  debugLogObject('Included workspaces', workspaces);
29
28
  const report = chief.resolveIncludedIssueTypes();
30
29
  const workspaceDirs = Object.values(workspaces)
@@ -54,6 +53,7 @@ export const main = async (unresolvedConfiguration) => {
54
53
  const workspaceManifest = deputy.getWorkspaceManifest(name);
55
54
  if (!workspaceManifest)
56
55
  continue;
56
+ const negatedWorkspacePatterns = await chief.getNegatedWorkspacePatterns(name);
57
57
  const worker = new WorkspaceWorker({
58
58
  name,
59
59
  dir,
@@ -0,0 +1,7 @@
1
+ import type { IsPluginEnabledCallback, GenericPluginCallback } from '../../types/plugins.js';
2
+ export declare const CONFIG_FILE_PATTERNS: never[];
3
+ export declare const ENTRY_FILE_PATTERNS: never[];
4
+ export declare const PRODUCTION_ENTRY_FILE_PATTERNS: never[];
5
+ export declare const PROJECT_FILE_PATTERNS: never[];
6
+ export declare const isEnabled: IsPluginEnabledCallback;
7
+ export declare const findDependencies: GenericPluginCallback;
@@ -0,0 +1,14 @@
1
+ import { _load } from '../../util/loader.js';
2
+ import { timerify } from '../../util/performance.js';
3
+ export const CONFIG_FILE_PATTERNS = [];
4
+ export const ENTRY_FILE_PATTERNS = [];
5
+ export const PRODUCTION_ENTRY_FILE_PATTERNS = [];
6
+ export const PROJECT_FILE_PATTERNS = [];
7
+ export const isEnabled = ({ dependencies }) => {
8
+ return dependencies.has('[pkg]');
9
+ };
10
+ const findPluginDependencies = async (configFilePath, { manifest }) => {
11
+ const config = configFilePath.endsWith('package.json') ? manifest.plugin : await _load(configFilePath);
12
+ return config?.plugins ?? [];
13
+ };
14
+ export const findDependencies = timerify(findPluginDependencies);
@@ -0,0 +1,3 @@
1
+ export type PluginConfig = {
2
+ plugins?: string[];
3
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,34 +1,12 @@
1
+ import * as Plugins from '../plugins/index.js';
1
2
  type NormalizedGlob = string[];
3
+ export type PluginName = keyof typeof Plugins;
2
4
  export type PluginConfiguration = {
3
5
  config: NormalizedGlob | null;
4
6
  entry: NormalizedGlob | null;
5
7
  project: NormalizedGlob | null;
6
8
  } | false;
7
- interface PluginsConfiguration {
8
- babel: PluginConfiguration;
9
- capacitor: PluginConfiguration;
10
- changesets: PluginConfiguration;
11
- commitlint: PluginConfiguration;
12
- cypress: PluginConfiguration;
13
- eslint: PluginConfiguration;
14
- gatsby: PluginConfiguration;
15
- jest: PluginConfiguration;
16
- mocha: PluginConfiguration;
17
- next: PluginConfiguration;
18
- nx: PluginConfiguration;
19
- nyc: PluginConfiguration;
20
- playwright: PluginConfiguration;
21
- postcss: PluginConfiguration;
22
- prettier: PluginConfiguration;
23
- remark: PluginConfiguration;
24
- remix: PluginConfiguration;
25
- rollup: PluginConfiguration;
26
- sentry: PluginConfiguration;
27
- storybook: PluginConfiguration;
28
- stryker: PluginConfiguration;
29
- typescript: PluginConfiguration;
30
- webpack: PluginConfiguration;
31
- }
9
+ type PluginsConfiguration = Record<PluginName, PluginConfiguration>;
32
10
  interface BaseWorkspaceConfiguration {
33
11
  entry: NormalizedGlob;
34
12
  project: NormalizedGlob;
@@ -36,7 +14,6 @@ interface BaseWorkspaceConfiguration {
36
14
  }
37
15
  export interface WorkspaceConfiguration extends BaseWorkspaceConfiguration, Partial<PluginsConfiguration> {
38
16
  }
39
- export type PluginName = keyof PluginsConfiguration;
40
17
  export interface Configuration {
41
18
  include: string[];
42
19
  exclude: string[];
@@ -30,8 +30,12 @@ const findImportModuleSpecifiers = (sourceFile, options = { skipInternal: false
30
30
  const moduleSpecifiers = compact([...importLiterals, ...requireCallExpressions].map(importLiteral => {
31
31
  if (!importLiteral)
32
32
  return;
33
- if (importLiteral.isKind(ts.SyntaxKind.TemplateExpression))
34
- return importLiteral.getFullText().slice(1, -1);
33
+ if (importLiteral.isKind(ts.SyntaxKind.TemplateExpression)) {
34
+ const literalText = importLiteral.getFullText();
35
+ if (literalText.includes('${'))
36
+ return;
37
+ return literalText.slice(1, -1);
38
+ }
35
39
  return importLiteral?.getLiteralText();
36
40
  }));
37
41
  const internalModuleSpecifiers = options.skipInternal ? [] : resolveInternal(filePath, moduleSpecifiers);
@@ -76,7 +76,7 @@ export default class WorkspaceWorker {
76
76
  const { entry } = this.config;
77
77
  if (entry.length === 0)
78
78
  return [];
79
- return [entry, TEST_FILE_PATTERNS, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
79
+ return [entry, TEST_FILE_PATTERNS, this.negatedWorkspacePatterns].flat();
80
80
  }
81
81
  getProjectFilePatterns() {
82
82
  const { project } = this.config;
@@ -91,7 +91,7 @@ export default class WorkspaceWorker {
91
91
  negatedPluginEntryFilePatterns,
92
92
  negatedPluginProjectFilePatterns,
93
93
  TEST_FILE_PATTERNS,
94
- this.isRoot ? this.negatedWorkspacePatterns : [],
94
+ this.negatedWorkspacePatterns,
95
95
  ].flat();
96
96
  }
97
97
  getPluginEntryFilePatterns(isIncludeProductionEntryFiles = true) {
@@ -108,7 +108,7 @@ export default class WorkspaceWorker {
108
108
  }
109
109
  }
110
110
  }
111
- return [patterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
111
+ return [patterns, this.negatedWorkspacePatterns].flat();
112
112
  }
113
113
  getPluginProjectFilePatterns() {
114
114
  const patterns = [];
@@ -125,7 +125,7 @@ export default class WorkspaceWorker {
125
125
  : [])));
126
126
  }
127
127
  }
128
- return [patterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
128
+ return [patterns, this.negatedWorkspacePatterns].flat();
129
129
  }
130
130
  getPluginConfigPatterns() {
131
131
  const patterns = [];
@@ -144,7 +144,7 @@ export default class WorkspaceWorker {
144
144
  if (entry.length === 0)
145
145
  return [];
146
146
  const negatedEntryFiles = this.config.entry.filter(hasNoProductionSuffix).map(negate);
147
- return [entry, negatedEntryFiles, negatedTestFilePatterns, this.isRoot ? this.negatedWorkspacePatterns : []].flat();
147
+ return [entry, negatedEntryFiles, negatedTestFilePatterns, this.negatedWorkspacePatterns].flat();
148
148
  }
149
149
  getProductionProjectFilePatterns() {
150
150
  const project = this.config.project;
@@ -166,7 +166,7 @@ export default class WorkspaceWorker {
166
166
  negatedPluginEntryFilePatterns,
167
167
  negatedPluginProjectFilePatterns,
168
168
  negatedTestFilePatterns,
169
- this.isRoot ? this.negatedWorkspacePatterns : [],
169
+ this.negatedWorkspacePatterns,
170
170
  ].flat();
171
171
  }
172
172
  getProductionPluginEntryFilePatterns() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knip",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.3",
4
4
  "description": "Find unused files, dependencies and exports in your TypeScript and JavaScript project",
5
5
  "keywords": [
6
6
  "find",
@@ -42,7 +42,9 @@
42
42
  "prepublishOnly": "npm test && npm run build && npm run knip",
43
43
  "format": "remark README.md -o",
44
44
  "release": "release-it",
45
- "postinstall": "patch-package"
45
+ "postinstall": "patch-package",
46
+ "add-plugin:help": "echo 'Usage: npm run add-plugin --name=[name] (and update README.md and schema.json)'",
47
+ "add-plugin": "cp -R src/plugins/_template src/plugins/$npm_config_name && echo \"export * as $npm_config_name from \\\"./$npm_config_name/index.js\\\";\" >> src/plugins/index.ts"
46
48
  },
47
49
  "files": [
48
50
  "dist",
@@ -59,7 +61,7 @@
59
61
  "@snyk/github-codeowners": "1.1.0",
60
62
  "chalk": "5.2.0",
61
63
  "easy-table": "1.2.0",
62
- "esbuild": "0.16.10",
64
+ "esbuild": "0.16.11",
63
65
  "esbuild-register": "3.4.2",
64
66
  "eslint": "8.30.0",
65
67
  "fast-glob": "3.2.12",
@@ -81,11 +83,11 @@
81
83
  "@types/eslint": "8.4.10",
82
84
  "@types/js-yaml": "4.0.5",
83
85
  "@types/micromatch": "4.0.2",
84
- "@types/node": "18.11.17",
86
+ "@types/node": "18.11.18",
85
87
  "@types/npmcli__map-workspaces": "3.0.0",
86
88
  "@types/webpack": "5.28.0",
87
- "@typescript-eslint/eslint-plugin": "5.47.0",
88
- "@typescript-eslint/parser": "5.47.0",
89
+ "@typescript-eslint/eslint-plugin": "5.47.1",
90
+ "@typescript-eslint/parser": "5.47.1",
89
91
  "eslint-import-resolver-typescript": "3.5.2",
90
92
  "eslint-plugin-import": "2.26.0",
91
93
  "globstar": "1.0.0",
@@ -93,7 +95,7 @@
93
95
  "remark-cli": "11.0.0",
94
96
  "remark-preset-webpro": "0.0.1",
95
97
  "tsx": "3.12.1",
96
- "type-fest": "3.4.0",
98
+ "type-fest": "3.5.0",
97
99
  "typescript": "4.9.4"
98
100
  },
99
101
  "release-it": {
package/schema.json CHANGED
@@ -1,5 +1,7 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "Knip configuration",
4
+ "description": "See https://github.com/webpro/knip",
3
5
  "type": "object",
4
6
  "allOf": [
5
7
  {
@@ -7,25 +9,45 @@
7
9
  },
8
10
  {
9
11
  "$ref": "#/definitions/plugins"
12
+ },
13
+ {
14
+ "properties": {
15
+ "$schema": {
16
+ "type": "string",
17
+ "title": "JSON Schema",
18
+ "description": "Pointer to the schema against which this document should be validated."
19
+ }
20
+ }
10
21
  }
11
22
  ],
12
23
  "properties": {
13
24
  "ignoreBinaries": {
25
+ "title": "Binaries to ignore",
26
+ "examples": ["rm", "docker-compose", "eslint"],
14
27
  "$ref": "#/definitions/list"
15
28
  },
16
29
  "ignoreDependencies": {
30
+ "title": "Dependencies from package.json to ignore",
31
+ "examples": ["husky", "lint-staged"],
17
32
  "$ref": "#/definitions/list"
18
33
  },
19
34
  "ignoreWorkspaces": {
35
+ "title": "Workspaces to ignore",
36
+ "examples": ["packages/ignore-me"],
20
37
  "$ref": "#/definitions/list"
21
38
  },
22
39
  "include": {
23
- "$ref": "#/definitions/list"
40
+ "title": "Include issue types in the report",
41
+ "examples": ["files", "dependencies"],
42
+ "$ref": "#/definitions/issueTypes"
24
43
  },
25
44
  "exclude": {
26
- "$ref": "#/definitions/list"
45
+ "title": "Exclude issue types from the report",
46
+ "examples": ["classMembers", "enumMembers"],
47
+ "$ref": "#/definitions/issueTypes"
27
48
  },
28
49
  "workspaces": {
50
+ "title": "Configuration for workspaces",
29
51
  "type": "object",
30
52
  "additionalProperties": {
31
53
  "allOf": [
@@ -48,7 +70,26 @@
48
70
  "type": "string"
49
71
  }
50
72
  },
73
+ "issueTypes": {
74
+ "type": "array",
75
+ "items": {
76
+ "type": "string",
77
+ "enum": [
78
+ "files",
79
+ "dependencies",
80
+ "unlisted",
81
+ "exports",
82
+ "nsExports",
83
+ "classMembers",
84
+ "types",
85
+ "nsTypes",
86
+ "enumMembers",
87
+ "duplicates"
88
+ ]
89
+ }
90
+ },
51
91
  "globPatterns": {
92
+ "description": "Use file paths and glob patterns to match files. Knip uses fast-glob and and minimatch (https://github.com/micromatch/micromatch#matching-features)",
52
93
  "anyOf": [
53
94
  {
54
95
  "type": "string"
@@ -62,22 +103,30 @@
62
103
  ]
63
104
  },
64
105
  "workspace": {
65
- "description": "Workspace configuration.",
66
106
  "type": "object",
67
107
  "properties": {
68
108
  "entry": {
109
+ "title": "The entry files target the starting point(s) to resolve the rest of the imported code.",
110
+ "example": ["lib/index.ts"],
111
+ "default": ["index.{js,ts,tsx}", "src/index.{js,ts,tsx}"],
69
112
  "$ref": "#/definitions/globPatterns"
70
113
  },
71
114
  "project": {
115
+ "title": "The project files should contain all files to match against the files resolved from the entry files, including potentially unused files.",
116
+ "example": ["lib/**/*.ts"],
117
+ "default": ["**/*.{js,ts,tsx}"],
72
118
  "$ref": "#/definitions/globPatterns"
73
119
  },
74
120
  "ignore": {
121
+ "title": "Files to ignore in the analysis.",
122
+ "example": ["**/fixtures", "mocks"],
123
+ "default": [],
75
124
  "$ref": "#/definitions/globPatterns"
76
125
  }
77
126
  }
78
127
  },
79
128
  "plugin": {
80
- "description": "Knip plugin configuration. See https://github.com/webpro/knip#plugins",
129
+ "description": "Knip plugin configuration. See https://github.com/webpro/knip/blob/next/README.md#plugins",
81
130
  "anyOf": [
82
131
  { "const": false },
83
132
  {
@@ -87,12 +136,17 @@
87
136
  "type": "object",
88
137
  "properties": {
89
138
  "config": {
139
+ "title": "The custom dependency resolver of this plugin is applied to the files listed here. Also see https://github.com/webpro/knip/blob/next/README.md#config",
140
+ "examples": [".eslintrc.json"],
90
141
  "$ref": "#/definitions/globPatterns"
91
142
  },
92
143
  "entry": {
144
+ "title": "The entry files target the starting point(s) to resolve its imported dependencies, like regular source code.",
145
+ "examples": ["**/*.story.ts", "**/*.spec.ts"],
93
146
  "$ref": "#/definitions/globPatterns"
94
147
  },
95
148
  "project": {
149
+ "title": "The project files should contain all files to match against the files resolved from the entry files for this plugin, including potentially unused files.",
96
150
  "$ref": "#/definitions/globPatterns"
97
151
  }
98
152
  },
@@ -103,72 +157,95 @@
103
157
  "plugins": {
104
158
  "properties": {
105
159
  "babel": {
160
+ "title": "Babel plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/babel/README.md)",
106
161
  "$ref": "#/definitions/plugin"
107
162
  },
108
163
  "capacitor": {
164
+ "title": "Capacitor plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/capacitor/README.md)",
109
165
  "$ref": "#/definitions/plugin"
110
166
  },
111
167
  "changesets": {
168
+ "title": "Changesets plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/changesets/README.md)",
112
169
  "$ref": "#/definitions/plugin"
113
170
  },
114
171
  "commitlint": {
172
+ "title": "commitlint plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/commitlint/README.md)",
115
173
  "$ref": "#/definitions/plugin"
116
174
  },
117
175
  "cypress": {
176
+ "title": "Cypress plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/cypress/README.md)",
118
177
  "$ref": "#/definitions/plugin"
119
178
  },
120
179
  "eslint": {
180
+ "title": "ESLint plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/eslint/README.md)",
121
181
  "$ref": "#/definitions/plugin"
122
182
  },
123
183
  "gatsby": {
184
+ "title": "Gatsby plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/gatsby/README.md)",
124
185
  "$ref": "#/definitions/plugin"
125
186
  },
126
187
  "jest": {
188
+ "title": "Jest plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/jest/README.md)",
127
189
  "$ref": "#/definitions/plugin"
128
190
  },
129
191
  "mocha": {
192
+ "title": "Mocha plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/mocha/README.md)",
130
193
  "$ref": "#/definitions/plugin"
131
194
  },
132
195
  "next": {
196
+ "title": "Next.js plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/next/README.md)",
133
197
  "$ref": "#/definitions/plugin"
134
198
  },
135
199
  "nx": {
200
+ "title": "Nx plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/nx/README.md)",
136
201
  "$ref": "#/definitions/plugin"
137
202
  },
138
203
  "nyc": {
204
+ "title": "nyc plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/nyc/README.md)",
139
205
  "$ref": "#/definitions/plugin"
140
206
  },
141
207
  "playwright": {
208
+ "title": "Playwright plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/playwright/README.md)",
142
209
  "$ref": "#/definitions/plugin"
143
210
  },
144
211
  "postcss": {
212
+ "title": "PostCSS plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/postcss/README.md)",
145
213
  "$ref": "#/definitions/plugin"
146
214
  },
147
215
  "prettier": {
216
+ "title": "Prettier plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/prettier/README.md)",
148
217
  "$ref": "#/definitions/plugin"
149
218
  },
150
219
  "remark": {
220
+ "title": "Remark plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/remark/README.md)",
151
221
  "$ref": "#/definitions/plugin"
152
222
  },
153
223
  "remix": {
224
+ "title": "Remix plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/remix/README.md)",
154
225
  "$ref": "#/definitions/plugin"
155
226
  },
156
227
  "rollup": {
228
+ "title": "Rollup plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/rollup/README.md)",
157
229
  "$ref": "#/definitions/plugin"
158
230
  },
159
231
  "sentry": {
232
+ "title": "Sentry plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/sentry/README.md)",
160
233
  "$ref": "#/definitions/plugin"
161
234
  },
162
235
  "storybook": {
236
+ "title": "Storybook plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/storybook/README.md)",
163
237
  "$ref": "#/definitions/plugin"
164
238
  },
165
239
  "stryker": {
240
+ "title": "Stryker plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/stryker/README.md)",
166
241
  "$ref": "#/definitions/plugin"
167
242
  },
168
243
  "typescript": {
244
+ "title": "TypeScript plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/typescript/README.md)",
169
245
  "$ref": "#/definitions/plugin"
170
246
  },
171
247
  "webpack": {
248
+ "title": "Webpack plugin configuration (https://github.com/webpro/knip/blob/next/src/plugins/webpack/README.md)",
172
249
  "$ref": "#/definitions/plugin"
173
250
  }
174
251
  }