@dcoder-x/plugin-shared 0.1.12 → 0.1.13
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.
|
@@ -24,14 +24,21 @@ class ComponentExtractor {
|
|
|
24
24
|
// parent route happened to import them first.
|
|
25
25
|
const fileRouteIndex = new Map();
|
|
26
26
|
for (const route of this.routes) {
|
|
27
|
-
const relFwd = route.filePath.replace(/\\/g, '/');
|
|
28
|
-
fileRouteIndex.set(relFwd, route.path);
|
|
29
|
-
// Also index by just the basename-less relative path variations
|
|
30
27
|
fileRouteIndex.set(route.filePath, route.path);
|
|
28
|
+
fileRouteIndex.set(route.filePath.replace(/\\/g, '/'), route.path);
|
|
29
|
+
}
|
|
30
|
+
// Stop the module walk at other route entry files — they will be
|
|
31
|
+
// processed in their own iteration with the correct route assigned.
|
|
32
|
+
const allRouteFiles = new Set();
|
|
33
|
+
for (const route of this.routes) {
|
|
34
|
+
allRouteFiles.add(route.filePath);
|
|
35
|
+
allRouteFiles.add(route.filePath.replace(/\\/g, '/'));
|
|
31
36
|
}
|
|
32
37
|
const seen = new Set(); // deduplicate across routes
|
|
33
38
|
for (const route of this.routes) {
|
|
34
|
-
|
|
39
|
+
// The stop boundary excludes the current entry file itself (we need to visit it).
|
|
40
|
+
const stopAt = new Set([...allRouteFiles].filter((f) => f !== route.filePath && f !== route.filePath.replace(/\\/g, '/')));
|
|
41
|
+
const moduleFiles = this.getModuleFilesForRoute(route.filePath, stopAt);
|
|
35
42
|
for (const filePath of moduleFiles) {
|
|
36
43
|
if (seen.has(filePath))
|
|
37
44
|
continue;
|
|
@@ -62,9 +69,15 @@ class ComponentExtractor {
|
|
|
62
69
|
fileRouteIndex.set(route.filePath, route.path);
|
|
63
70
|
fileRouteIndex.set(route.filePath.replace(/\\/g, '/'), route.path);
|
|
64
71
|
}
|
|
72
|
+
const allRouteFiles = new Set();
|
|
73
|
+
for (const route of this.routes) {
|
|
74
|
+
allRouteFiles.add(route.filePath);
|
|
75
|
+
allRouteFiles.add(route.filePath.replace(/\\/g, '/'));
|
|
76
|
+
}
|
|
65
77
|
const seen = new Set();
|
|
66
78
|
for (const route of this.routes) {
|
|
67
|
-
const
|
|
79
|
+
const stopAt = new Set([...allRouteFiles].filter((f) => f !== route.filePath && f !== route.filePath.replace(/\\/g, '/')));
|
|
80
|
+
const moduleFiles = this.getModuleFilesForRoute(route.filePath, stopAt);
|
|
68
81
|
for (const filePath of moduleFiles) {
|
|
69
82
|
if (seen.has(filePath))
|
|
70
83
|
continue;
|
|
@@ -121,15 +134,13 @@ class ComponentExtractor {
|
|
|
121
134
|
}
|
|
122
135
|
return components;
|
|
123
136
|
}
|
|
124
|
-
getModuleFilesForRoute(entryFilePath) {
|
|
137
|
+
getModuleFilesForRoute(entryFilePath, stopAt) {
|
|
125
138
|
if (this.source.type === 'webpack') {
|
|
126
|
-
return this.walkWebpackGraph(entryFilePath, this.source.compilation);
|
|
139
|
+
return this.walkWebpackGraph(entryFilePath, this.source.compilation, stopAt);
|
|
127
140
|
}
|
|
128
|
-
return this.walkRollupGraph(entryFilePath, this.source.moduleGraph);
|
|
141
|
+
return this.walkRollupGraph(entryFilePath, this.source.moduleGraph, stopAt);
|
|
129
142
|
}
|
|
130
|
-
walkWebpackGraph(entryFilePath, compilation) {
|
|
131
|
-
// Normalise to relative forward-slash paths so visited keys and injectedMap
|
|
132
|
-
// keys are consistent across macOS and Windows.
|
|
143
|
+
walkWebpackGraph(entryFilePath, compilation, stopAt) {
|
|
133
144
|
const toRelFwd = (p) => path_1.default.isAbsolute(p)
|
|
134
145
|
? path_1.default.relative(process.cwd(), p).replace(/\\/g, '/')
|
|
135
146
|
: p.replace(/\\/g, '/');
|
|
@@ -139,6 +150,9 @@ class ComponentExtractor {
|
|
|
139
150
|
const current = queue.shift();
|
|
140
151
|
if (visited.has(current))
|
|
141
152
|
continue;
|
|
153
|
+
// Stop recursing into other route entry files — they own their own walk.
|
|
154
|
+
if (stopAt && current !== toRelFwd(entryFilePath) && (stopAt.has(current) || stopAt.has(path_1.default.resolve(process.cwd(), current))))
|
|
155
|
+
continue;
|
|
142
156
|
visited.add(current);
|
|
143
157
|
const mod = this.findWebpackModule(compilation, current);
|
|
144
158
|
let queuedFromWebpackGraph = false;
|
|
@@ -150,10 +164,7 @@ class ComponentExtractor {
|
|
|
150
164
|
}
|
|
151
165
|
}
|
|
152
166
|
}
|
|
153
|
-
// Fallback for webpack variants where moduleGraph helpers are unavailable.
|
|
154
167
|
if (!queuedFromWebpackGraph) {
|
|
155
|
-
// getFileImportPaths resolves to absolute paths via resolveImportFile;
|
|
156
|
-
// normalise them before queuing.
|
|
157
168
|
for (const depPath of this.getFileImportPaths(current)) {
|
|
158
169
|
if (depPath && !depPath.includes('node_modules')) {
|
|
159
170
|
queue.push(toRelFwd(depPath));
|
|
@@ -266,24 +277,25 @@ class ComponentExtractor {
|
|
|
266
277
|
}
|
|
267
278
|
return resolved;
|
|
268
279
|
}
|
|
269
|
-
walkRollupGraph(entryFilePath, graph) {
|
|
270
|
-
// Normalise the entry to a relative forward-slash path so it matches the
|
|
271
|
-
// keys stored by ClippyVitePlugin (which also normalises to relative).
|
|
280
|
+
walkRollupGraph(entryFilePath, graph, stopAt) {
|
|
272
281
|
const toRelFwd = (p) => path_1.default.isAbsolute(p)
|
|
273
282
|
? path_1.default.relative(process.cwd(), p).replace(/\\/g, '/')
|
|
274
283
|
: p.replace(/\\/g, '/');
|
|
284
|
+
const entryKey = toRelFwd(entryFilePath);
|
|
275
285
|
const visited = new Set();
|
|
276
|
-
const queue = [
|
|
286
|
+
const queue = [entryKey];
|
|
277
287
|
while (queue.length > 0) {
|
|
278
288
|
const current = queue.shift();
|
|
279
289
|
if (visited.has(current))
|
|
280
290
|
continue;
|
|
291
|
+
// Stop recursing into other route entry files — they own their own walk.
|
|
292
|
+
if (stopAt && current !== entryKey && (stopAt.has(current) || stopAt.has(path_1.default.resolve(process.cwd(), current))))
|
|
293
|
+
continue;
|
|
281
294
|
visited.add(current);
|
|
282
295
|
const mod = graph.get(current);
|
|
283
296
|
if (!mod)
|
|
284
297
|
continue;
|
|
285
298
|
for (const importId of mod.importedIds) {
|
|
286
|
-
// importedIds are already relative keys after the vite plugin normalised them
|
|
287
299
|
if (importId && !importId.includes('node_modules')) {
|
|
288
300
|
queue.push(toRelFwd(importId));
|
|
289
301
|
}
|
|
@@ -194,16 +194,32 @@ class RouteExtractor {
|
|
|
194
194
|
const expr = elementAttr.value?.expression;
|
|
195
195
|
if (!expr)
|
|
196
196
|
return null;
|
|
197
|
-
//
|
|
198
|
-
//
|
|
199
|
-
//
|
|
197
|
+
// Collect all JSX component names in document order (outermost first, then
|
|
198
|
+
// children). For each, resolve via the import map, then pick the best candidate:
|
|
199
|
+
// a file under pages/ beats a wrapper/provider/layout/guard/context.
|
|
200
200
|
const componentNames = this.collectJSXComponentNames(expr);
|
|
201
|
+
const candidates = [];
|
|
201
202
|
for (const componentName of componentNames) {
|
|
202
203
|
const resolved = importMap.get(componentName);
|
|
203
204
|
if (resolved)
|
|
204
|
-
|
|
205
|
+
candidates.push(resolved);
|
|
205
206
|
}
|
|
206
|
-
|
|
207
|
+
if (candidates.length === 0)
|
|
208
|
+
return null;
|
|
209
|
+
// Score: page files rank highest, known non-page patterns rank lowest.
|
|
210
|
+
const score = (filePath) => {
|
|
211
|
+
const p = filePath.replace(/\\/g, '/').toLowerCase();
|
|
212
|
+
if (p.includes('/pages/'))
|
|
213
|
+
return 3;
|
|
214
|
+
if (p.includes('/views/') || p.includes('/screens/'))
|
|
215
|
+
return 2;
|
|
216
|
+
// Wrappers, providers, guards, layouts, contexts are structural — not page components
|
|
217
|
+
if (/\/(contexts?|providers?|guards?|layouts?|wrappers?|hoc|utils?|helpers?)\//.test(p) ||
|
|
218
|
+
/(provider|context|guard|layout|redirect|catchall|catch-all)/.test(p))
|
|
219
|
+
return 0;
|
|
220
|
+
return 1;
|
|
221
|
+
};
|
|
222
|
+
return candidates.reduce((best, c) => (score(c) >= score(best) ? c : best));
|
|
207
223
|
}
|
|
208
224
|
collectJSXComponentNames(node) {
|
|
209
225
|
if (!node)
|