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