react-code-locator 0.1.5 → 0.1.7
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 +63 -25
- package/dist/babel.cjs +27 -11
- package/dist/babel.cjs.map +1 -1
- package/dist/babel.d.cts +1 -1
- package/dist/babel.d.ts +1 -1
- package/dist/babel.js +27 -11
- package/dist/babel.js.map +1 -1
- package/dist/babelInjectComponentSource.cjs +27 -11
- package/dist/babelInjectComponentSource.cjs.map +1 -1
- package/dist/babelInjectComponentSource.d.cts +6 -2
- package/dist/babelInjectComponentSource.d.ts +6 -2
- package/dist/babelInjectComponentSource.js +27 -11
- package/dist/babelInjectComponentSource.js.map +1 -1
- package/dist/client.cjs +20 -5
- package/dist/client.cjs.map +1 -1
- package/dist/client.js +20 -5
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +20 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -5
- package/dist/index.js.map +1 -1
- package/dist/vite.cjs +71 -66
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.d.cts +2 -2
- package/dist/vite.d.ts +2 -2
- package/dist/vite.js +70 -66
- package/dist/vite.js.map +1 -1
- package/dist/webpackRuntimeEntry.cjs +20 -5
- package/dist/webpackRuntimeEntry.cjs.map +1 -1
- package/dist/webpackRuntimeEntry.js +20 -5
- package/dist/webpackRuntimeEntry.js.map +1 -1
- package/package.json +4 -9
|
@@ -1 +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 (!
|
|
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\nexport type BabelInjectComponentSourceOptions = {\n injectJsxSource?: boolean;\n injectComponentSource?: boolean;\n};\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 isSupportedComponentInit(node: t.Expression | null | undefined): boolean {\n if (!node) {\n return false;\n }\n\n if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {\n return true;\n }\n\n if (!t.isCallExpression(node)) {\n return false;\n }\n\n if (t.isIdentifier(node.callee) && (node.callee.name === \"memo\" || node.callee.name === \"forwardRef\")) {\n return true;\n }\n\n return (\n t.isMemberExpression(node.callee) &&\n t.isIdentifier(node.callee.object, { name: \"React\" }) &&\n t.isIdentifier(node.callee.property) &&\n (node.callee.property.name === \"memo\" || node.callee.property.name === \"forwardRef\")\n );\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 (!isSupportedComponentInit(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(\n options: BabelInjectComponentSourceOptions = {},\n): PluginObj<BabelState> {\n const { injectJsxSource = false, injectComponentSource = true } = options;\n\n return {\n name: \"babel-inject-component-source\",\n visitor: {\n JSXOpeningElement(pathNode, state) {\n if (!injectJsxSource) {\n return;\n }\n\n const hasSourceProp = pathNode.node.attributes.some(\n (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === SOURCE_PROP,\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_PROP),\n t.stringLiteral(getSourceValue(state, loc) ?? `${filename.replace(/\\\\/g, \"/\")}:${loc.line}:${loc.column + 1}`),\n ),\n );\n },\n Program(programPath, state) {\n if (!injectComponentSource) {\n return;\n }\n\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":[]}
|
package/dist/client.cjs
CHANGED
|
@@ -73,7 +73,22 @@ function getSourceFromType(type) {
|
|
|
73
73
|
const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
|
|
74
74
|
return typeof source === "string" ? source : null;
|
|
75
75
|
}
|
|
76
|
-
function
|
|
76
|
+
function getSourceFromProps(props) {
|
|
77
|
+
const source = props?.[SOURCE_PROP];
|
|
78
|
+
return typeof source === "string" ? source : null;
|
|
79
|
+
}
|
|
80
|
+
function resolveJsxSourceFromFiber(fiber) {
|
|
81
|
+
let current = fiber;
|
|
82
|
+
while (current) {
|
|
83
|
+
const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);
|
|
84
|
+
if (source) {
|
|
85
|
+
return source;
|
|
86
|
+
}
|
|
87
|
+
current = current.return ?? null;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function resolveComponentSourceFromFiber(fiber) {
|
|
77
92
|
let current = fiber;
|
|
78
93
|
while (current) {
|
|
79
94
|
const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
|
|
@@ -101,14 +116,14 @@ function locateComponentSource(target) {
|
|
|
101
116
|
if (!fiber) {
|
|
102
117
|
return null;
|
|
103
118
|
}
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
119
|
+
const jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);
|
|
120
|
+
if (jsxSource) {
|
|
106
121
|
return {
|
|
107
|
-
source:
|
|
122
|
+
source: jsxSource,
|
|
108
123
|
mode: "jsx"
|
|
109
124
|
};
|
|
110
125
|
}
|
|
111
|
-
const componentSource =
|
|
126
|
+
const componentSource = resolveComponentSourceFromFiber(fiber);
|
|
112
127
|
if (!componentSource) {
|
|
113
128
|
return null;
|
|
114
129
|
}
|
package/dist/client.cjs.map
CHANGED
|
@@ -1 +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
|
|
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 pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\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 getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n const source = props?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveJsxSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction resolveComponentSourceFromFiber(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 jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);\n if (jsxSource) {\n return {\n source: jsxSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(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-code-locator] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", 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"]}
|
package/dist/client.js
CHANGED
|
@@ -46,7 +46,22 @@ function getSourceFromType(type) {
|
|
|
46
46
|
const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
|
|
47
47
|
return typeof source === "string" ? source : null;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function getSourceFromProps(props) {
|
|
50
|
+
const source = props?.[SOURCE_PROP];
|
|
51
|
+
return typeof source === "string" ? source : null;
|
|
52
|
+
}
|
|
53
|
+
function resolveJsxSourceFromFiber(fiber) {
|
|
54
|
+
let current = fiber;
|
|
55
|
+
while (current) {
|
|
56
|
+
const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);
|
|
57
|
+
if (source) {
|
|
58
|
+
return source;
|
|
59
|
+
}
|
|
60
|
+
current = current.return ?? null;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function resolveComponentSourceFromFiber(fiber) {
|
|
50
65
|
let current = fiber;
|
|
51
66
|
while (current) {
|
|
52
67
|
const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
|
|
@@ -74,14 +89,14 @@ function locateComponentSource(target) {
|
|
|
74
89
|
if (!fiber) {
|
|
75
90
|
return null;
|
|
76
91
|
}
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
92
|
+
const jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);
|
|
93
|
+
if (jsxSource) {
|
|
79
94
|
return {
|
|
80
|
-
source:
|
|
95
|
+
source: jsxSource,
|
|
81
96
|
mode: "jsx"
|
|
82
97
|
};
|
|
83
98
|
}
|
|
84
|
-
const componentSource =
|
|
99
|
+
const componentSource = resolveComponentSourceFromFiber(fiber);
|
|
85
100
|
if (!componentSource) {
|
|
86
101
|
return null;
|
|
87
102
|
}
|
package/dist/client.js.map
CHANGED
|
@@ -1 +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
|
|
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 pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\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 getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n const source = props?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveJsxSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction resolveComponentSourceFromFiber(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 jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);\n if (jsxSource) {\n return {\n source: jsxSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(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-code-locator] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", 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"]}
|
package/dist/index.cjs
CHANGED
|
@@ -73,7 +73,22 @@ function getSourceFromType(type) {
|
|
|
73
73
|
const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
|
|
74
74
|
return typeof source === "string" ? source : null;
|
|
75
75
|
}
|
|
76
|
-
function
|
|
76
|
+
function getSourceFromProps(props) {
|
|
77
|
+
const source = props?.[SOURCE_PROP];
|
|
78
|
+
return typeof source === "string" ? source : null;
|
|
79
|
+
}
|
|
80
|
+
function resolveJsxSourceFromFiber(fiber) {
|
|
81
|
+
let current = fiber;
|
|
82
|
+
while (current) {
|
|
83
|
+
const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);
|
|
84
|
+
if (source) {
|
|
85
|
+
return source;
|
|
86
|
+
}
|
|
87
|
+
current = current.return ?? null;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function resolveComponentSourceFromFiber(fiber) {
|
|
77
92
|
let current = fiber;
|
|
78
93
|
while (current) {
|
|
79
94
|
const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
|
|
@@ -101,14 +116,14 @@ function locateComponentSource(target) {
|
|
|
101
116
|
if (!fiber) {
|
|
102
117
|
return null;
|
|
103
118
|
}
|
|
104
|
-
const
|
|
105
|
-
if (
|
|
119
|
+
const jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);
|
|
120
|
+
if (jsxSource) {
|
|
106
121
|
return {
|
|
107
|
-
source:
|
|
122
|
+
source: jsxSource,
|
|
108
123
|
mode: "jsx"
|
|
109
124
|
};
|
|
110
125
|
}
|
|
111
|
-
const componentSource =
|
|
126
|
+
const componentSource = resolveComponentSourceFromFiber(fiber);
|
|
112
127
|
if (!componentSource) {
|
|
113
128
|
return null;
|
|
114
129
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/runtime.ts"],"sourcesContent":["export { enableReactComponentJump, locateComponentSource } from \"./runtime\";\nexport type { LocatorOptions, LocatorResult, TriggerKey } from \"./runtime\";\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
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/runtime.ts"],"sourcesContent":["export { enableReactComponentJump, locateComponentSource } from \"./runtime\";\nexport type { LocatorOptions, LocatorResult, TriggerKey } from \"./runtime\";\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 pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\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 getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n const source = props?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveJsxSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction resolveComponentSourceFromFiber(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 jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);\n if (jsxSource) {\n return {\n source: jsxSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(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-code-locator] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", 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"]}
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,22 @@ function getSourceFromType(type) {
|
|
|
46
46
|
const source = record[SOURCE_PROP] ?? record.type?.[SOURCE_PROP] ?? record.render?.[SOURCE_PROP];
|
|
47
47
|
return typeof source === "string" ? source : null;
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
function getSourceFromProps(props) {
|
|
50
|
+
const source = props?.[SOURCE_PROP];
|
|
51
|
+
return typeof source === "string" ? source : null;
|
|
52
|
+
}
|
|
53
|
+
function resolveJsxSourceFromFiber(fiber) {
|
|
54
|
+
let current = fiber;
|
|
55
|
+
while (current) {
|
|
56
|
+
const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);
|
|
57
|
+
if (source) {
|
|
58
|
+
return source;
|
|
59
|
+
}
|
|
60
|
+
current = current.return ?? null;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function resolveComponentSourceFromFiber(fiber) {
|
|
50
65
|
let current = fiber;
|
|
51
66
|
while (current) {
|
|
52
67
|
const source = getSourceFromType(current.type) ?? getSourceFromType(current.elementType);
|
|
@@ -74,14 +89,14 @@ function locateComponentSource(target) {
|
|
|
74
89
|
if (!fiber) {
|
|
75
90
|
return null;
|
|
76
91
|
}
|
|
77
|
-
const
|
|
78
|
-
if (
|
|
92
|
+
const jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);
|
|
93
|
+
if (jsxSource) {
|
|
79
94
|
return {
|
|
80
|
-
source:
|
|
95
|
+
source: jsxSource,
|
|
81
96
|
mode: "jsx"
|
|
82
97
|
};
|
|
83
98
|
}
|
|
84
|
-
const componentSource =
|
|
99
|
+
const componentSource = resolveComponentSourceFromFiber(fiber);
|
|
85
100
|
if (!componentSource) {
|
|
86
101
|
return null;
|
|
87
102
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +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
|
|
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 pendingProps?: Record<string, unknown> | null;\n memoizedProps?: Record<string, unknown> | null;\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 getSourceFromProps(props: Record<string, unknown> | null | undefined) {\n const source = props?.[SOURCE_PROP];\n return typeof source === \"string\" ? source : null;\n}\n\nfunction resolveJsxSourceFromFiber(fiber: ReactFiber | null) {\n let current = fiber;\n\n while (current) {\n const source = getSourceFromProps(current.pendingProps) ?? getSourceFromProps(current.memoizedProps);\n if (source) {\n return source;\n }\n\n current = current.return ?? null;\n }\n\n return null;\n}\n\nfunction resolveComponentSourceFromFiber(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 jsxSource = resolveJsxSourceFromFiber(fiber) ?? getDebugSource(fiber);\n if (jsxSource) {\n return {\n source: jsxSource,\n mode: \"jsx\",\n };\n }\n\n const componentSource = resolveComponentSourceFromFiber(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-code-locator] ${result.source}`);\n },\n onError = (error) => {\n console.error(\"[react-code-locator]\", 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"]}
|
package/dist/vite.cjs
CHANGED
|
@@ -30,13 +30,55 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/vite.ts
|
|
31
31
|
var vite_exports = {};
|
|
32
32
|
__export(vite_exports, {
|
|
33
|
+
babelInjectComponentSource: () => babelInjectComponentSource,
|
|
33
34
|
elementLocatorReact: () => elementLocatorReact,
|
|
34
35
|
reactComponentJump: () => elementLocatorReact
|
|
35
36
|
});
|
|
36
37
|
module.exports = __toCommonJS(vite_exports);
|
|
37
38
|
|
|
38
39
|
// src/elementLocatorReact.ts
|
|
39
|
-
var
|
|
40
|
+
var VIRTUAL_CLIENT_MODULE_ID = "virtual:react-code-locator/client";
|
|
41
|
+
var RESOLVED_VIRTUAL_CLIENT_MODULE_ID = `\0${VIRTUAL_CLIENT_MODULE_ID}`;
|
|
42
|
+
function createClientInjector(locatorOptions = {}) {
|
|
43
|
+
const serialized = JSON.stringify(locatorOptions);
|
|
44
|
+
return {
|
|
45
|
+
name: "element-locator-client-injector",
|
|
46
|
+
apply: "serve",
|
|
47
|
+
resolveId(id) {
|
|
48
|
+
if (id === VIRTUAL_CLIENT_MODULE_ID) {
|
|
49
|
+
return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
},
|
|
53
|
+
load(id) {
|
|
54
|
+
if (id !== RESOLVED_VIRTUAL_CLIENT_MODULE_ID) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return `
|
|
58
|
+
import { enableReactComponentJump } from "react-code-locator/client";
|
|
59
|
+
|
|
60
|
+
enableReactComponentJump(${serialized});
|
|
61
|
+
`;
|
|
62
|
+
},
|
|
63
|
+
transformIndexHtml() {
|
|
64
|
+
return [
|
|
65
|
+
{
|
|
66
|
+
tag: "script",
|
|
67
|
+
attrs: {
|
|
68
|
+
type: "module"
|
|
69
|
+
},
|
|
70
|
+
children: `import "${VIRTUAL_CLIENT_MODULE_ID}";`,
|
|
71
|
+
injectTo: "head"
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function elementLocatorReact(options = {}) {
|
|
78
|
+
const { command = "serve", locator = {}, injectClient = true } = options;
|
|
79
|
+
const isServe = command === "serve";
|
|
80
|
+
return [isServe && injectClient ? createClientInjector(locator) : null].filter(Boolean);
|
|
81
|
+
}
|
|
40
82
|
|
|
41
83
|
// src/babelInjectComponentSource.ts
|
|
42
84
|
var import_node_path = __toESM(require("path"), 1);
|
|
@@ -49,6 +91,21 @@ var SOURCE_PROP = "__componentSourceLoc";
|
|
|
49
91
|
function isComponentName(name) {
|
|
50
92
|
return /^[A-Z]/.test(name);
|
|
51
93
|
}
|
|
94
|
+
function isSupportedComponentInit(node) {
|
|
95
|
+
if (!node) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (import_core.types.isArrowFunctionExpression(node) || import_core.types.isFunctionExpression(node)) {
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
if (!import_core.types.isCallExpression(node)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (import_core.types.isIdentifier(node.callee) && (node.callee.name === "memo" || node.callee.name === "forwardRef")) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
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");
|
|
108
|
+
}
|
|
52
109
|
function getSourceValue(state, loc) {
|
|
53
110
|
const filename = state.file?.opts?.filename;
|
|
54
111
|
if (!filename || !loc) {
|
|
@@ -90,7 +147,7 @@ function visitDeclaration(declarationPath, insertAfterPath, state, seen) {
|
|
|
90
147
|
if (!declarator.init) {
|
|
91
148
|
return [];
|
|
92
149
|
}
|
|
93
|
-
if (!
|
|
150
|
+
if (!isSupportedComponentInit(declarator.init)) {
|
|
94
151
|
return [];
|
|
95
152
|
}
|
|
96
153
|
const sourceValue = getSourceValue(state, declarator.loc?.start ?? declarator.init.loc?.start);
|
|
@@ -104,13 +161,17 @@ function visitDeclaration(declarationPath, insertAfterPath, state, seen) {
|
|
|
104
161
|
insertAfterPath.insertAfter(assignments);
|
|
105
162
|
}
|
|
106
163
|
}
|
|
107
|
-
function babelInjectComponentSource() {
|
|
164
|
+
function babelInjectComponentSource(options = {}) {
|
|
165
|
+
const { injectJsxSource = false, injectComponentSource = true } = options;
|
|
108
166
|
return {
|
|
109
167
|
name: "babel-inject-component-source",
|
|
110
168
|
visitor: {
|
|
111
169
|
JSXOpeningElement(pathNode, state) {
|
|
170
|
+
if (!injectJsxSource) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
112
173
|
const hasSourceProp = pathNode.node.attributes.some(
|
|
113
|
-
(attr) => import_core.types.isJSXAttribute(attr) && import_core.types.isJSXIdentifier(attr.name) && attr.name.name ===
|
|
174
|
+
(attr) => import_core.types.isJSXAttribute(attr) && import_core.types.isJSXIdentifier(attr.name) && attr.name.name === SOURCE_PROP
|
|
114
175
|
);
|
|
115
176
|
if (hasSourceProp) {
|
|
116
177
|
return;
|
|
@@ -122,18 +183,15 @@ function babelInjectComponentSource() {
|
|
|
122
183
|
}
|
|
123
184
|
pathNode.node.attributes.push(
|
|
124
185
|
import_core.types.jsxAttribute(
|
|
125
|
-
import_core.types.jsxIdentifier(
|
|
126
|
-
import_core.types.
|
|
127
|
-
import_core.types.objectExpression([
|
|
128
|
-
import_core.types.objectProperty(import_core.types.identifier("fileName"), import_core.types.stringLiteral(filename)),
|
|
129
|
-
import_core.types.objectProperty(import_core.types.identifier("lineNumber"), import_core.types.numericLiteral(loc.line)),
|
|
130
|
-
import_core.types.objectProperty(import_core.types.identifier("columnNumber"), import_core.types.numericLiteral(loc.column + 1))
|
|
131
|
-
])
|
|
132
|
-
)
|
|
186
|
+
import_core.types.jsxIdentifier(SOURCE_PROP),
|
|
187
|
+
import_core.types.stringLiteral(getSourceValue(state, loc) ?? `${filename.replace(/\\/g, "/")}:${loc.line}:${loc.column + 1}`)
|
|
133
188
|
)
|
|
134
189
|
);
|
|
135
190
|
},
|
|
136
191
|
Program(programPath, state) {
|
|
192
|
+
if (!injectComponentSource) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
137
195
|
const seen = /* @__PURE__ */ new Set();
|
|
138
196
|
for (const childPath of programPath.get("body")) {
|
|
139
197
|
if (childPath.isExportNamedDeclaration() || childPath.isExportDefaultDeclaration()) {
|
|
@@ -149,62 +207,9 @@ function babelInjectComponentSource() {
|
|
|
149
207
|
}
|
|
150
208
|
};
|
|
151
209
|
}
|
|
152
|
-
|
|
153
|
-
// src/elementLocatorReact.ts
|
|
154
|
-
function withLocatorBabel(reactOptions = {}) {
|
|
155
|
-
const baseBabel = reactOptions.babel;
|
|
156
|
-
if (typeof baseBabel === "function") {
|
|
157
|
-
return {
|
|
158
|
-
...reactOptions,
|
|
159
|
-
babel(id, options) {
|
|
160
|
-
const result = baseBabel(id, options);
|
|
161
|
-
const resolved2 = result ?? {};
|
|
162
|
-
const plugins = [...resolved2.plugins ?? [], babelInjectComponentSource];
|
|
163
|
-
return {
|
|
164
|
-
...resolved2,
|
|
165
|
-
plugins
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
const resolved = baseBabel ?? {};
|
|
171
|
-
return {
|
|
172
|
-
...reactOptions,
|
|
173
|
-
babel: {
|
|
174
|
-
...resolved,
|
|
175
|
-
plugins: [...resolved.plugins ?? [], babelInjectComponentSource]
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
function createClientInjector(locatorOptions = {}) {
|
|
180
|
-
const serialized = JSON.stringify(locatorOptions);
|
|
181
|
-
return {
|
|
182
|
-
name: "element-locator-client-injector",
|
|
183
|
-
apply: "serve",
|
|
184
|
-
transformIndexHtml() {
|
|
185
|
-
return [
|
|
186
|
-
{
|
|
187
|
-
tag: "script",
|
|
188
|
-
attrs: {
|
|
189
|
-
type: "module"
|
|
190
|
-
},
|
|
191
|
-
children: `import { enableReactComponentJump } from "react-code-locator/client"; enableReactComponentJump(${serialized});`,
|
|
192
|
-
injectTo: "head"
|
|
193
|
-
}
|
|
194
|
-
];
|
|
195
|
-
}
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
function elementLocatorReact(options = {}) {
|
|
199
|
-
const { command = "serve", react: reactOptions, locator = {}, injectClient = true } = options;
|
|
200
|
-
const isServe = command === "serve";
|
|
201
|
-
return [
|
|
202
|
-
(0, import_plugin_react.default)(isServe ? withLocatorBabel(reactOptions) : reactOptions),
|
|
203
|
-
isServe && injectClient ? createClientInjector(locator) : null
|
|
204
|
-
].filter(Boolean);
|
|
205
|
-
}
|
|
206
210
|
// Annotate the CommonJS export names for ESM import in node:
|
|
207
211
|
0 && (module.exports = {
|
|
212
|
+
babelInjectComponentSource,
|
|
208
213
|
elementLocatorReact,
|
|
209
214
|
reactComponentJump
|
|
210
215
|
});
|
package/dist/vite.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vite.ts","../src/elementLocatorReact.ts","../src/babelInjectComponentSource.ts","../src/constants.ts"],"sourcesContent":["export { elementLocatorReact as reactComponentJump } from \"./elementLocatorReact\";\nexport { elementLocatorReact } from \"./elementLocatorReact\";\nexport type { ElementLocatorReactOptions } from \"./elementLocatorReact\";\n\n","import type { TransformOptions, PluginItem } from \"@babel/core\";\nimport react, { type Options as ReactOptions } from \"@vitejs/plugin-react\";\nimport type { Plugin, PluginOption } from \"vite\";\nimport { babelInjectComponentSource } from \"./babelInjectComponentSource\";\nimport { type LocatorOptions } from \"./runtime\";\n\nexport type ElementLocatorReactOptions = {\n command?: \"serve\" | \"build\";\n react?: ReactOptions;\n locator?: LocatorOptions;\n injectClient?: boolean;\n};\n\nfunction withLocatorBabel(reactOptions: ReactOptions = {}): ReactOptions {\n const baseBabel = reactOptions.babel;\n\n if (typeof baseBabel === \"function\") {\n return {\n ...reactOptions,\n babel(id, options) {\n const result = baseBabel(id, options);\n const resolved = (result ?? {}) as TransformOptions;\n const plugins = [...(resolved.plugins ?? []), babelInjectComponentSource as PluginItem];\n\n return {\n ...resolved,\n plugins,\n };\n },\n };\n }\n\n const resolved = (baseBabel ?? {}) as TransformOptions;\n return {\n ...reactOptions,\n babel: {\n ...resolved,\n plugins: [...(resolved.plugins ?? []), babelInjectComponentSource as PluginItem],\n },\n };\n}\n\nfunction createClientInjector(locatorOptions: LocatorOptions = {}): Plugin {\n const serialized = JSON.stringify(locatorOptions);\n\n return {\n name: \"element-locator-client-injector\",\n apply: \"serve\",\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: {\n type: \"module\",\n },\n children: `import { enableReactComponentJump } from \"react-code-locator/client\"; enableReactComponentJump(${serialized});`,\n injectTo: \"head\",\n },\n ];\n },\n };\n}\n\nexport function elementLocatorReact(options: ElementLocatorReactOptions = {}): PluginOption[] {\n const { command = \"serve\", react: reactOptions, locator = {}, injectClient = true } = options;\n const isServe = command === \"serve\";\n\n return [\n react(isServe ? withLocatorBabel(reactOptions) : reactOptions),\n isServe && injectClient ? createClientInjector(locator) : null,\n ].filter(Boolean);\n}\n","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","resolved","react"]}
|
|
1
|
+
{"version":3,"sources":["../src/vite.ts","../src/elementLocatorReact.ts","../src/babelInjectComponentSource.ts","../src/constants.ts"],"sourcesContent":["export { elementLocatorReact as reactComponentJump } from \"./elementLocatorReact\";\nexport { elementLocatorReact } from \"./elementLocatorReact\";\nexport type { ElementLocatorReactOptions } from \"./elementLocatorReact\";\nexport { babelInjectComponentSource } from \"./babelInjectComponentSource\";\nexport type { BabelInjectComponentSourceOptions } from \"./babelInjectComponentSource\";\n","import type { Plugin, PluginOption } from \"vite\";\nimport { type LocatorOptions } from \"./runtime\";\n\nconst VIRTUAL_CLIENT_MODULE_ID = \"virtual:react-code-locator/client\";\nconst RESOLVED_VIRTUAL_CLIENT_MODULE_ID = `\\0${VIRTUAL_CLIENT_MODULE_ID}`;\n\nexport type ElementLocatorReactOptions = {\n command?: \"serve\" | \"build\";\n locator?: LocatorOptions;\n injectClient?: boolean;\n};\n\nfunction createClientInjector(locatorOptions: LocatorOptions = {}): Plugin {\n const serialized = JSON.stringify(locatorOptions);\n\n return {\n name: \"element-locator-client-injector\",\n apply: \"serve\",\n resolveId(id) {\n if (id === VIRTUAL_CLIENT_MODULE_ID) {\n return RESOLVED_VIRTUAL_CLIENT_MODULE_ID;\n }\n\n return null;\n },\n load(id) {\n if (id !== RESOLVED_VIRTUAL_CLIENT_MODULE_ID) {\n return null;\n }\n\n return `\n import { enableReactComponentJump } from \"react-code-locator/client\";\n\n enableReactComponentJump(${serialized});\n `;\n },\n transformIndexHtml() {\n return [\n {\n tag: \"script\",\n attrs: {\n type: \"module\",\n },\n children: `import \"${VIRTUAL_CLIENT_MODULE_ID}\";`,\n injectTo: \"head\",\n },\n ];\n },\n };\n}\n\nexport function elementLocatorReact(options: ElementLocatorReactOptions = {}): PluginOption[] {\n const { command = \"serve\", locator = {}, injectClient = true } = options;\n const isServe = command === \"serve\";\n\n return [isServe && injectClient ? createClientInjector(locator) : null].filter(Boolean);\n}\n","import path from \"node:path\";\nimport { types as t, type NodePath, type PluginObj } from \"@babel/core\";\nimport { SOURCE_PROP } from \"./constants\";\n\nexport type BabelInjectComponentSourceOptions = {\n injectJsxSource?: boolean;\n injectComponentSource?: boolean;\n};\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 isSupportedComponentInit(node: t.Expression | null | undefined): boolean {\n if (!node) {\n return false;\n }\n\n if (t.isArrowFunctionExpression(node) || t.isFunctionExpression(node)) {\n return true;\n }\n\n if (!t.isCallExpression(node)) {\n return false;\n }\n\n if (t.isIdentifier(node.callee) && (node.callee.name === \"memo\" || node.callee.name === \"forwardRef\")) {\n return true;\n }\n\n return (\n t.isMemberExpression(node.callee) &&\n t.isIdentifier(node.callee.object, { name: \"React\" }) &&\n t.isIdentifier(node.callee.property) &&\n (node.callee.property.name === \"memo\" || node.callee.property.name === \"forwardRef\")\n );\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 (!isSupportedComponentInit(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(\n options: BabelInjectComponentSourceOptions = {},\n): PluginObj<BabelState> {\n const { injectJsxSource = false, injectComponentSource = true } = options;\n\n return {\n name: \"babel-inject-component-source\",\n visitor: {\n JSXOpeningElement(pathNode, state) {\n if (!injectJsxSource) {\n return;\n }\n\n const hasSourceProp = pathNode.node.attributes.some(\n (attr) => t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name) && attr.name.name === SOURCE_PROP,\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_PROP),\n t.stringLiteral(getSourceValue(state, loc) ?? `${filename.replace(/\\\\/g, \"/\")}:${loc.line}:${loc.column + 1}`),\n ),\n );\n },\n Program(programPath, state) {\n if (!injectComponentSource) {\n return;\n }\n\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGA,IAAM,2BAA2B;AACjC,IAAM,oCAAoC,KAAK,wBAAwB;AAQvE,SAAS,qBAAqB,iBAAiC,CAAC,GAAW;AACzE,QAAM,aAAa,KAAK,UAAU,cAAc;AAEhD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IACP,UAAU,IAAI;AACZ,UAAI,OAAO,0BAA0B;AACnC,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,IACA,KAAK,IAAI;AACP,UAAI,OAAO,mCAAmC;AAC5C,eAAO;AAAA,MACT;AAEA,aAAO;AAAA;AAAA;AAAA,mCAGsB,UAAU;AAAA;AAAA,IAEzC;AAAA,IACA,qBAAqB;AACnB,aAAO;AAAA,QACL;AAAA,UACE,KAAK;AAAA,UACL,OAAO;AAAA,YACL,MAAM;AAAA,UACR;AAAA,UACA,UAAU,WAAW,wBAAwB;AAAA,UAC7C,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,UAAsC,CAAC,GAAmB;AAC5F,QAAM,EAAE,UAAU,SAAS,UAAU,CAAC,GAAG,eAAe,KAAK,IAAI;AACjE,QAAM,UAAU,YAAY;AAE5B,SAAO,CAAC,WAAW,eAAe,qBAAqB,OAAO,IAAI,IAAI,EAAE,OAAO,OAAO;AACxF;;;ACxDA,uBAAiB;AACjB,kBAA0D;;;ACDnD,IAAM,cAAc;;;ADiB3B,SAAS,gBAAgB,MAAc;AACrC,SAAO,SAAS,KAAK,IAAI;AAC3B;AAEA,SAAS,yBAAyB,MAAgD;AAChF,MAAI,CAAC,MAAM;AACT,WAAO;AAAA,EACT;AAEA,MAAI,YAAAA,MAAE,0BAA0B,IAAI,KAAK,YAAAA,MAAE,qBAAqB,IAAI,GAAG;AACrE,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,YAAAA,MAAE,iBAAiB,IAAI,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,MAAI,YAAAA,MAAE,aAAa,KAAK,MAAM,MAAM,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,eAAe;AACrG,WAAO;AAAA,EACT;AAEA,SACE,YAAAA,MAAE,mBAAmB,KAAK,MAAM,KAChC,YAAAA,MAAE,aAAa,KAAK,OAAO,QAAQ,EAAE,MAAM,QAAQ,CAAC,KACpD,YAAAA,MAAE,aAAa,KAAK,OAAO,QAAQ,MAClC,KAAK,OAAO,SAAS,SAAS,UAAU,KAAK,OAAO,SAAS,SAAS;AAE3E;AAEA,SAAS,eAAe,OAAmB,KAA0D;AACnG,QAAM,WAAW,MAAM,MAAM,MAAM;AACnC,MAAI,CAAC,YAAY,CAAC,KAAK;AACrB,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,iBAAAC,QAAK,SAAS,QAAQ,IAAI,GAAG,QAAQ,EAAE,QAAQ,OAAO,GAAG;AACzE,SAAO,GAAG,OAAO,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC;AACjD;AAEA,SAAS,gBAAgB,MAAc,aAAqB;AAC1D,SAAO,YAAAD,MAAE;AAAA,IACP,YAAAA,MAAE;AAAA,MACA;AAAA,MACA,YAAAA,MAAE,iBAAiB,YAAAA,MAAE,WAAW,IAAI,GAAG,YAAAA,MAAE,WAAW,WAAW,CAAC;AAAA,MAChE,YAAAA,MAAE,cAAc,WAAW;AAAA,IAC7B;AAAA,EACF;AACF;AAEA,SAAS,iBACP,iBACA,iBACA,OACA,MACA;AACA,MAAI,gBAAgB,sBAAsB,KAAK,gBAAgB,mBAAmB,GAAG;AACnF,UAAM,OAAO,gBAAgB,KAAK,IAAI;AACtC,QAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG;AACrD;AAAA,IACF;AAEA,UAAM,cAAc,eAAe,OAAO,gBAAgB,KAAK,KAAK,KAAK;AACzE,QAAI,CAAC,aAAa;AAChB;AAAA,IACF;AAEA,SAAK,IAAI,IAAI;AACb,oBAAgB,YAAY,gBAAgB,MAAM,WAAW,CAAC;AAC9D;AAAA,EACF;AAEA,MAAI,CAAC,gBAAgB,sBAAsB,GAAG;AAC5C;AAAA,EACF;AAEA,QAAM,cAAc,gBAAgB,KAAK,aAAa,QAAQ,CAAC,eAAe;AAC5E,QAAI,CAAC,YAAAA,MAAE,aAAa,WAAW,EAAE,KAAK,CAAC,gBAAgB,WAAW,GAAG,IAAI,KAAK,KAAK,IAAI,WAAW,GAAG,IAAI,GAAG;AAC1G,aAAO,CAAC;AAAA,IACV;AAEA,QAAI,CAAC,WAAW,MAAM;AACpB,aAAO,CAAC;AAAA,IACV;AAEA,QAAI,CAAC,yBAAyB,WAAW,IAAI,GAAG;AAC9C,aAAO,CAAC;AAAA,IACV;AAEA,UAAM,cAAc,eAAe,OAAO,WAAW,KAAK,SAAS,WAAW,KAAK,KAAK,KAAK;AAC7F,QAAI,CAAC,aAAa;AAChB,aAAO,CAAC;AAAA,IACV;AAEA,SAAK,IAAI,WAAW,GAAG,IAAI;AAC3B,WAAO,CAAC,gBAAgB,WAAW,GAAG,MAAM,WAAW,CAAC;AAAA,EAC1D,CAAC;AAED,MAAI,YAAY,SAAS,GAAG;AAC1B,oBAAgB,YAAY,WAAW;AAAA,EACzC;AACF;AAEO,SAAS,2BACd,UAA6C,CAAC,GACvB;AACvB,QAAM,EAAE,kBAAkB,OAAO,wBAAwB,KAAK,IAAI;AAElE,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,MACP,kBAAkB,UAAU,OAAO;AACjC,YAAI,CAAC,iBAAiB;AACpB;AAAA,QACF;AAEA,cAAM,gBAAgB,SAAS,KAAK,WAAW;AAAA,UAC7C,CAAC,SAAS,YAAAA,MAAE,eAAe,IAAI,KAAK,YAAAA,MAAE,gBAAgB,KAAK,IAAI,KAAK,KAAK,KAAK,SAAS;AAAA,QACzF;AACA,YAAI,eAAe;AACjB;AAAA,QACF;AAEA,cAAM,WAAW,MAAM,MAAM,MAAM;AACnC,cAAM,MAAM,SAAS,KAAK,KAAK;AAC/B,YAAI,CAAC,YAAY,CAAC,KAAK;AACrB;AAAA,QACF;AAEA,iBAAS,KAAK,WAAW;AAAA,UACvB,YAAAA,MAAE;AAAA,YACA,YAAAA,MAAE,cAAc,WAAW;AAAA,YAC3B,YAAAA,MAAE,cAAc,eAAe,OAAO,GAAG,KAAK,GAAG,SAAS,QAAQ,OAAO,GAAG,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC,EAAE;AAAA,UAC/G;AAAA,QACF;AAAA,MACF;AAAA,MACA,QAAQ,aAAa,OAAO;AAC1B,YAAI,CAAC,uBAAuB;AAC1B;AAAA,QACF;AAEA,cAAM,OAAO,oBAAI,IAAY;AAE7B,mBAAW,aAAa,YAAY,IAAI,MAAM,GAAG;AAC/C,cAAI,UAAU,yBAAyB,KAAK,UAAU,2BAA2B,GAAG;AAClF,kBAAM,kBAAkB,UAAU,IAAI,aAAa;AACnD,gBAAI,CAAC,MAAM,QAAQ,eAAe,KAAK,gBAAgB,MAAM;AAC3D,+BAAiB,iBAAiB,WAAW,OAAO,IAAI;AAAA,YAC1D;AACA;AAAA,UACF;AAEA,2BAAiB,WAAW,WAAW,OAAO,IAAI;AAAA,QACpD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":["t","path"]}
|
package/dist/vite.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Options } from '@vitejs/plugin-react';
|
|
2
1
|
import { PluginOption } from 'vite';
|
|
3
2
|
import { LocatorOptions } from './client.cjs';
|
|
3
|
+
export { BabelInjectComponentSourceOptions, babelInjectComponentSource } from './babelInjectComponentSource.cjs';
|
|
4
|
+
import '@babel/core';
|
|
4
5
|
|
|
5
6
|
type ElementLocatorReactOptions = {
|
|
6
7
|
command?: "serve" | "build";
|
|
7
|
-
react?: Options;
|
|
8
8
|
locator?: LocatorOptions;
|
|
9
9
|
injectClient?: boolean;
|
|
10
10
|
};
|