@visual-agentic-dev/react-devtools 1.1.4 → 1.2.0

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/dist/index.mjs CHANGED
@@ -54,74 +54,153 @@ var Highlighter = ({
54
54
  import { useEffect as useEffect2, useState as useState2 } from "react";
55
55
 
56
56
  // src/utils/sourceLocator.ts
57
- function getReactFiber(element) {
58
- const key = Object.keys(element).find(
59
- (k) => k.startsWith("__reactFiber$") || k.startsWith("__reactInternalInstance$")
60
- );
61
- return key ? element[key] : null;
57
+ function getFiberFromElement(element) {
58
+ if (!element || typeof element !== "object") {
59
+ return null;
60
+ }
61
+ const keys = Object.keys(element);
62
+ const fiberKey = keys.find((key) => key.startsWith("__reactFiber$"));
63
+ if (fiberKey) {
64
+ return element[fiberKey];
65
+ }
66
+ const instanceKey = keys.find((key) => key.startsWith("__reactInternalInstance$"));
67
+ if (instanceKey) {
68
+ return element[instanceKey];
69
+ }
70
+ const possibleFiberKey = keys.find((key) => {
71
+ if (!key.startsWith("__react")) return false;
72
+ if (key.startsWith("__reactContainer") || key.startsWith("__reactProps") || key.startsWith("__reactEvents")) return false;
73
+ const value = element[key];
74
+ return value && typeof value === "object" && ("_debugSource" in value || "tag" in value || "return" in value);
75
+ });
76
+ if (possibleFiberKey) {
77
+ return element[possibleFiberKey];
78
+ }
79
+ return null;
62
80
  }
63
- function findFiberWithSource(fiber) {
81
+ function getComponentName(fiber) {
82
+ if (!fiber.type) return null;
83
+ if (typeof fiber.type === "string") return null;
84
+ if (typeof fiber.type === "object" || typeof fiber.type === "function") {
85
+ return fiber.type.displayName || fiber.type.name || null;
86
+ }
87
+ return null;
88
+ }
89
+ function findDebugSource(fiber, maxDepth = 50) {
64
90
  let current = fiber;
65
- while (current) {
91
+ let depth = 0;
92
+ while (current && depth < maxDepth) {
66
93
  if (current._debugSource) {
67
- return current;
94
+ return {
95
+ source: current._debugSource,
96
+ componentName: getComponentName(current)
97
+ };
98
+ }
99
+ if (current._debugOwner?._debugSource) {
100
+ return {
101
+ source: current._debugOwner._debugSource,
102
+ componentName: getComponentName(current._debugOwner)
103
+ };
68
104
  }
69
105
  current = current.return;
106
+ depth++;
70
107
  }
71
108
  return null;
72
109
  }
73
- function getSourceFromFiber(element) {
74
- const fiber = getReactFiber(element);
75
- if (!fiber) return null;
76
- const fiberWithSource = findFiberWithSource(fiber);
77
- if (fiberWithSource?._debugSource) {
78
- const { fileName, lineNumber, columnNumber } = fiberWithSource._debugSource;
79
- return {
80
- fileName,
81
- lineNumber,
82
- columnNumber: columnNumber || 1
83
- };
110
+ function findDebugSourceReact19(fiber) {
111
+ let current = fiber;
112
+ let depth = 0;
113
+ const maxDepth = 50;
114
+ while (current && depth < maxDepth) {
115
+ const anyFiber = current;
116
+ const possibleSourceKeys = ["_debugSource", "__source", "_source", "debugSource", "_debugInfo"];
117
+ for (const key of possibleSourceKeys) {
118
+ const source = anyFiber[key];
119
+ if (source) {
120
+ if (typeof source === "object" && typeof source.fileName === "string") {
121
+ return {
122
+ source,
123
+ componentName: getComponentName(current)
124
+ };
125
+ }
126
+ if (Array.isArray(source)) {
127
+ for (const info of source) {
128
+ if (info && typeof info.fileName === "string") {
129
+ return {
130
+ source: info,
131
+ componentName: getComponentName(current)
132
+ };
133
+ }
134
+ }
135
+ }
136
+ }
137
+ }
138
+ const props = current.memoizedProps || current.pendingProps;
139
+ if (props && typeof props === "object") {
140
+ if (props.__source && typeof props.__source === "object" && props.__source.fileName) {
141
+ return {
142
+ source: props.__source,
143
+ componentName: getComponentName(current)
144
+ };
145
+ }
146
+ }
147
+ current = current.return;
148
+ depth++;
84
149
  }
85
150
  return null;
86
151
  }
87
152
  function parseSourceAttr(attrValue) {
88
153
  if (!attrValue) return null;
89
154
  try {
90
- const parsed = JSON.parse(attrValue);
91
- if (typeof parsed.fileName === "string" && typeof parsed.lineNumber === "number" && typeof parsed.columnNumber === "number") {
92
- return parsed;
155
+ if (attrValue.startsWith("{")) {
156
+ const parsed = JSON.parse(attrValue);
157
+ if (parsed.fileName && typeof parsed.lineNumber === "number") {
158
+ return parsed;
159
+ }
93
160
  }
94
161
  } catch {
95
162
  }
96
163
  return null;
97
164
  }
165
+ function getSourceFromElement(element, prefix = "vdev") {
166
+ const fiber = getFiberFromElement(element);
167
+ if (fiber) {
168
+ let result = findDebugSource(fiber);
169
+ if (!result) {
170
+ result = findDebugSourceReact19(fiber);
171
+ }
172
+ if (result) {
173
+ return {
174
+ fileName: result.source.fileName,
175
+ lineNumber: result.source.lineNumber,
176
+ columnNumber: result.source.columnNumber || 1,
177
+ componentName: result.componentName || void 0
178
+ };
179
+ }
180
+ }
181
+ const file = element.getAttribute(`data-${prefix}-file`);
182
+ const line = element.getAttribute(`data-${prefix}-line`);
183
+ const col = element.getAttribute(`data-${prefix}-col`);
184
+ if (file && line) {
185
+ return {
186
+ fileName: file,
187
+ lineNumber: parseInt(line, 10),
188
+ columnNumber: col ? parseInt(col, 10) : 1,
189
+ componentName: element.tagName.toLowerCase()
190
+ // Simple fallback
191
+ };
192
+ }
193
+ return null;
194
+ }
98
195
  function findSourceElement(target, prefix = "vdev") {
99
196
  let current = target;
100
197
  while (current && current !== document.body) {
101
- if (getSourceFromFiber(current)) {
198
+ if (getSourceFromElement(current, prefix)) {
102
199
  return current;
103
200
  }
104
201
  current = current.parentElement;
105
202
  }
106
- return target.closest(`[data-${prefix}-file], [data-${prefix}-source]`);
107
- }
108
- function getSourceFromElement(element, prefix = "vdev") {
109
- const fiberSource = getSourceFromFiber(element);
110
- if (fiberSource) {
111
- return fiberSource;
112
- }
113
- const fileName = element.getAttribute(`data-${prefix}-file`);
114
- const lineStr = element.getAttribute(`data-${prefix}-line`);
115
- const colStr = element.getAttribute(`data-${prefix}-col`);
116
- if (fileName && lineStr) {
117
- return {
118
- fileName,
119
- lineNumber: parseInt(lineStr, 10),
120
- columnNumber: colStr ? parseInt(colStr, 10) : 1
121
- };
122
- }
123
- const attrValue = element.getAttribute(`data-${prefix}-source`);
124
- return parseSourceAttr(attrValue);
203
+ return null;
125
204
  }
126
205
 
127
206
  // src/overlay/SelectionBox.tsx
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/DevToolsProvider.tsx","../src/overlay/Highlighter.tsx","../src/overlay/SelectionBox.tsx","../src/utils/sourceLocator.ts","../src/utils/messaging.ts"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode\n} from 'react';\nimport { Highlighter } from '../overlay/Highlighter';\nimport { SelectionBox } from '../overlay/SelectionBox';\nimport { getSourceFromElement, findSourceElement } from '../utils/sourceLocator';\nimport { sendToExtension, createMessageHandler, notifyReady } from '../utils/messaging';\nimport type { SourceLocation, VDevMessage } from '../types';\n\ninterface DevToolsContextValue {\n isInspecting: boolean;\n setInspecting: (v: boolean) => void;\n selectedElement: HTMLElement | null;\n selectedSource: SourceLocation | null;\n clearSelection: () => void;\n}\n\nconst DevToolsContext = createContext<DevToolsContextValue | null>(null);\n\nexport const useDevTools = () => {\n const context = useContext(DevToolsContext);\n if (!context) {\n throw new Error('useDevTools must be used within a DevToolsProvider');\n }\n return context;\n};\n\ninterface DevToolsProviderProps {\n children: ReactNode;\n /** Only enable in development mode (default: true) */\n enabled?: boolean;\n /** Attribute prefix (default: 'vdev') */\n prefix?: string;\n}\n\nexport const DevToolsProvider: React.FC<DevToolsProviderProps> = ({\n children,\n enabled = true,\n prefix = 'vdev'\n}) => {\n const [isInspecting, setInspecting] = useState(false);\n const [hoveredElement, setHoveredElement] = useState<HTMLElement | null>(null);\n const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(null);\n const [selectedSource, setSelectedSource] = useState<SourceLocation | null>(null);\n\n const clearSelection = useCallback(() => {\n setSelectedElement(null);\n setSelectedSource(null);\n }, []);\n\n // Listen to messages from extension\n useEffect(() => {\n if (!enabled) return;\n\n const handler = createMessageHandler((message: VDevMessage) => {\n console.log('[DevTools] Received message:', message);\n if (message.type === 'VDEV_START_INSPECT') {\n console.log('[DevTools] Starting inspection');\n setInspecting(true);\n clearSelection();\n } else if (message.type === 'VDEV_STOP_INSPECT') {\n console.log('[DevTools] Stopping inspection');\n setInspecting(false);\n setHoveredElement(null);\n } else if (message.type === 'VDEV_TOGGLE_INSPECT') {\n console.log('[DevTools] Toggling inspection');\n setInspecting(prev => {\n const newState = !prev;\n if (newState) {\n // Starting inspection, clear selection\n clearSelection();\n } else {\n // Stopping inspection, clear hovered\n setHoveredElement(null);\n }\n // Notify extension of state change\n sendToExtension({\n type: 'VDEV_INSPECT_STATE_CHANGED',\n payload: { isInspecting: newState }\n });\n return newState;\n });\n } else if (message.type === 'VDEV_CLEAR_SELECTION') {\n clearSelection();\n }\n });\n\n window.addEventListener('message', handler);\n\n // Notify extension that SDK is ready\n notifyReady();\n console.log('[DevTools] SDK Ready, listening for messages');\n\n return () => window.removeEventListener('message', handler);\n }, [enabled, clearSelection]);\n\n // Handle mouse events in inspect mode\n useEffect(() => {\n if (!isInspecting || !enabled) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore our own overlay elements\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n // console.log('[DevTools] Mouse move', target, sourceElement);\n\n if (sourceElement && sourceElement !== hoveredElement) {\n console.log('[DevTools] Hovered element found:', sourceElement);\n setHoveredElement(sourceElement);\n }\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n\n // Ignore clicks on overlay\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n\n if (sourceElement) {\n const source = getSourceFromElement(sourceElement, prefix);\n setSelectedElement(sourceElement);\n setSelectedSource(source);\n setInspecting(false);\n setHoveredElement(null);\n\n // Notify extension of selection\n sendToExtension({\n type: 'VDEV_ELEMENT_SELECTED',\n payload: {\n source,\n elementInfo: {\n tagName: sourceElement.tagName.toLowerCase(),\n className: sourceElement.className,\n textContent: sourceElement.textContent?.slice(0, 100) || '',\n },\n },\n });\n }\n };\n\n // Use capture to intercept before normal handlers\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n\n // Add cursor style\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n };\n }, [isInspecting, enabled, hoveredElement, prefix]);\n\n // Don't render anything if disabled\n if (!enabled) {\n return <>{children}</>;\n }\n\n return (\n <DevToolsContext.Provider\n value={{\n isInspecting,\n setInspecting,\n selectedElement,\n selectedSource,\n clearSelection\n }}\n >\n {children}\n\n {/* Hover highlighter */}\n {isInspecting && hoveredElement && (\n <Highlighter element={hoveredElement} />\n )}\n\n {/* Selection box */}\n {selectedElement && (\n <SelectionBox element={selectedElement} prefix={prefix} />\n )}\n </DevToolsContext.Provider>\n );\n};\n","import React, { useEffect, useState } from 'react';\n\ninterface Props {\n element: HTMLElement;\n color?: string;\n}\n\n/**\n * Highlighter overlay component - shows a blue overlay on hovered elements\n */\nexport const Highlighter: React.FC<Props> = ({\n element,\n color = 'rgba(66, 153, 225, 0.3)'\n}) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n backgroundColor: color,\n border: '2px solid #4299e1',\n pointerEvents: 'none',\n zIndex: 999999,\n transition: 'all 0.1s ease',\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"highlighter\"\n />\n );\n};\n","import React, { useEffect, useState } from 'react';\nimport type { SourceLocation } from '../types';\nimport { getSourceFromElement } from '../utils/sourceLocator';\n\ninterface Props {\n element: HTMLElement;\n prefix?: string;\n}\n\n/**\n * SelectionBox component - shows a persistent selection box with source info label\n */\nexport const SelectionBox: React.FC<Props> = ({ element, prefix = 'vdev' }) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n const [source, setSource] = useState<SourceLocation | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n // Get source info\n setSource(getSourceFromElement(element, prefix));\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element, prefix]);\n\n if (!rect) return null;\n\n // Format file path for display (show only basename)\n const fileName = source?.fileName.split('/').pop() || 'unknown';\n const lineInfo = source ? `${fileName}:${source.lineNumber}` : '';\n\n return (\n <>\n {/* Selection border */}\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n border: '2px solid #6366f1',\n backgroundColor: 'rgba(99, 102, 241, 0.1)',\n pointerEvents: 'none',\n zIndex: 999999,\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"selection\"\n />\n\n {/* Label showing file:line */}\n {lineInfo && (\n <div\n style={{\n position: 'fixed',\n top: Math.max(0, rect.top - 24),\n left: rect.left,\n backgroundColor: '#6366f1',\n color: 'white',\n fontSize: '11px',\n fontFamily: 'monospace',\n padding: '2px 6px',\n borderRadius: '3px',\n pointerEvents: 'none',\n zIndex: 999999,\n whiteSpace: 'nowrap',\n }}\n data-vdev-overlay=\"label\"\n >\n {lineInfo}\n </div>\n )}\n </>\n );\n};\n","import type { SourceLocation } from '../types';\n\n/**\n * Get React Fiber node from DOM element\n * React attaches fiber information to DOM elements with internal keys\n */\nfunction getReactFiber(element: HTMLElement): any {\n const key = Object.keys(element).find(\n k => k.startsWith('__reactFiber$') || k.startsWith('__reactInternalInstance$')\n );\n return key ? (element as any)[key] : null;\n}\n\n/**\n * Walk up the fiber tree to find a fiber with _debugSource\n */\nfunction findFiberWithSource(fiber: any): any {\n let current = fiber;\n while (current) {\n if (current._debugSource) {\n return current;\n }\n current = current.return;\n }\n return null;\n}\n\n/**\n * Get source from React Fiber's _debugSource (runtime detection)\n * This is the preferred method as it doesn't require any build plugin\n */\nexport function getSourceFromFiber(element: HTMLElement): SourceLocation | null {\n const fiber = getReactFiber(element);\n if (!fiber) return null;\n\n const fiberWithSource = findFiberWithSource(fiber);\n if (fiberWithSource?._debugSource) {\n const { fileName, lineNumber, columnNumber } = fiberWithSource._debugSource;\n return {\n fileName,\n lineNumber,\n columnNumber: columnNumber || 1\n };\n }\n return null;\n}\n\n/**\n * Parse the data-vdev-source attribute value into a SourceLocation object\n * (Legacy support for projects using the babel/vite plugin)\n */\nexport function parseSourceAttr(attrValue: string | null): SourceLocation | null {\n if (!attrValue) return null;\n\n try {\n const parsed = JSON.parse(attrValue);\n if (\n typeof parsed.fileName === 'string' &&\n typeof parsed.lineNumber === 'number' &&\n typeof parsed.columnNumber === 'number'\n ) {\n return parsed as SourceLocation;\n }\n } catch {\n // Ignore parse errors\n }\n\n return null;\n}\n\n/**\n * Find the closest element with source information\n * First tries React Fiber (runtime), then falls back to data attributes\n */\nexport function findSourceElement(target: HTMLElement, prefix = 'vdev'): HTMLElement | null {\n // First, try to find source from React Fiber (runtime)\n let current: HTMLElement | null = target;\n while (current && current !== document.body) {\n if (getSourceFromFiber(current)) {\n return current;\n }\n current = current.parentElement;\n }\n\n // Fallback: check for data attributes (legacy plugin support)\n return target.closest(`[data-${prefix}-file], [data-${prefix}-source]`) as HTMLElement | null;\n}\n\n/**\n * Get source location from an element\n * Prioritizes React Fiber _debugSource, falls back to data attributes\n */\nexport function getSourceFromElement(element: HTMLElement, prefix = 'vdev'): SourceLocation | null {\n // 1. Try React Fiber _debugSource first (runtime, no plugin needed)\n const fiberSource = getSourceFromFiber(element);\n if (fiberSource) {\n return fiberSource;\n }\n\n // 2. Try new data attribute format (plugin-based)\n const fileName = element.getAttribute(`data-${prefix}-file`);\n const lineStr = element.getAttribute(`data-${prefix}-line`);\n const colStr = element.getAttribute(`data-${prefix}-col`);\n\n if (fileName && lineStr) {\n return {\n fileName,\n lineNumber: parseInt(lineStr, 10),\n columnNumber: colStr ? parseInt(colStr, 10) : 1\n };\n }\n\n // 3. Fallback to legacy format (JSON in single attribute)\n const attrValue = element.getAttribute(`data-${prefix}-source`);\n return parseSourceAttr(attrValue);\n}\n\n","import type { VDevMessage } from '../types';\n\nconst MESSAGE_SOURCE = 'vdev-react-sdk';\n\n/**\n * Send a message to the Chrome extension via window.postMessage\n */\nexport function sendToExtension(message: VDevMessage): void {\n window.postMessage(\n { ...message, source: MESSAGE_SOURCE },\n '*'\n );\n}\n\n/**\n * Notify extension that SDK is ready\n */\nexport function notifyReady(): void {\n sendToExtension({ type: 'VDEV_SDK_READY' });\n}\n\n/**\n * Create a message handler that only processes messages from the extension\n */\nexport function createMessageHandler(\n handler: (message: VDevMessage) => void\n): (event: MessageEvent) => void {\n return (event: MessageEvent) => {\n // Only process messages from the same window\n if (event.source !== window) return;\n\n // Only process messages from extension (not from SDK itself)\n if (event.data?.source === MESSAGE_SOURCE) return;\n\n // Process VDEV messages\n if (event.data?.type?.startsWith('VDEV_')) {\n handler(event.data as VDevMessage);\n }\n };\n}\n"],"mappings":"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","names":["useState","useEffect","useEffect","useState","jsx","useState","useEffect","Fragment","jsx","jsxs","useState","useEffect"]}
1
+ {"version":3,"sources":["../src/components/DevToolsProvider.tsx","../src/overlay/Highlighter.tsx","../src/overlay/SelectionBox.tsx","../src/utils/sourceLocator.ts","../src/utils/messaging.ts"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n type ReactNode\n} from 'react';\nimport { Highlighter } from '../overlay/Highlighter';\nimport { SelectionBox } from '../overlay/SelectionBox';\nimport { getSourceFromElement, findSourceElement } from '../utils/sourceLocator';\nimport { sendToExtension, createMessageHandler, notifyReady } from '../utils/messaging';\nimport type { SourceLocation, VDevMessage } from '../types';\n\ninterface DevToolsContextValue {\n isInspecting: boolean;\n setInspecting: (v: boolean) => void;\n selectedElement: HTMLElement | null;\n selectedSource: SourceLocation | null;\n clearSelection: () => void;\n}\n\nconst DevToolsContext = createContext<DevToolsContextValue | null>(null);\n\nexport const useDevTools = () => {\n const context = useContext(DevToolsContext);\n if (!context) {\n throw new Error('useDevTools must be used within a DevToolsProvider');\n }\n return context;\n};\n\ninterface DevToolsProviderProps {\n children: ReactNode;\n /** Only enable in development mode (default: true) */\n enabled?: boolean;\n /** Attribute prefix (default: 'vdev') */\n prefix?: string;\n}\n\nexport const DevToolsProvider: React.FC<DevToolsProviderProps> = ({\n children,\n enabled = true,\n prefix = 'vdev'\n}) => {\n const [isInspecting, setInspecting] = useState(false);\n const [hoveredElement, setHoveredElement] = useState<HTMLElement | null>(null);\n const [selectedElement, setSelectedElement] = useState<HTMLElement | null>(null);\n const [selectedSource, setSelectedSource] = useState<SourceLocation | null>(null);\n\n const clearSelection = useCallback(() => {\n setSelectedElement(null);\n setSelectedSource(null);\n }, []);\n\n // Listen to messages from extension\n useEffect(() => {\n if (!enabled) return;\n\n const handler = createMessageHandler((message: VDevMessage) => {\n console.log('[DevTools] Received message:', message);\n if (message.type === 'VDEV_START_INSPECT') {\n console.log('[DevTools] Starting inspection');\n setInspecting(true);\n clearSelection();\n } else if (message.type === 'VDEV_STOP_INSPECT') {\n console.log('[DevTools] Stopping inspection');\n setInspecting(false);\n setHoveredElement(null);\n } else if (message.type === 'VDEV_TOGGLE_INSPECT') {\n console.log('[DevTools] Toggling inspection');\n setInspecting(prev => {\n const newState = !prev;\n if (newState) {\n // Starting inspection, clear selection\n clearSelection();\n } else {\n // Stopping inspection, clear hovered\n setHoveredElement(null);\n }\n // Notify extension of state change\n sendToExtension({\n type: 'VDEV_INSPECT_STATE_CHANGED',\n payload: { isInspecting: newState }\n });\n return newState;\n });\n } else if (message.type === 'VDEV_CLEAR_SELECTION') {\n clearSelection();\n }\n });\n\n window.addEventListener('message', handler);\n\n // Notify extension that SDK is ready\n notifyReady();\n console.log('[DevTools] SDK Ready, listening for messages');\n\n return () => window.removeEventListener('message', handler);\n }, [enabled, clearSelection]);\n\n // Handle mouse events in inspect mode\n useEffect(() => {\n if (!isInspecting || !enabled) return;\n\n const handleMouseMove = (e: MouseEvent) => {\n const target = e.target as HTMLElement;\n\n // Ignore our own overlay elements\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n // console.log('[DevTools] Mouse move', target, sourceElement);\n\n if (sourceElement && sourceElement !== hoveredElement) {\n console.log('[DevTools] Hovered element found:', sourceElement);\n setHoveredElement(sourceElement);\n }\n };\n\n const handleClick = (e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n\n const target = e.target as HTMLElement;\n\n // Ignore clicks on overlay\n if (target.hasAttribute('data-vdev-overlay')) return;\n\n const sourceElement = findSourceElement(target, prefix);\n\n if (sourceElement) {\n const source = getSourceFromElement(sourceElement, prefix);\n setSelectedElement(sourceElement);\n setSelectedSource(source);\n setInspecting(false);\n setHoveredElement(null);\n\n // Notify extension of selection\n sendToExtension({\n type: 'VDEV_ELEMENT_SELECTED',\n payload: {\n source,\n elementInfo: {\n tagName: sourceElement.tagName.toLowerCase(),\n className: sourceElement.className,\n textContent: sourceElement.textContent?.slice(0, 100) || '',\n },\n },\n });\n }\n };\n\n // Use capture to intercept before normal handlers\n document.addEventListener('mousemove', handleMouseMove, true);\n document.addEventListener('click', handleClick, true);\n\n // Add cursor style\n document.body.style.cursor = 'crosshair';\n\n return () => {\n document.removeEventListener('mousemove', handleMouseMove, true);\n document.removeEventListener('click', handleClick, true);\n document.body.style.cursor = '';\n };\n }, [isInspecting, enabled, hoveredElement, prefix]);\n\n // Don't render anything if disabled\n if (!enabled) {\n return <>{children}</>;\n }\n\n return (\n <DevToolsContext.Provider\n value={{\n isInspecting,\n setInspecting,\n selectedElement,\n selectedSource,\n clearSelection\n }}\n >\n {children}\n\n {/* Hover highlighter */}\n {isInspecting && hoveredElement && (\n <Highlighter element={hoveredElement} />\n )}\n\n {/* Selection box */}\n {selectedElement && (\n <SelectionBox element={selectedElement} prefix={prefix} />\n )}\n </DevToolsContext.Provider>\n );\n};\n","import React, { useEffect, useState } from 'react';\n\ninterface Props {\n element: HTMLElement;\n color?: string;\n}\n\n/**\n * Highlighter overlay component - shows a blue overlay on hovered elements\n */\nexport const Highlighter: React.FC<Props> = ({\n element,\n color = 'rgba(66, 153, 225, 0.3)'\n}) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element]);\n\n if (!rect) return null;\n\n return (\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n backgroundColor: color,\n border: '2px solid #4299e1',\n pointerEvents: 'none',\n zIndex: 999999,\n transition: 'all 0.1s ease',\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"highlighter\"\n />\n );\n};\n","import React, { useEffect, useState } from 'react';\nimport type { SourceLocation } from '../types';\nimport { getSourceFromElement } from '../utils/sourceLocator';\n\ninterface Props {\n element: HTMLElement;\n prefix?: string;\n}\n\n/**\n * SelectionBox component - shows a persistent selection box with source info label\n */\nexport const SelectionBox: React.FC<Props> = ({ element, prefix = 'vdev' }) => {\n const [rect, setRect] = useState<DOMRect | null>(null);\n const [source, setSource] = useState<SourceLocation | null>(null);\n\n useEffect(() => {\n const update = () => setRect(element.getBoundingClientRect());\n update();\n\n // Get source info\n setSource(getSourceFromElement(element, prefix));\n\n const observer = new ResizeObserver(update);\n observer.observe(element);\n\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n\n return () => {\n observer.disconnect();\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [element, prefix]);\n\n if (!rect) return null;\n\n // Format file path for display (show only basename)\n const fileName = source?.fileName.split('/').pop() || 'unknown';\n const lineInfo = source ? `${fileName}:${source.lineNumber}` : '';\n\n return (\n <>\n {/* Selection border */}\n <div\n style={{\n position: 'fixed',\n top: rect.top,\n left: rect.left,\n width: rect.width,\n height: rect.height,\n border: '2px solid #6366f1',\n backgroundColor: 'rgba(99, 102, 241, 0.1)',\n pointerEvents: 'none',\n zIndex: 999999,\n boxSizing: 'border-box',\n }}\n data-vdev-overlay=\"selection\"\n />\n\n {/* Label showing file:line */}\n {lineInfo && (\n <div\n style={{\n position: 'fixed',\n top: Math.max(0, rect.top - 24),\n left: rect.left,\n backgroundColor: '#6366f1',\n color: 'white',\n fontSize: '11px',\n fontFamily: 'monospace',\n padding: '2px 6px',\n borderRadius: '3px',\n pointerEvents: 'none',\n zIndex: 999999,\n whiteSpace: 'nowrap',\n }}\n data-vdev-overlay=\"label\"\n >\n {lineInfo}\n </div>\n )}\n </>\n );\n};\n","/**\n * Source Location Detection Utilities\n * Reference implementation based on:\n * https://github.com/benjitaylor/agentation/blob/main/package/src/utils/source-location.ts\n */\n\nexport interface SourceLocation {\n fileName: string;\n lineNumber: number;\n columnNumber: number;\n componentName?: string;\n}\n\n/**\n * React Fiber node structure (partial)\n */\ninterface ReactFiber {\n _debugSource?: {\n fileName: string;\n lineNumber: number;\n columnNumber?: number;\n };\n _debugOwner?: ReactFiber;\n _debugInfo?: any; // React 19 specific\n type?: {\n displayName?: string;\n name?: string;\n } | string | any;\n tag?: number;\n return?: ReactFiber | null;\n memoizedProps?: Record<string, any>;\n pendingProps?: Record<string, any>;\n}\n\n/**\n * Gets the React fiber node associated with a DOM element\n */\nfunction getFiberFromElement(element: HTMLElement): ReactFiber | null {\n if (!element || typeof element !== \"object\") {\n return null;\n }\n\n const keys = Object.keys(element);\n\n // React 18+ uses __reactFiber$ prefix\n const fiberKey = keys.find((key) => key.startsWith(\"__reactFiber$\"));\n if (fiberKey) {\n return (element as any)[fiberKey];\n }\n\n // React 16-17 uses __reactInternalInstance$ prefix\n const instanceKey = keys.find((key) => key.startsWith(\"__reactInternalInstance$\"));\n if (instanceKey) {\n return (element as any)[instanceKey];\n }\n\n // React 19 may use different patterns - check for any fiber-like object\n // that contains _debugSource, or looks like a fiber\n const possibleFiberKey = keys.find((key) => {\n if (!key.startsWith(\"__react\")) return false;\n // Avoid known non-fiber keys\n if (key.startsWith(\"__reactContainer\") || key.startsWith(\"__reactProps\") || key.startsWith(\"__reactEvents\")) return false;\n\n const value = (element as any)[key];\n return value && typeof value === \"object\" &&\n (\"_debugSource\" in value || \"tag\" in value || \"return\" in value);\n });\n\n if (possibleFiberKey) {\n return (element as any)[possibleFiberKey];\n }\n\n return null;\n}\n\n/**\n * Gets the display name of a React component from its fiber\n */\nfunction getComponentName(fiber: ReactFiber): string | null {\n if (!fiber.type) return null;\n if (typeof fiber.type === \"string\") return null;\n\n if (typeof fiber.type === \"object\" || typeof fiber.type === \"function\") {\n return fiber.type.displayName || fiber.type.name || null;\n }\n return null;\n}\n\n/**\n * Walks up the fiber tree to find the nearest component with _debugSource\n * (Standard React 16-18)\n */\nfunction findDebugSource(fiber: ReactFiber, maxDepth = 50): { source: NonNullable<ReactFiber[\"_debugSource\"]>; componentName: string | null } | null {\n let current: ReactFiber | null | undefined = fiber;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n if (current._debugSource) {\n return {\n source: current._debugSource,\n componentName: getComponentName(current),\n };\n }\n\n if (current._debugOwner?._debugSource) {\n return {\n source: current._debugOwner._debugSource,\n componentName: getComponentName(current._debugOwner),\n };\n }\n\n current = current.return;\n depth++;\n }\n\n return null;\n}\n\n/**\n * Attempts to find source location using React 19's potentially different structure\n * or alternative build tool injections\n */\nfunction findDebugSourceReact19(fiber: ReactFiber): { source: NonNullable<ReactFiber[\"_debugSource\"]>; componentName: string | null } | null {\n let current: ReactFiber | null | undefined = fiber;\n let depth = 0;\n const maxDepth = 50;\n\n while (current && depth < maxDepth) {\n const anyFiber = current as any;\n\n // 1. Check for valid keys on the fiber itself\n const possibleSourceKeys = [\"_debugSource\", \"__source\", \"_source\", \"debugSource\", \"_debugInfo\"];\n for (const key of possibleSourceKeys) {\n const source = anyFiber[key];\n if (source) {\n // Handle standard object with fileName\n if (typeof source === \"object\" && typeof source.fileName === 'string') {\n return {\n source: source,\n componentName: getComponentName(current),\n };\n }\n // Handle React 19 _debugInfo array\n if (Array.isArray(source)) {\n for (const info of source) {\n if (info && typeof info.fileName === 'string') {\n return {\n source: info,\n componentName: getComponentName(current)\n };\n }\n }\n }\n }\n }\n\n // 2. Check memoizedProps/pendingProps for injected __source\n const props = current.memoizedProps || current.pendingProps;\n if (props && typeof props === 'object') {\n if (props.__source && typeof props.__source === 'object' && props.__source.fileName) {\n return {\n source: props.__source as any,\n componentName: getComponentName(current)\n };\n }\n }\n\n current = current.return;\n depth++;\n }\n\n return null;\n}\n\n/**\n * Parse the data-vdev-source attribute value (Legacy/Fallback)\n */\nexport function parseSourceAttr(attrValue: string | null): SourceLocation | null {\n if (!attrValue) return null;\n try {\n // Try parsing JSON first\n if (attrValue.startsWith('{')) {\n const parsed = JSON.parse(attrValue);\n if (parsed.fileName && typeof parsed.lineNumber === 'number') {\n return parsed as SourceLocation;\n }\n }\n } catch { }\n return null;\n}\n\n/**\n * Main function to get source location from an element\n * Combines Fiber inspection and data attribute fallbacks\n */\nexport function getSourceFromElement(element: HTMLElement, prefix = 'vdev'): SourceLocation | null {\n // 1. Try React Fiber (Runtime)\n const fiber = getFiberFromElement(element);\n if (fiber) {\n // Try standard strategy\n let result = findDebugSource(fiber);\n\n // Try React 19 strategy if standard failed\n if (!result) {\n result = findDebugSourceReact19(fiber);\n }\n\n if (result) {\n return {\n fileName: result.source.fileName,\n lineNumber: result.source.lineNumber,\n columnNumber: result.source.columnNumber || 1,\n componentName: result.componentName || undefined\n };\n }\n }\n\n // 2. Fallback: Data attributes (Build-time plugin)\n // Check for explicit individual attributes from vite-plugin\n const file = element.getAttribute(`data-${prefix}-file`);\n const line = element.getAttribute(`data-${prefix}-line`);\n const col = element.getAttribute(`data-${prefix}-col`);\n\n if (file && line) {\n return {\n fileName: file,\n lineNumber: parseInt(line, 10),\n columnNumber: col ? parseInt(col, 10) : 1,\n componentName: element.tagName.toLowerCase() // Simple fallback\n };\n }\n\n return null;\n}\n\n/**\n * Find the closest element with source information\n */\nexport function findSourceElement(target: HTMLElement, prefix = 'vdev'): HTMLElement | null {\n let current: HTMLElement | null = target;\n\n // Check up to Body\n while (current && current !== document.body) {\n // Check if this element has source info via Fiber OR Attributes\n if (getSourceFromElement(current, prefix)) {\n return current;\n }\n current = current.parentElement;\n }\n\n return null;\n}\n","import type { VDevMessage } from '../types';\n\nconst MESSAGE_SOURCE = 'vdev-react-sdk';\n\n/**\n * Send a message to the Chrome extension via window.postMessage\n */\nexport function sendToExtension(message: VDevMessage): void {\n window.postMessage(\n { ...message, source: MESSAGE_SOURCE },\n '*'\n );\n}\n\n/**\n * Notify extension that SDK is ready\n */\nexport function notifyReady(): void {\n sendToExtension({ type: 'VDEV_SDK_READY' });\n}\n\n/**\n * Create a message handler that only processes messages from the extension\n */\nexport function createMessageHandler(\n handler: (message: VDevMessage) => void\n): (event: MessageEvent) => void {\n return (event: MessageEvent) => {\n // Only process messages from the same window\n if (event.source !== window) return;\n\n // Only process messages from extension (not from SDK itself)\n if (event.data?.source === MESSAGE_SOURCE) return;\n\n // Process VDEV messages\n if (event.data?.type?.startsWith('VDEV_')) {\n handler(event.data as VDevMessage);\n }\n };\n}\n"],"mappings":";AAAA;AAAA,EACI;AAAA,EACA;AAAA,EACA,YAAAA;AAAA,EACA;AAAA,EACA,aAAAC;AAAA,OAEG;;;ACPP,SAAgB,WAAW,gBAAgB;AAoCnC;AA1BD,IAAM,cAA+B,CAAC;AAAA,EACzC;AAAA,EACA,QAAQ;AACZ,MAAM;AACF,QAAM,CAAC,MAAM,OAAO,IAAI,SAAyB,IAAI;AAErD,YAAU,MAAM;AACZ,UAAM,SAAS,MAAM,QAAQ,QAAQ,sBAAsB,CAAC;AAC5D,WAAO;AAEP,UAAM,WAAW,IAAI,eAAe,MAAM;AAC1C,aAAS,QAAQ,OAAO;AAExB,WAAO,iBAAiB,UAAU,QAAQ,IAAI;AAC9C,WAAO,iBAAiB,UAAU,MAAM;AAExC,WAAO,MAAM;AACT,eAAS,WAAW;AACpB,aAAO,oBAAoB,UAAU,QAAQ,IAAI;AACjD,aAAO,oBAAoB,UAAU,MAAM;AAAA,IAC/C;AAAA,EACJ,GAAG,CAAC,OAAO,CAAC;AAEZ,MAAI,CAAC,KAAM,QAAO;AAElB,SACI;AAAA,IAAC;AAAA;AAAA,MACG,OAAO;AAAA,QACH,UAAU;AAAA,QACV,KAAK,KAAK;AAAA,QACV,MAAM,KAAK;AAAA,QACX,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,iBAAiB;AAAA,QACjB,QAAQ;AAAA,QACR,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,YAAY;AAAA,QACZ,WAAW;AAAA,MACf;AAAA,MACA,qBAAkB;AAAA;AAAA,EACtB;AAER;;;ACrDA,SAAgB,aAAAC,YAAW,YAAAC,iBAAgB;;;ACqC3C,SAAS,oBAAoB,SAAyC;AAClE,MAAI,CAAC,WAAW,OAAO,YAAY,UAAU;AACzC,WAAO;AAAA,EACX;AAEA,QAAM,OAAO,OAAO,KAAK,OAAO;AAGhC,QAAM,WAAW,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,eAAe,CAAC;AACnE,MAAI,UAAU;AACV,WAAQ,QAAgB,QAAQ;AAAA,EACpC;AAGA,QAAM,cAAc,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,0BAA0B,CAAC;AACjF,MAAI,aAAa;AACb,WAAQ,QAAgB,WAAW;AAAA,EACvC;AAIA,QAAM,mBAAmB,KAAK,KAAK,CAAC,QAAQ;AACxC,QAAI,CAAC,IAAI,WAAW,SAAS,EAAG,QAAO;AAEvC,QAAI,IAAI,WAAW,kBAAkB,KAAK,IAAI,WAAW,cAAc,KAAK,IAAI,WAAW,eAAe,EAAG,QAAO;AAEpH,UAAM,QAAS,QAAgB,GAAG;AAClC,WAAO,SAAS,OAAO,UAAU,aAC5B,kBAAkB,SAAS,SAAS,SAAS,YAAY;AAAA,EAClE,CAAC;AAED,MAAI,kBAAkB;AAClB,WAAQ,QAAgB,gBAAgB;AAAA,EAC5C;AAEA,SAAO;AACX;AAKA,SAAS,iBAAiB,OAAkC;AACxD,MAAI,CAAC,MAAM,KAAM,QAAO;AACxB,MAAI,OAAO,MAAM,SAAS,SAAU,QAAO;AAE3C,MAAI,OAAO,MAAM,SAAS,YAAY,OAAO,MAAM,SAAS,YAAY;AACpE,WAAO,MAAM,KAAK,eAAe,MAAM,KAAK,QAAQ;AAAA,EACxD;AACA,SAAO;AACX;AAMA,SAAS,gBAAgB,OAAmB,WAAW,IAA8F;AACjJ,MAAI,UAAyC;AAC7C,MAAI,QAAQ;AAEZ,SAAO,WAAW,QAAQ,UAAU;AAChC,QAAI,QAAQ,cAAc;AACtB,aAAO;AAAA,QACH,QAAQ,QAAQ;AAAA,QAChB,eAAe,iBAAiB,OAAO;AAAA,MAC3C;AAAA,IACJ;AAEA,QAAI,QAAQ,aAAa,cAAc;AACnC,aAAO;AAAA,QACH,QAAQ,QAAQ,YAAY;AAAA,QAC5B,eAAe,iBAAiB,QAAQ,WAAW;AAAA,MACvD;AAAA,IACJ;AAEA,cAAU,QAAQ;AAClB;AAAA,EACJ;AAEA,SAAO;AACX;AAMA,SAAS,uBAAuB,OAA6G;AACzI,MAAI,UAAyC;AAC7C,MAAI,QAAQ;AACZ,QAAM,WAAW;AAEjB,SAAO,WAAW,QAAQ,UAAU;AAChC,UAAM,WAAW;AAGjB,UAAM,qBAAqB,CAAC,gBAAgB,YAAY,WAAW,eAAe,YAAY;AAC9F,eAAW,OAAO,oBAAoB;AAClC,YAAM,SAAS,SAAS,GAAG;AAC3B,UAAI,QAAQ;AAER,YAAI,OAAO,WAAW,YAAY,OAAO,OAAO,aAAa,UAAU;AACnE,iBAAO;AAAA,YACH;AAAA,YACA,eAAe,iBAAiB,OAAO;AAAA,UAC3C;AAAA,QACJ;AAEA,YAAI,MAAM,QAAQ,MAAM,GAAG;AACvB,qBAAW,QAAQ,QAAQ;AACvB,gBAAI,QAAQ,OAAO,KAAK,aAAa,UAAU;AAC3C,qBAAO;AAAA,gBACH,QAAQ;AAAA,gBACR,eAAe,iBAAiB,OAAO;AAAA,cAC3C;AAAA,YACJ;AAAA,UACJ;AAAA,QACJ;AAAA,MACJ;AAAA,IACJ;AAGA,UAAM,QAAQ,QAAQ,iBAAiB,QAAQ;AAC/C,QAAI,SAAS,OAAO,UAAU,UAAU;AACpC,UAAI,MAAM,YAAY,OAAO,MAAM,aAAa,YAAY,MAAM,SAAS,UAAU;AACjF,eAAO;AAAA,UACH,QAAQ,MAAM;AAAA,UACd,eAAe,iBAAiB,OAAO;AAAA,QAC3C;AAAA,MACJ;AAAA,IACJ;AAEA,cAAU,QAAQ;AAClB;AAAA,EACJ;AAEA,SAAO;AACX;AAKO,SAAS,gBAAgB,WAAiD;AAC7E,MAAI,CAAC,UAAW,QAAO;AACvB,MAAI;AAEA,QAAI,UAAU,WAAW,GAAG,GAAG;AAC3B,YAAM,SAAS,KAAK,MAAM,SAAS;AACnC,UAAI,OAAO,YAAY,OAAO,OAAO,eAAe,UAAU;AAC1D,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ,QAAQ;AAAA,EAAE;AACV,SAAO;AACX;AAMO,SAAS,qBAAqB,SAAsB,SAAS,QAA+B;AAE/F,QAAM,QAAQ,oBAAoB,OAAO;AACzC,MAAI,OAAO;AAEP,QAAI,SAAS,gBAAgB,KAAK;AAGlC,QAAI,CAAC,QAAQ;AACT,eAAS,uBAAuB,KAAK;AAAA,IACzC;AAEA,QAAI,QAAQ;AACR,aAAO;AAAA,QACH,UAAU,OAAO,OAAO;AAAA,QACxB,YAAY,OAAO,OAAO;AAAA,QAC1B,cAAc,OAAO,OAAO,gBAAgB;AAAA,QAC5C,eAAe,OAAO,iBAAiB;AAAA,MAC3C;AAAA,IACJ;AAAA,EACJ;AAIA,QAAM,OAAO,QAAQ,aAAa,QAAQ,MAAM,OAAO;AACvD,QAAM,OAAO,QAAQ,aAAa,QAAQ,MAAM,OAAO;AACvD,QAAM,MAAM,QAAQ,aAAa,QAAQ,MAAM,MAAM;AAErD,MAAI,QAAQ,MAAM;AACd,WAAO;AAAA,MACH,UAAU;AAAA,MACV,YAAY,SAAS,MAAM,EAAE;AAAA,MAC7B,cAAc,MAAM,SAAS,KAAK,EAAE,IAAI;AAAA,MACxC,eAAe,QAAQ,QAAQ,YAAY;AAAA;AAAA,IAC/C;AAAA,EACJ;AAEA,SAAO;AACX;AAKO,SAAS,kBAAkB,QAAqB,SAAS,QAA4B;AACxF,MAAI,UAA8B;AAGlC,SAAO,WAAW,YAAY,SAAS,MAAM;AAEzC,QAAI,qBAAqB,SAAS,MAAM,GAAG;AACvC,aAAO;AAAA,IACX;AACA,cAAU,QAAQ;AAAA,EACtB;AAEA,SAAO;AACX;;;ADhNQ,mBAEI,OAAAC,MAFJ;AA/BD,IAAM,eAAgC,CAAC,EAAE,SAAS,SAAS,OAAO,MAAM;AAC3E,QAAM,CAAC,MAAM,OAAO,IAAIC,UAAyB,IAAI;AACrD,QAAM,CAAC,QAAQ,SAAS,IAAIA,UAAgC,IAAI;AAEhE,EAAAC,WAAU,MAAM;AACZ,UAAM,SAAS,MAAM,QAAQ,QAAQ,sBAAsB,CAAC;AAC5D,WAAO;AAGP,cAAU,qBAAqB,SAAS,MAAM,CAAC;AAE/C,UAAM,WAAW,IAAI,eAAe,MAAM;AAC1C,aAAS,QAAQ,OAAO;AAExB,WAAO,iBAAiB,UAAU,QAAQ,IAAI;AAC9C,WAAO,iBAAiB,UAAU,MAAM;AAExC,WAAO,MAAM;AACT,eAAS,WAAW;AACpB,aAAO,oBAAoB,UAAU,QAAQ,IAAI;AACjD,aAAO,oBAAoB,UAAU,MAAM;AAAA,IAC/C;AAAA,EACJ,GAAG,CAAC,SAAS,MAAM,CAAC;AAEpB,MAAI,CAAC,KAAM,QAAO;AAGlB,QAAM,WAAW,QAAQ,SAAS,MAAM,GAAG,EAAE,IAAI,KAAK;AACtD,QAAM,WAAW,SAAS,GAAG,QAAQ,IAAI,OAAO,UAAU,KAAK;AAE/D,SACI,iCAEI;AAAA,oBAAAF;AAAA,MAAC;AAAA;AAAA,QACG,OAAO;AAAA,UACH,UAAU;AAAA,UACV,KAAK,KAAK;AAAA,UACV,MAAM,KAAK;AAAA,UACX,OAAO,KAAK;AAAA,UACZ,QAAQ,KAAK;AAAA,UACb,QAAQ;AAAA,UACR,iBAAiB;AAAA,UACjB,eAAe;AAAA,UACf,QAAQ;AAAA,UACR,WAAW;AAAA,QACf;AAAA,QACA,qBAAkB;AAAA;AAAA,IACtB;AAAA,IAGC,YACG,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACG,OAAO;AAAA,UACH,UAAU;AAAA,UACV,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE;AAAA,UAC9B,MAAM,KAAK;AAAA,UACX,iBAAiB;AAAA,UACjB,OAAO;AAAA,UACP,UAAU;AAAA,UACV,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,cAAc;AAAA,UACd,eAAe;AAAA,UACf,QAAQ;AAAA,UACR,YAAY;AAAA,QAChB;AAAA,QACA,qBAAkB;AAAA,QAEjB;AAAA;AAAA,IACL;AAAA,KAER;AAER;;;AEnFA,IAAM,iBAAiB;AAKhB,SAAS,gBAAgB,SAA4B;AACxD,SAAO;AAAA,IACH,EAAE,GAAG,SAAS,QAAQ,eAAe;AAAA,IACrC;AAAA,EACJ;AACJ;AAKO,SAAS,cAAoB;AAChC,kBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9C;AAKO,SAAS,qBACZ,SAC6B;AAC7B,SAAO,CAAC,UAAwB;AAE5B,QAAI,MAAM,WAAW,OAAQ;AAG7B,QAAI,MAAM,MAAM,WAAW,eAAgB;AAG3C,QAAI,MAAM,MAAM,MAAM,WAAW,OAAO,GAAG;AACvC,cAAQ,MAAM,IAAmB;AAAA,IACrC;AAAA,EACJ;AACJ;;;AJkIe,qBAAAG,WAAA,OAAAC,MAIP,QAAAC,aAJO;AAnJf,IAAM,kBAAkB,cAA2C,IAAI;AAEhE,IAAM,cAAc,MAAM;AAC7B,QAAM,UAAU,WAAW,eAAe;AAC1C,MAAI,CAAC,SAAS;AACV,UAAM,IAAI,MAAM,oDAAoD;AAAA,EACxE;AACA,SAAO;AACX;AAUO,IAAM,mBAAoD,CAAC;AAAA,EAC9D;AAAA,EACA,UAAU;AAAA,EACV,SAAS;AACb,MAAM;AACF,QAAM,CAAC,cAAc,aAAa,IAAIC,UAAS,KAAK;AACpD,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAA6B,IAAI;AAC7E,QAAM,CAAC,iBAAiB,kBAAkB,IAAIA,UAA6B,IAAI;AAC/E,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAgC,IAAI;AAEhF,QAAM,iBAAiB,YAAY,MAAM;AACrC,uBAAmB,IAAI;AACvB,sBAAkB,IAAI;AAAA,EAC1B,GAAG,CAAC,CAAC;AAGL,EAAAC,WAAU,MAAM;AACZ,QAAI,CAAC,QAAS;AAEd,UAAM,UAAU,qBAAqB,CAAC,YAAyB;AAC3D,cAAQ,IAAI,gCAAgC,OAAO;AACnD,UAAI,QAAQ,SAAS,sBAAsB;AACvC,gBAAQ,IAAI,gCAAgC;AAC5C,sBAAc,IAAI;AAClB,uBAAe;AAAA,MACnB,WAAW,QAAQ,SAAS,qBAAqB;AAC7C,gBAAQ,IAAI,gCAAgC;AAC5C,sBAAc,KAAK;AACnB,0BAAkB,IAAI;AAAA,MAC1B,WAAW,QAAQ,SAAS,uBAAuB;AAC/C,gBAAQ,IAAI,gCAAgC;AAC5C,sBAAc,UAAQ;AAClB,gBAAM,WAAW,CAAC;AAClB,cAAI,UAAU;AAEV,2BAAe;AAAA,UACnB,OAAO;AAEH,8BAAkB,IAAI;AAAA,UAC1B;AAEA,0BAAgB;AAAA,YACZ,MAAM;AAAA,YACN,SAAS,EAAE,cAAc,SAAS;AAAA,UACtC,CAAC;AACD,iBAAO;AAAA,QACX,CAAC;AAAA,MACL,WAAW,QAAQ,SAAS,wBAAwB;AAChD,uBAAe;AAAA,MACnB;AAAA,IACJ,CAAC;AAED,WAAO,iBAAiB,WAAW,OAAO;AAG1C,gBAAY;AACZ,YAAQ,IAAI,8CAA8C;AAE1D,WAAO,MAAM,OAAO,oBAAoB,WAAW,OAAO;AAAA,EAC9D,GAAG,CAAC,SAAS,cAAc,CAAC;AAG5B,EAAAA,WAAU,MAAM;AACZ,QAAI,CAAC,gBAAgB,CAAC,QAAS;AAE/B,UAAM,kBAAkB,CAAC,MAAkB;AACvC,YAAM,SAAS,EAAE;AAGjB,UAAI,OAAO,aAAa,mBAAmB,EAAG;AAE9C,YAAM,gBAAgB,kBAAkB,QAAQ,MAAM;AAGtD,UAAI,iBAAiB,kBAAkB,gBAAgB;AACnD,gBAAQ,IAAI,qCAAqC,aAAa;AAC9D,0BAAkB,aAAa;AAAA,MACnC;AAAA,IACJ;AAEA,UAAM,cAAc,CAAC,MAAkB;AACnC,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAElB,YAAM,SAAS,EAAE;AAGjB,UAAI,OAAO,aAAa,mBAAmB,EAAG;AAE9C,YAAM,gBAAgB,kBAAkB,QAAQ,MAAM;AAEtD,UAAI,eAAe;AACf,cAAM,SAAS,qBAAqB,eAAe,MAAM;AACzD,2BAAmB,aAAa;AAChC,0BAAkB,MAAM;AACxB,sBAAc,KAAK;AACnB,0BAAkB,IAAI;AAGtB,wBAAgB;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA,YACL;AAAA,YACA,aAAa;AAAA,cACT,SAAS,cAAc,QAAQ,YAAY;AAAA,cAC3C,WAAW,cAAc;AAAA,cACzB,aAAa,cAAc,aAAa,MAAM,GAAG,GAAG,KAAK;AAAA,YAC7D;AAAA,UACJ;AAAA,QACJ,CAAC;AAAA,MACL;AAAA,IACJ;AAGA,aAAS,iBAAiB,aAAa,iBAAiB,IAAI;AAC5D,aAAS,iBAAiB,SAAS,aAAa,IAAI;AAGpD,aAAS,KAAK,MAAM,SAAS;AAE7B,WAAO,MAAM;AACT,eAAS,oBAAoB,aAAa,iBAAiB,IAAI;AAC/D,eAAS,oBAAoB,SAAS,aAAa,IAAI;AACvD,eAAS,KAAK,MAAM,SAAS;AAAA,IACjC;AAAA,EACJ,GAAG,CAAC,cAAc,SAAS,gBAAgB,MAAM,CAAC;AAGlD,MAAI,CAAC,SAAS;AACV,WAAO,gBAAAH,KAAAD,WAAA,EAAG,UAAS;AAAA,EACvB;AAEA,SACI,gBAAAE;AAAA,IAAC,gBAAgB;AAAA,IAAhB;AAAA,MACG,OAAO;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACJ;AAAA,MAEC;AAAA;AAAA,QAGA,gBAAgB,kBACb,gBAAAD,KAAC,eAAY,SAAS,gBAAgB;AAAA,QAIzC,mBACG,gBAAAA,KAAC,gBAAa,SAAS,iBAAiB,QAAgB;AAAA;AAAA;AAAA,EAEhE;AAER;","names":["useState","useEffect","useEffect","useState","jsx","useState","useEffect","Fragment","jsx","jsxs","useState","useEffect"]}
@@ -0,0 +1,19 @@
1
+ import * as rollup from 'rollup';
2
+ import * as _unplugin from 'unplugin';
3
+
4
+ interface VdevPluginOptions {
5
+ /** Prefix for the data attribute (default: 'vdev') */
6
+ prefix?: string;
7
+ /** File patterns to include (default: /\.[jt]sx$/) */
8
+ include?: RegExp[] | string[];
9
+ /** File patterns to exclude (default: [/node_modules/]) */
10
+ exclude?: RegExp[] | string[];
11
+ }
12
+ declare const unplugin: _unplugin.UnpluginInstance<VdevPluginOptions | undefined, boolean>;
13
+ declare const vitePlugin: (options?: VdevPluginOptions | undefined) => _unplugin.VitePlugin<any> | _unplugin.VitePlugin<any>[];
14
+ declare const rollupPlugin: (options?: VdevPluginOptions | undefined) => rollup.Plugin<any> | rollup.Plugin<any>[];
15
+ declare const webpackPlugin: (options?: VdevPluginOptions | undefined) => WebpackPluginInstance;
16
+ declare const rspackPlugin: (options?: VdevPluginOptions | undefined) => RspackPluginInstance;
17
+ declare const esbuildPlugin: (options?: VdevPluginOptions | undefined) => _unplugin.EsbuildPlugin;
18
+
19
+ export { type VdevPluginOptions, esbuildPlugin, rollupPlugin, rspackPlugin, unplugin, vitePlugin, webpackPlugin };
@@ -0,0 +1,19 @@
1
+ import * as rollup from 'rollup';
2
+ import * as _unplugin from 'unplugin';
3
+
4
+ interface VdevPluginOptions {
5
+ /** Prefix for the data attribute (default: 'vdev') */
6
+ prefix?: string;
7
+ /** File patterns to include (default: /\.[jt]sx$/) */
8
+ include?: RegExp[] | string[];
9
+ /** File patterns to exclude (default: [/node_modules/]) */
10
+ exclude?: RegExp[] | string[];
11
+ }
12
+ declare const unplugin: _unplugin.UnpluginInstance<VdevPluginOptions | undefined, boolean>;
13
+ declare const vitePlugin: (options?: VdevPluginOptions | undefined) => _unplugin.VitePlugin<any> | _unplugin.VitePlugin<any>[];
14
+ declare const rollupPlugin: (options?: VdevPluginOptions | undefined) => rollup.Plugin<any> | rollup.Plugin<any>[];
15
+ declare const webpackPlugin: (options?: VdevPluginOptions | undefined) => WebpackPluginInstance;
16
+ declare const rspackPlugin: (options?: VdevPluginOptions | undefined) => RspackPluginInstance;
17
+ declare const esbuildPlugin: (options?: VdevPluginOptions | undefined) => _unplugin.EsbuildPlugin;
18
+
19
+ export { type VdevPluginOptions, esbuildPlugin, rollupPlugin, rspackPlugin, unplugin, vitePlugin, webpackPlugin };
@@ -27,26 +27,31 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
27
27
  ));
28
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
29
 
30
- // src/vite-plugin/jsx-source.ts
30
+ // src/unplugin/jsx-source.ts
31
31
  var jsx_source_exports = {};
32
32
  __export(jsx_source_exports, {
33
- default: () => jsx_source_default,
34
- vdevJsxSource: () => vdevJsxSource
33
+ esbuildPlugin: () => esbuildPlugin,
34
+ rollupPlugin: () => rollupPlugin,
35
+ rspackPlugin: () => rspackPlugin,
36
+ unplugin: () => unplugin,
37
+ vitePlugin: () => vitePlugin,
38
+ webpackPlugin: () => webpackPlugin
35
39
  });
36
40
  module.exports = __toCommonJS(jsx_source_exports);
41
+ var import_unplugin = require("unplugin");
42
+ var import_pluginutils = require("@rollup/pluginutils");
37
43
  var import_magic_string = __toESM(require("magic-string"));
38
- function vdevJsxSource(options = {}) {
44
+ var unplugin = (0, import_unplugin.createUnplugin)((options = {}) => {
39
45
  const prefix = options.prefix || "vdev";
40
- const exclude = options.exclude || [/node_modules/];
46
+ const filter = (0, import_pluginutils.createFilter)(
47
+ options.include || [/\.[jt]sx$/],
48
+ options.exclude || [/node_modules/]
49
+ );
41
50
  return {
42
51
  name: "vdev-jsx-source",
43
- // Use 'post' to run after other transforms, avoiding HMR issues
44
52
  enforce: "post",
45
53
  transform(code, id) {
46
- if (exclude.some((pattern) => pattern.test(id))) {
47
- return null;
48
- }
49
- if (!/\.[jt]sx$/.test(id)) {
54
+ if (!filter(id)) {
50
55
  return null;
51
56
  }
52
57
  if (!code.includes("jsx(") && !code.includes("jsxs(") && !code.includes("jsxDEV(")) {
@@ -55,7 +60,6 @@ function vdevJsxSource(options = {}) {
55
60
  const magicString = new import_magic_string.default(code);
56
61
  let modified = false;
57
62
  const jsxCallRegex = /\b(jsx|jsxs|jsxDEV)\s*\(\s*(?:"([^"]+)"|'([^']+)'|([A-Z][a-zA-Z0-9_$.]*)|([a-z][a-zA-Z0-9_]*))\s*,\s*\{/g;
58
- const lines = code.split("\n");
59
63
  const getLineCol = (index) => {
60
64
  let line = 1;
61
65
  let lastNewline = -1;
@@ -70,12 +74,16 @@ function vdevJsxSource(options = {}) {
70
74
  let match;
71
75
  while ((match = jsxCallRegex.exec(code)) !== null) {
72
76
  const openBraceIndex = match.index + match[0].length - 1;
77
+ const componentName = match[4] || match[5];
78
+ if (componentName && (componentName === "Fragment" || componentName === "React.Fragment")) {
79
+ continue;
80
+ }
73
81
  const { line, col } = getLineCol(match.index);
74
82
  const nextChars = code.slice(openBraceIndex + 1, openBraceIndex + 100);
75
83
  if (nextChars.includes(`"data-${prefix}-file"`)) {
76
84
  continue;
77
85
  }
78
- const injection = `"data-${prefix}-file": "${id}", "data-${prefix}-line": "${line}", "data-${prefix}-col": "${col}", `;
86
+ const injection = `"data-${prefix}-file": ${JSON.stringify(id)}, "data-${prefix}-line": "${line}", "data-${prefix}-col": "${col}", `;
79
87
  magicString.appendLeft(openBraceIndex + 1, injection);
80
88
  modified = true;
81
89
  }
@@ -84,14 +92,23 @@ function vdevJsxSource(options = {}) {
84
92
  }
85
93
  return {
86
94
  code: magicString.toString(),
87
- map: magicString.generateMap({ hires: true })
95
+ map: magicString.generateMap({ hires: true, source: id })
88
96
  };
89
97
  }
90
98
  };
91
- }
92
- var jsx_source_default = vdevJsxSource;
99
+ });
100
+ var vitePlugin = unplugin.vite;
101
+ var rollupPlugin = unplugin.rollup;
102
+ var webpackPlugin = unplugin.webpack;
103
+ var rspackPlugin = unplugin.rspack;
104
+ var esbuildPlugin = unplugin.esbuild;
93
105
  // Annotate the CommonJS export names for ESM import in node:
94
106
  0 && (module.exports = {
95
- vdevJsxSource
107
+ esbuildPlugin,
108
+ rollupPlugin,
109
+ rspackPlugin,
110
+ unplugin,
111
+ vitePlugin,
112
+ webpackPlugin
96
113
  });
97
114
  //# sourceMappingURL=jsx-source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/unplugin/jsx-source.ts"],"sourcesContent":["import { createUnplugin } from 'unplugin';\nimport { createFilter } from '@rollup/pluginutils';\nimport MagicString from 'magic-string';\n\nexport interface VdevPluginOptions {\n /** Prefix for the data attribute (default: 'vdev') */\n prefix?: string;\n /** File patterns to include (default: /\\.[jt]sx$/) */\n include?: RegExp[] | string[];\n /** File patterns to exclude (default: [/node_modules/]) */\n exclude?: RegExp[] | string[];\n}\n\nexport const unplugin = createUnplugin((options: VdevPluginOptions | undefined = {}) => {\n const prefix = options.prefix || 'vdev';\n const filter = createFilter(\n options.include || [/\\.[jt]sx$/],\n options.exclude || [/node_modules/]\n );\n\n return {\n name: 'vdev-jsx-source',\n enforce: 'post',\n\n transform(code: string, id: string) {\n if (!filter(id)) {\n return null;\n }\n\n // Skip if no JSX-like patterns (quick check)\n if (!code.includes('jsx(') && !code.includes('jsxs(') && !code.includes('jsxDEV(')) {\n return null;\n }\n\n const magicString = new MagicString(code);\n let modified = false;\n\n // Match jsx/jsxs/jsxDEV function calls\n // Pattern: jsx(\"tagName\", { props }) or jsx(Component, { props })\n const jsxCallRegex = /\\b(jsx|jsxs|jsxDEV)\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([A-Z][a-zA-Z0-9_$.]*)|([a-z][a-zA-Z0-9_]*))\\s*,\\s*\\{/g;\n\n // Simple line counting helper\n // Note: This could be optimized but serves for now\n const getLineCol = (index: number) => {\n let line = 1;\n let lastNewline = -1;\n for (let i = 0; i < index && i < code.length; i++) {\n if (code[i] === '\\n') {\n line++;\n lastNewline = i;\n }\n }\n return { line, col: index - lastNewline - 1 };\n };\n\n let match;\n while ((match = jsxCallRegex.exec(code)) !== null) {\n const openBraceIndex = match.index + match[0].length - 1;\n\n // Skip React Fragments (they don't support custom props)\n const componentName = match[4] || match[5]; // Capture group 4 is Capitalized, 5 is lowercase\n if (componentName && (componentName === 'Fragment' || componentName === 'React.Fragment')) {\n continue;\n }\n\n const { line, col } = getLineCol(match.index);\n\n // Check if already has our data attribute\n // Optimization: check next 100 chars\n const nextChars = code.slice(openBraceIndex + 1, openBraceIndex + 100);\n if (nextChars.includes(`\"data-${prefix}-file\"`)) {\n continue;\n }\n\n // Inject data attributes as first properties\n // We use JSON.stringify for the file path to ensure it's properly escaped\n const injection = `\"data-${prefix}-file\": ${JSON.stringify(id)}, \"data-${prefix}-line\": \"${line}\", \"data-${prefix}-col\": \"${col}\", `;\n\n magicString.appendLeft(openBraceIndex + 1, injection);\n modified = true;\n }\n\n if (!modified) {\n return null;\n }\n\n return {\n code: magicString.toString(),\n map: magicString.generateMap({ hires: true, source: id })\n };\n },\n };\n});\n\nexport const vitePlugin = unplugin.vite;\nexport const rollupPlugin = unplugin.rollup;\nexport const webpackPlugin = unplugin.webpack;\nexport const rspackPlugin = unplugin.rspack;\nexport const esbuildPlugin = unplugin.esbuild;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,sBAA+B;AAC/B,yBAA6B;AAC7B,0BAAwB;AAWjB,IAAM,eAAW,gCAAe,CAAC,UAAyC,CAAC,MAAM;AACpF,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,aAAS;AAAA,IACX,QAAQ,WAAW,CAAC,WAAW;AAAA,IAC/B,QAAQ,WAAW,CAAC,cAAc;AAAA,EACtC;AAEA,SAAO;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IAET,UAAU,MAAc,IAAY;AAChC,UAAI,CAAC,OAAO,EAAE,GAAG;AACb,eAAO;AAAA,MACX;AAGA,UAAI,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,KAAK,SAAS,OAAO,KAAK,CAAC,KAAK,SAAS,SAAS,GAAG;AAChF,eAAO;AAAA,MACX;AAEA,YAAM,cAAc,IAAI,oBAAAA,QAAY,IAAI;AACxC,UAAI,WAAW;AAIf,YAAM,eAAe;AAIrB,YAAM,aAAa,CAAC,UAAkB;AAClC,YAAI,OAAO;AACX,YAAI,cAAc;AAClB,iBAAS,IAAI,GAAG,IAAI,SAAS,IAAI,KAAK,QAAQ,KAAK;AAC/C,cAAI,KAAK,CAAC,MAAM,MAAM;AAClB;AACA,0BAAc;AAAA,UAClB;AAAA,QACJ;AACA,eAAO,EAAE,MAAM,KAAK,QAAQ,cAAc,EAAE;AAAA,MAChD;AAEA,UAAI;AACJ,cAAQ,QAAQ,aAAa,KAAK,IAAI,OAAO,MAAM;AAC/C,cAAM,iBAAiB,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AAGvD,cAAM,gBAAgB,MAAM,CAAC,KAAK,MAAM,CAAC;AACzC,YAAI,kBAAkB,kBAAkB,cAAc,kBAAkB,mBAAmB;AACvF;AAAA,QACJ;AAEA,cAAM,EAAE,MAAM,IAAI,IAAI,WAAW,MAAM,KAAK;AAI5C,cAAM,YAAY,KAAK,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;AACrE,YAAI,UAAU,SAAS,SAAS,MAAM,QAAQ,GAAG;AAC7C;AAAA,QACJ;AAIA,cAAM,YAAY,SAAS,MAAM,WAAW,KAAK,UAAU,EAAE,CAAC,WAAW,MAAM,YAAY,IAAI,YAAY,MAAM,WAAW,GAAG;AAE/H,oBAAY,WAAW,iBAAiB,GAAG,SAAS;AACpD,mBAAW;AAAA,MACf;AAEA,UAAI,CAAC,UAAU;AACX,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,QACH,MAAM,YAAY,SAAS;AAAA,QAC3B,KAAK,YAAY,YAAY,EAAE,OAAO,MAAM,QAAQ,GAAG,CAAC;AAAA,MAC5D;AAAA,IACJ;AAAA,EACJ;AACJ,CAAC;AAEM,IAAM,aAAa,SAAS;AAC5B,IAAM,eAAe,SAAS;AAC9B,IAAM,gBAAgB,SAAS;AAC/B,IAAM,eAAe,SAAS;AAC9B,IAAM,gBAAgB,SAAS;","names":["MagicString"]}
@@ -1,17 +1,18 @@
1
- // src/vite-plugin/jsx-source.ts
1
+ // src/unplugin/jsx-source.ts
2
+ import { createUnplugin } from "unplugin";
3
+ import { createFilter } from "@rollup/pluginutils";
2
4
  import MagicString from "magic-string";
3
- function vdevJsxSource(options = {}) {
5
+ var unplugin = createUnplugin((options = {}) => {
4
6
  const prefix = options.prefix || "vdev";
5
- const exclude = options.exclude || [/node_modules/];
7
+ const filter = createFilter(
8
+ options.include || [/\.[jt]sx$/],
9
+ options.exclude || [/node_modules/]
10
+ );
6
11
  return {
7
12
  name: "vdev-jsx-source",
8
- // Use 'post' to run after other transforms, avoiding HMR issues
9
13
  enforce: "post",
10
14
  transform(code, id) {
11
- if (exclude.some((pattern) => pattern.test(id))) {
12
- return null;
13
- }
14
- if (!/\.[jt]sx$/.test(id)) {
15
+ if (!filter(id)) {
15
16
  return null;
16
17
  }
17
18
  if (!code.includes("jsx(") && !code.includes("jsxs(") && !code.includes("jsxDEV(")) {
@@ -20,7 +21,6 @@ function vdevJsxSource(options = {}) {
20
21
  const magicString = new MagicString(code);
21
22
  let modified = false;
22
23
  const jsxCallRegex = /\b(jsx|jsxs|jsxDEV)\s*\(\s*(?:"([^"]+)"|'([^']+)'|([A-Z][a-zA-Z0-9_$.]*)|([a-z][a-zA-Z0-9_]*))\s*,\s*\{/g;
23
- const lines = code.split("\n");
24
24
  const getLineCol = (index) => {
25
25
  let line = 1;
26
26
  let lastNewline = -1;
@@ -35,12 +35,16 @@ function vdevJsxSource(options = {}) {
35
35
  let match;
36
36
  while ((match = jsxCallRegex.exec(code)) !== null) {
37
37
  const openBraceIndex = match.index + match[0].length - 1;
38
+ const componentName = match[4] || match[5];
39
+ if (componentName && (componentName === "Fragment" || componentName === "React.Fragment")) {
40
+ continue;
41
+ }
38
42
  const { line, col } = getLineCol(match.index);
39
43
  const nextChars = code.slice(openBraceIndex + 1, openBraceIndex + 100);
40
44
  if (nextChars.includes(`"data-${prefix}-file"`)) {
41
45
  continue;
42
46
  }
43
- const injection = `"data-${prefix}-file": "${id}", "data-${prefix}-line": "${line}", "data-${prefix}-col": "${col}", `;
47
+ const injection = `"data-${prefix}-file": ${JSON.stringify(id)}, "data-${prefix}-line": "${line}", "data-${prefix}-col": "${col}", `;
44
48
  magicString.appendLeft(openBraceIndex + 1, injection);
45
49
  modified = true;
46
50
  }
@@ -49,14 +53,22 @@ function vdevJsxSource(options = {}) {
49
53
  }
50
54
  return {
51
55
  code: magicString.toString(),
52
- map: magicString.generateMap({ hires: true })
56
+ map: magicString.generateMap({ hires: true, source: id })
53
57
  };
54
58
  }
55
59
  };
56
- }
57
- var jsx_source_default = vdevJsxSource;
60
+ });
61
+ var vitePlugin = unplugin.vite;
62
+ var rollupPlugin = unplugin.rollup;
63
+ var webpackPlugin = unplugin.webpack;
64
+ var rspackPlugin = unplugin.rspack;
65
+ var esbuildPlugin = unplugin.esbuild;
58
66
  export {
59
- jsx_source_default as default,
60
- vdevJsxSource
67
+ esbuildPlugin,
68
+ rollupPlugin,
69
+ rspackPlugin,
70
+ unplugin,
71
+ vitePlugin,
72
+ webpackPlugin
61
73
  };
62
74
  //# sourceMappingURL=jsx-source.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/unplugin/jsx-source.ts"],"sourcesContent":["import { createUnplugin } from 'unplugin';\nimport { createFilter } from '@rollup/pluginutils';\nimport MagicString from 'magic-string';\n\nexport interface VdevPluginOptions {\n /** Prefix for the data attribute (default: 'vdev') */\n prefix?: string;\n /** File patterns to include (default: /\\.[jt]sx$/) */\n include?: RegExp[] | string[];\n /** File patterns to exclude (default: [/node_modules/]) */\n exclude?: RegExp[] | string[];\n}\n\nexport const unplugin = createUnplugin((options: VdevPluginOptions | undefined = {}) => {\n const prefix = options.prefix || 'vdev';\n const filter = createFilter(\n options.include || [/\\.[jt]sx$/],\n options.exclude || [/node_modules/]\n );\n\n return {\n name: 'vdev-jsx-source',\n enforce: 'post',\n\n transform(code: string, id: string) {\n if (!filter(id)) {\n return null;\n }\n\n // Skip if no JSX-like patterns (quick check)\n if (!code.includes('jsx(') && !code.includes('jsxs(') && !code.includes('jsxDEV(')) {\n return null;\n }\n\n const magicString = new MagicString(code);\n let modified = false;\n\n // Match jsx/jsxs/jsxDEV function calls\n // Pattern: jsx(\"tagName\", { props }) or jsx(Component, { props })\n const jsxCallRegex = /\\b(jsx|jsxs|jsxDEV)\\s*\\(\\s*(?:\"([^\"]+)\"|'([^']+)'|([A-Z][a-zA-Z0-9_$.]*)|([a-z][a-zA-Z0-9_]*))\\s*,\\s*\\{/g;\n\n // Simple line counting helper\n // Note: This could be optimized but serves for now\n const getLineCol = (index: number) => {\n let line = 1;\n let lastNewline = -1;\n for (let i = 0; i < index && i < code.length; i++) {\n if (code[i] === '\\n') {\n line++;\n lastNewline = i;\n }\n }\n return { line, col: index - lastNewline - 1 };\n };\n\n let match;\n while ((match = jsxCallRegex.exec(code)) !== null) {\n const openBraceIndex = match.index + match[0].length - 1;\n\n // Skip React Fragments (they don't support custom props)\n const componentName = match[4] || match[5]; // Capture group 4 is Capitalized, 5 is lowercase\n if (componentName && (componentName === 'Fragment' || componentName === 'React.Fragment')) {\n continue;\n }\n\n const { line, col } = getLineCol(match.index);\n\n // Check if already has our data attribute\n // Optimization: check next 100 chars\n const nextChars = code.slice(openBraceIndex + 1, openBraceIndex + 100);\n if (nextChars.includes(`\"data-${prefix}-file\"`)) {\n continue;\n }\n\n // Inject data attributes as first properties\n // We use JSON.stringify for the file path to ensure it's properly escaped\n const injection = `\"data-${prefix}-file\": ${JSON.stringify(id)}, \"data-${prefix}-line\": \"${line}\", \"data-${prefix}-col\": \"${col}\", `;\n\n magicString.appendLeft(openBraceIndex + 1, injection);\n modified = true;\n }\n\n if (!modified) {\n return null;\n }\n\n return {\n code: magicString.toString(),\n map: magicString.generateMap({ hires: true, source: id })\n };\n },\n };\n});\n\nexport const vitePlugin = unplugin.vite;\nexport const rollupPlugin = unplugin.rollup;\nexport const webpackPlugin = unplugin.webpack;\nexport const rspackPlugin = unplugin.rspack;\nexport const esbuildPlugin = unplugin.esbuild;\n"],"mappings":";AAAA,SAAS,sBAAsB;AAC/B,SAAS,oBAAoB;AAC7B,OAAO,iBAAiB;AAWjB,IAAM,WAAW,eAAe,CAAC,UAAyC,CAAC,MAAM;AACpF,QAAM,SAAS,QAAQ,UAAU;AACjC,QAAM,SAAS;AAAA,IACX,QAAQ,WAAW,CAAC,WAAW;AAAA,IAC/B,QAAQ,WAAW,CAAC,cAAc;AAAA,EACtC;AAEA,SAAO;AAAA,IACH,MAAM;AAAA,IACN,SAAS;AAAA,IAET,UAAU,MAAc,IAAY;AAChC,UAAI,CAAC,OAAO,EAAE,GAAG;AACb,eAAO;AAAA,MACX;AAGA,UAAI,CAAC,KAAK,SAAS,MAAM,KAAK,CAAC,KAAK,SAAS,OAAO,KAAK,CAAC,KAAK,SAAS,SAAS,GAAG;AAChF,eAAO;AAAA,MACX;AAEA,YAAM,cAAc,IAAI,YAAY,IAAI;AACxC,UAAI,WAAW;AAIf,YAAM,eAAe;AAIrB,YAAM,aAAa,CAAC,UAAkB;AAClC,YAAI,OAAO;AACX,YAAI,cAAc;AAClB,iBAAS,IAAI,GAAG,IAAI,SAAS,IAAI,KAAK,QAAQ,KAAK;AAC/C,cAAI,KAAK,CAAC,MAAM,MAAM;AAClB;AACA,0BAAc;AAAA,UAClB;AAAA,QACJ;AACA,eAAO,EAAE,MAAM,KAAK,QAAQ,cAAc,EAAE;AAAA,MAChD;AAEA,UAAI;AACJ,cAAQ,QAAQ,aAAa,KAAK,IAAI,OAAO,MAAM;AAC/C,cAAM,iBAAiB,MAAM,QAAQ,MAAM,CAAC,EAAE,SAAS;AAGvD,cAAM,gBAAgB,MAAM,CAAC,KAAK,MAAM,CAAC;AACzC,YAAI,kBAAkB,kBAAkB,cAAc,kBAAkB,mBAAmB;AACvF;AAAA,QACJ;AAEA,cAAM,EAAE,MAAM,IAAI,IAAI,WAAW,MAAM,KAAK;AAI5C,cAAM,YAAY,KAAK,MAAM,iBAAiB,GAAG,iBAAiB,GAAG;AACrE,YAAI,UAAU,SAAS,SAAS,MAAM,QAAQ,GAAG;AAC7C;AAAA,QACJ;AAIA,cAAM,YAAY,SAAS,MAAM,WAAW,KAAK,UAAU,EAAE,CAAC,WAAW,MAAM,YAAY,IAAI,YAAY,MAAM,WAAW,GAAG;AAE/H,oBAAY,WAAW,iBAAiB,GAAG,SAAS;AACpD,mBAAW;AAAA,MACf;AAEA,UAAI,CAAC,UAAU;AACX,eAAO;AAAA,MACX;AAEA,aAAO;AAAA,QACH,MAAM,YAAY,SAAS;AAAA,QAC3B,KAAK,YAAY,YAAY,EAAE,OAAO,MAAM,QAAQ,GAAG,CAAC;AAAA,MAC5D;AAAA,IACJ;AAAA,EACJ;AACJ,CAAC;AAEM,IAAM,aAAa,SAAS;AAC5B,IAAM,eAAe,SAAS;AAC9B,IAAM,gBAAgB,SAAS;AAC/B,IAAM,eAAe,SAAS;AAC9B,IAAM,gBAAgB,SAAS;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@visual-agentic-dev/react-devtools",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "React DevTools SDK for Visual Agentic Dev - element source locating and highlight overlay",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,15 +11,10 @@
11
11
  "import": "./dist/index.mjs",
12
12
  "require": "./dist/index.js"
13
13
  },
14
- "./babel-plugin": {
15
- "types": "./dist/babel-plugin/jsx-source.d.ts",
16
- "import": "./dist/babel-plugin/jsx-source.mjs",
17
- "require": "./dist/babel-plugin/jsx-source.js"
18
- },
19
- "./vite-plugin": {
20
- "types": "./dist/vite-plugin/jsx-source.d.ts",
21
- "import": "./dist/vite-plugin/jsx-source.mjs",
22
- "require": "./dist/vite-plugin/jsx-source.js"
14
+ "./unplugin": {
15
+ "types": "./dist/unplugin/jsx-source.d.ts",
16
+ "import": "./dist/unplugin/jsx-source.mjs",
17
+ "require": "./dist/unplugin/jsx-source.js"
23
18
  }
24
19
  },
25
20
  "files": [
@@ -35,20 +30,19 @@
35
30
  "react": ">=17.0.0",
36
31
  "react-dom": ">=17.0.0"
37
32
  },
33
+ "dependencies": {
34
+ "@rollup/pluginutils": "^5.3.0",
35
+ "magic-string": "^0.30.0",
36
+ "unplugin": "^3.0.0"
37
+ },
38
38
  "devDependencies": {
39
- "@babel/core": "^7.24.0",
40
- "@babel/helper-plugin-utils": "^7.24.0",
41
- "@babel/types": "^7.24.0",
42
- "@types/babel__core": "^7.20.5",
43
- "@types/babel__helper-plugin-utils": "^7.10.0",
44
39
  "@types/react": "^18.2.0",
45
40
  "@types/react-dom": "^18.2.0",
46
41
  "react": "^18.2.0",
47
42
  "react-dom": "^18.2.0",
48
43
  "tsup": "^8.0.0",
49
44
  "typescript": "^5.3.0",
50
- "vite": "^5.0.0",
51
- "magic-string": "^0.30.0"
45
+ "vite": "^5.0.0"
52
46
  },
53
47
  "keywords": [
54
48
  "react",
@@ -1,12 +0,0 @@
1
- import * as _babel_core from '@babel/core';
2
- import { PluginObj } from '@babel/core';
3
-
4
- interface PluginOptions {
5
- /** Prefix for the data attribute (default: 'vdev') */
6
- prefix?: string;
7
- /** File patterns to exclude */
8
- exclude?: RegExp[];
9
- }
10
- declare const _default: (api: object, options: PluginOptions | null | undefined, dirname: string) => PluginObj<_babel_core.PluginPass>;
11
-
12
- export { _default as default };