knip 5.70.2 → 5.72.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 (86) hide show
  1. package/dist/ConfigurationChief.d.ts +6 -0
  2. package/dist/ConsoleStreamer.js +1 -1
  3. package/dist/DependencyDeputy.js +2 -2
  4. package/dist/ProjectPrincipal.js +1 -1
  5. package/dist/WorkspaceWorker.js +1 -1
  6. package/dist/binaries/bash-parser.js +14 -1
  7. package/dist/compilers/index.d.ts +10 -0
  8. package/dist/compilers/index.js +4 -1
  9. package/dist/compilers/scss.d.ts +6 -0
  10. package/dist/compilers/scss.js +14 -0
  11. package/dist/constants.js +1 -0
  12. package/dist/graph/analyze.js +38 -22
  13. package/dist/graph-explorer/constants.d.ts +2 -0
  14. package/dist/graph-explorer/constants.js +2 -0
  15. package/dist/graph-explorer/explorer.d.ts +11 -0
  16. package/dist/graph-explorer/explorer.js +10 -0
  17. package/dist/graph-explorer/operations/build-exports-tree.d.ts +15 -0
  18. package/dist/graph-explorer/operations/build-exports-tree.js +96 -0
  19. package/dist/graph-explorer/operations/has-strictly-ns-references.d.ts +2 -0
  20. package/dist/graph-explorer/operations/has-strictly-ns-references.js +98 -0
  21. package/dist/graph-explorer/operations/is-referenced.d.ts +4 -0
  22. package/dist/graph-explorer/operations/is-referenced.js +89 -0
  23. package/dist/graph-explorer/utils.d.ts +3 -0
  24. package/dist/graph-explorer/utils.js +13 -0
  25. package/dist/graph-explorer/visitors.d.ts +12 -0
  26. package/dist/graph-explorer/visitors.js +30 -0
  27. package/dist/graph-explorer/walk-down.d.ts +5 -0
  28. package/dist/graph-explorer/walk-down.js +116 -0
  29. package/dist/index.js +2 -98
  30. package/dist/plugins/angular/index.js +3 -3
  31. package/dist/plugins/index.d.ts +1 -0
  32. package/dist/plugins/index.js +2 -0
  33. package/dist/plugins/next/index.js +4 -3
  34. package/dist/plugins/next/resolveFromAST.d.ts +1 -0
  35. package/dist/plugins/next/resolveFromAST.js +42 -1
  36. package/dist/plugins/rsbuild/index.js +8 -0
  37. package/dist/plugins/rsbuild/types.d.ts +1 -0
  38. package/dist/plugins/storybook/index.js +12 -4
  39. package/dist/plugins/storybook/types.d.ts +5 -0
  40. package/dist/plugins/svgo/index.js +1 -1
  41. package/dist/plugins/svgr/index.d.ts +3 -0
  42. package/dist/plugins/svgr/index.js +24 -0
  43. package/dist/plugins/svgr/types.d.ts +3 -0
  44. package/dist/plugins/svgr/types.js +1 -0
  45. package/dist/plugins/vite/helpers.js +1 -1
  46. package/dist/plugins/vite/index.js +4 -0
  47. package/dist/plugins/vitest/index.js +1 -1
  48. package/dist/reporters/codeclimate.js +3 -7
  49. package/dist/reporters/util/util.d.ts +2 -1
  50. package/dist/reporters/util/util.js +1 -0
  51. package/dist/reporters/watch.js +1 -1
  52. package/dist/run.d.ts +25 -0
  53. package/dist/run.js +107 -0
  54. package/dist/schema/configuration.d.ts +10 -0
  55. package/dist/schema/plugins.d.ts +5 -0
  56. package/dist/schema/plugins.js +1 -0
  57. package/dist/types/PluginNames.d.ts +2 -2
  58. package/dist/types/PluginNames.js +1 -0
  59. package/dist/types/issues.d.ts +4 -4
  60. package/dist/types/module-graph.d.ts +11 -13
  61. package/dist/typescript/ast-helpers.d.ts +5 -1
  62. package/dist/typescript/ast-helpers.js +47 -2
  63. package/dist/typescript/get-imports-and-exports.js +78 -12
  64. package/dist/typescript/resolve-module-names.js +5 -4
  65. package/dist/typescript/visitors/dynamic-imports/importCall.js +5 -19
  66. package/dist/util/Performance.js +4 -2
  67. package/dist/util/create-options.d.ts +10 -0
  68. package/dist/util/create-options.js +8 -4
  69. package/dist/util/file-entry-cache.js +1 -1
  70. package/dist/util/graph-sequencer.js +1 -1
  71. package/dist/util/module-graph.js +7 -8
  72. package/dist/util/resolve.d.ts +3 -2
  73. package/dist/util/resolve.js +25 -2
  74. package/dist/util/trace.d.ts +2 -20
  75. package/dist/util/trace.js +41 -66
  76. package/dist/util/watch.d.ts +19 -3
  77. package/dist/util/watch.js +28 -17
  78. package/dist/version.d.ts +1 -1
  79. package/dist/version.js +1 -1
  80. package/package.json +7 -7
  81. package/schema.json +4 -0
  82. package/vendor/bash-parser/index.d.ts +6 -1
  83. package/dist/util/has-strictly-ns-references.d.ts +0 -4
  84. package/dist/util/has-strictly-ns-references.js +0 -103
  85. package/dist/util/is-identifier-referenced.d.ts +0 -9
  86. package/dist/util/is-identifier-referenced.js +0 -145
@@ -0,0 +1,89 @@
1
+ import { OPAQUE } from '../../constants.js';
2
+ import { getAliasReExportMap, getNamespaceReExportSources, getPassThroughReExportSources, getStarReExportSources, } from '../visitors.js';
3
+ export const isReferenced = (graph, entryPaths, filePath, id, options) => {
4
+ const seen = new Set();
5
+ const check = (currentPath, currentId) => {
6
+ const isEntryFile = entryPaths.has(currentPath);
7
+ let reExportingEntryFile = isEntryFile ? currentPath : undefined;
8
+ if (seen.has(currentPath))
9
+ return [false, reExportingEntryFile];
10
+ seen.add(currentPath);
11
+ const restIds = currentId.split('.');
12
+ const identifier = restIds.shift();
13
+ const file = graph.get(currentPath)?.imported;
14
+ if (!identifier || !file) {
15
+ return [false, reExportingEntryFile];
16
+ }
17
+ const followSources = (sources, nextId) => {
18
+ for (const byFilePath of sources) {
19
+ if (seen.has(byFilePath))
20
+ continue;
21
+ const result = check(byFilePath, nextId);
22
+ if (result[1])
23
+ reExportingEntryFile = result[1];
24
+ if (result[0])
25
+ return true;
26
+ }
27
+ return false;
28
+ };
29
+ if (file.imported.get(OPAQUE) ||
30
+ ((identifier === currentId || (identifier !== currentId && file.refs.has(currentId))) &&
31
+ (file.imported.has(identifier) || file.importedAs.has(identifier)))) {
32
+ return [true, reExportingEntryFile];
33
+ }
34
+ for (const [exportId, aliases] of file.importedAs) {
35
+ if (identifier === exportId) {
36
+ for (const alias of aliases.keys()) {
37
+ const aliasedRef = [alias, ...restIds].join('.');
38
+ if (file.refs.has(aliasedRef)) {
39
+ return [true, reExportingEntryFile];
40
+ }
41
+ }
42
+ }
43
+ }
44
+ for (const namespace of file.importedNs.keys()) {
45
+ if (file.refs.has(`${namespace}.${currentId}`)) {
46
+ return [true, reExportingEntryFile];
47
+ }
48
+ const nsAliasMap = getAliasReExportMap(file, namespace);
49
+ if (nsAliasMap) {
50
+ for (const [alias, sources] of nsAliasMap) {
51
+ if (followSources(sources, `${alias}.${currentId}`))
52
+ return [true, reExportingEntryFile];
53
+ }
54
+ }
55
+ const nsReExportSources = getNamespaceReExportSources(file, namespace);
56
+ if (nsReExportSources) {
57
+ if (followSources(nsReExportSources, `${namespace}.${currentId}`))
58
+ return [true, reExportingEntryFile];
59
+ }
60
+ }
61
+ if (isEntryFile && !options.includeEntryExports)
62
+ return [false, reExportingEntryFile];
63
+ const aliasMap = getAliasReExportMap(file, identifier);
64
+ if (aliasMap) {
65
+ for (const [alias, sources] of aliasMap) {
66
+ const ref = [alias, ...restIds].join('.');
67
+ if (followSources(sources, ref))
68
+ return [true, reExportingEntryFile];
69
+ }
70
+ }
71
+ const directSources = getPassThroughReExportSources(file, identifier);
72
+ const starSources = getStarReExportSources(file);
73
+ if (directSources) {
74
+ if (followSources(directSources, currentId))
75
+ return [true, reExportingEntryFile];
76
+ }
77
+ else if (starSources) {
78
+ if (followSources(starSources, currentId))
79
+ return [true, reExportingEntryFile];
80
+ }
81
+ for (const [namespace, sources] of file.reExportedNs) {
82
+ if (followSources(sources, `${namespace}.${currentId}`)) {
83
+ return [true, reExportingEntryFile];
84
+ }
85
+ }
86
+ return [false, reExportingEntryFile];
87
+ };
88
+ return check(filePath, id);
89
+ };
@@ -0,0 +1,3 @@
1
+ import type { ImportMaps } from '../types/module-graph.js';
2
+ export declare const hasStrictlyEnumReferences: (importsForExport: ImportMaps | undefined, identifier: string) => boolean;
3
+ export declare const getIssueType: (hasOnlyNsReference: boolean, isType: boolean) => "exports" | "nsExports" | "types" | "nsTypes";
@@ -0,0 +1,13 @@
1
+ export const hasStrictlyEnumReferences = (importsForExport, identifier) => {
2
+ if (!importsForExport || !importsForExport.refs.has(identifier))
3
+ return false;
4
+ for (const ref of importsForExport.refs)
5
+ if (ref.startsWith(`${identifier}.`))
6
+ return false;
7
+ return true;
8
+ };
9
+ export const getIssueType = (hasOnlyNsReference, isType) => {
10
+ if (hasOnlyNsReference)
11
+ return isType ? 'nsTypes' : 'nsExports';
12
+ return isType ? 'types' : 'exports';
13
+ };
@@ -0,0 +1,12 @@
1
+ import type { ImportMaps } from '../types/module-graph.js';
2
+ type PassThroughReExportCallback = (identifier: string, sources: Set<string>) => boolean | void;
3
+ type AliasReExportCallback = (identifier: string, alias: string, sources: Set<string>) => boolean | void;
4
+ type NamespaceReExportCallback = (namespace: string, sources: Set<string>) => boolean | void;
5
+ export declare const forEachPassThroughReExport: (importMaps: ImportMaps, callback: PassThroughReExportCallback) => boolean;
6
+ export declare const forEachAliasReExport: (importMaps: ImportMaps, callback: AliasReExportCallback) => boolean;
7
+ export declare const forEachNamespaceReExport: (importMaps: ImportMaps, callback: NamespaceReExportCallback) => boolean;
8
+ export declare const getStarReExportSources: (importMaps: ImportMaps) => Set<string> | undefined;
9
+ export declare const getPassThroughReExportSources: (importMaps: ImportMaps, identifier: string) => Set<string> | undefined;
10
+ export declare const getAliasReExportMap: (importMaps: ImportMaps, identifier: string) => Map<string, Set<string>> | undefined;
11
+ export declare const getNamespaceReExportSources: (importMaps: ImportMaps, namespace: string) => Set<string> | undefined;
12
+ export {};
@@ -0,0 +1,30 @@
1
+ import { IMPORT_STAR } from '../constants.js';
2
+ export const forEachPassThroughReExport = (importMaps, callback) => {
3
+ for (const [identifier, sources] of importMaps.reExported) {
4
+ if (identifier === IMPORT_STAR)
5
+ continue;
6
+ if (callback(identifier, sources ?? new Set()) === false)
7
+ return false;
8
+ }
9
+ return true;
10
+ };
11
+ export const forEachAliasReExport = (importMaps, callback) => {
12
+ for (const [identifier, aliasMap] of importMaps.reExportedAs) {
13
+ for (const [alias, sources] of aliasMap) {
14
+ if (callback(identifier, alias, sources ?? new Set()) === false)
15
+ return false;
16
+ }
17
+ }
18
+ return true;
19
+ };
20
+ export const forEachNamespaceReExport = (importMaps, callback) => {
21
+ for (const [namespace, sources] of importMaps.reExportedNs) {
22
+ if (callback(namespace, sources ?? new Set()) === false)
23
+ return false;
24
+ }
25
+ return true;
26
+ };
27
+ export const getStarReExportSources = (importMaps) => importMaps.reExported.get(IMPORT_STAR);
28
+ export const getPassThroughReExportSources = (importMaps, identifier) => importMaps.reExported.get(identifier);
29
+ export const getAliasReExportMap = (importMaps, identifier) => importMaps.reExportedAs.get(identifier);
30
+ export const getNamespaceReExportSources = (importMaps, namespace) => importMaps.reExportedNs.get(namespace);
@@ -0,0 +1,5 @@
1
+ import type { ModuleGraph } from '../types/module-graph.js';
2
+ export type Via = 'import' | 'importAs' | 'importNS' | 'reExport' | 'reExportAs' | 'reExportNS' | 'reExportStar';
3
+ type Visitor = (sourceFile: string, identifier: string, importingFile: string, identifierPath: string, isEntry: boolean, via: Via) => 'continue' | 'stop' | undefined;
4
+ export declare const walkDown: (graph: ModuleGraph, filePath: string, identifier: string, visitor: Visitor, entryPaths: Set<string>, visited?: Set<string>) => boolean;
5
+ export {};
@@ -0,0 +1,116 @@
1
+ import { STOP } from './constants.js';
2
+ import { getAliasReExportMap, getPassThroughReExportSources, getStarReExportSources } from './visitors.js';
3
+ export const walkDown = (graph, filePath, identifier, visitor, entryPaths, visited = new Set()) => {
4
+ const key = `${filePath}:${identifier}`;
5
+ if (visited.has(key))
6
+ return false;
7
+ visited.add(key);
8
+ const file = graph.get(filePath);
9
+ if (!file?.imported)
10
+ return false;
11
+ const restIds = identifier.split('.');
12
+ const id = restIds.shift();
13
+ if (!id)
14
+ return false;
15
+ const imported = file.imported;
16
+ const importedByFiles = imported.imported.get(id);
17
+ if (importedByFiles) {
18
+ for (const importingFile of importedByFiles) {
19
+ const isEntry = entryPaths.has(importingFile);
20
+ if (visitor(filePath, id, importingFile, id, isEntry, 'import') === STOP)
21
+ return true;
22
+ }
23
+ }
24
+ const importedAsAliases = imported.importedAs.get(id);
25
+ if (importedAsAliases) {
26
+ for (const [alias, byFilePaths] of importedAsAliases) {
27
+ for (const importingFile of byFilePaths) {
28
+ const isEntry = entryPaths.has(importingFile);
29
+ if (visitor(filePath, id, importingFile, alias, isEntry, 'importAs') === STOP)
30
+ return true;
31
+ }
32
+ }
33
+ }
34
+ for (const [namespace, byFilePaths] of imported.importedNs) {
35
+ for (const importingFile of byFilePaths) {
36
+ const isEntry = entryPaths.has(importingFile);
37
+ if (visitor(filePath, identifier, importingFile, `${namespace}.${identifier}`, isEntry, 'importNS') === STOP) {
38
+ return true;
39
+ }
40
+ }
41
+ }
42
+ let done = false;
43
+ if (!done) {
44
+ const passThroughSources = getPassThroughReExportSources(imported, id);
45
+ if (passThroughSources) {
46
+ for (const reExportingFile of passThroughSources) {
47
+ const isEntry = entryPaths.has(reExportingFile);
48
+ if (visitor(filePath, id, reExportingFile, id, isEntry, 'reExport') === STOP) {
49
+ done = true;
50
+ break;
51
+ }
52
+ if (!isEntry && walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) {
53
+ done = true;
54
+ break;
55
+ }
56
+ }
57
+ }
58
+ }
59
+ if (!done) {
60
+ const aliasReExportMap = getAliasReExportMap(imported, id);
61
+ if (aliasReExportMap) {
62
+ for (const [alias, sources] of aliasReExportMap) {
63
+ for (const reExportingFile of sources) {
64
+ const isEntry = entryPaths.has(reExportingFile);
65
+ if (visitor(filePath, id, reExportingFile, alias, isEntry, 'reExportAs') === STOP) {
66
+ done = true;
67
+ break;
68
+ }
69
+ if (!isEntry) {
70
+ const ref = [alias, ...restIds].join('.');
71
+ if (walkDown(graph, reExportingFile, ref, visitor, entryPaths, visited)) {
72
+ done = true;
73
+ break;
74
+ }
75
+ }
76
+ }
77
+ if (done)
78
+ break;
79
+ }
80
+ }
81
+ }
82
+ if (!done) {
83
+ for (const [namespace, sources] of imported.reExportedNs) {
84
+ for (const reExportingFile of sources) {
85
+ const isEntry = entryPaths.has(reExportingFile);
86
+ if (visitor(filePath, identifier, reExportingFile, `${namespace}.${identifier}`, isEntry, 'reExportNS') === STOP) {
87
+ done = true;
88
+ break;
89
+ }
90
+ if (!isEntry && walkDown(graph, reExportingFile, `${namespace}.${identifier}`, visitor, entryPaths, visited)) {
91
+ done = true;
92
+ break;
93
+ }
94
+ }
95
+ if (done)
96
+ break;
97
+ }
98
+ }
99
+ if (!done) {
100
+ const starSources = getStarReExportSources(imported);
101
+ if (starSources) {
102
+ for (const reExportingFile of starSources) {
103
+ const isEntry = entryPaths.has(reExportingFile);
104
+ if (visitor(filePath, id, reExportingFile, id, isEntry, 'reExportStar') === STOP) {
105
+ done = true;
106
+ break;
107
+ }
108
+ if (!isEntry && walkDown(graph, reExportingFile, identifier, visitor, entryPaths, visited)) {
109
+ done = true;
110
+ break;
111
+ }
112
+ }
113
+ }
114
+ }
115
+ return done;
116
+ };
package/dist/index.js CHANGED
@@ -1,98 +1,2 @@
1
- import { watch } from 'node:fs';
2
- import { formatly } from 'formatly';
3
- import { CatalogCounselor } from './CatalogCounselor.js';
4
- import { ConfigurationChief } from './ConfigurationChief.js';
5
- import { ConsoleStreamer } from './ConsoleStreamer.js';
6
- import { DependencyDeputy } from './DependencyDeputy.js';
7
- import { analyze } from './graph/analyze.js';
8
- import { build } from './graph/build.js';
9
- import { IssueCollector } from './IssueCollector.js';
10
- import { IssueFixer } from './IssueFixer.js';
11
- import { PrincipalFactory } from './PrincipalFactory.js';
12
- import watchReporter from './reporters/watch.js';
13
- import { debugLogArray, debugLogObject } from './util/debug.js';
14
- import { getGitIgnoredHandler } from './util/glob-core.js';
15
- import { getWatchHandler } from './util/watch.js';
16
- export const main = async (options) => {
17
- debugLogObject('*', 'Unresolved configuration', options);
18
- debugLogObject('*', 'Included issue types', options.includedIssueTypes);
19
- const chief = new ConfigurationChief(options);
20
- const deputy = new DependencyDeputy(options);
21
- const factory = new PrincipalFactory();
22
- const streamer = new ConsoleStreamer(options);
23
- const fixer = new IssueFixer(options);
24
- const collector = new IssueCollector(options);
25
- const counselor = new CatalogCounselor(options);
26
- streamer.cast('Reading workspace configuration');
27
- const workspaces = await chief.getWorkspaces();
28
- const isGitIgnored = await getGitIgnoredHandler(options);
29
- collector.setIgnoreIssues(chief.config.ignoreIssues);
30
- debugLogObject('*', 'Included workspaces', () => workspaces.map(w => w.pkgName));
31
- debugLogObject('*', 'Included workspace configs', () => workspaces.map(w => ({ pkgName: w.pkgName, name: w.name, config: w.config, ancestors: w.ancestors })));
32
- const { graph, entryPaths, analyzedFiles, unreferencedFiles, analyzeSourceFile } = await build({
33
- chief,
34
- collector,
35
- counselor,
36
- deputy,
37
- factory,
38
- isGitIgnored,
39
- streamer,
40
- workspaces,
41
- options,
42
- });
43
- const reAnalyze = await analyze({
44
- analyzedFiles,
45
- counselor,
46
- chief,
47
- collector,
48
- deputy,
49
- entryPaths,
50
- factory,
51
- fixer,
52
- graph,
53
- streamer,
54
- unreferencedFiles,
55
- options,
56
- });
57
- if (options.isWatch) {
58
- const isIgnored = (filePath) => filePath.startsWith(options.cacheLocation) || filePath.includes('/.git/') || isGitIgnored(filePath);
59
- const onUpdate = options.isWatch
60
- ? ({ issues, duration }) => watchReporter(options, { issues, streamer, size: analyzedFiles.size, duration })
61
- : () => { };
62
- const watchHandler = await getWatchHandler(options, {
63
- analyzedFiles,
64
- analyzeSourceFile,
65
- chief,
66
- collector,
67
- analyze: reAnalyze,
68
- factory,
69
- graph,
70
- isIgnored,
71
- onUpdate,
72
- unreferencedFiles,
73
- });
74
- watch('.', { recursive: true }, watchHandler);
75
- }
76
- const { issues, counters, tagHints, configurationHints } = collector.getIssues();
77
- if (options.isFix) {
78
- const touchedFiles = await fixer.fixIssues(issues);
79
- if (options.isFormat) {
80
- const report = await formatly(Array.from(touchedFiles));
81
- if (report.ran && report.result && (report.result.runner === 'virtual' || report.result.code === 0)) {
82
- debugLogArray('*', `Formatted files using ${report.formatter.name} (${report.formatter.runner})`, touchedFiles);
83
- }
84
- else {
85
- debugLogObject('*', 'Formatting files failed', report);
86
- }
87
- }
88
- }
89
- if (!options.isWatch)
90
- streamer.clear();
91
- return {
92
- issues,
93
- counters,
94
- tagHints,
95
- configurationHints,
96
- includedWorkspaceDirs: chief.includedWorkspaces.map(w => w.dir),
97
- };
98
- };
1
+ import { run } from './run.js';
2
+ export const main = async (options) => (await run(options)).results;
@@ -36,8 +36,8 @@ const resolveConfig = async (config, options) => {
36
36
  }
37
37
  return opts.isProduction ? toProductionEntry(normalizedPath) : toEntry(normalizedPath);
38
38
  };
39
- for (const [configName, entriesByOption] of entriesByOptionByConfig.entries()) {
40
- for (const [option, entries] of entriesByOption.entries()) {
39
+ for (const [configName, entriesByOption] of entriesByOptionByConfig) {
40
+ for (const [option, entries] of entriesByOption) {
41
41
  for (const entry of entries) {
42
42
  inputs.add(toInput(entry, {
43
43
  isProduction: isBuildTarget && configName === PRODUCTION_CONFIG_NAME,
@@ -46,7 +46,7 @@ const resolveConfig = async (config, options) => {
46
46
  }
47
47
  }
48
48
  }
49
- for (const [option, entries] of defaultEntriesByOption.entries()) {
49
+ for (const [option, entries] of defaultEntriesByOption) {
50
50
  for (const entry of entries) {
51
51
  inputs.add(toInput(entry, {
52
52
  isProduction: isBuildTarget && !productionEntriesByOption.get(option)?.length,
@@ -94,6 +94,7 @@ export declare const Plugins: {
94
94
  stylelint: import("../types/config.js").Plugin;
95
95
  svelte: import("../types/config.js").Plugin;
96
96
  svgo: import("../types/config.js").Plugin;
97
+ svgr: import("../types/config.js").Plugin;
97
98
  syncpack: import("../types/config.js").Plugin;
98
99
  tailwind: import("../types/config.js").Plugin;
99
100
  taskfile: import("../types/config.js").Plugin;
@@ -93,6 +93,7 @@ import { default as stryker } from './stryker/index.js';
93
93
  import { default as stylelint } from './stylelint/index.js';
94
94
  import { default as svelte } from './svelte/index.js';
95
95
  import { default as svgo } from './svgo/index.js';
96
+ import { default as svgr } from './svgr/index.js';
96
97
  import { default as syncpack } from './syncpack/index.js';
97
98
  import { default as tailwind } from './tailwind/index.js';
98
99
  import { default as taskfile } from './taskfile/index.js';
@@ -213,6 +214,7 @@ export const Plugins = {
213
214
  stylelint,
214
215
  svelte,
215
216
  svgo,
217
+ svgr,
216
218
  syncpack,
217
219
  tailwind,
218
220
  taskfile,
@@ -1,6 +1,6 @@
1
- import { toProductionEntry } from '../../util/input.js';
1
+ import { toDependency, toProductionEntry } from '../../util/input.js';
2
2
  import { hasDependency } from '../../util/plugin.js';
3
- import { getPageExtensions } from './resolveFromAST.js';
3
+ import { getMdxPlugins, getPageExtensions } from './resolveFromAST.js';
4
4
  const title = 'Next.js';
5
5
  const enablers = ['next'];
6
6
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
@@ -26,7 +26,8 @@ const resolveFromAST = sourceFile => {
26
26
  const pageExtensions = getPageExtensions(sourceFile);
27
27
  const extensions = pageExtensions.length > 0 ? pageExtensions : defaultPageExtensions;
28
28
  const patterns = getEntryFilePatterns(extensions);
29
- return patterns.map(id => toProductionEntry(id));
29
+ const mdxPlugins = getMdxPlugins(sourceFile);
30
+ return [...patterns.map(id => toProductionEntry(id)), ...Array.from(mdxPlugins).map(id => toDependency(id))];
30
31
  };
31
32
  const plugin = {
32
33
  title,
@@ -1,2 +1,3 @@
1
1
  import ts from 'typescript';
2
2
  export declare const getPageExtensions: (sourceFile: ts.SourceFile) => string[];
3
+ export declare const getMdxPlugins: (sourceFile: ts.SourceFile) => Set<string>;
@@ -1,5 +1,5 @@
1
1
  import ts from 'typescript';
2
- import { getPropertyValues } from '../../typescript/ast-helpers.js';
2
+ import { getDefaultImportName, getImportMap, getPropertyValues, stripQuotes } from '../../typescript/ast-helpers.js';
3
3
  export const getPageExtensions = (sourceFile) => {
4
4
  const pageExtensions = new Set();
5
5
  function visit(node) {
@@ -13,3 +13,44 @@ export const getPageExtensions = (sourceFile) => {
13
13
  visit(sourceFile);
14
14
  return Array.from(pageExtensions);
15
15
  };
16
+ const isNamedProp = (prop, name) => ts.isPropertyAssignment(prop) && prop.name.getText() === name;
17
+ export const getMdxPlugins = (sourceFile) => {
18
+ const plugins = new Set();
19
+ const importMap = getImportMap(sourceFile);
20
+ const mdxImportName = getDefaultImportName(importMap, '@next/mdx');
21
+ if (!mdxImportName)
22
+ return plugins;
23
+ function visit(node) {
24
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === mdxImportName) {
25
+ if (node.arguments.length > 0 && ts.isObjectLiteralExpression(node.arguments[0])) {
26
+ const options = node.arguments[0]?.properties.find(prop => isNamedProp(prop, 'options'));
27
+ if (options && ts.isPropertyAssignment(options)) {
28
+ if (ts.isObjectLiteralExpression(options.initializer)) {
29
+ for (const pluginType of ['remarkPlugins', 'rehypePlugins', 'recmaPlugins']) {
30
+ const props = options.initializer.properties.find(prop => isNamedProp(prop, pluginType));
31
+ if (props && ts.isPropertyAssignment(props)) {
32
+ if (ts.isArrayLiteralExpression(props.initializer)) {
33
+ for (const element of props.initializer.elements) {
34
+ if (ts.isStringLiteral(element)) {
35
+ plugins.add(stripQuotes(element.text));
36
+ }
37
+ else if (ts.isArrayLiteralExpression(element) && element.elements.length > 0) {
38
+ const firstElement = element.elements[0];
39
+ if (ts.isStringLiteral(firstElement)) {
40
+ plugins.add(stripQuotes(firstElement.text));
41
+ }
42
+ }
43
+ }
44
+ }
45
+ }
46
+ }
47
+ }
48
+ }
49
+ }
50
+ return true;
51
+ }
52
+ return ts.forEachChild(node, visit) ?? false;
53
+ }
54
+ visit(sourceFile);
55
+ return plugins;
56
+ };
@@ -23,6 +23,14 @@ const resolveConfig = async (config) => {
23
23
  }
24
24
  }
25
25
  }
26
+ if (source?.preEntry) {
27
+ const entry = source.preEntry;
28
+ if (typeof entry === 'string')
29
+ entries.add(entry);
30
+ else if (Array.isArray(entry))
31
+ for (const e of entry)
32
+ entries.add(e);
33
+ }
26
34
  };
27
35
  checkSource(config.source);
28
36
  if (config.environments) {
@@ -6,6 +6,7 @@ export type RsbuildConfig = {
6
6
  plugins?: unknown[];
7
7
  source?: {
8
8
  entry?: Entry;
9
+ preEntry?: string | string[];
9
10
  };
10
11
  environments?: {
11
12
  [k: string]: Pick<RsbuildConfig, 'plugins' | 'source'>;
@@ -1,4 +1,4 @@
1
- import { toDeferResolve, toDependency, toEntry } from '../../util/input.js';
1
+ import { toConfig, toDeferResolve, toDependency, toEntry } from '../../util/input.js';
2
2
  import { join, relative } from '../../util/path.js';
3
3
  import { hasDependency } from '../../util/plugin.js';
4
4
  const title = 'Storybook';
@@ -10,7 +10,7 @@ const restEntry = ['.{storybook,rnstorybook}/{manager,preview,index,vitest.setup
10
10
  const entry = [...restEntry, ...stories];
11
11
  const project = ['.{storybook,rnstorybook}/**/*.{js,jsx,ts,tsx,mts}'];
12
12
  const resolveConfig = async (localConfig, options) => {
13
- const { cwd, configFileDir } = options;
13
+ const { cwd, configFileDir, configFilePath } = options;
14
14
  const strs = typeof localConfig?.stories === 'function' ? await localConfig.stories(stories) : localConfig?.stories;
15
15
  const relativePatterns = strs?.map(pattern => {
16
16
  if (typeof pattern === 'string')
@@ -29,13 +29,21 @@ const resolveConfig = async (localConfig, options) => {
29
29
  ? [`@storybook/builder-${builder}`, `@storybook/manager-${builder}`]
30
30
  : [builder]
31
31
  : [];
32
- const framework = typeof localConfig.framework === 'string' ? localConfig.framework : localConfig.framework?.name;
33
- const frameworks = framework ? [framework] : [];
32
+ const framework = localConfig.framework;
33
+ const frameworkName = typeof framework === 'string' ? framework : framework?.name;
34
+ const frameworks = frameworkName ? [frameworkName] : [];
35
+ const viteConfigPath = typeof framework === 'object' &&
36
+ framework?.name === '@storybook/react-vite' &&
37
+ framework?.options?.builder?.viteConfigPath;
38
+ const configs = viteConfigPath
39
+ ? [toConfig('vite', viteConfigPath, { dir: cwd, containingFilePath: configFilePath })]
40
+ : [];
34
41
  return [
35
42
  ...patterns.map(id => toEntry(id)),
36
43
  ...addons.map(id => toDeferResolve(id)),
37
44
  ...builderPackages.map(id => toDependency(id)),
38
45
  ...frameworks.map(id => toDependency(id)),
46
+ ...configs,
39
47
  ];
40
48
  };
41
49
  const plugin = {
@@ -15,6 +15,11 @@ export type StorybookConfig = {
15
15
  };
16
16
  framework?: string | {
17
17
  name?: string;
18
+ options?: {
19
+ builder?: {
20
+ viteConfigPath?: string;
21
+ };
22
+ };
18
23
  };
19
24
  };
20
25
  export {};
@@ -1,6 +1,6 @@
1
1
  import { hasDependency } from '../../util/plugin.js';
2
2
  const title = 'SVGO';
3
- const enablers = ['svgo'];
3
+ const enablers = ['svgo', '@svgr/plugin-svgo'];
4
4
  const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
5
5
  const entry = ['svgo.config.{js,cjs,mjs}'];
6
6
  const plugin = {
@@ -0,0 +1,3 @@
1
+ import type { Plugin } from '../../types/config.js';
2
+ declare const plugin: Plugin;
3
+ export default plugin;
@@ -0,0 +1,24 @@
1
+ import { toDependency } from '../../util/input.js';
2
+ import { hasDependency } from '../../util/plugin.js';
3
+ const title = 'SVGR';
4
+ const enablers = ['@svgr/cli', '@svgr/core'];
5
+ const isEnabled = ({ dependencies }) => hasDependency(dependencies, enablers);
6
+ const config = ['.svgrrc', '.svgrrc.{yaml,yml,json,js}', 'svgr.config.{js,cjs}', 'package.json'];
7
+ const resolveConfig = async (config) => {
8
+ const inputs = [];
9
+ if (config.plugins) {
10
+ for (const plugin of config.plugins) {
11
+ if (typeof plugin === 'string')
12
+ inputs.push(toDependency(plugin));
13
+ }
14
+ }
15
+ return inputs;
16
+ };
17
+ const plugin = {
18
+ title,
19
+ enablers,
20
+ isEnabled,
21
+ config,
22
+ resolveConfig,
23
+ };
24
+ export default plugin;
@@ -0,0 +1,3 @@
1
+ export type SvgrConfig = {
2
+ plugins?: (string | unknown)[];
3
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -4,7 +4,7 @@ export const getReactBabelPlugins = (sourceFile) => {
4
4
  const babelPlugins = [];
5
5
  const importMap = getImportMap(sourceFile);
6
6
  const reactPluginNames = new Set();
7
- for (const [importName, importPath] of importMap.entries()) {
7
+ for (const [importName, importPath] of importMap) {
8
8
  if (importPath.includes('@vitejs/plugin-react')) {
9
9
  reactPluginNames.add(importName);
10
10
  }
@@ -10,6 +10,9 @@ const resolveFromAST = (sourceFile) => {
10
10
  const babelPlugins = getReactBabelPlugins(sourceFile);
11
11
  return babelPlugins.map(plugin => toDependency(plugin));
12
12
  };
13
+ const args = {
14
+ config: true,
15
+ };
13
16
  const plugin = {
14
17
  title,
15
18
  enablers,
@@ -17,5 +20,6 @@ const plugin = {
17
20
  config,
18
21
  resolveConfig,
19
22
  resolveFromAST,
23
+ args,
20
24
  };
21
25
  export default plugin;