knip 5.55.0 → 5.56.0

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.
Files changed (60) hide show
  1. package/README.md +1 -1
  2. package/dist/CacheConsultant.d.ts +1 -0
  3. package/dist/CacheConsultant.js +1 -1
  4. package/dist/ConfigurationChief.d.ts +1 -0
  5. package/dist/ConsoleStreamer.d.ts +1 -1
  6. package/dist/ConsoleStreamer.js +2 -2
  7. package/dist/DependencyDeputy.d.ts +2 -0
  8. package/dist/DependencyDeputy.js +6 -0
  9. package/dist/PrincipalFactory.d.ts +2 -9
  10. package/dist/PrincipalFactory.js +10 -6
  11. package/dist/ProjectPrincipal.d.ts +1 -1
  12. package/dist/ProjectPrincipal.js +3 -3
  13. package/dist/WorkspaceWorker.js +1 -1
  14. package/dist/cli.js +6 -5
  15. package/dist/compilers/index.d.ts +10 -0
  16. package/dist/constants.js +1 -0
  17. package/dist/graph/analyze.js +1 -1
  18. package/dist/graph/build.js +14 -5
  19. package/dist/index.js +1 -1
  20. package/dist/plugins/docusaurus/helpers.d.ts +5 -0
  21. package/dist/plugins/docusaurus/helpers.js +89 -0
  22. package/dist/plugins/docusaurus/index.d.ts +12 -0
  23. package/dist/plugins/docusaurus/index.js +36 -0
  24. package/dist/plugins/docusaurus/types.d.ts +40 -0
  25. package/dist/plugins/docusaurus/types.js +1 -0
  26. package/dist/plugins/index.d.ts +9 -0
  27. package/dist/plugins/index.js +2 -0
  28. package/dist/plugins/webpack/index.js +9 -9
  29. package/dist/reporters/codeclimate.js +3 -3
  30. package/dist/reporters/codeowners.js +15 -30
  31. package/dist/reporters/compact.js +10 -4
  32. package/dist/reporters/disclosure.js +5 -24
  33. package/dist/reporters/markdown.js +2 -2
  34. package/dist/reporters/symbols.d.ts +1 -1
  35. package/dist/reporters/symbols.js +10 -45
  36. package/dist/reporters/util.d.ts +11 -7
  37. package/dist/reporters/util.js +45 -14
  38. package/dist/reporters/watch.js +7 -21
  39. package/dist/schema/configuration.d.ts +56 -0
  40. package/dist/schema/plugins.d.ts +23 -0
  41. package/dist/schema/plugins.js +1 -0
  42. package/dist/types/PluginNames.d.ts +2 -2
  43. package/dist/types/PluginNames.js +1 -0
  44. package/dist/types/project.d.ts +1 -0
  45. package/dist/typescript/resolve-module-names.js +2 -2
  46. package/dist/util/Performance.d.ts +7 -7
  47. package/dist/util/Performance.js +20 -16
  48. package/dist/util/cli-arguments.d.ts +2 -1
  49. package/dist/util/cli-arguments.js +2 -0
  50. package/dist/util/input.d.ts +8 -1
  51. package/dist/util/input.js +6 -0
  52. package/dist/util/resolve.d.ts +3 -1
  53. package/dist/util/resolve.js +7 -9
  54. package/dist/util/table.d.ts +4 -2
  55. package/dist/util/table.js +20 -24
  56. package/dist/util/watch.js +2 -2
  57. package/dist/version.d.ts +1 -1
  58. package/dist/version.js +1 -1
  59. package/package.json +2 -2
  60. package/schema.json +4 -0
package/README.md CHANGED
@@ -41,4 +41,4 @@ Special thanks to [the wonderful people who have contributed to Knip][8]!
41
41
  [5]: https://github.com/webpro-nl/knip/blob/main/.github/CONTRIBUTING.md
42
42
  [6]: https://knip.dev/sponsors
43
43
  [7]: https://www.youtube.com/watch?v=PE7h7KvQoUI&t=9s
44
- [8]: https://knip.dev/#-contributors
44
+ [8]: https://knip.dev/#created-by-awesome-contributors
@@ -3,6 +3,7 @@ type CacheOptions = {
3
3
  name: string;
4
4
  isEnabled: boolean;
5
5
  cacheLocation: string;
6
+ isProduction: boolean;
6
7
  };
7
8
  export declare class CacheConsultant<T> {
8
9
  private isEnabled;
@@ -8,7 +8,7 @@ export class CacheConsultant {
8
8
  constructor(options) {
9
9
  this.isEnabled = options.isEnabled;
10
10
  if (this.isEnabled) {
11
- const cacheName = `${options.name.replace(/[^a-z0-9]/g, '-').replace(/-*$/, '')}-${version}`;
11
+ const cacheName = `${options.name.replace(/[^a-z0-9]/g, '-').replace(/-*$/, '')}-${options.isProduction ? '-prod' : ''}-${version}`;
12
12
  this.cache = new FileEntryCache(cacheName, options.cacheLocation);
13
13
  this.reconcile = timerify(this.cache.reconcile).bind(this.cache);
14
14
  this.getFileDescriptor = timerify(this.cache.getFileDescriptor).bind(this.cache);
@@ -88,6 +88,7 @@ export declare class ConfigurationChief {
88
88
  cucumber?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
89
89
  cypress?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
90
90
  "dependency-cruiser"?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
91
+ docusaurus?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
91
92
  dotenv?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
92
93
  drizzle?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
93
94
  eleventy?: (boolean | import("./types/config.js").EnsuredPluginConfiguration) | undefined;
@@ -7,6 +7,6 @@ export declare class ConsoleStreamer {
7
7
  private clearLines;
8
8
  private resetLines;
9
9
  private update;
10
- cast(message: string | string[]): void;
10
+ cast(message: string | string[], sub?: string): void;
11
11
  clear(): void;
12
12
  }
@@ -21,13 +21,13 @@ export class ConsoleStreamer {
21
21
  process.stdout.write(`${messages.join('\n')}\n`);
22
22
  this.lines = messages.length;
23
23
  }
24
- cast(message) {
24
+ cast(message, sub) {
25
25
  if (!this.isEnabled)
26
26
  return;
27
27
  if (Array.isArray(message))
28
28
  this.update(message);
29
29
  else
30
- this.update([message]);
30
+ this.update([`${message}${!sub || sub === '.' ? '' : ` (${sub})`}…`]);
31
31
  }
32
32
  clear() {
33
33
  if (!this.isEnabled)
@@ -74,5 +74,7 @@ export declare class DependencyDeputy {
74
74
  counters: Counters;
75
75
  }): void;
76
76
  getConfigurationHints(): ConfigurationHints;
77
+ addIgnoredDependencies(workspaceName: string, identifier: string): void;
78
+ addIgnoredBinaries(workspaceName: string, identifier: string): void;
77
79
  }
78
80
  export {};
@@ -350,4 +350,10 @@ export class DependencyDeputy {
350
350
  }
351
351
  return configurationHints;
352
352
  }
353
+ addIgnoredDependencies(workspaceName, identifier) {
354
+ this._manifests.get(workspaceName)?.ignoreDependencies.push(toRegexOrString(identifier));
355
+ }
356
+ addIgnoredBinaries(workspaceName, identifier) {
357
+ this._manifests.get(workspaceName)?.ignoreBinaries.push(toRegexOrString(identifier));
358
+ }
353
359
  }
@@ -1,14 +1,8 @@
1
1
  import { ProjectPrincipal } from './ProjectPrincipal.js';
2
2
  import type { PrincipalOptions } from './types/project.js';
3
- type Principal = {
4
- principal: ProjectPrincipal;
5
- wsDirs: Set<string>;
6
- pathKeys: Set<string>;
7
- pkgNames: Set<string>;
8
- };
9
- type Principals = Set<Principal>;
10
3
  export declare class PrincipalFactory {
11
- principals: Principals;
4
+ private principals;
5
+ getPrincipalCount(): number;
12
6
  createPrincipal(options: PrincipalOptions): ProjectPrincipal;
13
7
  private findReusablePrincipal;
14
8
  private linkPrincipal;
@@ -17,4 +11,3 @@ export declare class PrincipalFactory {
17
11
  getPrincipalByPackageName(packageName: string): ProjectPrincipal | undefined;
18
12
  deletePrincipal(principal: ProjectPrincipal): void;
19
13
  }
20
- export {};
@@ -4,20 +4,25 @@ import { debugLog } from './util/debug.js';
4
4
  import { toRelative } from './util/path.js';
5
5
  export class PrincipalFactory {
6
6
  principals = new Set();
7
+ getPrincipalCount() {
8
+ return this.principals.size;
9
+ }
7
10
  createPrincipal(options) {
8
11
  const { cwd, compilerOptions, isFile, pkgName, isIsolateWorkspaces, compilers } = options;
9
12
  if (isFile && compilerOptions.module !== ts.ModuleKind.CommonJS)
10
13
  compilerOptions.moduleResolution ??= ts.ModuleResolutionKind.Bundler;
11
- const principal = this.findReusablePrincipal(compilerOptions);
12
- if (!isIsolateWorkspaces && principal) {
13
- this.linkPrincipal(principal, cwd, compilerOptions, pkgName, compilers);
14
- return principal.principal;
14
+ if (!isIsolateWorkspaces) {
15
+ const principal = this.findReusablePrincipal(compilerOptions);
16
+ if (principal) {
17
+ this.linkPrincipal(principal, cwd, compilerOptions, pkgName, compilers);
18
+ return principal.principal;
19
+ }
15
20
  }
16
21
  return this.addNewPrincipal(options);
17
22
  }
18
23
  findReusablePrincipal(compilerOptions) {
19
24
  const workspacePaths = compilerOptions?.paths ? Object.keys(compilerOptions.paths) : [];
20
- const principal = Array.from(this.principals).find(principal => {
25
+ return Array.from(this.principals).find(principal => {
21
26
  if (compilerOptions.pathsBasePath && principal.principal.compilerOptions.pathsBasePath)
22
27
  return false;
23
28
  if (compilerOptions.baseUrl === principal.principal.compilerOptions.baseUrl) {
@@ -25,7 +30,6 @@ export class PrincipalFactory {
25
30
  }
26
31
  return !compilerOptions.baseUrl;
27
32
  });
28
- return principal;
29
33
  }
30
34
  linkPrincipal(principal, cwd, compilerOptions, pkgName, compilers) {
31
35
  const { pathsBasePath, paths } = compilerOptions;
@@ -30,7 +30,7 @@ export declare class ProjectPrincipal {
30
30
  languageServiceHost: ts.LanguageServiceHost;
31
31
  };
32
32
  findReferences?: ts.LanguageService['findReferences'];
33
- constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, }: PrincipalOptions);
33
+ constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, isProduction, }: PrincipalOptions);
34
34
  init(): void;
35
35
  addPaths(paths: Paths, basePath: string): void;
36
36
  addCompilers(compilers: [SyncCompilers, AsyncCompilers]): void;
@@ -43,7 +43,7 @@ export class ProjectPrincipal {
43
43
  toSourceFilePath;
44
44
  backend;
45
45
  findReferences;
46
- constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, }) {
46
+ constructor({ compilerOptions, cwd, compilers, isSkipLibs, isWatch, pkgName, toSourceFilePath, isCache, cacheLocation, isProduction, }) {
47
47
  this.cwd = cwd;
48
48
  this.compilerOptions = {
49
49
  ...compilerOptions,
@@ -57,7 +57,7 @@ export class ProjectPrincipal {
57
57
  this.asyncCompilers = asyncCompilers;
58
58
  this.isSkipLibs = isSkipLibs;
59
59
  this.isWatch = isWatch;
60
- this.cache = new CacheConsultant({ name: pkgName || ANONYMOUS, isEnabled: isCache, cacheLocation });
60
+ this.cache = new CacheConsultant({ name: pkgName || ANONYMOUS, isEnabled: isCache, cacheLocation, isProduction });
61
61
  this.toSourceFilePath = toSourceFilePath;
62
62
  this.backend = {
63
63
  fileManager: new SourceFileManager({ compilers, isSkipLibs }),
@@ -162,7 +162,7 @@ export class ProjectPrincipal {
162
162
  return fd.meta.data;
163
163
  const typeChecker = this.backend.typeChecker;
164
164
  if (!typeChecker)
165
- throw new Error('Must initialize TypeChecker before source file analysis');
165
+ throw new Error('TypeChecker must be initialized before source file analysis');
166
166
  const sourceFile = this.backend.fileManager.getSourceFile(filePath);
167
167
  if (!sourceFile)
168
168
  throw new Error(`Unable to find ${filePath}`);
@@ -49,7 +49,7 @@ export class WorkspaceWorker {
49
49
  this.getReferencedInternalFilePath = getReferencedInternalFilePath;
50
50
  this.findWorkspaceByFilePath = findWorkspaceByFilePath;
51
51
  this.getSourceFile = getSourceFile;
52
- this.cache = new CacheConsultant({ name: `plugins-${name}`, isEnabled: isCache, cacheLocation });
52
+ this.cache = new CacheConsultant({ name: `plugins-${name}`, isEnabled: isCache, cacheLocation, isProduction });
53
53
  }
54
54
  async init() {
55
55
  this.enabledPlugins = await this.determineEnabledPlugins();
package/dist/cli.js CHANGED
@@ -10,7 +10,7 @@ import { splitTags } from './util/tag.js';
10
10
  import { isTrace } from './util/trace.js';
11
11
  import { version } from './version.js';
12
12
  const defaultCacheLocation = join(cwd, 'node_modules', '.cache', 'knip');
13
- const { 'allow-remove-files': isRemoveFiles = false, cache: isCache = false, 'cache-location': cacheLocation = defaultCacheLocation, debug: isDebug = false, dependencies: isDependenciesShorthand = false, exclude: excludedIssueTypes = [], 'experimental-tags': experimentalTags = [], exports: isExportsShorthand = false, files: isFilesShorthand = false, fix: isFix = false, format: isFormat = false, 'fix-type': fixTypes = [], help: isHelp, include: includedIssueTypes = [], 'include-entry-exports': isIncludeEntryExports = false, 'include-libs': isIncludeLibs = false, 'isolate-workspaces': isIsolateWorkspaces = false, 'max-issues': maxIssues = '0', 'no-config-hints': isDisableConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = isDebug || isTrace, preprocessor = [], 'preprocessor-options': preprocessorOptions = '', production: isProduction = false, reporter = ['symbols'], 'reporter-options': reporterOptions = '', strict: isStrict = false, tags = [], 'treat-config-hints-as-errors': treatConfigHintsAsErrors = false, tsConfig, version: isVersion, watch: isWatch = false, workspace: rawWorkspaceArg, } = parsedArgValues;
13
+ const { 'allow-remove-files': isRemoveFiles = false, cache: isCache = false, 'cache-location': cacheLocation = defaultCacheLocation, debug: isDebug = false, dependencies: isDependenciesShorthand = false, exclude: excludedIssueTypes = [], 'experimental-tags': experimentalTags = [], exports: isExportsShorthand = false, files: isFilesShorthand = false, fix: isFix = false, format: isFormat = false, 'fix-type': fixTypes = [], help: isHelp, include: includedIssueTypes = [], 'include-entry-exports': isIncludeEntryExports = false, 'include-libs': isIncludeLibs = false, 'isolate-workspaces': isIsolateWorkspaces = false, 'max-issues': maxIssues = '0', 'memory-realtime': memoryRealtime = false, 'no-config-hints': isDisableConfigHints = false, 'no-exit-code': noExitCode = false, 'no-gitignore': isNoGitIgnore = false, 'no-progress': isNoProgress = isDebug || isTrace || memoryRealtime, preprocessor = [], 'preprocessor-options': preprocessorOptions = '', production: isProduction = false, reporter = ['symbols'], 'reporter-options': reporterOptions = '', strict: isStrict = false, tags = [], 'treat-config-hints-as-errors': treatConfigHintsAsErrors = false, tsConfig, version: isVersion, watch: isWatch = false, workspace: rawWorkspaceArg, } = parsedArgValues;
14
14
  if (isHelp) {
15
15
  console.log(helpText);
16
16
  process.exit(0);
@@ -73,10 +73,10 @@ const run = async () => {
73
73
  .reduce((errorCount, reportGroup) => errorCount + finalData.counters[reportGroup], 0);
74
74
  if (perfObserver.isEnabled)
75
75
  await perfObserver.finalize();
76
- if (perfObserver.isPerformanceEnabled)
77
- console.log(`\n${perfObserver.getPerformanceTable()}`);
78
- if (perfObserver.isMemoryEnabled)
79
- console.log(`\n${perfObserver.getMemoryTable()}`);
76
+ if (perfObserver.isTimerifyFunctions)
77
+ console.log(`\n${perfObserver.getTimerifiedFunctionsTable()}`);
78
+ if (perfObserver.isMemoryUsageEnabled)
79
+ console.log(`\n${perfObserver.getMemoryUsageTable()}`);
80
80
  if (perfObserver.isEnabled) {
81
81
  const duration = perfObserver.getCurrentDurationInMs();
82
82
  console.log('\nTotal running time:', prettyMilliseconds(duration));
@@ -106,5 +106,6 @@ const run = async () => {
106
106
  }
107
107
  throw error;
108
108
  }
109
+ process.exit(0);
109
110
  };
110
111
  await run();
@@ -89,6 +89,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
89
89
  entry?: string | string[] | undefined;
90
90
  project?: string | string[] | undefined;
91
91
  } | undefined;
92
+ docusaurus?: string | boolean | string[] | {
93
+ config?: string | string[] | undefined;
94
+ entry?: string | string[] | undefined;
95
+ project?: string | string[] | undefined;
96
+ } | undefined;
92
97
  dotenv?: string | boolean | string[] | {
93
98
  config?: string | string[] | undefined;
94
99
  entry?: string | string[] | undefined;
@@ -615,6 +620,11 @@ export declare const partitionCompilers: (rawLocalConfig: RawConfiguration) => {
615
620
  entry?: string | string[] | undefined;
616
621
  project?: string | string[] | undefined;
617
622
  } | undefined;
623
+ docusaurus?: string | boolean | string[] | {
624
+ config?: string | string[] | undefined;
625
+ entry?: string | string[] | undefined;
626
+ project?: string | string[] | undefined;
627
+ } | undefined;
618
628
  dotenv?: string | boolean | string[] | {
619
629
  config?: string | string[] | undefined;
620
630
  entry?: string | string[] | undefined;
package/dist/constants.js CHANGED
@@ -50,6 +50,7 @@ export const IGNORED_GLOBAL_BINARIES = new Set([
50
50
  'exec',
51
51
  'exit',
52
52
  'expand',
53
+ 'export',
53
54
  'expr',
54
55
  'factor',
55
56
  'false',
@@ -23,7 +23,7 @@ export const analyze = async (options) => {
23
23
  : ignoreExportsUsedInFile));
24
24
  const analyzeGraph = async () => {
25
25
  if (isReportValues || isReportTypes) {
26
- streamer.cast('Connecting the dots...');
26
+ streamer.cast('Connecting the dots');
27
27
  for (const [filePath, file] of graph.entries()) {
28
28
  const exportItems = file.exports;
29
29
  if (!exportItems || exportItems.size === 0)
@@ -6,7 +6,7 @@ import { perfObserver } from '../util/Performance.js';
6
6
  import { debugLog, debugLogArray } from '../util/debug.js';
7
7
  import { getReferencedInputsHandler } from '../util/get-referenced-inputs.js';
8
8
  import { _glob, negate } from '../util/glob.js';
9
- import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
9
+ import { isAlias, isConfig, isDeferResolveEntry, isDeferResolveProductionEntry, isEntry, isIgnore, isProductionEntry, isProject, toProductionEntry, } from '../util/input.js';
10
10
  import { getOrCreateFileNode, updateImportMap } from '../util/module-graph.js';
11
11
  import { getEntryPathsFromManifest } from '../util/package-json.js';
12
12
  import { dirname, isAbsolute, join, relative, toRelative } from '../util/path.js';
@@ -29,7 +29,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
29
29
  }
30
30
  for (const workspace of workspaces) {
31
31
  const { name, dir, ancestors, pkgName } = workspace;
32
- streamer.cast(`Analyzing workspace (${name})...`);
32
+ streamer.cast('Analyzing workspace', name);
33
33
  const manifest = chief.getManifestForWorkspace(name);
34
34
  if (!manifest) {
35
35
  continue;
@@ -89,6 +89,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
89
89
  toSourceFilePath,
90
90
  isCache,
91
91
  cacheLocation,
92
+ isProduction,
92
93
  });
93
94
  principal.addPaths(config.paths, dir);
94
95
  const inputsFromPlugins = await worker.runPlugins();
@@ -126,6 +127,14 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
126
127
  else if (isAlias(input)) {
127
128
  principal.addPaths({ [input.specifier]: input.prefixes }, input.dir ?? dir);
128
129
  }
130
+ else if (isIgnore(input)) {
131
+ if (input.issueType === 'dependencies' || input.issueType === 'unlisted') {
132
+ deputy.addIgnoredDependencies(name, input.specifier);
133
+ }
134
+ else if (input.issueType === 'binaries') {
135
+ deputy.addIgnoredBinaries(name, input.specifier);
136
+ }
137
+ }
129
138
  else if (!isConfig(input)) {
130
139
  const ws = (input.containingFilePath && chief.findWorkspaceByFilePath(input.containingFilePath)) || workspace;
131
140
  const resolvedFilePath = getReferencedInternalFilePath(input, ws);
@@ -276,10 +285,10 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
276
285
  continue;
277
286
  principal.init();
278
287
  if (principal.asyncCompilers.size > 0) {
279
- streamer.cast('Running async compilers...');
288
+ streamer.cast('Running async compilers');
280
289
  await principal.runAsyncCompilers();
281
290
  }
282
- streamer.cast(`Analyzing source files (${toRelative(principal.cwd) || '.'})...`);
291
+ streamer.cast('Analyzing source files', toRelative(principal.cwd));
283
292
  let size = principal.entryPaths.size;
284
293
  let round = 0;
285
294
  do {
@@ -299,7 +308,7 @@ export async function build({ cacheLocation, chief, collector, cwd, deputy, fact
299
308
  factory.deletePrincipal(principal);
300
309
  principals[i] = undefined;
301
310
  }
302
- perfObserver.addMemoryMark(factory.principals.size);
311
+ perfObserver.addMemoryMark(factory.getPrincipalCount());
303
312
  }
304
313
  if (!isWatch && isSkipLibs && !isIsolateWorkspaces) {
305
314
  for (const principal of principals) {
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ export const main = async (unresolvedConfiguration) => {
18
18
  const deputy = new DependencyDeputy({ isProduction, isStrict });
19
19
  const factory = new PrincipalFactory();
20
20
  const streamer = new ConsoleStreamer({ isEnabled: isShowProgress });
21
- streamer.cast('Reading workspace configuration(s)...');
21
+ streamer.cast('Reading workspace configuration');
22
22
  await chief.init();
23
23
  const workspaces = chief.getWorkspaces();
24
24
  const report = chief.getIncludedIssueTypes({
@@ -0,0 +1,5 @@
1
+ import type { PluginOptions as Options } from '../../types/config.js';
2
+ import { type Input } from '../../util/input.js';
3
+ import type { ConfigItem, ModuleType } from './types.js';
4
+ export declare const CORE_CLIENT_API: string[];
5
+ export declare const resolveConfigItems: (items: ConfigItem[], type: ModuleType, options: Options) => Promise<Set<Input>>;
@@ -0,0 +1,89 @@
1
+ import { toDeferResolve, toProductionEntry } from '../../util/input.js';
2
+ import { findWebpackDependenciesFromConfig } from '../webpack/index.js';
3
+ const FIRST_PARTY_MODULES = new Set([
4
+ 'content-docs',
5
+ 'content-blog',
6
+ 'content-pages',
7
+ 'debug',
8
+ 'sitemap',
9
+ 'svgr',
10
+ 'rsdoctor',
11
+ 'pwa',
12
+ 'client-redirects',
13
+ 'ideal-image',
14
+ 'google-analytics',
15
+ 'google-gtag',
16
+ 'google-tag-manager',
17
+ 'classic',
18
+ 'live-codeblock',
19
+ 'search-algolia',
20
+ 'mermaid',
21
+ ]);
22
+ export const CORE_CLIENT_API = [
23
+ 'BrowserOnly',
24
+ 'ComponentCreator',
25
+ 'constants',
26
+ 'ExecutionEnvironment',
27
+ 'Head',
28
+ 'Interpolate',
29
+ 'isInternalUrl',
30
+ 'Link',
31
+ 'Noop',
32
+ 'renderRoutes',
33
+ 'router',
34
+ 'Translate',
35
+ 'useBaseUrl',
36
+ 'useBrokenLinks',
37
+ 'useDocusaurusContext',
38
+ 'useGlobalData',
39
+ 'useIsBrowser',
40
+ 'useIsomorphicLayoutEffect',
41
+ 'useRouteContext',
42
+ ];
43
+ const resolveModuleName = (name, type) => {
44
+ if (name.includes(`${type}-`))
45
+ return name;
46
+ if (!name.startsWith('@')) {
47
+ const prefix = FIRST_PARTY_MODULES.has(name) ? '@docusaurus/' : 'docusaurus-';
48
+ return `${prefix}${type}-${name}`;
49
+ }
50
+ const [scope, ...rest] = name.split('/');
51
+ const baseName = rest.length ? `-${rest.join('/')}` : '';
52
+ return `${scope}/docusaurus-${type}${baseName}`;
53
+ };
54
+ const resolveSidebarPath = (config) => {
55
+ const path = config?.sidebarPath ?? config?.docs?.sidebarPath;
56
+ return typeof path === 'string' ? path : undefined;
57
+ };
58
+ const resolveArrayConfig = ([name, config], type) => {
59
+ if (typeof name !== 'string')
60
+ return [];
61
+ const resolvedName = resolveModuleName(name, type);
62
+ const sidebarPath = type !== 'theme' ? resolveSidebarPath(config) : undefined;
63
+ return [toDeferResolve(resolvedName), ...(sidebarPath ? [toProductionEntry(sidebarPath)] : [])];
64
+ };
65
+ export const resolveConfigItems = async (items, type, options) => {
66
+ const inputs = new Set();
67
+ for (let item of items) {
68
+ if (typeof item === 'function')
69
+ item = item();
70
+ if (!item)
71
+ continue;
72
+ if (typeof item === 'string') {
73
+ inputs.add(toDeferResolve(resolveModuleName(item, type)));
74
+ }
75
+ else if (Array.isArray(item)) {
76
+ for (const input of resolveArrayConfig(item, type))
77
+ inputs.add(input);
78
+ }
79
+ else if (typeof item.configureWebpack === 'function') {
80
+ const utils = { getStyleLoaders: () => [], getJSLoader: () => null };
81
+ const config = item.configureWebpack({}, false, utils);
82
+ for (const input of await findWebpackDependenciesFromConfig(config, options))
83
+ inputs.add(input);
84
+ }
85
+ else if (typeof item.configurePostCss === 'function') {
86
+ }
87
+ }
88
+ return inputs;
89
+ };
@@ -0,0 +1,12 @@
1
+ import type { IsPluginEnabled, ResolveConfig } from '../../types/config.js';
2
+ import type { DocusaurusConfig } from './types.js';
3
+ declare const _default: {
4
+ title: string;
5
+ enablers: string[];
6
+ isEnabled: IsPluginEnabled;
7
+ config: string[];
8
+ entry: string[];
9
+ production: string[];
10
+ resolveConfig: ResolveConfig<DocusaurusConfig>;
11
+ };
12
+ export default _default;
@@ -0,0 +1,36 @@
1
+ import { toAlias, toDependency, toEntry, toIgnore, toProductionEntry } from '../../util/input.js';
2
+ import { hasDependency } from '../../util/plugin.js';
3
+ import { CORE_CLIENT_API, resolveConfigItems } from './helpers.js';
4
+ const title = 'Docusaurus';
5
+ const enablers = ['@docusaurus/core'];
6
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
7
+ const config = ['docusaurus.config.{js,mjs,ts}'];
8
+ const production = ['src/pages/**/*.{js,ts,jsx,tsx}', '{blog,docs}/**/*.mdx', 'versioned_docs/**/*.{mdx,jsx,tsx}'];
9
+ const entry = ['babel.config.{js,cjs,mjs,cts}'];
10
+ const resolveConfig = async (config, options) => {
11
+ const themes = await resolveConfigItems(config.themes ?? [], 'theme', options);
12
+ const plugins = await resolveConfigItems(config.plugins ?? [], 'plugin', options);
13
+ const presets = await resolveConfigItems(config.presets ?? [], 'preset', options);
14
+ const hasClassicTheme = options.manifest.dependencies?.['@docusaurus/theme-classic'] ||
15
+ options.manifest.dependencies?.['@docusaurus/preset-classic'];
16
+ return [
17
+ toAlias('@site/*', './*'),
18
+ toDependency('@docusaurus/module-type-aliases', { optional: true }),
19
+ ...(hasClassicTheme ? [toIgnore('(@theme|@theme-init|@theme-original)/*', 'dependencies')] : []),
20
+ toIgnore(`@docusaurus/(${CORE_CLIENT_API.join('|')})`, 'dependencies'),
21
+ ...production.map(id => toProductionEntry(id)),
22
+ ...entry.map(id => toEntry(id)),
23
+ ...themes,
24
+ ...plugins,
25
+ ...presets,
26
+ ];
27
+ };
28
+ export default {
29
+ title,
30
+ enablers,
31
+ isEnabled,
32
+ config,
33
+ entry,
34
+ production,
35
+ resolveConfig,
36
+ };
@@ -0,0 +1,40 @@
1
+ import type { WebpackConfig } from '../webpack/types.js';
2
+ export type ModuleType = 'plugin' | 'theme' | 'preset';
3
+ type DocsConfig = {
4
+ sidebarPath?: string;
5
+ [key: string]: unknown;
6
+ };
7
+ export type PluginOptions = {
8
+ sidebarPath?: string;
9
+ [key: string]: unknown;
10
+ };
11
+ export type PresetOptions = {
12
+ docs?: DocsConfig;
13
+ [key: string]: unknown;
14
+ };
15
+ type Loader = unknown;
16
+ type PluginConfig = string | [string, PluginOptions] | false | null | {
17
+ name?: string;
18
+ configureWebpack?: (config?: PluginConfig, isServer?: boolean, utils?: {
19
+ getStyleLoaders(isServer: boolean, cssOptions: {
20
+ [key: string]: any;
21
+ }): Loader[];
22
+ getJSLoader(isServer: boolean, cacheOptions?: {}): Loader | null;
23
+ }, content?: unknown) => WebpackConfig;
24
+ configurePostCss?: (postcssOptions: {
25
+ plugins: unknown[];
26
+ }) => {
27
+ plugins: unknown[];
28
+ };
29
+ };
30
+ type PresetConfig = string | [string, PresetOptions] | false | null;
31
+ type Config = PresetConfig | PluginConfig;
32
+ export type ConfigItem = Config | (() => Config);
33
+ export type DocusaurusConfig = {
34
+ title: string;
35
+ url: string;
36
+ themes?: PluginConfig[];
37
+ plugins?: PluginConfig[];
38
+ presets: PresetConfig[];
39
+ };
40
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -117,6 +117,15 @@ export declare const Plugins: {
117
117
  config: boolean;
118
118
  };
119
119
  };
120
+ docusaurus: {
121
+ title: string;
122
+ enablers: string[];
123
+ isEnabled: import("../types/config.js").IsPluginEnabled;
124
+ config: string[];
125
+ entry: string[];
126
+ production: string[];
127
+ resolveConfig: import("../types/config.js").ResolveConfig<import("./docusaurus/types.js").DocusaurusConfig>;
128
+ };
120
129
  dotenv: {
121
130
  title: string;
122
131
  args: {
@@ -13,6 +13,7 @@ import { default as cspell } from './cspell/index.js';
13
13
  import { default as cucumber } from './cucumber/index.js';
14
14
  import { default as cypress } from './cypress/index.js';
15
15
  import { default as dependencyCruiser } from './dependency-cruiser/index.js';
16
+ import { default as docusaurus } from './docusaurus/index.js';
16
17
  import { default as dotenv } from './dotenv/index.js';
17
18
  import { default as drizzle } from './drizzle/index.js';
18
19
  import { default as eleventy } from './eleventy/index.js';
@@ -116,6 +117,7 @@ export const Plugins = {
116
117
  cucumber,
117
118
  cypress,
118
119
  'dependency-cruiser': dependencyCruiser,
120
+ docusaurus,
119
121
  dotenv,
120
122
  drizzle,
121
123
  eleventy,
@@ -57,8 +57,8 @@ const resolveUseItem = (use) => {
57
57
  return [];
58
58
  };
59
59
  export const findWebpackDependenciesFromConfig = async (config, options) => {
60
- const { cwd } = options;
61
- const passes = typeof config === 'function' ? [false, true] : [false];
60
+ const { cwd, isProduction } = options;
61
+ const passes = typeof config === 'function' ? [false, true] : [isProduction];
62
62
  const inputs = new Set();
63
63
  for (const isProduction of passes) {
64
64
  const mode = isProduction ? 'production' : 'development';
@@ -98,16 +98,16 @@ export const findWebpackDependenciesFromConfig = async (config, options) => {
98
98
  }
99
99
  }
100
100
  for (const entry of entries) {
101
- if (!isInternal(entry)) {
102
- inputs.add(toDependency(entry));
103
- }
104
- else {
101
+ if (isInternal(entry)) {
105
102
  const dir = opts.context ? opts.context : cwd;
106
- const input = opts.mode === 'development'
107
- ? toDeferResolveEntry(entry, { dir })
108
- : toDeferResolveProductionEntry(entry, { dir });
103
+ const input = isProduction
104
+ ? toDeferResolveProductionEntry(entry, { dir })
105
+ : toDeferResolveEntry(entry, { dir });
109
106
  inputs.add(input);
110
107
  }
108
+ else {
109
+ inputs.add(toDeferResolve(entry));
110
+ }
111
111
  }
112
112
  if (opts.resolve?.alias) {
113
113
  const addStar = (value) => (value.endsWith('*') ? value : join(value, '*').replace(/\/\*\*$/, '/*'));
@@ -1,7 +1,7 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { ISSUE_TYPE_TITLE } from '../constants.js';
3
3
  import { toRelative } from '../util/path.js';
4
- import { getTitle } from './util.js';
4
+ import { getIssueTypeTitle } from './util.js';
5
5
  export default async ({ report, issues }) => {
6
6
  const entries = [];
7
7
  for (const [type, isReportType] of Object.entries(report)) {
@@ -14,7 +14,7 @@ export default async ({ report, issues }) => {
14
14
  if (fixedType === 'duplicates' && issue.symbols) {
15
15
  entries.push(...issue.symbols.map(symbol => ({
16
16
  type: 'issue',
17
- check_name: getTitle(fixedType),
17
+ check_name: getIssueTypeTitle(fixedType),
18
18
  description: getSymbolDescription({ type: issue.type, symbol, parentSymbol: issue.parentSymbol }),
19
19
  categories: ['Duplication'],
20
20
  location: createLocation(filePath, symbol.line, symbol.col),
@@ -25,7 +25,7 @@ export default async ({ report, issues }) => {
25
25
  else {
26
26
  entries.push({
27
27
  type: 'issue',
28
- check_name: getTitle(fixedType),
28
+ check_name: getIssueTypeTitle(fixedType),
29
29
  description: getIssueDescription(issue),
30
30
  categories: ['Bug Risk'],
31
31
  location: createLocation(filePath, issue.line, issue.col),