react-code-locator 0.1.8 → 0.1.12
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 +49 -44
- package/dist/babel.cjs +427 -40
- package/dist/babel.cjs.map +1 -1
- package/dist/babel.d.cts +12 -1
- package/dist/babel.d.ts +12 -1
- package/dist/babel.js +424 -29
- package/dist/babel.js.map +1 -1
- package/dist/babelInjectComponentSource.cjs +403 -38
- package/dist/babelInjectComponentSource.cjs.map +1 -1
- package/dist/babelInjectComponentSource.d.cts +3 -4
- package/dist/babelInjectComponentSource.d.ts +3 -4
- package/dist/babelInjectComponentSource.js +403 -28
- package/dist/babelInjectComponentSource.js.map +1 -1
- package/dist/client-sm5wi0uT.d.cts +15 -0
- package/dist/client-sm5wi0uT.d.ts +15 -0
- package/dist/client.cjs +166 -27
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +1 -14
- package/dist/client.d.ts +1 -14
- package/dist/client.js +166 -27
- package/dist/client.js.map +1 -1
- package/dist/esbuild.cjs +615 -0
- package/dist/esbuild.cjs.map +1 -0
- package/dist/esbuild.d.cts +25 -0
- package/dist/esbuild.d.ts +25 -0
- package/dist/esbuild.js +588 -0
- package/dist/esbuild.js.map +1 -0
- package/dist/index.cjs +833 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +820 -28
- package/dist/index.js.map +1 -1
- package/dist/sourceAdapter-DLWo_ABo.d.cts +15 -0
- package/dist/sourceAdapter-DLWo_ABo.d.ts +15 -0
- package/dist/swc.cjs +588 -0
- package/dist/swc.cjs.map +1 -0
- package/dist/swc.d.cts +29 -0
- package/dist/swc.d.ts +29 -0
- package/dist/swc.js +559 -0
- package/dist/swc.js.map +1 -0
- package/dist/vite.cjs +525 -84
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +20 -6
- package/dist/vite.d.ts +20 -6
- package/dist/vite.js +520 -72
- package/dist/vite.js.map +1 -1
- package/dist/webpackRuntimeEntry.cjs +166 -27
- package/dist/webpackRuntimeEntry.cjs.map +1 -1
- package/dist/webpackRuntimeEntry.js +166 -27
- package/dist/webpackRuntimeEntry.js.map +1 -1
- package/package.json +12 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
// src/constants.ts
|
|
2
2
|
var SOURCE_PROP = "__componentSourceLoc";
|
|
3
|
+
var JSX_SOURCE_PROP = "$componentSourceLoc";
|
|
4
|
+
var JSX_SOURCE_REGISTRY_SYMBOL = "react-code-locator.jsxSourceRegistry";
|
|
5
|
+
|
|
6
|
+
// src/sourceMetadata.ts
|
|
7
|
+
function normalizeSlashes(value) {
|
|
8
|
+
return value.replace(/\\/g, "/");
|
|
9
|
+
}
|
|
10
|
+
function trimTrailingSlash(value) {
|
|
11
|
+
return value.replace(/\/+$/, "");
|
|
12
|
+
}
|
|
13
|
+
function splitPathSegments(value) {
|
|
14
|
+
return normalizeSlashes(value).split("/").filter(Boolean);
|
|
15
|
+
}
|
|
16
|
+
function computeRelativePath(fromPath, toPath) {
|
|
17
|
+
const fromSegments = splitPathSegments(fromPath);
|
|
18
|
+
const toSegments = splitPathSegments(toPath);
|
|
19
|
+
let sharedIndex = 0;
|
|
20
|
+
while (sharedIndex < fromSegments.length && sharedIndex < toSegments.length && fromSegments[sharedIndex] === toSegments[sharedIndex]) {
|
|
21
|
+
sharedIndex += 1;
|
|
22
|
+
}
|
|
23
|
+
const upSegments = new Array(Math.max(0, fromSegments.length - sharedIndex)).fill("..");
|
|
24
|
+
const downSegments = toSegments.slice(sharedIndex);
|
|
25
|
+
const relativeSegments = [...upSegments, ...downSegments];
|
|
26
|
+
return relativeSegments.length > 0 ? relativeSegments.join("/") : ".";
|
|
27
|
+
}
|
|
28
|
+
function normalizeProjectRoot(projectRoot) {
|
|
29
|
+
if (projectRoot) {
|
|
30
|
+
return trimTrailingSlash(normalizeSlashes(projectRoot));
|
|
31
|
+
}
|
|
32
|
+
if (typeof process !== "undefined" && typeof process.cwd === "function") {
|
|
33
|
+
return trimTrailingSlash(normalizeSlashes(process.cwd()));
|
|
34
|
+
}
|
|
35
|
+
return "";
|
|
36
|
+
}
|
|
37
|
+
function toRelativeSource(filename, loc, projectRoot) {
|
|
38
|
+
if (!filename || !loc) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const root = normalizeProjectRoot(projectRoot);
|
|
42
|
+
const normalizedFilename = normalizeSlashes(filename);
|
|
43
|
+
const relPath = root && normalizedFilename.startsWith(`${root}/`) ? normalizedFilename.slice(root.length + 1) : root ? computeRelativePath(root, normalizedFilename) : normalizedFilename;
|
|
44
|
+
return `${relPath}:${loc.line}:${loc.column + 1}`;
|
|
45
|
+
}
|
|
46
|
+
function getSourceFile(source) {
|
|
47
|
+
if (!source) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const match = source.match(/^(.*):\d+:\d+$/);
|
|
51
|
+
return match?.[1] ?? null;
|
|
52
|
+
}
|
|
53
|
+
function isProjectLocalFile(filename, projectRoot) {
|
|
54
|
+
if (!filename) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const root = normalizeProjectRoot(projectRoot);
|
|
58
|
+
const normalizedFilename = normalizeSlashes(filename);
|
|
59
|
+
if (!root) {
|
|
60
|
+
return !normalizedFilename.startsWith("../") && !normalizedFilename.startsWith("/") && !/^[A-Za-z]:\//.test(normalizedFilename);
|
|
61
|
+
}
|
|
62
|
+
if (normalizedFilename.startsWith(`${root}/`) || normalizedFilename === root) {
|
|
63
|
+
return true;
|
|
64
|
+
}
|
|
65
|
+
const relativePath = computeRelativePath(root, normalizedFilename);
|
|
66
|
+
return !relativePath.startsWith("../");
|
|
67
|
+
}
|
|
68
|
+
function isExternalToProjectRoot(filename, projectRoot) {
|
|
69
|
+
return !isProjectLocalFile(filename, projectRoot);
|
|
70
|
+
}
|
|
71
|
+
function isProjectLocalSource(source, projectRoot) {
|
|
72
|
+
const file = getSourceFile(source);
|
|
73
|
+
return isProjectLocalFile(file ?? void 0, projectRoot);
|
|
74
|
+
}
|
|
3
75
|
|
|
4
76
|
// src/runtime.ts
|
|
5
77
|
function isTriggerPressed(event, triggerKey) {
|
|
@@ -47,19 +119,17 @@ function getSourceFromType(type) {
|
|
|
47
119
|
return typeof source === "string" ? source : null;
|
|
48
120
|
}
|
|
49
121
|
function getSourceFromProps(props) {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
if (source) {
|
|
58
|
-
return source;
|
|
122
|
+
if (props && typeof props === "object") {
|
|
123
|
+
const registry = globalThis[Symbol.for(JSX_SOURCE_REGISTRY_SYMBOL)];
|
|
124
|
+
if (registry instanceof WeakMap) {
|
|
125
|
+
const intrinsicSource = registry.get(props);
|
|
126
|
+
if (typeof intrinsicSource === "string") {
|
|
127
|
+
return intrinsicSource;
|
|
128
|
+
}
|
|
59
129
|
}
|
|
60
|
-
current = current.return ?? null;
|
|
61
130
|
}
|
|
62
|
-
|
|
131
|
+
const source = props?.[JSX_SOURCE_PROP];
|
|
132
|
+
return typeof source === "string" ? source : null;
|
|
63
133
|
}
|
|
64
134
|
function resolveComponentSourceFromFiber(fiber) {
|
|
65
135
|
let current = fiber;
|
|
@@ -72,24 +142,76 @@ function resolveComponentSourceFromFiber(fiber) {
|
|
|
72
142
|
}
|
|
73
143
|
return null;
|
|
74
144
|
}
|
|
75
|
-
function
|
|
145
|
+
function getDirectDebugSource(fiber) {
|
|
146
|
+
const debugSource = fiber?._debugSource;
|
|
147
|
+
if (debugSource?.fileName && typeof debugSource.lineNumber === "number") {
|
|
148
|
+
return `${debugSource.fileName.replace(/\\/g, "/")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
function resolveSourceCandidates(fiber) {
|
|
76
153
|
let current = fiber;
|
|
154
|
+
const jsxCandidates = [];
|
|
155
|
+
const componentCandidates = [];
|
|
77
156
|
while (current) {
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
|
|
157
|
+
const jsxSource = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps) ?? getDirectDebugSource(current);
|
|
158
|
+
if (jsxSource) {
|
|
159
|
+
const file = getSourceFile(jsxSource);
|
|
160
|
+
if (file && !jsxCandidates.some((candidate) => candidate.source === jsxSource)) {
|
|
161
|
+
jsxCandidates.push({ source: jsxSource, file });
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const componentSource = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
|
|
165
|
+
if (componentSource) {
|
|
166
|
+
const file = getSourceFile(componentSource);
|
|
167
|
+
if (file && !componentCandidates.some((candidate) => candidate.source === componentSource)) {
|
|
168
|
+
componentCandidates.push({ source: componentSource, file });
|
|
169
|
+
}
|
|
81
170
|
}
|
|
82
171
|
current = current.return ?? null;
|
|
83
172
|
}
|
|
84
|
-
|
|
173
|
+
const direct = jsxCandidates[0]?.source ?? null;
|
|
174
|
+
const nearestProjectLocalComponentFile = componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.file;
|
|
175
|
+
let screen = null;
|
|
176
|
+
if (nearestProjectLocalComponentFile) {
|
|
177
|
+
const matchingJsxCandidate = jsxCandidates.find((candidate) => candidate.file === nearestProjectLocalComponentFile);
|
|
178
|
+
if (matchingJsxCandidate) {
|
|
179
|
+
screen = matchingJsxCandidate.source;
|
|
180
|
+
} else {
|
|
181
|
+
const matchingComponentCandidate = componentCandidates.find(
|
|
182
|
+
(candidate) => candidate.file === nearestProjectLocalComponentFile
|
|
183
|
+
);
|
|
184
|
+
if (matchingComponentCandidate) {
|
|
185
|
+
screen = matchingComponentCandidate.source;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
const implementationComponentCandidate = componentCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;
|
|
190
|
+
const implementationJsxCandidate = jsxCandidates.find((candidate) => !isProjectLocalSource(candidate.source))?.source ?? null;
|
|
191
|
+
const projectLocalJsxCandidate = jsxCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;
|
|
192
|
+
const screenFallback = screen ?? projectLocalJsxCandidate ?? componentCandidates.find((candidate) => isProjectLocalSource(candidate.source))?.source ?? null;
|
|
193
|
+
return {
|
|
194
|
+
direct: direct ?? screenFallback,
|
|
195
|
+
screen: screenFallback,
|
|
196
|
+
implementation: implementationComponentCandidate ?? implementationJsxCandidate ?? screenFallback
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function getModeDescription(mode) {
|
|
200
|
+
if (mode === "direct") {
|
|
201
|
+
return "Direct JSX";
|
|
202
|
+
}
|
|
203
|
+
if (mode === "screen") {
|
|
204
|
+
return "Screen source";
|
|
205
|
+
}
|
|
206
|
+
return "Implementation source";
|
|
85
207
|
}
|
|
86
208
|
function createStatusOverlay(triggerKey) {
|
|
87
209
|
if (typeof document === "undefined") {
|
|
88
210
|
return null;
|
|
89
211
|
}
|
|
90
212
|
const element = document.createElement("div");
|
|
91
|
-
let currentText = "";
|
|
92
213
|
let copyValue = null;
|
|
214
|
+
let currentMode = "screen";
|
|
93
215
|
let hideTimer = null;
|
|
94
216
|
element.setAttribute("data-react-code-locator", "true");
|
|
95
217
|
Object.assign(element.style, {
|
|
@@ -113,7 +235,6 @@ function createStatusOverlay(triggerKey) {
|
|
|
113
235
|
transition: "opacity 120ms ease"
|
|
114
236
|
});
|
|
115
237
|
const show = (message, tone) => {
|
|
116
|
-
currentText = message;
|
|
117
238
|
element.textContent = message;
|
|
118
239
|
element.style.background = tone === "success" ? "rgba(6, 95, 70, 0.92)" : tone === "error" ? "rgba(153, 27, 27, 0.94)" : "rgba(17, 24, 39, 0.92)";
|
|
119
240
|
element.style.opacity = "1";
|
|
@@ -124,7 +245,7 @@ function createStatusOverlay(triggerKey) {
|
|
|
124
245
|
hideTimer = setTimeout(() => {
|
|
125
246
|
element.style.opacity = "0";
|
|
126
247
|
element.style.pointerEvents = "none";
|
|
127
|
-
},
|
|
248
|
+
}, 2e3);
|
|
128
249
|
};
|
|
129
250
|
element.addEventListener("click", async () => {
|
|
130
251
|
if (!copyValue) {
|
|
@@ -137,7 +258,7 @@ function createStatusOverlay(triggerKey) {
|
|
|
137
258
|
show(`[react-code-locator] copy failed`, "error");
|
|
138
259
|
}
|
|
139
260
|
});
|
|
140
|
-
show(`[react-code-locator] enabled (${triggerKey}+click)`, "idle");
|
|
261
|
+
show(`[react-code-locator] enabled (${triggerKey}+click, alt+1/2/3 to switch mode)`, "idle");
|
|
141
262
|
const mount = () => {
|
|
142
263
|
if (!element.isConnected && document.body) {
|
|
143
264
|
document.body.appendChild(element);
|
|
@@ -155,6 +276,10 @@ function createStatusOverlay(triggerKey) {
|
|
|
155
276
|
setCopyValue(value) {
|
|
156
277
|
copyValue = value;
|
|
157
278
|
},
|
|
279
|
+
setMode(mode) {
|
|
280
|
+
currentMode = mode;
|
|
281
|
+
show(`[react-code-locator] ${getModeDescription(mode)}`, "idle");
|
|
282
|
+
},
|
|
158
283
|
remove() {
|
|
159
284
|
if (hideTimer) {
|
|
160
285
|
clearTimeout(hideTimer);
|
|
@@ -163,17 +288,18 @@ function createStatusOverlay(triggerKey) {
|
|
|
163
288
|
}
|
|
164
289
|
};
|
|
165
290
|
}
|
|
166
|
-
function locateComponentSource(target) {
|
|
291
|
+
function locateComponentSource(target, mode = "screen") {
|
|
167
292
|
const elementTarget = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
|
|
168
293
|
const fiber = getClosestReactFiber(elementTarget);
|
|
169
294
|
if (!fiber) {
|
|
170
295
|
return null;
|
|
171
296
|
}
|
|
172
|
-
const
|
|
173
|
-
|
|
297
|
+
const candidates = resolveSourceCandidates(fiber);
|
|
298
|
+
const source = candidates[mode] ?? candidates.screen ?? candidates.direct ?? candidates.implementation;
|
|
299
|
+
if (source) {
|
|
174
300
|
return {
|
|
175
|
-
source
|
|
176
|
-
mode
|
|
301
|
+
source,
|
|
302
|
+
mode
|
|
177
303
|
};
|
|
178
304
|
}
|
|
179
305
|
const componentSource = resolveComponentSourceFromFiber(fiber);
|
|
@@ -182,11 +308,12 @@ function locateComponentSource(target) {
|
|
|
182
308
|
}
|
|
183
309
|
return {
|
|
184
310
|
source: componentSource,
|
|
185
|
-
mode
|
|
311
|
+
mode
|
|
186
312
|
};
|
|
187
313
|
}
|
|
188
314
|
function enableReactComponentJump(options = {}) {
|
|
189
315
|
const overlay = createStatusOverlay(options.triggerKey ?? "shift");
|
|
316
|
+
let currentMode = "screen";
|
|
190
317
|
const {
|
|
191
318
|
triggerKey = "shift",
|
|
192
319
|
onLocate = (result) => {
|
|
@@ -202,6 +329,28 @@ function enableReactComponentJump(options = {}) {
|
|
|
202
329
|
}
|
|
203
330
|
} = options;
|
|
204
331
|
console.log("[react-code-locator] enabled", { triggerKey });
|
|
332
|
+
const keyHandler = (event) => {
|
|
333
|
+
if (!event.altKey) {
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (event.code === "Digit1") {
|
|
337
|
+
currentMode = "direct";
|
|
338
|
+
overlay?.setMode(currentMode);
|
|
339
|
+
event.preventDefault();
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
if (event.code === "Digit2") {
|
|
343
|
+
currentMode = "screen";
|
|
344
|
+
overlay?.setMode(currentMode);
|
|
345
|
+
event.preventDefault();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (event.code === "Digit3") {
|
|
349
|
+
currentMode = "implementation";
|
|
350
|
+
overlay?.setMode(currentMode);
|
|
351
|
+
event.preventDefault();
|
|
352
|
+
}
|
|
353
|
+
};
|
|
205
354
|
const handler = (event) => {
|
|
206
355
|
console.log("[react-code-locator] click", {
|
|
207
356
|
triggerKey,
|
|
@@ -214,7 +363,7 @@ function enableReactComponentJump(options = {}) {
|
|
|
214
363
|
if (!isTriggerPressed(event, triggerKey)) {
|
|
215
364
|
return;
|
|
216
365
|
}
|
|
217
|
-
const result = locateComponentSource(event.target);
|
|
366
|
+
const result = locateComponentSource(event.target, currentMode);
|
|
218
367
|
if (!result) {
|
|
219
368
|
onError(new Error("No React component source metadata found for clicked element."));
|
|
220
369
|
return;
|
|
@@ -224,13 +373,656 @@ function enableReactComponentJump(options = {}) {
|
|
|
224
373
|
onLocate(result);
|
|
225
374
|
};
|
|
226
375
|
document.addEventListener("click", handler, true);
|
|
376
|
+
document.addEventListener("keydown", keyHandler, true);
|
|
227
377
|
return () => {
|
|
228
378
|
document.removeEventListener("click", handler, true);
|
|
379
|
+
document.removeEventListener("keydown", keyHandler, true);
|
|
229
380
|
overlay?.remove();
|
|
230
381
|
};
|
|
231
382
|
}
|
|
383
|
+
|
|
384
|
+
// src/sourceAdapter.ts
|
|
385
|
+
function defineSourceAdapter(descriptor) {
|
|
386
|
+
return descriptor;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// src/babelInjectComponentSource.ts
|
|
390
|
+
import { types as t } from "@babel/core";
|
|
391
|
+
var SOURCE_PROP_LOCAL = "_componentSourceLoc";
|
|
392
|
+
var SOURCE_PROPS_REST = "__reactCodeLocatorProps";
|
|
393
|
+
function isComponentName(name) {
|
|
394
|
+
return /^[A-Z]/.test(name);
|
|
395
|
+
}
|
|
396
|
+
function isCustomComponentTag(name) {
|
|
397
|
+
if (t.isJSXIdentifier(name)) {
|
|
398
|
+
return isComponentName(name.name);
|
|
399
|
+
}
|
|
400
|
+
if (t.isJSXMemberExpression(name)) {
|
|
401
|
+
return true;
|
|
402
|
+
}
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
function isIntrinsicElementTag(name) {
|
|
406
|
+
return t.isJSXIdentifier(name) && /^[a-z]/.test(name.name);
|
|
407
|
+
}
|
|
408
|
+
function isElementFactoryIdentifier(name) {
|
|
409
|
+
return name === "jsx" || name === "jsxs" || name === "jsxDEV" || name === "_jsx" || name === "_jsxs" || name === "_jsxDEV" || name === "createElement";
|
|
410
|
+
}
|
|
411
|
+
function isReactElementFactoryCall(pathNode) {
|
|
412
|
+
const callee = pathNode.node.callee;
|
|
413
|
+
if (t.isIdentifier(callee)) {
|
|
414
|
+
return isElementFactoryIdentifier(callee.name);
|
|
415
|
+
}
|
|
416
|
+
return t.isMemberExpression(callee) && t.isIdentifier(callee.object, { name: "React" }) && t.isIdentifier(callee.property, { name: "createElement" });
|
|
417
|
+
}
|
|
418
|
+
function getRootJsxIdentifierName(name) {
|
|
419
|
+
if (t.isJSXIdentifier(name)) {
|
|
420
|
+
return name.name;
|
|
421
|
+
}
|
|
422
|
+
if (t.isJSXMemberExpression(name)) {
|
|
423
|
+
return getRootJsxIdentifierName(name.object);
|
|
424
|
+
}
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
function isStyledModuleImport(binding) {
|
|
428
|
+
if (!binding) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
if (!binding.path.isImportSpecifier() && !binding.path.isImportDefaultSpecifier() && !binding.path.isImportNamespaceSpecifier()) {
|
|
432
|
+
return false;
|
|
433
|
+
}
|
|
434
|
+
const source = binding.path.parentPath.isImportDeclaration() ? binding.path.parentPath.node.source.value : null;
|
|
435
|
+
if (typeof source !== "string") {
|
|
436
|
+
return false;
|
|
437
|
+
}
|
|
438
|
+
const normalized = source.replace(/\\/g, "/");
|
|
439
|
+
return normalized === "./styled" || normalized === "../styled" || normalized.endsWith("/styled");
|
|
440
|
+
}
|
|
441
|
+
function isSupportedComponentInit(node) {
|
|
442
|
+
if (!node) {
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {
|
|
446
|
+
return true;
|
|
447
|
+
}
|
|
448
|
+
if (!t.isCallExpression(node)) {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
if (t.isIdentifier(node.callee) && (node.callee.name === "memo" || node.callee.name === "forwardRef")) {
|
|
452
|
+
return true;
|
|
453
|
+
}
|
|
454
|
+
return t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.object, { name: "React" }) && t.isIdentifier(node.callee.property) && (node.callee.property.name === "memo" || node.callee.property.name === "forwardRef");
|
|
455
|
+
}
|
|
456
|
+
function hasSourcePropBinding(pattern) {
|
|
457
|
+
return pattern.properties.some((property) => {
|
|
458
|
+
if (!t.isObjectProperty(property)) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
return t.isIdentifier(property.key) && property.key.name === JSX_SOURCE_PROP;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
function injectSourcePropBinding(pattern) {
|
|
465
|
+
if (hasSourcePropBinding(pattern)) {
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const sourceBinding = t.objectProperty(
|
|
469
|
+
t.identifier(JSX_SOURCE_PROP),
|
|
470
|
+
t.identifier(SOURCE_PROP_LOCAL),
|
|
471
|
+
false,
|
|
472
|
+
false
|
|
473
|
+
);
|
|
474
|
+
const restIndex = pattern.properties.findIndex(
|
|
475
|
+
(property) => t.isRestElement(property)
|
|
476
|
+
);
|
|
477
|
+
if (restIndex === -1) {
|
|
478
|
+
pattern.properties.push(sourceBinding);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
pattern.properties.splice(restIndex, 0, sourceBinding);
|
|
482
|
+
}
|
|
483
|
+
function injectSourcePropIntoIdentifierParam(node, param) {
|
|
484
|
+
if (!t.isBlockStatement(node.body)) {
|
|
485
|
+
node.body = t.blockStatement([t.returnStatement(node.body)]);
|
|
486
|
+
}
|
|
487
|
+
const alreadyInjected = node.body.body.some(
|
|
488
|
+
(statement) => t.isVariableDeclaration(statement) && statement.declarations.some(
|
|
489
|
+
(declaration) => t.isIdentifier(declaration.id) && declaration.id.name === SOURCE_PROPS_REST
|
|
490
|
+
)
|
|
491
|
+
);
|
|
492
|
+
if (alreadyInjected) {
|
|
493
|
+
return;
|
|
494
|
+
}
|
|
495
|
+
node.body.body.unshift(
|
|
496
|
+
t.variableDeclaration("const", [
|
|
497
|
+
t.variableDeclarator(
|
|
498
|
+
t.objectPattern([
|
|
499
|
+
t.objectProperty(
|
|
500
|
+
t.identifier(JSX_SOURCE_PROP),
|
|
501
|
+
t.identifier(SOURCE_PROP_LOCAL),
|
|
502
|
+
false,
|
|
503
|
+
false
|
|
504
|
+
),
|
|
505
|
+
t.restElement(t.identifier(SOURCE_PROPS_REST))
|
|
506
|
+
]),
|
|
507
|
+
param
|
|
508
|
+
)
|
|
509
|
+
]),
|
|
510
|
+
t.expressionStatement(
|
|
511
|
+
t.assignmentExpression(
|
|
512
|
+
"=",
|
|
513
|
+
t.identifier(param.name),
|
|
514
|
+
t.identifier(SOURCE_PROPS_REST)
|
|
515
|
+
)
|
|
516
|
+
)
|
|
517
|
+
);
|
|
518
|
+
}
|
|
519
|
+
function injectSourcePropIntoFunctionParams(node) {
|
|
520
|
+
const firstParam = node.params[0];
|
|
521
|
+
if (!firstParam) {
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
524
|
+
if (t.isObjectPattern(firstParam)) {
|
|
525
|
+
injectSourcePropBinding(firstParam);
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (t.isIdentifier(firstParam)) {
|
|
529
|
+
injectSourcePropIntoIdentifierParam(node, firstParam);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
function injectSourcePropIntoExpression(node) {
|
|
533
|
+
if (!node) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (t.isFunctionExpression(node) || t.isArrowFunctionExpression(node)) {
|
|
537
|
+
injectSourcePropIntoFunctionParams(node);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
if (!t.isCallExpression(node)) {
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const firstArg = node.arguments[0];
|
|
544
|
+
if (firstArg && !t.isSpreadElement(firstArg) && (t.isFunctionExpression(firstArg) || t.isArrowFunctionExpression(firstArg))) {
|
|
545
|
+
injectSourcePropIntoFunctionParams(firstArg);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
function getSourceValue(state, loc, projectRoot) {
|
|
549
|
+
const filename = state.file?.opts?.filename;
|
|
550
|
+
if (!filename || !loc) {
|
|
551
|
+
return null;
|
|
552
|
+
}
|
|
553
|
+
return toRelativeSource(filename, loc, projectRoot);
|
|
554
|
+
}
|
|
555
|
+
function buildAssignment(name, sourceValue) {
|
|
556
|
+
return t.expressionStatement(
|
|
557
|
+
t.assignmentExpression(
|
|
558
|
+
"=",
|
|
559
|
+
t.memberExpression(t.identifier(name), t.identifier(SOURCE_PROP)),
|
|
560
|
+
t.stringLiteral(sourceValue)
|
|
561
|
+
)
|
|
562
|
+
);
|
|
563
|
+
}
|
|
564
|
+
function buildIntrinsicSourceHelper() {
|
|
565
|
+
return t.functionDeclaration(
|
|
566
|
+
t.identifier("_markIntrinsicElementSource"),
|
|
567
|
+
[t.identifier("element"), t.identifier("source")],
|
|
568
|
+
t.blockStatement([
|
|
569
|
+
t.variableDeclaration("const", [
|
|
570
|
+
t.variableDeclarator(
|
|
571
|
+
t.identifier("registryKey"),
|
|
572
|
+
t.callExpression(
|
|
573
|
+
t.memberExpression(t.identifier("Symbol"), t.identifier("for")),
|
|
574
|
+
[t.stringLiteral(JSX_SOURCE_REGISTRY_SYMBOL)]
|
|
575
|
+
)
|
|
576
|
+
)
|
|
577
|
+
]),
|
|
578
|
+
t.variableDeclaration("let", [
|
|
579
|
+
t.variableDeclarator(
|
|
580
|
+
t.identifier("registry"),
|
|
581
|
+
t.memberExpression(t.identifier("globalThis"), t.identifier("registryKey"), true)
|
|
582
|
+
)
|
|
583
|
+
]),
|
|
584
|
+
t.ifStatement(
|
|
585
|
+
t.unaryExpression(
|
|
586
|
+
"!",
|
|
587
|
+
t.binaryExpression("instanceof", t.identifier("registry"), t.identifier("WeakMap"))
|
|
588
|
+
),
|
|
589
|
+
t.blockStatement([
|
|
590
|
+
t.expressionStatement(
|
|
591
|
+
t.assignmentExpression(
|
|
592
|
+
"=",
|
|
593
|
+
t.identifier("registry"),
|
|
594
|
+
t.assignmentExpression(
|
|
595
|
+
"=",
|
|
596
|
+
t.memberExpression(t.identifier("globalThis"), t.identifier("registryKey"), true),
|
|
597
|
+
t.newExpression(t.identifier("WeakMap"), [])
|
|
598
|
+
)
|
|
599
|
+
)
|
|
600
|
+
)
|
|
601
|
+
])
|
|
602
|
+
),
|
|
603
|
+
t.ifStatement(
|
|
604
|
+
t.logicalExpression(
|
|
605
|
+
"&&",
|
|
606
|
+
t.identifier("element"),
|
|
607
|
+
t.logicalExpression(
|
|
608
|
+
"&&",
|
|
609
|
+
t.binaryExpression("===", t.unaryExpression("typeof", t.identifier("element")), t.stringLiteral("object")),
|
|
610
|
+
t.binaryExpression(
|
|
611
|
+
"===",
|
|
612
|
+
t.unaryExpression("typeof", t.memberExpression(t.identifier("element"), t.identifier("props"))),
|
|
613
|
+
t.stringLiteral("object")
|
|
614
|
+
)
|
|
615
|
+
)
|
|
616
|
+
),
|
|
617
|
+
t.blockStatement([
|
|
618
|
+
t.expressionStatement(
|
|
619
|
+
t.callExpression(
|
|
620
|
+
t.memberExpression(t.identifier("registry"), t.identifier("set")),
|
|
621
|
+
[t.memberExpression(t.identifier("element"), t.identifier("props")), t.identifier("source")]
|
|
622
|
+
)
|
|
623
|
+
)
|
|
624
|
+
])
|
|
625
|
+
),
|
|
626
|
+
t.returnStatement(t.identifier("element"))
|
|
627
|
+
])
|
|
628
|
+
);
|
|
629
|
+
}
|
|
630
|
+
function ensureIntrinsicSourceHelper(programPath, state) {
|
|
631
|
+
if (state.injectedIntrinsicHelper) {
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
const alreadyExists = programPath.node.body.some(
|
|
635
|
+
(node) => t.isFunctionDeclaration(node) && t.isIdentifier(node.id, { name: "_markIntrinsicElementSource" })
|
|
636
|
+
);
|
|
637
|
+
if (!alreadyExists) {
|
|
638
|
+
programPath.unshiftContainer("body", buildIntrinsicSourceHelper());
|
|
639
|
+
}
|
|
640
|
+
state.injectedIntrinsicHelper = true;
|
|
641
|
+
}
|
|
642
|
+
function visitDeclaration(declarationPath, insertAfterPath, state, seen, projectRoot) {
|
|
643
|
+
if (declarationPath.isFunctionDeclaration() || declarationPath.isClassDeclaration()) {
|
|
644
|
+
const name = declarationPath.node.id?.name;
|
|
645
|
+
if (!name || !isComponentName(name) || seen.has(name)) {
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
if (declarationPath.isFunctionDeclaration()) {
|
|
649
|
+
injectSourcePropIntoFunctionParams(declarationPath.node);
|
|
650
|
+
}
|
|
651
|
+
const sourceValue = getSourceValue(
|
|
652
|
+
state,
|
|
653
|
+
declarationPath.node.loc?.start,
|
|
654
|
+
projectRoot
|
|
655
|
+
);
|
|
656
|
+
if (!sourceValue) {
|
|
657
|
+
return;
|
|
658
|
+
}
|
|
659
|
+
seen.add(name);
|
|
660
|
+
insertAfterPath.insertAfter(buildAssignment(name, sourceValue));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (!declarationPath.isVariableDeclaration()) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
const assignments = declarationPath.node.declarations.flatMap(
|
|
667
|
+
(declarator) => {
|
|
668
|
+
if (!t.isIdentifier(declarator.id) || !isComponentName(declarator.id.name) || seen.has(declarator.id.name)) {
|
|
669
|
+
return [];
|
|
670
|
+
}
|
|
671
|
+
if (!declarator.init) {
|
|
672
|
+
return [];
|
|
673
|
+
}
|
|
674
|
+
if (!isSupportedComponentInit(declarator.init)) {
|
|
675
|
+
return [];
|
|
676
|
+
}
|
|
677
|
+
injectSourcePropIntoExpression(declarator.init);
|
|
678
|
+
const sourceValue = getSourceValue(
|
|
679
|
+
state,
|
|
680
|
+
declarator.loc?.start ?? declarator.init.loc?.start,
|
|
681
|
+
projectRoot
|
|
682
|
+
);
|
|
683
|
+
if (!sourceValue) {
|
|
684
|
+
return [];
|
|
685
|
+
}
|
|
686
|
+
seen.add(declarator.id.name);
|
|
687
|
+
return [buildAssignment(declarator.id.name, sourceValue)];
|
|
688
|
+
}
|
|
689
|
+
);
|
|
690
|
+
if (assignments.length > 0) {
|
|
691
|
+
insertAfterPath.insertAfter(assignments);
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
function babelInjectComponentSource(options = {}) {
|
|
695
|
+
const {
|
|
696
|
+
injectJsxSource = true,
|
|
697
|
+
injectComponentSource = true,
|
|
698
|
+
projectRoot
|
|
699
|
+
} = options;
|
|
700
|
+
return {
|
|
701
|
+
name: "babel-inject-component-source",
|
|
702
|
+
visitor: {
|
|
703
|
+
CallExpression(pathNode, state) {
|
|
704
|
+
if (!injectJsxSource) {
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
if (!isReactElementFactoryCall(pathNode)) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
if (pathNode.parentPath.isCallExpression() && t.isIdentifier(pathNode.parentPath.node.callee, {
|
|
711
|
+
name: "_markIntrinsicElementSource"
|
|
712
|
+
})) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
const sourceValue = getSourceValue(
|
|
716
|
+
state,
|
|
717
|
+
pathNode.node.loc?.start,
|
|
718
|
+
projectRoot
|
|
719
|
+
);
|
|
720
|
+
if (!sourceValue) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
const programPath = pathNode.findParent((parent) => parent.isProgram());
|
|
724
|
+
if (!programPath || !programPath.isProgram()) {
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
ensureIntrinsicSourceHelper(programPath, state);
|
|
728
|
+
pathNode.replaceWith(
|
|
729
|
+
t.callExpression(t.identifier("_markIntrinsicElementSource"), [
|
|
730
|
+
pathNode.node,
|
|
731
|
+
t.stringLiteral(sourceValue)
|
|
732
|
+
])
|
|
733
|
+
);
|
|
734
|
+
pathNode.skip();
|
|
735
|
+
},
|
|
736
|
+
JSXElement: {
|
|
737
|
+
exit(pathNode, state) {
|
|
738
|
+
if (!injectJsxSource) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
741
|
+
if (!isIntrinsicElementTag(pathNode.node.openingElement.name)) {
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
if (pathNode.parentPath.isCallExpression() && t.isIdentifier(pathNode.parentPath.node.callee, { name: "_markIntrinsicElementSource" })) {
|
|
745
|
+
return;
|
|
746
|
+
}
|
|
747
|
+
const sourceValue = getSourceValue(
|
|
748
|
+
state,
|
|
749
|
+
pathNode.node.openingElement.loc?.start,
|
|
750
|
+
projectRoot
|
|
751
|
+
);
|
|
752
|
+
if (!sourceValue) {
|
|
753
|
+
return;
|
|
754
|
+
}
|
|
755
|
+
const programPath = pathNode.findParent((parent) => parent.isProgram());
|
|
756
|
+
if (!programPath || !programPath.isProgram()) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
ensureIntrinsicSourceHelper(programPath, state);
|
|
760
|
+
const wrappedNode = t.callExpression(t.identifier("_markIntrinsicElementSource"), [
|
|
761
|
+
pathNode.node,
|
|
762
|
+
t.stringLiteral(sourceValue)
|
|
763
|
+
]);
|
|
764
|
+
if (pathNode.parentPath.isJSXElement() || pathNode.parentPath.isJSXFragment()) {
|
|
765
|
+
pathNode.replaceWith(t.jsxExpressionContainer(wrappedNode));
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
if (pathNode.parentPath.isJSXExpressionContainer()) {
|
|
769
|
+
pathNode.parentPath.replaceWith(t.jsxExpressionContainer(wrappedNode));
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
pathNode.replaceWith(wrappedNode);
|
|
773
|
+
}
|
|
774
|
+
},
|
|
775
|
+
JSXOpeningElement(pathNode, state) {
|
|
776
|
+
if (!injectJsxSource) {
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
779
|
+
if (!isCustomComponentTag(pathNode.node.name)) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
const rootIdentifierName = getRootJsxIdentifierName(pathNode.node.name);
|
|
783
|
+
if (rootIdentifierName && isExternalToProjectRoot(state.file?.opts?.filename, projectRoot) && isStyledModuleImport(pathNode.scope.getBinding(rootIdentifierName))) {
|
|
784
|
+
return;
|
|
785
|
+
}
|
|
786
|
+
const hasSourceProp = pathNode.node.attributes.some(
|
|
787
|
+
(attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === JSX_SOURCE_PROP
|
|
788
|
+
);
|
|
789
|
+
if (hasSourceProp) {
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
const filename = state.file?.opts?.filename;
|
|
793
|
+
const loc = pathNode.node.loc?.start;
|
|
794
|
+
if (!filename || !loc) {
|
|
795
|
+
return;
|
|
796
|
+
}
|
|
797
|
+
pathNode.node.attributes.push(
|
|
798
|
+
t.jsxAttribute(
|
|
799
|
+
t.jsxIdentifier(JSX_SOURCE_PROP),
|
|
800
|
+
t.stringLiteral(
|
|
801
|
+
getSourceValue(state, loc, projectRoot) ?? `${filename.replace(/\\/g, "/")}:${loc.line}:${loc.column + 1}`
|
|
802
|
+
)
|
|
803
|
+
)
|
|
804
|
+
);
|
|
805
|
+
},
|
|
806
|
+
Program(programPath, state) {
|
|
807
|
+
if (!injectComponentSource) {
|
|
808
|
+
return;
|
|
809
|
+
}
|
|
810
|
+
const seen = /* @__PURE__ */ new Set();
|
|
811
|
+
for (const childPath of programPath.get("body")) {
|
|
812
|
+
if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {
|
|
813
|
+
const declarationPath = childPath.get("declaration");
|
|
814
|
+
if (!Array.isArray(declarationPath) && declarationPath.node) {
|
|
815
|
+
visitDeclaration(declarationPath, childPath, state, seen, projectRoot);
|
|
816
|
+
}
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
visitDeclaration(childPath, childPath, state, seen, projectRoot);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// src/babel.ts
|
|
827
|
+
function createBabelSourceAdapter(options = {}) {
|
|
828
|
+
return defineSourceAdapter({
|
|
829
|
+
kind: "babel",
|
|
830
|
+
name: "react-code-locator/babel",
|
|
831
|
+
options,
|
|
832
|
+
config: {
|
|
833
|
+
plugins: [[babelInjectComponentSource, options]]
|
|
834
|
+
}
|
|
835
|
+
});
|
|
836
|
+
}
|
|
837
|
+
var babelSourceAdapter = createBabelSourceAdapter();
|
|
838
|
+
|
|
839
|
+
// src/sourceTransform.ts
|
|
840
|
+
import { transformAsync } from "@babel/core";
|
|
841
|
+
async function transformSourceWithLocator(code, options) {
|
|
842
|
+
const { filename, sourceMaps = true, ...pluginOptions } = options;
|
|
843
|
+
const result = await transformAsync(code, {
|
|
844
|
+
filename,
|
|
845
|
+
babelrc: false,
|
|
846
|
+
configFile: false,
|
|
847
|
+
sourceMaps,
|
|
848
|
+
parserOpts: {
|
|
849
|
+
sourceType: "module",
|
|
850
|
+
plugins: ["jsx", "typescript"]
|
|
851
|
+
},
|
|
852
|
+
generatorOpts: {
|
|
853
|
+
retainLines: true
|
|
854
|
+
},
|
|
855
|
+
plugins: [[babelInjectComponentSource, pluginOptions]]
|
|
856
|
+
});
|
|
857
|
+
return {
|
|
858
|
+
code: result?.code ?? code,
|
|
859
|
+
map: result?.map ?? null
|
|
860
|
+
};
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// src/viteClientInjector.ts
|
|
864
|
+
var VIRTUAL_CLIENT_MODULE_ID = "virtual:react-code-locator/client";
|
|
865
|
+
var RESOLVED_VIRTUAL_CLIENT_MODULE_ID = `\0${VIRTUAL_CLIENT_MODULE_ID}`;
|
|
866
|
+
function createClientInjector(locatorOptions = {}) {
|
|
867
|
+
const serialized = JSON.stringify(locatorOptions);
|
|
868
|
+
return {
|
|
869
|
+
name: "react-code-locator-client-injector",
|
|
870
|
+
apply: "serve",
|
|
871
|
+
resolveId(id) {
|
|
872
|
+
if (id === VIRTUAL_CLIENT_MODULE_ID) {
|
|
873
|
+
return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;
|
|
874
|
+
}
|
|
875
|
+
return null;
|
|
876
|
+
},
|
|
877
|
+
load(id) {
|
|
878
|
+
if (id !== RESOLVED_VIRTUAL_CLIENT_MODULE_ID) {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
return `
|
|
882
|
+
import { enableReactComponentJump } from "react-code-locator/client";
|
|
883
|
+
|
|
884
|
+
enableReactComponentJump(${serialized});
|
|
885
|
+
`;
|
|
886
|
+
},
|
|
887
|
+
transformIndexHtml() {
|
|
888
|
+
return [
|
|
889
|
+
{
|
|
890
|
+
tag: "script",
|
|
891
|
+
attrs: {
|
|
892
|
+
type: "module",
|
|
893
|
+
src: `/@id/__x00__${VIRTUAL_CLIENT_MODULE_ID}`
|
|
894
|
+
},
|
|
895
|
+
injectTo: "head"
|
|
896
|
+
}
|
|
897
|
+
];
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
}
|
|
901
|
+
function createViteClientInjector(options = {}) {
|
|
902
|
+
const { command = "serve", locator = {}, injectClient = true } = options;
|
|
903
|
+
const isServe = command === "serve";
|
|
904
|
+
return [isServe && injectClient ? createClientInjector(locator) : null].filter(Boolean);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// src/vite.ts
|
|
908
|
+
function shouldTransformSource(id) {
|
|
909
|
+
if (id.includes("/node_modules/") || id.startsWith("\0")) {
|
|
910
|
+
return false;
|
|
911
|
+
}
|
|
912
|
+
return /\.[mc]?[jt]sx?$/.test(id);
|
|
913
|
+
}
|
|
914
|
+
function viteSourceTransformPlugin(options = {}) {
|
|
915
|
+
return {
|
|
916
|
+
name: "react-code-locator-source-transform",
|
|
917
|
+
enforce: "pre",
|
|
918
|
+
async transform(code, id) {
|
|
919
|
+
if (!shouldTransformSource(id)) {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
922
|
+
return transformSourceWithLocator(code, {
|
|
923
|
+
filename: id,
|
|
924
|
+
...options
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
};
|
|
928
|
+
}
|
|
929
|
+
function createViteSourceAdapter(options = {}) {
|
|
930
|
+
const { babel = {}, ...viteOptions } = options;
|
|
931
|
+
const plugins = [
|
|
932
|
+
viteSourceTransformPlugin(babel),
|
|
933
|
+
...createViteClientInjector(viteOptions)
|
|
934
|
+
].filter(Boolean);
|
|
935
|
+
return defineSourceAdapter({
|
|
936
|
+
kind: "vite",
|
|
937
|
+
name: "react-code-locator/vite",
|
|
938
|
+
options,
|
|
939
|
+
config: {
|
|
940
|
+
plugins
|
|
941
|
+
}
|
|
942
|
+
});
|
|
943
|
+
}
|
|
944
|
+
var viteSourceAdapter = createViteSourceAdapter();
|
|
945
|
+
|
|
946
|
+
// src/esbuild.ts
|
|
947
|
+
import { readFile } from "fs/promises";
|
|
948
|
+
function getEsbuildLoader(filename) {
|
|
949
|
+
if (filename.endsWith(".tsx")) {
|
|
950
|
+
return "tsx";
|
|
951
|
+
}
|
|
952
|
+
if (filename.endsWith(".ts")) {
|
|
953
|
+
return "ts";
|
|
954
|
+
}
|
|
955
|
+
if (filename.endsWith(".jsx")) {
|
|
956
|
+
return "jsx";
|
|
957
|
+
}
|
|
958
|
+
return "js";
|
|
959
|
+
}
|
|
960
|
+
function esbuildSourceTransformPlugin(options = {}) {
|
|
961
|
+
return {
|
|
962
|
+
name: "react-code-locator-source-transform",
|
|
963
|
+
setup(build) {
|
|
964
|
+
build.onLoad({ filter: /\.[mc]?[jt]sx?$/ }, async ({ path }) => {
|
|
965
|
+
if (path.includes("/node_modules/")) {
|
|
966
|
+
return null;
|
|
967
|
+
}
|
|
968
|
+
const code = await readFile(path, "utf8");
|
|
969
|
+
const result = await transformSourceWithLocator(code, {
|
|
970
|
+
filename: path,
|
|
971
|
+
...options
|
|
972
|
+
});
|
|
973
|
+
return {
|
|
974
|
+
contents: result.code,
|
|
975
|
+
loader: getEsbuildLoader(path)
|
|
976
|
+
};
|
|
977
|
+
});
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
function createEsbuildSourceAdapter(options = {}) {
|
|
982
|
+
return defineSourceAdapter({
|
|
983
|
+
kind: "esbuild",
|
|
984
|
+
name: "react-code-locator/esbuild",
|
|
985
|
+
options,
|
|
986
|
+
config: {
|
|
987
|
+
plugins: [esbuildSourceTransformPlugin(options)]
|
|
988
|
+
}
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
var esbuildSourceAdapter = createEsbuildSourceAdapter();
|
|
992
|
+
|
|
993
|
+
// src/swc.ts
|
|
994
|
+
async function transformSourceWithSwcLocator(code, options) {
|
|
995
|
+
return transformSourceWithLocator(code, options);
|
|
996
|
+
}
|
|
997
|
+
function createSwcSourceAdapter(options = {}) {
|
|
998
|
+
const transform = (code, transformOptions) => transformSourceWithSwcLocator(code, {
|
|
999
|
+
...options,
|
|
1000
|
+
...transformOptions
|
|
1001
|
+
});
|
|
1002
|
+
return defineSourceAdapter({
|
|
1003
|
+
kind: "swc",
|
|
1004
|
+
name: "react-code-locator/swc",
|
|
1005
|
+
options,
|
|
1006
|
+
config: {
|
|
1007
|
+
transform
|
|
1008
|
+
}
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
var swcSourceAdapter = createSwcSourceAdapter();
|
|
232
1012
|
export {
|
|
1013
|
+
babelInjectComponentSource,
|
|
1014
|
+
babelSourceAdapter,
|
|
1015
|
+
createBabelSourceAdapter,
|
|
1016
|
+
createEsbuildSourceAdapter,
|
|
1017
|
+
createSwcSourceAdapter,
|
|
1018
|
+
createViteClientInjector,
|
|
1019
|
+
createViteSourceAdapter,
|
|
1020
|
+
defineSourceAdapter,
|
|
233
1021
|
enableReactComponentJump,
|
|
234
|
-
|
|
1022
|
+
esbuildSourceAdapter,
|
|
1023
|
+
locateComponentSource,
|
|
1024
|
+
createViteClientInjector as reactComponentJump,
|
|
1025
|
+
swcSourceAdapter,
|
|
1026
|
+
viteSourceAdapter
|
|
235
1027
|
};
|
|
236
1028
|
//# sourceMappingURL=index.js.map
|