react-code-locator 0.1.4

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 (44) hide show
  1. package/README.md +243 -0
  2. package/dist/babel.cjs +152 -0
  3. package/dist/babel.cjs.map +1 -0
  4. package/dist/babel.d.cts +2 -0
  5. package/dist/babel.d.ts +2 -0
  6. package/dist/babel.js +115 -0
  7. package/dist/babel.js.map +1 -0
  8. package/dist/babelInjectComponentSource.cjs +150 -0
  9. package/dist/babelInjectComponentSource.cjs.map +1 -0
  10. package/dist/babelInjectComponentSource.d.cts +12 -0
  11. package/dist/babelInjectComponentSource.d.ts +12 -0
  12. package/dist/babelInjectComponentSource.js +115 -0
  13. package/dist/babelInjectComponentSource.js.map +1 -0
  14. package/dist/client.cjs +153 -0
  15. package/dist/client.cjs.map +1 -0
  16. package/dist/client.d.cts +14 -0
  17. package/dist/client.d.ts +14 -0
  18. package/dist/client.js +125 -0
  19. package/dist/client.js.map +1 -0
  20. package/dist/index.cjs +153 -0
  21. package/dist/index.cjs.map +1 -0
  22. package/dist/index.d.cts +1 -0
  23. package/dist/index.d.ts +1 -0
  24. package/dist/index.js +125 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/vite.cjs +211 -0
  27. package/dist/vite.cjs.map +1 -0
  28. package/dist/vite.d.cts +13 -0
  29. package/dist/vite.d.ts +13 -0
  30. package/dist/vite.js +173 -0
  31. package/dist/vite.js.map +1 -0
  32. package/dist/webpack.cjs +68 -0
  33. package/dist/webpack.cjs.map +1 -0
  34. package/dist/webpack.d.cts +2 -0
  35. package/dist/webpack.d.ts +2 -0
  36. package/dist/webpack.js +82 -0
  37. package/dist/webpack.js.map +1 -0
  38. package/dist/webpackRuntimeEntry.cjs +128 -0
  39. package/dist/webpackRuntimeEntry.cjs.map +1 -0
  40. package/dist/webpackRuntimeEntry.d.cts +2 -0
  41. package/dist/webpackRuntimeEntry.d.ts +2 -0
  42. package/dist/webpackRuntimeEntry.js +126 -0
  43. package/dist/webpackRuntimeEntry.js.map +1 -0
  44. package/package.json +64 -0
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/babelInjectComponentSource.ts
31
+ var babelInjectComponentSource_exports = {};
32
+ __export(babelInjectComponentSource_exports, {
33
+ babelInjectComponentSource: () => babelInjectComponentSource
34
+ });
35
+ module.exports = __toCommonJS(babelInjectComponentSource_exports);
36
+ var import_node_path = __toESM(require("path"), 1);
37
+ var import_core = require("@babel/core");
38
+
39
+ // src/constants.ts
40
+ var SOURCE_PROP = "__componentSourceLoc";
41
+
42
+ // src/babelInjectComponentSource.ts
43
+ function isComponentName(name) {
44
+ return /^[A-Z]/.test(name);
45
+ }
46
+ function getSourceValue(state, loc) {
47
+ const filename = state.file?.opts?.filename;
48
+ if (!filename || !loc) {
49
+ return null;
50
+ }
51
+ const relPath = import_node_path.default.relative(process.cwd(), filename).replace(/\\/g, "/");
52
+ return `${relPath}:${loc.line}:${loc.column + 1}`;
53
+ }
54
+ function buildAssignment(name, sourceValue) {
55
+ return import_core.types.expressionStatement(
56
+ import_core.types.assignmentExpression(
57
+ "=",
58
+ import_core.types.memberExpression(import_core.types.identifier(name), import_core.types.identifier(SOURCE_PROP)),
59
+ import_core.types.stringLiteral(sourceValue)
60
+ )
61
+ );
62
+ }
63
+ function visitDeclaration(declarationPath, insertAfterPath, state, seen) {
64
+ if (declarationPath.isFunctionDeclaration() || declarationPath.isClassDeclaration()) {
65
+ const name = declarationPath.node.id?.name;
66
+ if (!name || !isComponentName(name) || seen.has(name)) {
67
+ return;
68
+ }
69
+ const sourceValue = getSourceValue(state, declarationPath.node.loc?.start);
70
+ if (!sourceValue) {
71
+ return;
72
+ }
73
+ seen.add(name);
74
+ insertAfterPath.insertAfter(buildAssignment(name, sourceValue));
75
+ return;
76
+ }
77
+ if (!declarationPath.isVariableDeclaration()) {
78
+ return;
79
+ }
80
+ const assignments = declarationPath.node.declarations.flatMap((declarator) => {
81
+ if (!import_core.types.isIdentifier(declarator.id) || !isComponentName(declarator.id.name) || seen.has(declarator.id.name)) {
82
+ return [];
83
+ }
84
+ if (!declarator.init) {
85
+ return [];
86
+ }
87
+ if (!import_core.types.isArrowFunctionExpression(declarator.init) && !import_core.types.isFunctionExpression(declarator.init)) {
88
+ return [];
89
+ }
90
+ const sourceValue = getSourceValue(state, declarator.loc?.start ?? declarator.init.loc?.start);
91
+ if (!sourceValue) {
92
+ return [];
93
+ }
94
+ seen.add(declarator.id.name);
95
+ return [buildAssignment(declarator.id.name, sourceValue)];
96
+ });
97
+ if (assignments.length > 0) {
98
+ insertAfterPath.insertAfter(assignments);
99
+ }
100
+ }
101
+ function babelInjectComponentSource() {
102
+ return {
103
+ name: "babel-inject-component-source",
104
+ visitor: {
105
+ JSXOpeningElement(pathNode, state) {
106
+ const hasSourceProp = pathNode.node.attributes.some(
107
+ (attr) => import_core.types.isJSXAttribute(attr) && import_core.types.isJSXIdentifier(attr.name) && attr.name.name === "__source"
108
+ );
109
+ if (hasSourceProp) {
110
+ return;
111
+ }
112
+ const filename = state.file?.opts?.filename;
113
+ const loc = pathNode.node.loc?.start;
114
+ if (!filename || !loc) {
115
+ return;
116
+ }
117
+ pathNode.node.attributes.push(
118
+ import_core.types.jsxAttribute(
119
+ import_core.types.jsxIdentifier("__source"),
120
+ import_core.types.jsxExpressionContainer(
121
+ import_core.types.objectExpression([
122
+ import_core.types.objectProperty(import_core.types.identifier("fileName"), import_core.types.stringLiteral(filename)),
123
+ import_core.types.objectProperty(import_core.types.identifier("lineNumber"), import_core.types.numericLiteral(loc.line)),
124
+ import_core.types.objectProperty(import_core.types.identifier("columnNumber"), import_core.types.numericLiteral(loc.column + 1))
125
+ ])
126
+ )
127
+ )
128
+ );
129
+ },
130
+ Program(programPath, state) {
131
+ const seen = /* @__PURE__ */ new Set();
132
+ for (const childPath of programPath.get("body")) {
133
+ if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {
134
+ const declarationPath = childPath.get("declaration");
135
+ if (!Array.isArray(declarationPath) && declarationPath.node) {
136
+ visitDeclaration(declarationPath, childPath, state, seen);
137
+ }
138
+ continue;
139
+ }
140
+ visitDeclaration(childPath, childPath, state, seen);
141
+ }
142
+ }
143
+ }
144
+ };
145
+ }
146
+ // Annotate the CommonJS export names for ESM import in node:
147
+ 0 && (module.exports = {
148
+ babelInjectComponentSource
149
+ });
150
+ //# sourceMappingURL=babelInjectComponentSource.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/babelInjectComponentSource.ts","../src/constants.ts"],"sourcesContent":["import path from \"node:path\";\nimport { types as t, type NodePath, type PluginObj } from \"@babel/core\";\nimport { SOURCE_PROP } from \"./constants\";\n\ntype BabelState = {\n file?: {\n opts?: {\n filename?: string;\n };\n };\n};\n\nfunction isComponentName(name: string) {\n return /^[A-Z]/.test(name);\n}\n\nfunction getSourceValue(state: BabelState, loc: { line: number; column: number } | null | undefined) {\n const filename = state.file?.opts?.filename;\n if (!filename || !loc) {\n return null;\n }\n\n const relPath = path.relative(process.cwd(), filename).replace(/\\\\/g, \"/\");\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nfunction buildAssignment(name: string, sourceValue: string) {\n return t.expressionStatement(\n t.assignmentExpression(\n \"=\",\n t.memberExpression(t.identifier(name), t.identifier(SOURCE_PROP)),\n t.stringLiteral(sourceValue),\n ),\n );\n}\n\nfunction visitDeclaration(\n declarationPath: NodePath,\n insertAfterPath: NodePath,\n state: BabelState,\n seen: Set<string>,\n) {\n if (declarationPath.isFunctionDeclaration() || declarationPath.isClassDeclaration()) {\n const name = declarationPath.node.id?.name;\n if (!name || !isComponentName(name) || seen.has(name)) {\n return;\n }\n\n const sourceValue = getSourceValue(state, declarationPath.node.loc?.start);\n if (!sourceValue) {\n return;\n }\n\n seen.add(name);\n insertAfterPath.insertAfter(buildAssignment(name, sourceValue));\n return;\n }\n\n if (!declarationPath.isVariableDeclaration()) {\n return;\n }\n\n const assignments = declarationPath.node.declarations.flatMap((declarator) => {\n if (!t.isIdentifier(declarator.id) || !isComponentName(declarator.id.name) || seen.has(declarator.id.name)) {\n return [];\n }\n\n if (!declarator.init) {\n return [];\n }\n\n if (!t.isArrowFunctionExpression(declarator.init) && !t.isFunctionExpression(declarator.init)) {\n return [];\n }\n\n const sourceValue = getSourceValue(state, declarator.loc?.start ?? declarator.init.loc?.start);\n if (!sourceValue) {\n return [];\n }\n\n seen.add(declarator.id.name);\n return [buildAssignment(declarator.id.name, sourceValue)];\n });\n\n if (assignments.length > 0) {\n insertAfterPath.insertAfter(assignments);\n }\n}\n\nexport function babelInjectComponentSource(): PluginObj<BabelState> {\n return {\n name: \"babel-inject-component-source\",\n visitor: {\n JSXOpeningElement(pathNode, state) {\n const hasSourceProp = pathNode.node.attributes.some(\n (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === \"__source\",\n );\n if (hasSourceProp) {\n return;\n }\n\n const filename = state.file?.opts?.filename;\n const loc = pathNode.node.loc?.start;\n if (!filename || !loc) {\n return;\n }\n\n pathNode.node.attributes.push(\n t.jsxAttribute(\n t.jsxIdentifier(\"__source\"),\n t.jsxExpressionContainer(\n t.objectExpression([\n t.objectProperty(t.identifier(\"fileName\"), t.stringLiteral(filename)),\n t.objectProperty(t.identifier(\"lineNumber\"), t.numericLiteral(loc.line)),\n t.objectProperty(t.identifier(\"columnNumber\"), t.numericLiteral(loc.column + 1)),\n ]),\n ),\n ),\n );\n },\n Program(programPath, state) {\n const seen = new Set<string>();\n\n for (const childPath of programPath.get(\"body\")) {\n if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {\n const declarationPath = childPath.get(\"declaration\");\n if (!Array.isArray(declarationPath) && declarationPath.node) {\n visitDeclaration(declarationPath, childPath, state, seen);\n }\n continue;\n }\n\n visitDeclaration(childPath, childPath, state, seen);\n }\n },\n },\n };\n}\n","export const SOURCE_PROP = \"__componentSourceLoc\";\n\n"],"mappings":"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","names":["path","t"]}
@@ -0,0 +1,12 @@
1
+ import { PluginObj } from '@babel/core';
2
+
3
+ type BabelState = {
4
+ file?: {
5
+ opts?: {
6
+ filename?: string;
7
+ };
8
+ };
9
+ };
10
+ declare function babelInjectComponentSource(): PluginObj<BabelState>;
11
+
12
+ export { babelInjectComponentSource };
@@ -0,0 +1,12 @@
1
+ import { PluginObj } from '@babel/core';
2
+
3
+ type BabelState = {
4
+ file?: {
5
+ opts?: {
6
+ filename?: string;
7
+ };
8
+ };
9
+ };
10
+ declare function babelInjectComponentSource(): PluginObj<BabelState>;
11
+
12
+ export { babelInjectComponentSource };
@@ -0,0 +1,115 @@
1
+ // src/babelInjectComponentSource.ts
2
+ import path from "path";
3
+ import { types as t } from "@babel/core";
4
+
5
+ // src/constants.ts
6
+ var SOURCE_PROP = "__componentSourceLoc";
7
+
8
+ // src/babelInjectComponentSource.ts
9
+ function isComponentName(name) {
10
+ return /^[A-Z]/.test(name);
11
+ }
12
+ function getSourceValue(state, loc) {
13
+ const filename = state.file?.opts?.filename;
14
+ if (!filename || !loc) {
15
+ return null;
16
+ }
17
+ const relPath = path.relative(process.cwd(), filename).replace(/\\/g, "/");
18
+ return `${relPath}:${loc.line}:${loc.column + 1}`;
19
+ }
20
+ function buildAssignment(name, sourceValue) {
21
+ return t.expressionStatement(
22
+ t.assignmentExpression(
23
+ "=",
24
+ t.memberExpression(t.identifier(name), t.identifier(SOURCE_PROP)),
25
+ t.stringLiteral(sourceValue)
26
+ )
27
+ );
28
+ }
29
+ function visitDeclaration(declarationPath, insertAfterPath, state, seen) {
30
+ if (declarationPath.isFunctionDeclaration() || declarationPath.isClassDeclaration()) {
31
+ const name = declarationPath.node.id?.name;
32
+ if (!name || !isComponentName(name) || seen.has(name)) {
33
+ return;
34
+ }
35
+ const sourceValue = getSourceValue(state, declarationPath.node.loc?.start);
36
+ if (!sourceValue) {
37
+ return;
38
+ }
39
+ seen.add(name);
40
+ insertAfterPath.insertAfter(buildAssignment(name, sourceValue));
41
+ return;
42
+ }
43
+ if (!declarationPath.isVariableDeclaration()) {
44
+ return;
45
+ }
46
+ const assignments = declarationPath.node.declarations.flatMap((declarator) => {
47
+ if (!t.isIdentifier(declarator.id) || !isComponentName(declarator.id.name) || seen.has(declarator.id.name)) {
48
+ return [];
49
+ }
50
+ if (!declarator.init) {
51
+ return [];
52
+ }
53
+ if (!t.isArrowFunctionExpression(declarator.init) && !t.isFunctionExpression(declarator.init)) {
54
+ return [];
55
+ }
56
+ const sourceValue = getSourceValue(state, declarator.loc?.start ?? declarator.init.loc?.start);
57
+ if (!sourceValue) {
58
+ return [];
59
+ }
60
+ seen.add(declarator.id.name);
61
+ return [buildAssignment(declarator.id.name, sourceValue)];
62
+ });
63
+ if (assignments.length > 0) {
64
+ insertAfterPath.insertAfter(assignments);
65
+ }
66
+ }
67
+ function babelInjectComponentSource() {
68
+ return {
69
+ name: "babel-inject-component-source",
70
+ visitor: {
71
+ JSXOpeningElement(pathNode, state) {
72
+ const hasSourceProp = pathNode.node.attributes.some(
73
+ (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === "__source"
74
+ );
75
+ if (hasSourceProp) {
76
+ return;
77
+ }
78
+ const filename = state.file?.opts?.filename;
79
+ const loc = pathNode.node.loc?.start;
80
+ if (!filename || !loc) {
81
+ return;
82
+ }
83
+ pathNode.node.attributes.push(
84
+ t.jsxAttribute(
85
+ t.jsxIdentifier("__source"),
86
+ t.jsxExpressionContainer(
87
+ t.objectExpression([
88
+ t.objectProperty(t.identifier("fileName"), t.stringLiteral(filename)),
89
+ t.objectProperty(t.identifier("lineNumber"), t.numericLiteral(loc.line)),
90
+ t.objectProperty(t.identifier("columnNumber"), t.numericLiteral(loc.column + 1))
91
+ ])
92
+ )
93
+ )
94
+ );
95
+ },
96
+ Program(programPath, state) {
97
+ const seen = /* @__PURE__ */ new Set();
98
+ for (const childPath of programPath.get("body")) {
99
+ if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {
100
+ const declarationPath = childPath.get("declaration");
101
+ if (!Array.isArray(declarationPath) && declarationPath.node) {
102
+ visitDeclaration(declarationPath, childPath, state, seen);
103
+ }
104
+ continue;
105
+ }
106
+ visitDeclaration(childPath, childPath, state, seen);
107
+ }
108
+ }
109
+ }
110
+ };
111
+ }
112
+ export {
113
+ babelInjectComponentSource
114
+ };
115
+ //# sourceMappingURL=babelInjectComponentSource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/babelInjectComponentSource.ts","../src/constants.ts"],"sourcesContent":["import path from \"node:path\";\nimport { types as t, type NodePath, type PluginObj } from \"@babel/core\";\nimport { SOURCE_PROP } from \"./constants\";\n\ntype BabelState = {\n file?: {\n opts?: {\n filename?: string;\n };\n };\n};\n\nfunction isComponentName(name: string) {\n return /^[A-Z]/.test(name);\n}\n\nfunction getSourceValue(state: BabelState, loc: { line: number; column: number } | null | undefined) {\n const filename = state.file?.opts?.filename;\n if (!filename || !loc) {\n return null;\n }\n\n const relPath = path.relative(process.cwd(), filename).replace(/\\\\/g, \"/\");\n return `${relPath}:${loc.line}:${loc.column + 1}`;\n}\n\nfunction buildAssignment(name: string, sourceValue: string) {\n return t.expressionStatement(\n t.assignmentExpression(\n \"=\",\n t.memberExpression(t.identifier(name), t.identifier(SOURCE_PROP)),\n t.stringLiteral(sourceValue),\n ),\n );\n}\n\nfunction visitDeclaration(\n declarationPath: NodePath,\n insertAfterPath: NodePath,\n state: BabelState,\n seen: Set<string>,\n) {\n if (declarationPath.isFunctionDeclaration() || declarationPath.isClassDeclaration()) {\n const name = declarationPath.node.id?.name;\n if (!name || !isComponentName(name) || seen.has(name)) {\n return;\n }\n\n const sourceValue = getSourceValue(state, declarationPath.node.loc?.start);\n if (!sourceValue) {\n return;\n }\n\n seen.add(name);\n insertAfterPath.insertAfter(buildAssignment(name, sourceValue));\n return;\n }\n\n if (!declarationPath.isVariableDeclaration()) {\n return;\n }\n\n const assignments = declarationPath.node.declarations.flatMap((declarator) => {\n if (!t.isIdentifier(declarator.id) || !isComponentName(declarator.id.name) || seen.has(declarator.id.name)) {\n return [];\n }\n\n if (!declarator.init) {\n return [];\n }\n\n if (!t.isArrowFunctionExpression(declarator.init) && !t.isFunctionExpression(declarator.init)) {\n return [];\n }\n\n const sourceValue = getSourceValue(state, declarator.loc?.start ?? declarator.init.loc?.start);\n if (!sourceValue) {\n return [];\n }\n\n seen.add(declarator.id.name);\n return [buildAssignment(declarator.id.name, sourceValue)];\n });\n\n if (assignments.length > 0) {\n insertAfterPath.insertAfter(assignments);\n }\n}\n\nexport function babelInjectComponentSource(): PluginObj<BabelState> {\n return {\n name: \"babel-inject-component-source\",\n visitor: {\n JSXOpeningElement(pathNode, state) {\n const hasSourceProp = pathNode.node.attributes.some(\n (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === \"__source\",\n );\n if (hasSourceProp) {\n return;\n }\n\n const filename = state.file?.opts?.filename;\n const loc = pathNode.node.loc?.start;\n if (!filename || !loc) {\n return;\n }\n\n pathNode.node.attributes.push(\n t.jsxAttribute(\n t.jsxIdentifier(\"__source\"),\n t.jsxExpressionContainer(\n t.objectExpression([\n t.objectProperty(t.identifier(\"fileName\"), t.stringLiteral(filename)),\n t.objectProperty(t.identifier(\"lineNumber\"), t.numericLiteral(loc.line)),\n t.objectProperty(t.identifier(\"columnNumber\"), t.numericLiteral(loc.column + 1)),\n ]),\n ),\n ),\n );\n },\n Program(programPath, state) {\n const seen = new Set<string>();\n\n for (const childPath of programPath.get(\"body\")) {\n if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {\n const declarationPath = childPath.get(\"declaration\");\n if (!Array.isArray(declarationPath) && declarationPath.node) {\n visitDeclaration(declarationPath, childPath, state, seen);\n }\n continue;\n }\n\n visitDeclaration(childPath, childPath, state, seen);\n }\n },\n },\n };\n}\n","export const SOURCE_PROP = \"__componentSourceLoc\";\n\n"],"mappings":"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","names":[]}
@@ -0,0 +1,153 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/client.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ enableReactComponentJump: () => enableReactComponentJump,
24
+ locateComponentSource: () => locateComponentSource
25
+ });
26
+ module.exports = __toCommonJS(client_exports);
27
+
28
+ // src/constants.ts
29
+ var SOURCE_PROP = "__componentSourceLoc";
30
+
31
+ // src/runtime.ts
32
+ function isTriggerPressed(event, triggerKey) {
33
+ if (triggerKey === "none") {
34
+ return true;
35
+ }
36
+ if (triggerKey === "alt") {
37
+ return event.altKey;
38
+ }
39
+ if (triggerKey === "meta") {
40
+ return event.metaKey;
41
+ }
42
+ if (triggerKey === "ctrl") {
43
+ return event.ctrlKey;
44
+ }
45
+ return event.shiftKey;
46
+ }
47
+ function getReactFiberKey(element) {
48
+ return Object.keys(element).find((key) => key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$"));
49
+ }
50
+ function getClosestReactFiber(target) {
51
+ let current = target;
52
+ while (current) {
53
+ const fiberKey = getReactFiberKey(current);
54
+ if (fiberKey) {
55
+ return current[fiberKey];
56
+ }
57
+ current = current.parentElement;
58
+ }
59
+ return null;
60
+ }
61
+ function getSourceFromType(type) {
62
+ if (!type) {
63
+ return null;
64
+ }
65
+ if (typeof type === "function") {
66
+ const source2 = type[SOURCE_PROP];
67
+ return typeof source2 === "string" ? source2 : null;
68
+ }
69
+ if (typeof type !== "object") {
70
+ return null;
71
+ }
72
+ const record = type;
73
+ const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
74
+ return typeof source === "string" ? source : null;
75
+ }
76
+ function resolveSourceFromFiber(fiber) {
77
+ let current = fiber;
78
+ while (current) {
79
+ const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
80
+ if (source) {
81
+ return source;
82
+ }
83
+ current = current.return ?? null;
84
+ }
85
+ return null;
86
+ }
87
+ function getDebugSource(fiber) {
88
+ let current = fiber;
89
+ while (current) {
90
+ const debugSource = current._debugSource;
91
+ if (debugSource?.fileName && typeof debugSource.lineNumber === "number") {
92
+ return `${debugSource.fileName.replace(/\\/g, "/")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;
93
+ }
94
+ current = current.return ?? null;
95
+ }
96
+ return null;
97
+ }
98
+ function locateComponentSource(target) {
99
+ const elementTarget = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
100
+ const fiber = getClosestReactFiber(elementTarget);
101
+ if (!fiber) {
102
+ return null;
103
+ }
104
+ const debugSource = getDebugSource(fiber);
105
+ if (debugSource) {
106
+ return {
107
+ source: debugSource,
108
+ mode: "jsx"
109
+ };
110
+ }
111
+ const componentSource = resolveSourceFromFiber(fiber);
112
+ if (!componentSource) {
113
+ return null;
114
+ }
115
+ return {
116
+ source: componentSource,
117
+ mode: "component"
118
+ };
119
+ }
120
+ function enableReactComponentJump(options = {}) {
121
+ const {
122
+ triggerKey = "shift",
123
+ onLocate = (result) => {
124
+ console.log(`[react-component-jump] ${result.source}`);
125
+ },
126
+ onError = (error) => {
127
+ console.error("[react-component-jump]", error);
128
+ }
129
+ } = options;
130
+ const handler = (event) => {
131
+ if (!isTriggerPressed(event, triggerKey)) {
132
+ return;
133
+ }
134
+ const result = locateComponentSource(event.target);
135
+ if (!result) {
136
+ onError(new Error("No React component source metadata found for clicked element."));
137
+ return;
138
+ }
139
+ event.preventDefault();
140
+ event.stopPropagation();
141
+ onLocate(result);
142
+ };
143
+ document.addEventListener("click", handler, true);
144
+ return () => {
145
+ document.removeEventListener("click", handler, true);
146
+ };
147
+ }
148
+ // Annotate the CommonJS export names for ESM import in node:
149
+ 0 && (module.exports = {
150
+ enableReactComponentJump,
151
+ locateComponentSource
152
+ });
153
+ //# sourceMappingURL=client.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/constants.ts","../src/runtime.ts"],"sourcesContent":["export { enableReactComponentJump, locateComponentSource } from \"./runtime\";\nexport type { LocatorOptions, LocatorResult, TriggerKey } from \"./runtime\";\n\n","export const SOURCE_PROP = \"__componentSourceLoc\";\n\n","import { SOURCE_PROP } from \"./constants\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: \"jsx\" | \"component\";\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDebugSource(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const debugSource = current._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nexport function locateComponentSource(target: EventTarget | null): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const debugSource = getDebugSource(fiber);\n if (debugSource) {\n return {\n source: debugSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode: \"component\",\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n const {\n triggerKey = \"shift\",\n onLocate = (result) => {\n console.log(`[react-component-jump] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-component-jump]\", error);\n },\n } = options;\n\n const handler = (event: MouseEvent) => {\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n };\n}\n"],"mappings":"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","names":["source"]}
@@ -0,0 +1,14 @@
1
+ type TriggerKey = "alt" | "meta" | "ctrl" | "shift" | "none";
2
+ type LocatorResult = {
3
+ source: string;
4
+ mode: "jsx" | "component";
5
+ };
6
+ type LocatorOptions = {
7
+ triggerKey?: TriggerKey;
8
+ onLocate?: (result: LocatorResult) => void;
9
+ onError?: (error: unknown) => void;
10
+ };
11
+ declare function locateComponentSource(target: EventTarget | null): LocatorResult | null;
12
+ declare function enableReactComponentJump(options?: LocatorOptions): () => void;
13
+
14
+ export { type LocatorOptions, type LocatorResult, type TriggerKey, enableReactComponentJump, locateComponentSource };
@@ -0,0 +1,14 @@
1
+ type TriggerKey = "alt" | "meta" | "ctrl" | "shift" | "none";
2
+ type LocatorResult = {
3
+ source: string;
4
+ mode: "jsx" | "component";
5
+ };
6
+ type LocatorOptions = {
7
+ triggerKey?: TriggerKey;
8
+ onLocate?: (result: LocatorResult) => void;
9
+ onError?: (error: unknown) => void;
10
+ };
11
+ declare function locateComponentSource(target: EventTarget | null): LocatorResult | null;
12
+ declare function enableReactComponentJump(options?: LocatorOptions): () => void;
13
+
14
+ export { type LocatorOptions, type LocatorResult, type TriggerKey, enableReactComponentJump, locateComponentSource };
package/dist/client.js ADDED
@@ -0,0 +1,125 @@
1
+ // src/constants.ts
2
+ var SOURCE_PROP = "__componentSourceLoc";
3
+
4
+ // src/runtime.ts
5
+ function isTriggerPressed(event, triggerKey) {
6
+ if (triggerKey === "none") {
7
+ return true;
8
+ }
9
+ if (triggerKey === "alt") {
10
+ return event.altKey;
11
+ }
12
+ if (triggerKey === "meta") {
13
+ return event.metaKey;
14
+ }
15
+ if (triggerKey === "ctrl") {
16
+ return event.ctrlKey;
17
+ }
18
+ return event.shiftKey;
19
+ }
20
+ function getReactFiberKey(element) {
21
+ return Object.keys(element).find((key) => key.startsWith("__reactFiber$") || key.startsWith("__reactInternalInstance$"));
22
+ }
23
+ function getClosestReactFiber(target) {
24
+ let current = target;
25
+ while (current) {
26
+ const fiberKey = getReactFiberKey(current);
27
+ if (fiberKey) {
28
+ return current[fiberKey];
29
+ }
30
+ current = current.parentElement;
31
+ }
32
+ return null;
33
+ }
34
+ function getSourceFromType(type) {
35
+ if (!type) {
36
+ return null;
37
+ }
38
+ if (typeof type === "function") {
39
+ const source2 = type[SOURCE_PROP];
40
+ return typeof source2 === "string" ? source2 : null;
41
+ }
42
+ if (typeof type !== "object") {
43
+ return null;
44
+ }
45
+ const record = type;
46
+ const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
47
+ return typeof source === "string" ? source : null;
48
+ }
49
+ function resolveSourceFromFiber(fiber) {
50
+ let current = fiber;
51
+ while (current) {
52
+ const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
53
+ if (source) {
54
+ return source;
55
+ }
56
+ current = current.return ?? null;
57
+ }
58
+ return null;
59
+ }
60
+ function getDebugSource(fiber) {
61
+ let current = fiber;
62
+ while (current) {
63
+ const debugSource = current._debugSource;
64
+ if (debugSource?.fileName && typeof debugSource.lineNumber === "number") {
65
+ return `${debugSource.fileName.replace(/\\/g, "/")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;
66
+ }
67
+ current = current.return ?? null;
68
+ }
69
+ return null;
70
+ }
71
+ function locateComponentSource(target) {
72
+ const elementTarget = target instanceof Element ? target : target instanceof Node ? target.parentElement : null;
73
+ const fiber = getClosestReactFiber(elementTarget);
74
+ if (!fiber) {
75
+ return null;
76
+ }
77
+ const debugSource = getDebugSource(fiber);
78
+ if (debugSource) {
79
+ return {
80
+ source: debugSource,
81
+ mode: "jsx"
82
+ };
83
+ }
84
+ const componentSource = resolveSourceFromFiber(fiber);
85
+ if (!componentSource) {
86
+ return null;
87
+ }
88
+ return {
89
+ source: componentSource,
90
+ mode: "component"
91
+ };
92
+ }
93
+ function enableReactComponentJump(options = {}) {
94
+ const {
95
+ triggerKey = "shift",
96
+ onLocate = (result) => {
97
+ console.log(`[react-component-jump] ${result.source}`);
98
+ },
99
+ onError = (error) => {
100
+ console.error("[react-component-jump]", error);
101
+ }
102
+ } = options;
103
+ const handler = (event) => {
104
+ if (!isTriggerPressed(event, triggerKey)) {
105
+ return;
106
+ }
107
+ const result = locateComponentSource(event.target);
108
+ if (!result) {
109
+ onError(new Error("No React component source metadata found for clicked element."));
110
+ return;
111
+ }
112
+ event.preventDefault();
113
+ event.stopPropagation();
114
+ onLocate(result);
115
+ };
116
+ document.addEventListener("click", handler, true);
117
+ return () => {
118
+ document.removeEventListener("click", handler, true);
119
+ };
120
+ }
121
+ export {
122
+ enableReactComponentJump,
123
+ locateComponentSource
124
+ };
125
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts","../src/runtime.ts"],"sourcesContent":["export const SOURCE_PROP = \"__componentSourceLoc\";\n\n","import { SOURCE_PROP } from \"./constants\";\n\nexport type TriggerKey = \"alt\" | \"meta\" | \"ctrl\" | \"shift\" | \"none\";\n\ntype ReactFiber = {\n return?: ReactFiber | null;\n type?: unknown;\n elementType?: unknown;\n _debugSource?: {\n fileName?: string;\n lineNumber?: number;\n columnNumber?: number;\n } | null;\n};\n\nexport type LocatorResult = {\n source: string;\n mode: \"jsx\" | \"component\";\n};\n\nexport type LocatorOptions = {\n triggerKey?: TriggerKey;\n onLocate?: (result: LocatorResult) => void;\n onError?: (error: unknown) => void;\n};\n\nfunction isTriggerPressed(event: MouseEvent, triggerKey: TriggerKey) {\n if (triggerKey === \"none\") {\n return true;\n }\n\n if (triggerKey === \"alt\") {\n return event.altKey;\n }\n\n if (triggerKey === \"meta\") {\n return event.metaKey;\n }\n\n if (triggerKey === \"ctrl\") {\n return event.ctrlKey;\n }\n\n return event.shiftKey;\n}\n\nfunction getReactFiberKey(element: Element) {\n return Object.keys(element).find((key) => key.startsWith(\"__reactFiber$\") || key.startsWith(\"__reactInternalInstance$\"));\n}\n\nfunction getClosestReactFiber(target: Element | null) {\n let current = target;\n\n while (current) {\n const fiberKey = getReactFiberKey(current);\n if (fiberKey) {\n return (current as unknown as Record<string, unknown>)[fiberKey] as ReactFiber;\n }\n\n current = current.parentElement;\n }\n\n return null;\n}\n\nfunction getSourceFromType(type: unknown) {\n if (!type) {\n return null;\n }\n\n if (typeof type === \"function\") {\n const source = (type as unknown as Record<string, unknown>)[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n }\n\n if (typeof type !== \"object\") {\n return null;\n }\n\n const record = type as {\n type?: Record<string, unknown>;\n render?: Record<string, unknown>;\n [SOURCE_PROP]?: unknown;\n };\n\n const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction getDebugSource(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const debugSource = current._debugSource;\n if (debugSource?.fileName && typeof debugSource.lineNumber === \"number\") {\n return `${debugSource.fileName.replace(/\\\\/g, \"/\")}:${debugSource.lineNumber}:${debugSource.columnNumber ?? 1}`;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nexport function locateComponentSource(target: EventTarget | null): LocatorResult | null {\n const elementTarget =\n target instanceof Element ? target : target instanceof Node ? target.parentElement : null;\n const fiber = getClosestReactFiber(elementTarget);\n if (!fiber) {\n return null;\n }\n\n const debugSource = getDebugSource(fiber);\n if (debugSource) {\n return {\n source: debugSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveSourceFromFiber(fiber);\n if (!componentSource) {\n return null;\n }\n\n return {\n source: componentSource,\n mode: \"component\",\n };\n}\n\nexport function enableReactComponentJump(options: LocatorOptions = {}) {\n const {\n triggerKey = \"shift\",\n onLocate = (result) => {\n console.log(`[react-component-jump] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-component-jump]\", error);\n },\n } = options;\n\n const handler = (event: MouseEvent) => {\n if (!isTriggerPressed(event, triggerKey)) {\n return;\n }\n\n const result = locateComponentSource(event.target);\n if (!result) {\n onError(new Error(\"No React component source metadata found for clicked element.\"));\n return;\n }\n\n event.preventDefault();\n event.stopPropagation();\n onLocate(result);\n };\n\n document.addEventListener(\"click\", handler, true);\n\n return () => {\n document.removeEventListener(\"click\", handler, true);\n };\n}\n"],"mappings":"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","names":["source"]}