vite-plugin-visual-selector 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -2
- package/dist/index.js +278 -178
- package/dist/index.js.map +1 -1
- package/dist/{runtime-CpZH1D8y.d.ts → runtime-D695qvel.d.ts} +9 -3
- package/dist/runtime.d.ts +1 -1
- package/dist/runtime.js +278 -178
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/plugin.ts","../src/shared/constants.ts","../src/runtime/utils.ts","../src/runtime/inline-edit.ts","../src/runtime/layer-navigation.ts","../src/runtime/messages.ts","../src/runtime/overlay.ts","../src/runtime/state.ts","../src/runtime/index.ts"],"sourcesContent":["import { parse } from '@babel/parser';\nimport _traverse from '@babel/traverse';\nimport * as t from '@babel/types';\n\n// 兼容 CJS/ESM:@babel/traverse 在不同模块系统下导出形式不同\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : (_traverse as { default: typeof _traverse }).default;\nimport MagicString from 'magic-string';\nimport path from 'node:path';\nimport type { Plugin } from 'vite';\n\nimport { DEFAULT_ATTRIBUTE_NAME } from './shared/constants';\nimport type { VisualSelectorPluginOptions } from './shared/types';\n\n/**\n * 将绝对路径转换为相对于项目根目录的 Unix 风格路径(用 `/` 分隔)。\n * 例如:/project/src/App.tsx → src/App.tsx\n */\nfunction toRelativeUnixPath(root: string, filePath: string) {\n return path.relative(root, filePath).split(path.sep).join('/');\n}\n\n/**\n * 判断 JSX 开标签是否为原生 HTML 元素(小写字母开头,如 <div>、<span>)。\n * 自定义组件(大写字母开头,如 <MyButton>)不注入属性,避免干扰组件 props。\n */\nfunction isIntrinsicElement(node: t.JSXOpeningElement) {\n return t.isJSXIdentifier(node.name) && /^[a-z]/.test(node.name.name);\n}\n\n/**\n * 检查 JSX 开标签是否已经带有指定属性名,避免重复注入(如手动写了 data-source-location 的情况)。\n */\nfunction hasSourceLocationAttribute(node: t.JSXOpeningElement, attributeName: string) {\n return node.attributes.some(\n (attribute) =>\n t.isJSXAttribute(attribute) &&\n t.isJSXIdentifier(attribute.name) &&\n attribute.name.name === attributeName,\n );\n}\n\n/**\n * 创建 Vite 插件:在编译阶段(transform hook)向每个原生 JSX 元素注入\n * `data-source-location=\"文件路径:行号:列号\"` 属性,使运行时可以追溯到源码位置。\n */\nexport function visualSelectorPlugin(options: VisualSelectorPluginOptions = {}): Plugin {\n const attributeName = options.attributeName ?? DEFAULT_ATTRIBUTE_NAME;\n const root = options.root ?? process.cwd();\n // 默认只处理 .jsx/.tsx/.js/.ts(含 x)文件\n const include = options.include ?? [/\\.[jt]sx$/];\n // 默认跳过 node_modules\n const exclude = options.exclude ?? [/node_modules/];\n\n return {\n name: 'vite-plugin-visual-selector',\n enforce: 'pre', // 在其他插件(如 @vitejs/plugin-react)之前运行,确保 JSX 还未被转译\n transform(code, id) {\n // 不在 include 列表中的文件直接跳过\n if (!include.some((pattern) => pattern.test(id))) {\n return null;\n }\n\n // 在 exclude 列表中的文件直接跳过\n if (exclude.some((pattern) => pattern.test(id))) {\n return null;\n }\n\n let ast;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n } catch {\n // 解析失败时返回原始代码,不阻断构建\n return null;\n }\n\n const magicString = new MagicString(code);\n let mutated = false;\n\n traverse(ast, {\n // 遍历 AST 中所有 JSX 开标签节点\n JSXOpeningElement(jsxPath) {\n const node = jsxPath.node;\n\n // 跳过自定义组件(非原生 HTML 标签)\n if (!isIntrinsicElement(node)) {\n return;\n }\n\n // 跳过已有该属性的节点\n if (hasSourceLocationAttribute(node, attributeName)) {\n return;\n }\n\n // 缺少位置信息时跳过(通常不会发生)\n if (!node.loc || node.name.end == null) {\n return;\n }\n\n // 生成 \"相对路径:行号:列号\" 格式的位置字符串(列号从 1 开始)\n const location = `${toRelativeUnixPath(root, id)}:${node.loc.start.line}:${node.loc.start.column + 1}`;\n // 在标签名结尾处(name.end)插入属性,如 <div → <div data-source-location=\"...\"\n magicString.appendLeft(node.name.end, ` ${attributeName}=\"${location}\"`);\n mutated = true;\n },\n });\n\n // 没有任何修改时返回 null,告诉 Vite 文件未变化,避免不必要的 sourcemap 开销\n if (!mutated) {\n return null;\n }\n\n return {\n code: magicString.toString(),\n map: magicString.generateMap({ hires: true }), // 高精度 sourcemap,保证调试准确\n };\n },\n };\n}\n","// 注入到 JSX 元素上的默认属性名,值为源码文件路径+行列号(如 \"src/App.tsx:12:3\")\nexport const DEFAULT_ATTRIBUTE_NAME = 'data-source-location';\n\n// 父窗口发往子窗口(iframe)的控制消息类型:开启/关闭高亮编辑模式\nexport const CONTROL_MESSAGE_TYPE = 'visual-selector:set-active';\n\n// agent 自己创建的 DOM 元素标记属性,用于排除冻结和 pointer-events 禁用\nexport const AGENT_ATTR = 'data-vite-plugin-element';\n","import type { ElementPosition } from '../shared/types';\n\n/** 简易防抖 */\nexport function debounce<T extends (...args: unknown[]) => void>(fn: T, ms: number): T {\n let timer: ReturnType<typeof setTimeout> | null = null;\n return ((...args: unknown[]) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n }) as unknown as T;\n}\n\n/** 获取元素的 source id(data-source-location 或 data-visual-selector-id) */\nexport function getSourceId(element: Element): string | null {\n return (\n (element as HTMLElement).dataset?.sourceLocation ??\n (element as HTMLElement).dataset?.visualSelectorId ??\n null\n );\n}\n\n/** 查找所有同源元素 */\nexport function findAllElementsById(id: string): Element[] {\n let elements = Array.from(document.querySelectorAll(`[data-source-location=\"${id}\"]`));\n if (elements.length === 0) {\n elements = Array.from(document.querySelectorAll(`[data-visual-selector-id=\"${id}\"]`));\n }\n return elements;\n}\n\n/** 判断元素是否包含 data-source-location 属性 */\nexport function hasSourceLocation(el: Element): boolean {\n return el.hasAttribute('data-source-location') || el.hasAttribute('data-visual-selector-id');\n}\n\n/** 获取元素位置信息 */\nexport function getElementPosition(element: Element): ElementPosition {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n}\n\n/** 文本元素标签列表 */\nexport const TEXT_TAGS = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'SPAN', 'A', 'LABEL'];\n\n/** 可行内编辑的标签列表 */\nexport const INLINE_EDIT_TAGS = [\n 'div',\n 'p',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'span',\n 'li',\n 'td',\n 'a',\n 'button',\n 'label',\n];\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { AgentState } from './state';\nimport { debounce, INLINE_EDIT_TAGS } from './utils';\n\n// =====================================================\n// 行内编辑\n// =====================================================\n\nexport function canInlineEdit(element: HTMLElement): boolean {\n return (\n INLINE_EDIT_TAGS.includes(element.tagName.toLowerCase()) &&\n !!element.textContent?.trim() &&\n !element.querySelector('img, video, canvas, svg') &&\n element.children.length === 0\n );\n}\n\nexport function startInlineEditing(state: AgentState, element: HTMLElement) {\n if (!canInlineEdit(element)) return;\n\n state.editingElement = element;\n element.dataset.originalTextContent = element.textContent || '';\n element.contentEditable = 'true';\n element.setAttribute(AGENT_ATTR, '');\n element.style.cursor = 'text';\n\n const range = document.createRange();\n range.selectNodeContents(element);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n element.focus();\n\n state.selectionOverlays.forEach((o) => (o.style.display = 'none'));\n\n const debouncedReport = debounce(() => {\n try {\n window.parent.postMessage(\n {\n type: 'inline-edit',\n elementInfo: {\n tagName: element.tagName,\n visualSelectorId: state.selectedId,\n dataSourceLocation: element.dataset?.sourceLocation,\n },\n originalContent: element.dataset.originalTextContent || '',\n newContent: element.textContent || '',\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n }, 500);\n\n element.addEventListener('input', debouncedReport);\n (element as HTMLElement & { __inlineEditHandler?: EventListener }).__inlineEditHandler =\n debouncedReport;\n\n try {\n window.parent.postMessage(\n {\n type: 'content-editing-started',\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n}\n\nexport function stopInlineEditing(state: AgentState, updatePositions: () => void) {\n if (!state.editingElement) return;\n\n state.editingElement.contentEditable = 'false';\n state.editingElement.removeAttribute(AGENT_ATTR);\n state.editingElement.style.cursor = '';\n\n const handler = (state.editingElement as HTMLElement & { __inlineEditHandler?: EventListener })\n .__inlineEditHandler;\n if (handler) {\n state.editingElement.removeEventListener('input', handler);\n delete (state.editingElement as HTMLElement & { __inlineEditHandler?: EventListener })\n .__inlineEditHandler;\n }\n\n state.selectionOverlays.forEach((o) => (o.style.display = ''));\n updatePositions();\n\n try {\n window.parent.postMessage(\n {\n type: 'content-editing-ended',\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n\n state.editingElement = null;\n}\n\nexport function handleInlineEdit(\n state: AgentState,\n data: { dataSourceLocation: string; inlineEditingMode: boolean },\n updatePositions: () => void,\n) {\n if (data.inlineEditingMode) {\n const el = document.querySelector<HTMLElement>(\n `[data-source-location=\"${data.dataSourceLocation}\"]`,\n );\n if (el) {\n startInlineEditing(state, el);\n }\n } else {\n stopInlineEditing(state, updatePositions);\n }\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { LayerItem } from '../shared/types';\nimport type { AgentState } from './state';\nimport { hasSourceLocation } from './utils';\n\n// =====================================================\n// 层级导航(Layer Dropdown)\n// =====================================================\n\nexport function buildLayerTree(element: Element): LayerItem[] {\n const tree: LayerItem[] = [];\n\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n while (parent && parent !== document.body) {\n if (hasSourceLocation(parent)) {\n ancestors.push(parent);\n }\n parent = parent.parentElement;\n }\n ancestors.reverse();\n\n ancestors.forEach((el) => {\n tree.push({ element: el, tagName: el.tagName.toLowerCase(), depth: 0 });\n });\n\n tree.push({ element, tagName: element.tagName.toLowerCase(), depth: 0 });\n\n for (let i = 0; i < element.children.length; i++) {\n const child = element.children[i];\n if (hasSourceLocation(child)) {\n tree.push({ element: child, tagName: child.tagName.toLowerCase(), depth: 0 });\n }\n }\n\n return tree;\n}\n\nexport function removeLayerDropdown(state: AgentState) {\n if (state.layerDropdown) {\n const parentOverlay = state.layerDropdown.parentElement;\n if (parentOverlay) {\n const arrowEl = parentOverlay.querySelector('[data-tag-arrow]');\n if (arrowEl) arrowEl.textContent = '\\u2304';\n }\n state.layerDropdown.remove();\n state.layerDropdown = null;\n document.removeEventListener('keydown', handleLayerKeyboard);\n }\n}\n\nexport function toggleLayerDropdown(\n state: AgentState,\n element: Element,\n anchor: HTMLDivElement,\n onSelectElement: (el: Element) => void,\n) {\n if (state.layerDropdown) {\n removeLayerDropdown(state);\n return;\n }\n\n const layers = buildLayerTree(element);\n renderLayerDropdown(state, anchor, layers, element, onSelectElement);\n}\n\nfunction renderLayerDropdown(\n state: AgentState,\n anchor: HTMLElement,\n layers: LayerItem[],\n currentElement: Element,\n onSelectElement: (el: Element) => void,\n) {\n const dropdown = document.createElement('div');\n dropdown.setAttribute('data-layer-dropdown', 'true');\n dropdown.setAttribute(AGENT_ATTR, '');\n Object.assign(dropdown.style, {\n position: 'absolute',\n backgroundColor: '#ffffff',\n border: '1px solid #e2e8f0',\n borderRadius: '6px',\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n fontSize: '12px',\n zIndex: '99999',\n pointerEvents: 'auto',\n padding: '4px 0',\n minWidth: '120px',\n maxHeight: '320px',\n overflowY: 'auto',\n });\n\n let focusedIndex = -1;\n const items: HTMLDivElement[] = [];\n\n layers.forEach((layer, idx) => {\n const item = document.createElement('div');\n item.setAttribute(AGENT_ATTR, '');\n item.textContent = layer.tagName;\n item.style.padding = '6px 16px';\n item.style.cursor = 'pointer';\n item.style.whiteSpace = 'nowrap';\n\n if (layer.element === currentElement) {\n item.style.color = '#000000';\n item.style.backgroundColor = 'rgba(255, 204, 0, 0.2)';\n item.style.fontWeight = '600';\n focusedIndex = idx;\n } else {\n item.style.color = '#64748b';\n }\n\n item.addEventListener('click', (e) => {\n e.stopPropagation();\n removeLayerDropdown(state);\n onSelectElement(layer.element);\n });\n\n item.addEventListener('mouseenter', () => {\n if (layer.element !== currentElement) {\n item.style.backgroundColor = '#f1f5f9';\n item.style.color = '#334155';\n }\n });\n\n item.addEventListener('mouseleave', () => {\n if (layer.element !== currentElement) {\n item.style.backgroundColor = 'transparent';\n item.style.color = '#64748b';\n }\n });\n\n items.push(item);\n dropdown.appendChild(item);\n });\n\n document.body.appendChild(dropdown);\n\n const anchorRect = anchor.getBoundingClientRect();\n dropdown.style.top = `${anchorRect.bottom + window.scrollY + 2}px`;\n dropdown.style.left = `${anchorRect.left + window.scrollX}px`;\n\n requestAnimationFrame(() => {\n const ddRect = dropdown.getBoundingClientRect();\n if (ddRect.right > window.innerWidth - 4) {\n dropdown.style.left = `${window.innerWidth - ddRect.width - 4 + window.scrollX}px`;\n }\n if (ddRect.left < 4) {\n dropdown.style.left = `${4 + window.scrollX}px`;\n }\n if (ddRect.bottom > window.innerHeight) {\n dropdown.style.top = `${anchorRect.top + window.scrollY - ddRect.height - 2}px`;\n }\n });\n\n state.layerDropdown = dropdown;\n\n const handleKeydown = (e: KeyboardEvent) => {\n if (!state.layerDropdown) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusedIndex = Math.min(focusedIndex + 1, items.length - 1);\n highlightItem(items, focusedIndex, layers, currentElement);\n break;\n case 'ArrowUp':\n e.preventDefault();\n focusedIndex = Math.max(focusedIndex - 1, 0);\n highlightItem(items, focusedIndex, layers, currentElement);\n break;\n case 'Enter':\n e.preventDefault();\n if (focusedIndex >= 0 && focusedIndex < layers.length) {\n removeLayerDropdown(state);\n onSelectElement(layers[focusedIndex].element);\n }\n break;\n case 'Escape':\n e.preventDefault();\n removeLayerDropdown(state);\n break;\n }\n };\n\n (handleLayerKeyboard as { current?: (e: KeyboardEvent) => void }).current = handleKeydown;\n document.addEventListener('keydown', handleLayerKeyboard);\n}\n\nfunction handleLayerKeyboard(e: KeyboardEvent) {\n const current = (handleLayerKeyboard as { current?: (e: KeyboardEvent) => void }).current;\n if (current) current(e);\n}\n\nfunction highlightItem(\n items: HTMLDivElement[],\n index: number,\n layers: LayerItem[],\n currentElement: Element,\n) {\n items.forEach((item, i) => {\n if (layers[i].element === currentElement) {\n item.style.color = '#000000';\n item.style.backgroundColor =\n i === index ? 'rgba(255, 204, 0, 0.35)' : 'rgba(255, 204, 0, 0.2)';\n item.style.fontWeight = '600';\n } else {\n item.style.backgroundColor = i === index ? '#f1f5f9' : 'transparent';\n item.style.color = i === index ? '#334155' : '#64748b';\n item.style.fontWeight = 'normal';\n }\n });\n}\n","import { AGENT_ATTR, CONTROL_MESSAGE_TYPE } from '../shared/constants';\nimport type { ElementUpdateMessage, VisualSelectorControlMessage } from '../shared/types';\nimport type { AgentState } from './state';\nimport { findAllElementsById, getElementPosition, getSourceId, TEXT_TAGS } from './utils';\n\n// =====================================================\n// 上报消息(iframe → 主页面)\n// =====================================================\n\nexport function reportElementSelected(state: AgentState, element: Element) {\n const el = element as HTMLElement;\n const tagName = element.tagName;\n const isTextElement = TEXT_TAGS.includes(tagName);\n\n const computed = window.getComputedStyle(el);\n const computedStyles: Record<string, string> = {\n fontFamily: computed.fontFamily,\n fontSize: computed.fontSize,\n fontWeight: computed.fontWeight,\n textAlign: computed.textAlign,\n textDecoration: computed.textDecoration,\n textDecorationLine: computed.textDecorationLine,\n color: computed.color,\n backgroundColor: computed.backgroundColor,\n lineHeight: computed.lineHeight,\n letterSpacing: computed.letterSpacing,\n opacity: computed.opacity,\n };\n\n try {\n window.parent.postMessage(\n {\n type: 'element-selected',\n tagName,\n classes: typeof el.className === 'string' ? el.className : '',\n visualSelectorId: getSourceId(element),\n content: el.innerText,\n dataSourceLocation: el.dataset?.sourceLocation,\n isDynamicContent: el.dataset?.dynamicContent === 'true',\n position: getElementPosition(element),\n attributes: {},\n isTextElement,\n staticArrayName: null,\n collectionId: null,\n computedStyles,\n },\n state.targetOrigin,\n );\n } catch {\n // 跨域 postMessage 可能抛出 SecurityError\n }\n}\n\nexport function reportPositionUpdate(state: AgentState) {\n if (!state.selectedId || !state.selectedElement?.isConnected) return;\n\n const rect = state.selectedElement.getBoundingClientRect();\n const isInViewport =\n rect.top < window.innerHeight &&\n rect.bottom > 0 &&\n rect.left < window.innerWidth &&\n rect.right > 0;\n\n try {\n window.parent.postMessage(\n {\n type: 'element-position-update',\n position: getElementPosition(state.selectedElement),\n isInViewport,\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n}\n\n// =====================================================\n// 接收消息(主页面 → iframe)\n// =====================================================\n\nexport interface MessageHandlerCallbacks {\n enableEditMode: (enabled: boolean, specs?: { newInlineEditEnabled?: boolean }) => void;\n updateAllOverlayPositions: () => void;\n stopInlineEditing: () => void;\n handleInlineEdit: (data: { dataSourceLocation: string; inlineEditingMode: boolean }) => void;\n}\n\nexport function handleMessage(\n state: AgentState,\n e: MessageEvent,\n callbacks: MessageHandlerCallbacks,\n) {\n if (state.targetOrigin !== '*' && e.origin !== state.targetOrigin) return;\n\n const msg = e.data;\n if (!msg || typeof msg !== 'object' || !msg.type) return;\n\n switch (msg.type) {\n case 'toggle-visual-edit-mode':\n callbacks.enableEditMode(msg.data?.enabled ?? false, msg.data?.specs);\n break;\n\n case 'update-classes':\n if (msg.data?.visualSelectorId && typeof msg.data?.classes === 'string') {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) =>\n el.setAttribute('class', msg.data.classes),\n );\n setTimeout(callbacks.updateAllOverlayPositions, 50);\n }\n break;\n\n case 'update-attribute':\n if (msg.data?.visualSelectorId && msg.data?.attribute && msg.data?.value !== undefined) {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) =>\n el.setAttribute(msg.data.attribute, msg.data.value),\n );\n }\n break;\n\n case 'update-content':\n if (msg.data?.visualSelectorId && msg.data?.content !== undefined) {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) => {\n (el as HTMLElement).innerText = msg.data.content;\n });\n setTimeout(callbacks.updateAllOverlayPositions, 50);\n }\n break;\n\n case 'unselect-element':\n if (state.editingElement) callbacks.stopInlineEditing();\n // 直接清除选中状态(不调用 clearSelectionOverlays 避免循环依赖)\n state.selectionOverlays.forEach((o) => o.remove());\n state.selectionOverlays = [];\n state.selectedId = null;\n state.selectedElement = null;\n break;\n\n case 'update-theme-variables':\n if (msg.data?.variables) {\n const root =\n msg.data.mode === 'dark' ? document.querySelector('.dark') : document.documentElement;\n if (root) {\n for (const [name, value] of Object.entries(msg.data.variables)) {\n (root as HTMLElement).style.setProperty(name, value as string);\n }\n }\n }\n break;\n\n case 'toggle-inline-edit-mode':\n if (msg.data) {\n callbacks.handleInlineEdit(msg.data);\n }\n break;\n\n case 'inject-font-import':\n if (msg.data?.fontUrl && /^https?:\\/\\//.test(msg.data.fontUrl)) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = msg.data.fontUrl;\n link.setAttribute(AGENT_ATTR, '');\n document.head.appendChild(link);\n }\n break;\n\n case 'popover-drag-state':\n case 'dropdown-state':\n break;\n\n case 'refresh-page':\n window.location.reload();\n break;\n\n case 'request-element-position':\n reportPositionUpdate(state);\n break;\n\n case CONTROL_MESSAGE_TYPE: {\n const controlMsg = msg as VisualSelectorControlMessage;\n if (typeof controlMsg.active === 'boolean') {\n callbacks.enableEditMode(controlMsg.active);\n }\n break;\n }\n\n case 'update-element-style':\n case 'update-element-text':\n case 'update-element-class':\n handleLegacyUpdateMessage(state, msg as ElementUpdateMessage);\n break;\n }\n}\n\nfunction handleLegacyUpdateMessage(state: AgentState, msg: ElementUpdateMessage) {\n if (!msg.dataSourceLocation) return;\n\n const el = document.querySelector<HTMLElement>(\n `[${state.attributeName}=\"${msg.dataSourceLocation}\"]`,\n );\n if (!el) return;\n\n if (msg.type === 'update-element-style' && msg.styles) {\n for (const [prop, value] of Object.entries(msg.styles)) {\n el.style.setProperty(\n prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),\n value,\n );\n }\n } else if (msg.type === 'update-element-text' && typeof msg.text === 'string') {\n el.textContent = msg.text;\n } else if (msg.type === 'update-element-class' && typeof msg.className === 'string') {\n el.className = msg.className;\n }\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { AgentState } from './state';\n\n// =====================================================\n// Overlay 创建与定位\n// =====================================================\n\nexport function createOverlay(opts: { selected: boolean }): HTMLDivElement {\n const overlay = document.createElement('div');\n overlay.setAttribute(AGENT_ATTR, '');\n overlay.style.position = 'absolute';\n overlay.style.pointerEvents = 'none';\n overlay.style.zIndex = '9999';\n overlay.style.boxSizing = 'border-box';\n\n if (opts.selected) {\n overlay.style.boxShadow = 'inset 0 0 0 2px #FC0';\n } else {\n overlay.style.boxShadow = 'inset 0 0 0 2px rgba(255, 204, 0, 0.5)';\n overlay.style.backgroundColor = 'rgba(255, 204, 0, 0.05)';\n }\n\n return overlay;\n}\n\nexport function positionOverlay(\n overlay: HTMLDivElement,\n target: Element,\n tagMode: 'none' | 'hover' | 'selected' = 'none',\n callbacks?: {\n onTagClick?: (target: Element, tag: HTMLDivElement) => void;\n },\n) {\n const rect = target.getBoundingClientRect();\n overlay.style.top = `${rect.top + window.scrollY}px`;\n overlay.style.left = `${rect.left + window.scrollX}px`;\n overlay.style.width = `${rect.width}px`;\n overlay.style.height = `${rect.height}px`;\n\n if (tagMode !== 'none') {\n let tag = overlay.querySelector('[data-tag-label]') as HTMLDivElement | null;\n if (!tag) {\n tag = document.createElement('div');\n tag.setAttribute(AGENT_ATTR, '');\n tag.setAttribute('data-tag-label', '');\n Object.assign(tag.style, {\n position: 'absolute',\n padding: '2px 8px',\n fontSize: '11px',\n fontWeight: '500',\n borderRadius: '3px',\n minWidth: '24px',\n textAlign: 'center',\n display: 'flex',\n alignItems: 'center',\n gap: '3px',\n lineHeight: '1.4',\n });\n\n if (tagMode === 'selected') {\n tag.style.backgroundColor = '#FC0';\n tag.style.color = '#000000';\n tag.style.cursor = 'pointer';\n tag.style.pointerEvents = 'auto';\n\n const textSpan = document.createElement('span');\n textSpan.textContent = target.tagName.toLowerCase();\n tag.appendChild(textSpan);\n\n const arrow = document.createElement('span');\n arrow.setAttribute('data-tag-arrow', '');\n arrow.textContent = '\\u2304';\n arrow.style.fontSize = '10px';\n arrow.style.lineHeight = '1';\n tag.appendChild(arrow);\n\n if (callbacks?.onTagClick) {\n const onTagClick = callbacks.onTagClick;\n tag.addEventListener('click', (e) => {\n e.stopPropagation();\n onTagClick(target, tag as HTMLDivElement);\n });\n }\n } else {\n tag.style.backgroundColor = 'rgba(255, 204, 0, 0.7)';\n tag.style.color = '#000000';\n tag.style.pointerEvents = 'none';\n tag.textContent = target.tagName.toLowerCase();\n }\n\n overlay.appendChild(tag);\n }\n positionTag(tag, rect);\n }\n}\n\nfunction positionTag(tag: HTMLElement, rect: DOMRect) {\n const isNearTop = rect.top < 27;\n const isTallEnough = rect.height >= 54;\n const isFullWidth = rect.width >= window.innerWidth - 4;\n const leftOffset = isFullWidth ? 8 : 4;\n\n if (isNearTop && isTallEnough) {\n tag.style.top = '2px';\n } else if (isNearTop) {\n tag.style.top = `${rect.height + 2}px`;\n } else {\n tag.style.top = '-27px';\n }\n\n tag.style.left = `${leftOffset}px`;\n\n requestAnimationFrame(() => {\n const tagRect = tag.getBoundingClientRect();\n if (tagRect.right > window.innerWidth - 4) {\n const shift = tagRect.right - window.innerWidth + 8;\n tag.style.left = `${leftOffset - shift}px`;\n }\n if (tagRect.left < 4) {\n const shift = 4 - tagRect.left;\n tag.style.left = `${leftOffset + shift}px`;\n }\n });\n}\n\n// =====================================================\n// 清理函数\n// =====================================================\n\nexport function clearHoverOverlays(state: AgentState) {\n state.hoverOverlays.forEach((o) => o.remove());\n state.hoverOverlays = [];\n state.currentHoverId = null;\n}\n\nexport function clearSelectionOverlays(state: AgentState, removeDropdown: () => void) {\n state.selectionOverlays.forEach((o) => o.remove());\n state.selectionOverlays = [];\n removeDropdown();\n}\n\nexport function clearAllOverlays(state: AgentState, removeDropdown: () => void) {\n clearHoverOverlays(state);\n clearSelectionOverlays(state, removeDropdown);\n state.selectedId = null;\n state.selectedElement = null;\n}\n\n// =====================================================\n// 冻结动画与 pointer-events\n// =====================================================\n\nexport function freezeAnimations() {\n document.documentElement.setAttribute('data-visual-edit-active', '');\n\n if (!document.getElementById('freeze-animations')) {\n const style = document.createElement('style');\n style.id = 'freeze-animations';\n style.setAttribute(AGENT_ATTR, '');\n style.textContent = `\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *),\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *)::before,\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *)::after {\n animation-play-state: paused !important;\n transition: none !important;\n }\n `;\n document.head.appendChild(style);\n }\n\n if (!document.getElementById('freeze-overflow')) {\n const overflowStyle = document.createElement('style');\n overflowStyle.id = 'freeze-overflow';\n overflowStyle.setAttribute(AGENT_ATTR, '');\n overflowStyle.textContent = `\n html[data-visual-edit-active] {\n overflow-y: scroll !important;\n overflow-x: hidden !important;\n }\n `;\n document.head.appendChild(overflowStyle);\n }\n\n if (!document.getElementById('freeze-pointer-events')) {\n const pointerStyle = document.createElement('style');\n pointerStyle.id = 'freeze-pointer-events';\n pointerStyle.setAttribute(AGENT_ATTR, '');\n pointerStyle.textContent = `\n [data-visual-edit-active] * { pointer-events: none !important; }\n [${AGENT_ATTR}], [${AGENT_ATTR}] * { pointer-events: auto !important; }\n `;\n document.head.appendChild(pointerStyle);\n }\n\n try {\n document.getAnimations().forEach((anim) => {\n const effect = anim.effect as KeyframeEffect | null;\n const target = effect?.target;\n if (target instanceof Element && target.closest(`[${AGENT_ATTR}]`)) return;\n try {\n anim.finish();\n } catch {\n anim.pause();\n }\n });\n } catch {\n // getAnimations 在某些环境下不可用\n }\n}\n\nexport function unfreezeAnimations() {\n document.documentElement.removeAttribute('data-visual-edit-active');\n\n const freezeStyle = document.getElementById('freeze-animations');\n if (freezeStyle) freezeStyle.remove();\n\n const pointerStyle = document.getElementById('freeze-pointer-events');\n if (pointerStyle) pointerStyle.remove();\n\n const overflowStyle = document.getElementById('freeze-overflow');\n if (overflowStyle) overflowStyle.remove();\n}\n","import type { VisualEditAgentOptions } from '../shared/types';\nimport { DEFAULT_ATTRIBUTE_NAME } from '../shared/constants';\n\n/** agent 运行时内部状态 */\nexport interface AgentState {\n editModeEnabled: boolean;\n selectedId: string | null;\n selectedElement: Element | null;\n hoverOverlays: HTMLDivElement[];\n selectionOverlays: HTMLDivElement[];\n currentHoverId: string | null;\n editingElement: HTMLElement | null;\n layerDropdown: HTMLDivElement | null;\n mutationObserver: MutationObserver | null;\n attributeName: string;\n targetOrigin: string;\n}\n\nexport function createAgentState(options: VisualEditAgentOptions = {}): AgentState {\n return {\n editModeEnabled: false,\n selectedId: null,\n selectedElement: null,\n hoverOverlays: [],\n selectionOverlays: [],\n currentHoverId: null,\n editingElement: null,\n layerDropdown: null,\n mutationObserver: null,\n attributeName: options.attributeName ?? DEFAULT_ATTRIBUTE_NAME,\n targetOrigin: options.targetOrigin ?? '*',\n };\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { VisualEditAgentInstance, VisualEditAgentOptions } from '../shared/types';\nimport { stopInlineEditing } from './inline-edit';\nimport { handleInlineEdit } from './inline-edit';\nimport { removeLayerDropdown, toggleLayerDropdown } from './layer-navigation';\nimport { handleMessage, reportElementSelected, reportPositionUpdate } from './messages';\nimport {\n clearAllOverlays,\n clearHoverOverlays,\n clearSelectionOverlays,\n createOverlay,\n freezeAnimations,\n positionOverlay,\n unfreezeAnimations,\n} from './overlay';\nimport { createAgentState } from './state';\nimport { findAllElementsById, getSourceId, hasSourceLocation } from './utils';\n\n/**\n * 初始化 VisualEditAgent。\n * 在 iframe 内调用,负责元素选择、高亮、DOM 修改和消息通信。\n */\nexport function setupVisualEditAgent(\n options: VisualEditAgentOptions = {},\n): VisualEditAgentInstance {\n const state = createAgentState(options);\n\n // --- 更新所有 overlay 位置 ---\n\n function updateAllOverlayPositions() {\n if (state.selectedId && state.selectedElement?.isConnected) {\n const siblings = findAllElementsById(state.selectedId);\n state.selectionOverlays.forEach((overlay, i) => {\n if (siblings[i]) {\n positionOverlay(overlay, siblings[i], i === 0 ? 'selected' : 'none', {\n onTagClick: onTagClick,\n });\n }\n });\n }\n reportPositionUpdate(state);\n }\n\n // --- Tag 点击回调 ---\n\n function onTagClick(target: Element, tag: HTMLDivElement) {\n const arrowEl = tag.querySelector('[data-tag-arrow]');\n if (arrowEl) {\n arrowEl.textContent = state.layerDropdown ? '\\u2304' : '\\u2303';\n }\n toggleLayerDropdown(state, target, tag, selectElement);\n }\n\n // --- 元素查找(穿透 overlay) ---\n\n function findElementAtPoint(x: number, y: number): Element | null {\n const freezeStyle = document.getElementById('freeze-pointer-events') as HTMLStyleElement | null;\n if (freezeStyle) freezeStyle.disabled = true;\n\n const element = document.elementFromPoint(x, y);\n\n if (freezeStyle) freezeStyle.disabled = false;\n\n if (!element) return null;\n if (element.closest(`[${AGENT_ATTR}]`)) return null;\n\n return element.closest(`[${state.attributeName}], [data-visual-selector-id]`) ?? null;\n }\n\n function findHoverTarget(x: number, y: number, excludeId: string | null): string | null {\n const element = findElementAtPoint(x, y);\n if (!element) return null;\n\n const id = getSourceId(element);\n if (!id || id === excludeId) return null;\n\n return id;\n }\n\n // --- Hover 高亮 ---\n\n function onMouseMove(e: MouseEvent) {\n if (!state.editModeEnabled) return;\n\n requestAnimationFrame(() => {\n const id = findHoverTarget(e.clientX, e.clientY, state.selectedId);\n if (!id) {\n clearHoverOverlays(state);\n return;\n }\n if (id === state.currentHoverId) return;\n\n clearHoverOverlays(state);\n\n const elements = findAllElementsById(id);\n elements.forEach((el, i) => {\n const overlay = createOverlay({ selected: false });\n overlay.setAttribute(AGENT_ATTR, '');\n document.body.appendChild(overlay);\n positionOverlay(overlay, el, i === 0 ? 'hover' : 'none');\n state.hoverOverlays.push(overlay);\n });\n\n state.currentHoverId = id;\n });\n }\n\n function onMouseLeave() {\n clearHoverOverlays(state);\n }\n\n // --- Click 选中 ---\n\n function onClick(e: MouseEvent) {\n if (!state.editModeEnabled) return;\n\n const target = e.target as Element;\n\n if (target?.closest?.(`[data-layer-dropdown]`)) return;\n if (\n target?.closest?.(`[data-tag-label]`) &&\n state.selectionOverlays.some((o) => o.contains(target))\n )\n return;\n\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n clearHoverOverlays(state);\n\n const element = findElementAtPoint(e.clientX, e.clientY);\n if (!element) return;\n\n selectElement(element);\n }\n\n function selectElement(element: Element) {\n const id = getSourceId(element);\n if (!id) return;\n\n if (state.editingElement) {\n stopInlineEditing(state, updateAllOverlayPositions);\n }\n\n clearSelectionOverlays(state, () => removeLayerDropdown(state));\n\n const siblings = findAllElementsById(id);\n siblings.forEach((el, i) => {\n const overlay = createOverlay({ selected: true });\n overlay.setAttribute(AGENT_ATTR, '');\n document.body.appendChild(overlay);\n positionOverlay(overlay, el, i === 0 ? 'selected' : 'none', {\n onTagClick: onTagClick,\n });\n state.selectionOverlays.push(overlay);\n });\n\n state.selectedId = id;\n state.selectedElement = element;\n\n clearHoverOverlays(state);\n reportElementSelected(state, element);\n }\n\n // --- 位置持续更新 ---\n\n let rafPending = false;\n const throttledPositionUpdate = () => {\n if (rafPending) return;\n rafPending = true;\n requestAnimationFrame(() => {\n rafPending = false;\n reportPositionUpdate(state);\n });\n };\n\n // --- 激活/停用选择模式 ---\n\n function enableEditMode(enabled: boolean, _specs?: { newInlineEditEnabled?: boolean }) {\n state.editModeEnabled = enabled;\n\n if (enabled) {\n document.body.style.cursor = 'crosshair';\n freezeAnimations();\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseleave', onMouseLeave);\n document.addEventListener('click', onClick, true);\n window.addEventListener('scroll', throttledPositionUpdate, true);\n document.addEventListener('scroll', throttledPositionUpdate, true);\n window.addEventListener('resize', updateAllOverlayPositions);\n\n startMutationObserver();\n } else {\n document.body.style.cursor = 'default';\n unfreezeAnimations();\n clearAllOverlays(state, () => removeLayerDropdown(state));\n\n if (state.editingElement) {\n stopInlineEditing(state, updateAllOverlayPositions);\n }\n\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseleave', onMouseLeave);\n document.removeEventListener('click', onClick, true);\n window.removeEventListener('scroll', throttledPositionUpdate, true);\n document.removeEventListener('scroll', throttledPositionUpdate, true);\n window.removeEventListener('resize', updateAllOverlayPositions);\n\n stopMutationObserver();\n }\n }\n\n // --- MutationObserver ---\n\n function startMutationObserver() {\n if (state.mutationObserver) return;\n\n state.mutationObserver = new MutationObserver((mutations) => {\n const hasRelevantChange = mutations.some((m) => {\n if (\n m.type === 'attributes' &&\n ['style', 'class', 'width', 'height'].includes(m.attributeName ?? '') &&\n containsTrackedElement(m.target)\n )\n return true;\n if (m.type === 'childList' && containsTrackedElement(m.target)) return true;\n return false;\n });\n if (hasRelevantChange) {\n setTimeout(updateAllOverlayPositions, 50);\n }\n });\n\n state.mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n attributeFilter: ['style', 'class', 'width', 'height'],\n });\n }\n\n function stopMutationObserver() {\n if (state.mutationObserver) {\n state.mutationObserver.disconnect();\n state.mutationObserver = null;\n }\n }\n\n function containsTrackedElement(node: Node): boolean {\n if (!(node instanceof Element)) return false;\n if (node.hasAttribute(AGENT_ATTR)) return false;\n return hasSourceLocation(node) || !!node.querySelector(`[${state.attributeName}]`);\n }\n\n // --- Sandbox Mount Observer ---\n\n function setupSandboxMountObserver() {\n if (window.self === window.top) return;\n\n const mountObserver = new MutationObserver((mutations) => {\n const hasChanges = mutations.some(\n (m) => m.addedNodes.length > 0 || m.removedNodes.length > 0,\n );\n if (!hasChanges) return;\n\n const hasTrackedElements =\n document.body.querySelectorAll('[data-source-location], [data-dynamic-content]').length > 0;\n\n try {\n window.parent.postMessage(\n {\n type: hasTrackedElements ? 'sandbox:onMounted' : 'sandbox:onUnmounted',\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n });\n\n if (document.body) {\n mountObserver.observe(document.body, { childList: true, subtree: true });\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n mountObserver.observe(document.body, { childList: true, subtree: true });\n });\n }\n }\n\n // --- 消息监听器 ---\n\n const onMessage = (e: MessageEvent) => {\n handleMessage(state, e, {\n enableEditMode,\n updateAllOverlayPositions,\n stopInlineEditing: () => stopInlineEditing(state, updateAllOverlayPositions),\n handleInlineEdit: (data) => handleInlineEdit(state, data, updateAllOverlayPositions),\n });\n };\n\n // --- 初始化 ---\n\n window.addEventListener('message', onMessage);\n setupSandboxMountObserver();\n\n try {\n window.parent.postMessage({ type: 'visual-edit-agent-ready' }, state.targetOrigin);\n } catch {\n // 静默忽略\n }\n\n // --- 返回控制接口 ---\n\n return {\n destroy() {\n window.removeEventListener('message', onMessage);\n if (state.editModeEnabled) {\n enableEditMode(false);\n }\n },\n enableEditMode,\n selectElement,\n clearSelection() {\n clearAllOverlays(state, () => removeLayerDropdown(state));\n },\n getSelectedId() {\n return state.selectedId;\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/plugin.ts","../src/shared/constants.ts","../src/runtime/utils.ts","../src/runtime/inline-edit.ts","../src/runtime/messages.ts","../src/runtime/overlay.ts","../src/runtime/layer-navigation.ts","../src/runtime/state.ts","../src/runtime/index.ts"],"sourcesContent":["import { parse } from '@babel/parser';\nimport _traverse from '@babel/traverse';\nimport * as t from '@babel/types';\n\n// 兼容 CJS/ESM:@babel/traverse 在不同模块系统下导出形式不同\nconst traverse =\n typeof _traverse === 'function'\n ? _traverse\n : (_traverse as { default: typeof _traverse }).default;\nimport MagicString from 'magic-string';\nimport path from 'node:path';\nimport type { Plugin } from 'vite';\n\nimport { DEFAULT_ATTRIBUTE_NAME } from './shared/constants';\nimport type { VisualSelectorPluginOptions } from './shared/types';\n\n/**\n * 将绝对路径转换为相对于项目根目录的 Unix 风格路径(用 `/` 分隔)。\n * 例如:/project/src/App.tsx → src/App.tsx\n */\nfunction toRelativeUnixPath(root: string, filePath: string) {\n return path.relative(root, filePath).split(path.sep).join('/');\n}\n\n/**\n * 判断 JSX 开标签是否为原生 HTML 元素(小写字母开头,如 <div>、<span>)。\n * 自定义组件(大写字母开头,如 <MyButton>)不注入属性,避免干扰组件 props。\n */\nfunction isIntrinsicElement(node: t.JSXOpeningElement) {\n return t.isJSXIdentifier(node.name) && /^[a-z]/.test(node.name.name);\n}\n\n/**\n * 检查 JSX 开标签是否已经带有指定属性名,避免重复注入(如手动写了 data-source-location 的情况)。\n */\nfunction hasSourceLocationAttribute(node: t.JSXOpeningElement, attributeName: string) {\n return node.attributes.some(\n (attribute) =>\n t.isJSXAttribute(attribute) &&\n t.isJSXIdentifier(attribute.name) &&\n attribute.name.name === attributeName,\n );\n}\n\n/**\n * 创建 Vite 插件:在编译阶段(transform hook)向每个原生 JSX 元素注入\n * `data-source-location=\"文件路径:行号:列号\"` 属性,使运行时可以追溯到源码位置。\n */\nexport function visualSelectorPlugin(options: VisualSelectorPluginOptions = {}): Plugin {\n const attributeName = options.attributeName ?? DEFAULT_ATTRIBUTE_NAME;\n const root = options.root ?? process.cwd();\n // 默认只处理 .jsx/.tsx/.js/.ts(含 x)文件\n const include = options.include ?? [/\\.[jt]sx$/];\n // 默认跳过 node_modules\n const exclude = options.exclude ?? [/node_modules/];\n\n return {\n name: 'vite-plugin-visual-selector',\n enforce: 'pre', // 在其他插件(如 @vitejs/plugin-react)之前运行,确保 JSX 还未被转译\n transform(code, id) {\n // 不在 include 列表中的文件直接跳过\n if (!include.some((pattern) => pattern.test(id))) {\n return null;\n }\n\n // 在 exclude 列表中的文件直接跳过\n if (exclude.some((pattern) => pattern.test(id))) {\n return null;\n }\n\n let ast;\n try {\n ast = parse(code, {\n sourceType: 'module',\n plugins: ['jsx', 'typescript'],\n });\n } catch {\n // 解析失败时返回原始代码,不阻断构建\n return null;\n }\n\n const magicString = new MagicString(code);\n let mutated = false;\n\n traverse(ast, {\n // 遍历 AST 中所有 JSX 开标签节点\n JSXOpeningElement(jsxPath) {\n const node = jsxPath.node;\n\n // 跳过自定义组件(非原生 HTML 标签)\n if (!isIntrinsicElement(node)) {\n return;\n }\n\n // 跳过已有该属性的节点\n if (hasSourceLocationAttribute(node, attributeName)) {\n return;\n }\n\n // 缺少位置信息时跳过(通常不会发生)\n if (!node.loc || node.name.end == null) {\n return;\n }\n\n // 生成 \"相对路径:行号:列号\" 格式的位置字符串(列号从 1 开始)\n const location = `${toRelativeUnixPath(root, id)}:${node.loc.start.line}:${node.loc.start.column + 1}`;\n // 在标签名结尾处(name.end)插入属性,如 <div → <div data-source-location=\"...\"\n magicString.appendLeft(node.name.end, ` ${attributeName}=\"${location}\"`);\n mutated = true;\n },\n });\n\n // 没有任何修改时返回 null,告诉 Vite 文件未变化,避免不必要的 sourcemap 开销\n if (!mutated) {\n return null;\n }\n\n return {\n code: magicString.toString(),\n map: magicString.generateMap({ hires: true }), // 高精度 sourcemap,保证调试准确\n };\n },\n };\n}\n","// 注入到 JSX 元素上的默认属性名,值为源码文件路径+行列号(如 \"src/App.tsx:12:3\")\nexport const DEFAULT_ATTRIBUTE_NAME = 'data-source-location';\n\n// 父窗口发往子窗口(iframe)的控制消息类型:开启/关闭高亮编辑模式\nexport const CONTROL_MESSAGE_TYPE = 'visual-selector:set-active';\n\n// agent 自己创建的 DOM 元素标记属性,用于排除冻结和 pointer-events 禁用\nexport const AGENT_ATTR = 'data-vite-plugin-element';\n","import type { ElementPosition } from '../shared/types';\n\n/** 简易防抖 */\nexport function debounce<T extends (...args: unknown[]) => void>(fn: T, ms: number): T {\n let timer: ReturnType<typeof setTimeout> | null = null;\n return ((...args: unknown[]) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => fn(...args), ms);\n }) as unknown as T;\n}\n\n/** 获取元素的 source id(data-source-location 或 data-visual-selector-id) */\nexport function getSourceId(element: Element): string | null {\n return (\n (element as HTMLElement).dataset?.sourceLocation ??\n (element as HTMLElement).dataset?.visualSelectorId ??\n null\n );\n}\n\n/** 查找所有同源元素 */\nexport function findAllElementsById(id: string): Element[] {\n let elements = Array.from(document.querySelectorAll(`[data-source-location=\"${id}\"]`));\n if (elements.length === 0) {\n elements = Array.from(document.querySelectorAll(`[data-visual-selector-id=\"${id}\"]`));\n }\n return elements;\n}\n\n/** 判断元素是否包含 data-source-location 属性 */\nexport function hasSourceLocation(el: Element): boolean {\n return el.hasAttribute('data-source-location') || el.hasAttribute('data-visual-selector-id');\n}\n\n/** 获取元素位置信息 */\nexport function getElementPosition(element: Element): ElementPosition {\n const rect = element.getBoundingClientRect();\n return {\n top: rect.top,\n left: rect.left,\n right: rect.right,\n bottom: rect.bottom,\n width: rect.width,\n height: rect.height,\n centerX: rect.left + rect.width / 2,\n centerY: rect.top + rect.height / 2,\n };\n}\n\n/** 文本元素标签列表 */\nexport const TEXT_TAGS = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'SPAN', 'A', 'LABEL'];\n\n/** 可行内编辑的标签列表 */\nexport const INLINE_EDIT_TAGS = [\n 'div',\n 'p',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'span',\n 'li',\n 'td',\n 'a',\n 'button',\n 'label',\n];\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { AgentState } from './state';\nimport { debounce, INLINE_EDIT_TAGS } from './utils';\n\n// =====================================================\n// 行内编辑\n// =====================================================\n\nexport function canInlineEdit(element: HTMLElement): boolean {\n return (\n INLINE_EDIT_TAGS.includes(element.tagName.toLowerCase()) &&\n !!element.textContent?.trim() &&\n !element.querySelector('img, video, canvas, svg') &&\n element.children.length === 0\n );\n}\n\nexport function startInlineEditing(state: AgentState, element: HTMLElement) {\n if (!canInlineEdit(element)) return;\n\n state.editingElement = element;\n element.dataset.originalTextContent = element.textContent || '';\n element.contentEditable = 'true';\n element.setAttribute(AGENT_ATTR, '');\n element.style.cursor = 'text';\n\n const range = document.createRange();\n range.selectNodeContents(element);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n element.focus();\n\n state.selectionOverlays.forEach((o) => (o.style.display = 'none'));\n\n const debouncedReport = debounce(() => {\n try {\n window.parent.postMessage(\n {\n type: 'inline-edit',\n elementInfo: {\n tagName: element.tagName,\n visualSelectorId: state.selectedId,\n dataSourceLocation: element.dataset?.sourceLocation,\n },\n originalContent: element.dataset.originalTextContent || '',\n newContent: element.textContent || '',\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n }, 500);\n\n element.addEventListener('input', debouncedReport);\n (element as HTMLElement & { __inlineEditHandler?: EventListener }).__inlineEditHandler =\n debouncedReport;\n\n try {\n window.parent.postMessage(\n {\n type: 'content-editing-started',\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n}\n\nexport function stopInlineEditing(state: AgentState, updatePositions: () => void) {\n if (!state.editingElement) return;\n\n state.editingElement.contentEditable = 'false';\n state.editingElement.removeAttribute(AGENT_ATTR);\n state.editingElement.style.cursor = '';\n\n const handler = (state.editingElement as HTMLElement & { __inlineEditHandler?: EventListener })\n .__inlineEditHandler;\n if (handler) {\n state.editingElement.removeEventListener('input', handler);\n delete (state.editingElement as HTMLElement & { __inlineEditHandler?: EventListener })\n .__inlineEditHandler;\n }\n\n state.selectionOverlays.forEach((o) => (o.style.display = ''));\n updatePositions();\n\n try {\n window.parent.postMessage(\n {\n type: 'content-editing-ended',\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n\n state.editingElement = null;\n}\n\nexport function handleInlineEdit(\n state: AgentState,\n data: { dataSourceLocation: string; inlineEditingMode: boolean },\n updatePositions: () => void,\n) {\n if (data.inlineEditingMode) {\n const el = document.querySelector<HTMLElement>(\n `[data-source-location=\"${data.dataSourceLocation}\"]`,\n );\n if (el) {\n startInlineEditing(state, el);\n }\n } else {\n stopInlineEditing(state, updatePositions);\n }\n}\n","import { AGENT_ATTR, CONTROL_MESSAGE_TYPE } from '../shared/constants';\nimport type { ElementUpdateMessage, VisualSelectorControlMessage } from '../shared/types';\nimport type { AgentState } from './state';\nimport { findAllElementsById, getElementPosition, getSourceId, TEXT_TAGS } from './utils';\n\n// =====================================================\n// 上报消息(iframe → 主页面)\n// =====================================================\n\nexport function reportElementSelected(state: AgentState, element: Element) {\n const el = element as HTMLElement;\n const tagName = element.tagName;\n const isTextElement = TEXT_TAGS.includes(tagName);\n\n const computed = window.getComputedStyle(el);\n const computedStyles: Record<string, string> = {\n fontFamily: computed.fontFamily,\n fontSize: computed.fontSize,\n fontWeight: computed.fontWeight,\n textAlign: computed.textAlign,\n textDecoration: computed.textDecoration,\n textDecorationLine: computed.textDecorationLine,\n color: computed.color,\n backgroundColor: computed.backgroundColor,\n lineHeight: computed.lineHeight,\n letterSpacing: computed.letterSpacing,\n opacity: computed.opacity,\n };\n\n try {\n window.parent.postMessage(\n {\n type: 'element-selected',\n tagName,\n classes: typeof el.className === 'string' ? el.className : '',\n visualSelectorId: getSourceId(element),\n content: el.innerText,\n dataSourceLocation: el.dataset?.sourceLocation,\n isDynamicContent: el.dataset?.dynamicContent === 'true',\n position: getElementPosition(element),\n attributes: {},\n isTextElement,\n staticArrayName: null,\n collectionId: null,\n computedStyles,\n },\n state.targetOrigin,\n );\n } catch {\n // 跨域 postMessage 可能抛出 SecurityError\n }\n}\n\nexport function reportPositionUpdate(state: AgentState) {\n if (!state.selectedId || !state.selectedElement?.isConnected) return;\n\n const rect = state.selectedElement.getBoundingClientRect();\n const isInViewport =\n rect.top < window.innerHeight &&\n rect.bottom > 0 &&\n rect.left < window.innerWidth &&\n rect.right > 0;\n\n try {\n window.parent.postMessage(\n {\n type: 'element-position-update',\n position: getElementPosition(state.selectedElement),\n isInViewport,\n visualSelectorId: state.selectedId,\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n}\n\nexport function reportDropdownState(state: AgentState, isOpen: boolean) {\n try {\n window.parent.postMessage(\n {\n type: 'dropdown-state',\n data: { isOpen },\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n}\n\n// =====================================================\n// 接收消息(主页面 → iframe)\n// =====================================================\n\nexport interface MessageHandlerCallbacks {\n enableEditMode: (enabled: boolean, specs?: { newInlineEditEnabled?: boolean }) => void;\n updateAllOverlayPositions: () => void;\n stopInlineEditing: () => void;\n handleInlineEdit: (data: { dataSourceLocation: string; inlineEditingMode: boolean }) => void;\n selectElementById: (id: string) => void;\n clearSelectionState: () => void;\n}\n\nexport function handleMessage(\n state: AgentState,\n e: MessageEvent,\n callbacks: MessageHandlerCallbacks,\n) {\n if (state.targetOrigin !== '*' && e.origin !== state.targetOrigin) return;\n\n const msg = e.data;\n if (!msg || typeof msg !== 'object' || !msg.type) return;\n\n switch (msg.type) {\n case 'toggle-visual-edit-mode':\n callbacks.enableEditMode(msg.data?.enabled ?? false, msg.data?.specs);\n break;\n\n case 'update-classes':\n if (msg.data?.visualSelectorId && typeof msg.data?.classes === 'string') {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) =>\n el.setAttribute('class', msg.data.classes),\n );\n setTimeout(callbacks.updateAllOverlayPositions, 50);\n }\n break;\n\n case 'update-attribute':\n if (msg.data?.visualSelectorId && msg.data?.attribute && msg.data?.value !== undefined) {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) =>\n el.setAttribute(msg.data.attribute, msg.data.value),\n );\n }\n break;\n\n case 'update-content':\n if (msg.data?.visualSelectorId && msg.data?.content !== undefined) {\n findAllElementsById(msg.data.visualSelectorId).forEach((el) => {\n (el as HTMLElement).innerText = msg.data.content;\n });\n setTimeout(callbacks.updateAllOverlayPositions, 50);\n }\n break;\n\n case 'unselect-element':\n if (state.editingElement) callbacks.stopInlineEditing();\n callbacks.clearSelectionState();\n break;\n\n case 'update-theme-variables':\n if (msg.data?.variables) {\n const root =\n msg.data.mode === 'dark' ? document.querySelector('.dark') : document.documentElement;\n if (root) {\n for (const [name, value] of Object.entries(msg.data.variables)) {\n (root as HTMLElement).style.setProperty(name, value as string);\n }\n }\n }\n break;\n\n case 'toggle-inline-edit-mode':\n if (msg.data) {\n callbacks.handleInlineEdit(msg.data);\n }\n break;\n\n case 'inject-font-import':\n if (msg.data?.fontUrl && /^https?:\\/\\//.test(msg.data.fontUrl)) {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = msg.data.fontUrl;\n link.setAttribute(AGENT_ATTR, '');\n document.head.appendChild(link);\n }\n break;\n\n case 'popover-drag-state':\n case 'dropdown-state':\n break;\n\n case 'refresh-page':\n window.location.reload();\n break;\n\n case 'request-element-position':\n reportPositionUpdate(state);\n break;\n\n case 'select-element-by-id':\n if (msg.data?.visualSelectorId) {\n callbacks.selectElementById(msg.data.visualSelectorId);\n }\n break;\n\n case CONTROL_MESSAGE_TYPE: {\n const controlMsg = msg as VisualSelectorControlMessage;\n if (typeof controlMsg.active === 'boolean') {\n callbacks.enableEditMode(controlMsg.active);\n }\n break;\n }\n\n case 'update-element-style':\n case 'update-element-text':\n case 'update-element-class':\n handleLegacyUpdateMessage(state, msg as ElementUpdateMessage);\n break;\n }\n}\n\nfunction handleLegacyUpdateMessage(state: AgentState, msg: ElementUpdateMessage) {\n if (!msg.dataSourceLocation) return;\n\n const el = document.querySelector<HTMLElement>(\n `[${state.attributeName}=\"${msg.dataSourceLocation}\"]`,\n );\n if (!el) return;\n\n if (msg.type === 'update-element-style' && msg.styles) {\n for (const [prop, value] of Object.entries(msg.styles)) {\n el.style.setProperty(\n prop.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`),\n value,\n );\n }\n } else if (msg.type === 'update-element-text' && typeof msg.text === 'string') {\n el.textContent = msg.text;\n } else if (msg.type === 'update-element-class' && typeof msg.className === 'string') {\n el.className = msg.className;\n }\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { AgentState } from './state';\n\n// =====================================================\n// Overlay 创建与定位\n// =====================================================\n\nexport function createOverlay(opts: { selected: boolean }): HTMLDivElement {\n const overlay = document.createElement('div');\n overlay.setAttribute(AGENT_ATTR, '');\n overlay.style.position = 'absolute';\n overlay.style.pointerEvents = 'none';\n overlay.style.zIndex = '9999';\n overlay.style.boxSizing = 'border-box';\n\n if (opts.selected) {\n overlay.style.boxShadow = 'inset 0 0 0 2px #FC0';\n } else {\n overlay.style.boxShadow = 'inset 0 0 0 2px rgba(255, 204, 0, 0.5)';\n overlay.style.backgroundColor = 'rgba(255, 204, 0, 0.05)';\n }\n\n return overlay;\n}\n\nexport function setTagArrowExpanded(arrow: HTMLElement, expanded: boolean) {\n arrow.style.transform = expanded ? 'rotate(0deg)' : 'rotate(180deg)';\n}\n\nfunction createTagArrowSvg() {\n const svgNs = 'http://www.w3.org/2000/svg';\n const svg = document.createElementNS(svgNs, 'svg');\n svg.setAttribute('xmlns', svgNs);\n svg.setAttribute('width', '12');\n svg.setAttribute('height', '12');\n svg.setAttribute('viewBox', '0 0 12 12');\n svg.setAttribute('fill', 'none');\n svg.style.display = 'block';\n\n const path = document.createElementNS(svgNs, 'path');\n path.setAttribute('stroke', 'rgba(51, 51, 51, 1)');\n path.setAttribute('stroke-width', '0.8325');\n path.setAttribute('stroke-linejoin', 'round');\n path.setAttribute('stroke-linecap', 'round');\n path.setAttribute('d', 'M3.24994 7.5L6.24994 4.5L9.24994 7.5');\n svg.appendChild(path);\n\n return svg;\n}\n\nexport function positionOverlay(\n overlay: HTMLDivElement,\n target: Element,\n tagMode: 'none' | 'hover' | 'selected' = 'none',\n callbacks?: {\n onTagClick?: (target: Element, tag: HTMLDivElement) => void;\n },\n) {\n const rect = target.getBoundingClientRect();\n overlay.style.top = `${rect.top + window.scrollY}px`;\n overlay.style.left = `${rect.left + window.scrollX}px`;\n overlay.style.width = `${rect.width}px`;\n overlay.style.height = `${rect.height}px`;\n\n if (tagMode !== 'none') {\n let tag = overlay.querySelector('[data-tag-label]') as HTMLDivElement | null;\n if (!tag) {\n tag = document.createElement('div');\n tag.setAttribute(AGENT_ATTR, '');\n tag.setAttribute('data-tag-label', '');\n Object.assign(tag.style, {\n position: 'absolute',\n padding: '2px 8px',\n fontSize: '11px',\n fontWeight: '500',\n borderRadius: '3px',\n minWidth: '24px',\n textAlign: 'center',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: '3px',\n lineHeight: '1.4',\n whiteSpace: 'nowrap',\n });\n\n if (tagMode === 'selected') {\n tag.style.backgroundColor = '#FC0';\n tag.style.color = '#000000';\n tag.style.cursor = 'pointer';\n tag.style.pointerEvents = 'auto';\n\n const textSpan = document.createElement('span');\n textSpan.textContent = target.tagName.toLowerCase();\n textSpan.style.display = 'inline-flex';\n textSpan.style.alignItems = 'center';\n textSpan.style.lineHeight = '1';\n tag.appendChild(textSpan);\n\n const arrow = document.createElement('span');\n arrow.setAttribute('data-tag-arrow', '');\n arrow.textContent = '';\n arrow.style.display = 'inline-flex';\n arrow.style.alignItems = 'center';\n arrow.style.justifyContent = 'center';\n arrow.style.width = '12px';\n arrow.style.height = '12px';\n arrow.style.flex = '0 0 auto';\n arrow.style.transformOrigin = 'center';\n arrow.style.lineHeight = '1';\n arrow.appendChild(createTagArrowSvg());\n setTagArrowExpanded(arrow, false);\n tag.appendChild(arrow);\n\n if (callbacks?.onTagClick) {\n const onTagClick = callbacks.onTagClick;\n tag.addEventListener('click', (e) => {\n e.stopPropagation();\n onTagClick(target, tag as HTMLDivElement);\n });\n }\n } else {\n tag.style.backgroundColor = 'rgba(255, 204, 0, 0.7)';\n tag.style.color = '#000000';\n tag.style.pointerEvents = 'none';\n tag.textContent = target.tagName.toLowerCase();\n }\n\n overlay.appendChild(tag);\n }\n positionTag(tag, rect);\n }\n}\n\nfunction positionTag(tag: HTMLElement, rect: DOMRect) {\n const isNearTop = rect.top < 27;\n const isTallEnough = rect.height >= 54;\n const isFullWidth = rect.width >= window.innerWidth - 4;\n const leftOffset = isFullWidth ? 8 : 4;\n\n if (isNearTop && isTallEnough) {\n tag.style.top = '2px';\n } else if (isNearTop) {\n tag.style.top = `${rect.height + 2}px`;\n } else {\n tag.style.top = '-27px';\n }\n\n tag.style.left = `${leftOffset}px`;\n\n requestAnimationFrame(() => {\n const tagRect = tag.getBoundingClientRect();\n if (tagRect.right > window.innerWidth - 4) {\n const shift = tagRect.right - window.innerWidth + 8;\n tag.style.left = `${leftOffset - shift}px`;\n }\n if (tagRect.left < 4) {\n const shift = 4 - tagRect.left;\n tag.style.left = `${leftOffset + shift}px`;\n }\n });\n}\n\n// =====================================================\n// 清理函数\n// =====================================================\n\nexport function clearHoverOverlays(state: AgentState) {\n state.hoverOverlays.forEach((o) => o.remove());\n state.hoverOverlays = [];\n state.currentHoverId = null;\n}\n\nexport function clearSelectionOverlays(state: AgentState, removeDropdown: () => void) {\n state.selectionOverlays.forEach((o) => o.remove());\n state.selectionOverlays = [];\n removeDropdown();\n}\n\nexport function clearAllOverlays(state: AgentState, removeDropdown: () => void) {\n clearHoverOverlays(state);\n clearSelectionOverlays(state, removeDropdown);\n state.selectedId = null;\n state.selectedElement = null;\n}\n\n// =====================================================\n// 冻结动画与 pointer-events\n// =====================================================\n\nexport function freezeAnimations() {\n document.documentElement.setAttribute('data-visual-edit-active', '');\n\n if (!document.getElementById('freeze-animations')) {\n const style = document.createElement('style');\n style.id = 'freeze-animations';\n style.setAttribute(AGENT_ATTR, '');\n style.textContent = `\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *),\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *)::before,\n [data-visual-edit-active] *:not([${AGENT_ATTR}]):not([${AGENT_ATTR}] *)::after {\n animation-play-state: paused !important;\n transition: none !important;\n }\n `;\n document.head.appendChild(style);\n }\n\n if (!document.getElementById('freeze-overflow')) {\n const overflowStyle = document.createElement('style');\n overflowStyle.id = 'freeze-overflow';\n overflowStyle.setAttribute(AGENT_ATTR, '');\n overflowStyle.textContent = `\n html[data-visual-edit-active] {\n overflow-y: scroll !important;\n overflow-x: hidden !important;\n }\n `;\n document.head.appendChild(overflowStyle);\n }\n\n if (!document.getElementById('freeze-pointer-events')) {\n const pointerStyle = document.createElement('style');\n pointerStyle.id = 'freeze-pointer-events';\n pointerStyle.setAttribute(AGENT_ATTR, '');\n pointerStyle.textContent = `\n [data-visual-edit-active] * { pointer-events: none !important; }\n [${AGENT_ATTR}], [${AGENT_ATTR}] * { pointer-events: auto !important; }\n `;\n document.head.appendChild(pointerStyle);\n }\n\n try {\n document.getAnimations().forEach((anim) => {\n const effect = anim.effect as KeyframeEffect | null;\n const target = effect?.target;\n if (target instanceof Element && target.closest(`[${AGENT_ATTR}]`)) return;\n try {\n anim.finish();\n } catch {\n anim.pause();\n }\n });\n } catch {\n // getAnimations 在某些环境下不可用\n }\n}\n\nexport function unfreezeAnimations() {\n document.documentElement.removeAttribute('data-visual-edit-active');\n\n const freezeStyle = document.getElementById('freeze-animations');\n if (freezeStyle) freezeStyle.remove();\n\n const pointerStyle = document.getElementById('freeze-pointer-events');\n if (pointerStyle) pointerStyle.remove();\n\n const overflowStyle = document.getElementById('freeze-overflow');\n if (overflowStyle) overflowStyle.remove();\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { LayerItem } from '../shared/types';\nimport { reportDropdownState } from './messages';\nimport { setTagArrowExpanded } from './overlay';\nimport type { AgentState } from './state';\nimport { hasSourceLocation } from './utils';\n\n// =====================================================\n// 层级导航(Layer Dropdown)\n// =====================================================\n\nexport function buildLayerTree(element: Element): LayerItem[] {\n const tree: LayerItem[] = [];\n\n const ancestors: Element[] = [];\n let parent = element.parentElement;\n while (parent && parent !== document.body) {\n if (hasSourceLocation(parent)) {\n ancestors.push(parent);\n }\n parent = parent.parentElement;\n }\n ancestors.reverse();\n\n ancestors.forEach((el) => {\n tree.push({ element: el, tagName: el.tagName.toLowerCase(), depth: 0 });\n });\n\n tree.push({ element, tagName: element.tagName.toLowerCase(), depth: 0 });\n\n for (let i = 0; i < element.children.length; i++) {\n const child = element.children[i];\n if (hasSourceLocation(child)) {\n tree.push({ element: child, tagName: child.tagName.toLowerCase(), depth: 0 });\n }\n }\n\n return tree;\n}\n\nexport function removeLayerDropdown(state: AgentState) {\n if (state.layerDropdown) {\n const parentOverlay = state.layerDropdown.parentElement;\n if (parentOverlay) {\n const arrowEl = parentOverlay.querySelector('[data-tag-arrow]') as HTMLElement | null;\n if (arrowEl) setTagArrowExpanded(arrowEl, false);\n }\n state.layerDropdown.remove();\n state.layerDropdown = null;\n reportDropdownState(state, false);\n document.removeEventListener('keydown', handleLayerKeyboard);\n }\n}\n\nexport function toggleLayerDropdown(\n state: AgentState,\n element: Element,\n anchor: HTMLDivElement,\n onSelectElement: (el: Element) => void,\n) {\n if (state.layerDropdown) {\n removeLayerDropdown(state);\n return;\n }\n\n const layers = buildLayerTree(element);\n renderLayerDropdown(state, anchor, layers, element, onSelectElement);\n}\n\nfunction renderLayerDropdown(\n state: AgentState,\n anchor: HTMLElement,\n layers: LayerItem[],\n currentElement: Element,\n onSelectElement: (el: Element) => void,\n) {\n const dropdown = document.createElement('div');\n dropdown.setAttribute('data-layer-dropdown', 'true');\n dropdown.setAttribute(AGENT_ATTR, '');\n Object.assign(dropdown.style, {\n position: 'absolute',\n backgroundColor: '#ffffff',\n border: '1px solid #e2e8f0',\n borderRadius: '6px',\n boxShadow: '0 4px 12px rgba(0,0,0,0.15)',\n fontSize: '12px',\n zIndex: '2147483647',\n pointerEvents: 'auto',\n padding: '4px 0',\n minWidth: '120px',\n maxHeight: '320px',\n overflowY: 'auto',\n });\n\n let focusedIndex = -1;\n const items: HTMLDivElement[] = [];\n\n layers.forEach((layer, idx) => {\n const item = document.createElement('div');\n item.setAttribute(AGENT_ATTR, '');\n item.textContent = layer.tagName;\n item.style.padding = '6px 16px';\n item.style.cursor = 'pointer';\n item.style.whiteSpace = 'nowrap';\n\n if (layer.element === currentElement) {\n item.style.color = '#000000';\n item.style.backgroundColor = 'rgba(255, 204, 0, 0.2)';\n item.style.fontWeight = '600';\n focusedIndex = idx;\n } else {\n item.style.color = '#64748b';\n }\n\n item.addEventListener('click', (e) => {\n e.stopPropagation();\n removeLayerDropdown(state);\n onSelectElement(layer.element);\n });\n\n item.addEventListener('mouseenter', () => {\n if (layer.element !== currentElement) {\n item.style.backgroundColor = '#f1f5f9';\n item.style.color = '#334155';\n }\n });\n\n item.addEventListener('mouseleave', () => {\n if (layer.element !== currentElement) {\n item.style.backgroundColor = 'transparent';\n item.style.color = '#64748b';\n }\n });\n\n items.push(item);\n dropdown.appendChild(item);\n });\n\n document.body.appendChild(dropdown);\n\n const anchorRect = anchor.getBoundingClientRect();\n dropdown.style.top = `${anchorRect.bottom + window.scrollY + 2}px`;\n dropdown.style.left = `${anchorRect.left + window.scrollX}px`;\n\n requestAnimationFrame(() => {\n const ddRect = dropdown.getBoundingClientRect();\n if (ddRect.right > window.innerWidth - 4) {\n dropdown.style.left = `${window.innerWidth - ddRect.width - 4 + window.scrollX}px`;\n }\n if (ddRect.left < 4) {\n dropdown.style.left = `${4 + window.scrollX}px`;\n }\n if (ddRect.bottom > window.innerHeight) {\n dropdown.style.top = `${anchorRect.top + window.scrollY - ddRect.height - 2}px`;\n }\n });\n\n state.layerDropdown = dropdown;\n reportDropdownState(state, true);\n\n const handleKeydown = (e: KeyboardEvent) => {\n if (!state.layerDropdown) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n focusedIndex = Math.min(focusedIndex + 1, items.length - 1);\n highlightItem(items, focusedIndex, layers, currentElement);\n break;\n case 'ArrowUp':\n e.preventDefault();\n focusedIndex = Math.max(focusedIndex - 1, 0);\n highlightItem(items, focusedIndex, layers, currentElement);\n break;\n case 'Enter':\n e.preventDefault();\n if (focusedIndex >= 0 && focusedIndex < layers.length) {\n removeLayerDropdown(state);\n onSelectElement(layers[focusedIndex].element);\n }\n break;\n case 'Escape':\n e.preventDefault();\n removeLayerDropdown(state);\n break;\n }\n };\n\n (handleLayerKeyboard as { current?: (e: KeyboardEvent) => void }).current = handleKeydown;\n document.addEventListener('keydown', handleLayerKeyboard);\n}\n\nfunction handleLayerKeyboard(e: KeyboardEvent) {\n const current = (handleLayerKeyboard as { current?: (e: KeyboardEvent) => void }).current;\n if (current) current(e);\n}\n\nfunction highlightItem(\n items: HTMLDivElement[],\n index: number,\n layers: LayerItem[],\n currentElement: Element,\n) {\n items.forEach((item, i) => {\n if (layers[i].element === currentElement) {\n item.style.color = '#000000';\n item.style.backgroundColor =\n i === index ? 'rgba(255, 204, 0, 0.35)' : 'rgba(255, 204, 0, 0.2)';\n item.style.fontWeight = '600';\n } else {\n item.style.backgroundColor = i === index ? '#f1f5f9' : 'transparent';\n item.style.color = i === index ? '#334155' : '#64748b';\n item.style.fontWeight = 'normal';\n }\n });\n}\n","import type { VisualEditAgentOptions } from '../shared/types';\nimport { DEFAULT_ATTRIBUTE_NAME } from '../shared/constants';\n\n/** agent 运行时内部状态 */\nexport interface AgentState {\n editModeEnabled: boolean;\n selectedId: string | null;\n selectedElement: Element | null;\n hoverOverlays: HTMLDivElement[];\n selectionOverlays: HTMLDivElement[];\n currentHoverId: string | null;\n editingElement: HTMLElement | null;\n layerDropdown: HTMLDivElement | null;\n mutationObserver: MutationObserver | null;\n attributeName: string;\n targetOrigin: string;\n runtimeIdCounter: number;\n}\n\nexport function createAgentState(options: VisualEditAgentOptions = {}): AgentState {\n return {\n editModeEnabled: false,\n selectedId: null,\n selectedElement: null,\n hoverOverlays: [],\n selectionOverlays: [],\n currentHoverId: null,\n editingElement: null,\n layerDropdown: null,\n mutationObserver: null,\n attributeName: options.attributeName ?? DEFAULT_ATTRIBUTE_NAME,\n targetOrigin: options.targetOrigin ?? '*',\n runtimeIdCounter: 0,\n };\n}\n","import { AGENT_ATTR } from '../shared/constants';\nimport type { VisualEditAgentInstance, VisualEditAgentOptions } from '../shared/types';\nimport { stopInlineEditing } from './inline-edit';\nimport { handleInlineEdit } from './inline-edit';\nimport { removeLayerDropdown, toggleLayerDropdown } from './layer-navigation';\nimport { handleMessage, reportElementSelected, reportPositionUpdate } from './messages';\nimport {\n clearAllOverlays,\n clearHoverOverlays,\n clearSelectionOverlays,\n createOverlay,\n freezeAnimations,\n positionOverlay,\n setTagArrowExpanded,\n unfreezeAnimations,\n} from './overlay';\nimport { createAgentState } from './state';\nimport { findAllElementsById, getSourceId } from './utils';\n\n/**\n * 初始化 VisualEditAgent。\n * 在 iframe 内调用,负责元素选择、高亮、DOM 修改和消息通信。\n */\nexport function setupVisualEditAgent(\n options: VisualEditAgentOptions = {},\n): VisualEditAgentInstance {\n const state = createAgentState(options);\n const trackedSelector = `[${state.attributeName}], [data-visual-selector-id]`;\n\n function shouldAssignRuntimeId(element: Element) {\n return (\n !element.closest(`[${AGENT_ATTR}]`) &&\n !element.hasAttribute(state.attributeName) &&\n !element.hasAttribute('data-visual-selector-id')\n );\n }\n\n function assignRuntimeId(element: Element) {\n if (!shouldAssignRuntimeId(element)) return;\n\n state.runtimeIdCounter += 1;\n element.setAttribute('data-visual-selector-id', `runtime:${state.runtimeIdCounter}`);\n }\n\n function trackElementSubtree(root: Element) {\n assignRuntimeId(root);\n root.querySelectorAll('*').forEach((element) => assignRuntimeId(element));\n }\n\n function trackCurrentDom() {\n if (!document.body) return;\n trackElementSubtree(document.body);\n }\n\n function ensureElementTracked(element: Element) {\n if (!element.closest(`[${AGENT_ATTR}]`)) {\n assignRuntimeId(element);\n }\n }\n\n // --- 更新所有 overlay 位置 ---\n\n function updateAllOverlayPositions() {\n if (state.selectedId && state.selectedElement?.isConnected) {\n const siblings = findAllElementsById(state.selectedId);\n state.selectionOverlays.forEach((overlay, i) => {\n if (siblings[i]) {\n positionOverlay(overlay, siblings[i], i === 0 ? 'selected' : 'none', {\n onTagClick: onTagClick,\n });\n }\n });\n }\n reportPositionUpdate(state);\n }\n\n // --- Tag 点击回调 ---\n\n function onTagClick(target: Element, tag: HTMLDivElement) {\n const arrowEl = tag.querySelector('[data-tag-arrow]') as HTMLElement | null;\n if (arrowEl) {\n setTagArrowExpanded(arrowEl, !state.layerDropdown);\n }\n toggleLayerDropdown(state, target, tag, selectElement);\n }\n\n // --- 元素查找(穿透 overlay) ---\n\n function findElementAtPoint(x: number, y: number): Element | null {\n const freezeStyle = document.getElementById('freeze-pointer-events') as HTMLStyleElement | null;\n if (freezeStyle) freezeStyle.disabled = true;\n\n const element = document.elementFromPoint(x, y);\n\n if (freezeStyle) freezeStyle.disabled = false;\n\n if (!element) return null;\n if (element.closest(`[${AGENT_ATTR}]`)) return null;\n\n const trackedElement = element.closest(trackedSelector);\n if (trackedElement) return trackedElement;\n\n ensureElementTracked(element);\n return element.hasAttribute('data-visual-selector-id') ? element : null;\n }\n\n function findHoverTarget(x: number, y: number, excludeId: string | null): string | null {\n const element = findElementAtPoint(x, y);\n if (!element) return null;\n\n const id = getSourceId(element);\n if (!id || id === excludeId) return null;\n\n return id;\n }\n\n // --- Hover 高亮 ---\n\n function onMouseMove(e: MouseEvent) {\n if (!state.editModeEnabled) return;\n\n requestAnimationFrame(() => {\n const id = findHoverTarget(e.clientX, e.clientY, state.selectedId);\n if (!id) {\n clearHoverOverlays(state);\n return;\n }\n if (id === state.currentHoverId) return;\n\n clearHoverOverlays(state);\n\n const elements = findAllElementsById(id);\n elements.forEach((el, i) => {\n const overlay = createOverlay({ selected: false });\n overlay.setAttribute(AGENT_ATTR, '');\n document.body.appendChild(overlay);\n positionOverlay(overlay, el, i === 0 ? 'hover' : 'none');\n state.hoverOverlays.push(overlay);\n });\n\n state.currentHoverId = id;\n });\n }\n\n function onMouseLeave() {\n clearHoverOverlays(state);\n }\n\n // --- Click 选中 ---\n\n function onClick(e: MouseEvent) {\n if (!state.editModeEnabled) return;\n\n const target = e.target as Element;\n\n if (target?.closest?.(`[data-layer-dropdown]`)) return;\n if (\n target?.closest?.(`[data-tag-label]`) &&\n state.selectionOverlays.some((o) => o.contains(target))\n )\n return;\n\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n\n clearHoverOverlays(state);\n\n const element = findElementAtPoint(e.clientX, e.clientY);\n if (!element) return;\n\n selectElement(element);\n }\n\n function selectElement(element: Element) {\n ensureElementTracked(element);\n const id = getSourceId(element);\n if (!id) return;\n\n if (state.editingElement) {\n stopInlineEditing(state, updateAllOverlayPositions);\n }\n\n clearSelectionOverlays(state, () => removeLayerDropdown(state));\n\n const siblings = findAllElementsById(id);\n siblings.forEach((el, i) => {\n const overlay = createOverlay({ selected: true });\n overlay.setAttribute(AGENT_ATTR, '');\n document.body.appendChild(overlay);\n positionOverlay(overlay, el, i === 0 ? 'selected' : 'none', {\n onTagClick: onTagClick,\n });\n state.selectionOverlays.push(overlay);\n });\n\n state.selectedId = id;\n state.selectedElement = element;\n\n clearHoverOverlays(state);\n reportElementSelected(state, element);\n }\n\n // --- 位置持续更新 ---\n\n let rafPending = false;\n const throttledPositionUpdate = () => {\n if (rafPending) return;\n rafPending = true;\n requestAnimationFrame(() => {\n rafPending = false;\n reportPositionUpdate(state);\n });\n };\n\n // --- 激活/停用选择模式 ---\n\n function enableEditMode(enabled: boolean, _specs?: { newInlineEditEnabled?: boolean }) {\n state.editModeEnabled = enabled;\n\n if (enabled) {\n document.body.style.cursor = 'crosshair';\n freezeAnimations();\n trackCurrentDom();\n document.addEventListener('mousemove', onMouseMove);\n document.addEventListener('mouseleave', onMouseLeave);\n document.addEventListener('click', onClick, true);\n window.addEventListener('scroll', throttledPositionUpdate, true);\n document.addEventListener('scroll', throttledPositionUpdate, true);\n window.addEventListener('resize', updateAllOverlayPositions);\n\n startMutationObserver();\n } else {\n document.body.style.cursor = 'default';\n unfreezeAnimations();\n clearAllOverlays(state, () => removeLayerDropdown(state));\n\n if (state.editingElement) {\n stopInlineEditing(state, updateAllOverlayPositions);\n }\n\n document.removeEventListener('mousemove', onMouseMove);\n document.removeEventListener('mouseleave', onMouseLeave);\n document.removeEventListener('click', onClick, true);\n window.removeEventListener('scroll', throttledPositionUpdate, true);\n document.removeEventListener('scroll', throttledPositionUpdate, true);\n window.removeEventListener('resize', updateAllOverlayPositions);\n\n stopMutationObserver();\n }\n }\n\n // --- MutationObserver ---\n\n function startMutationObserver() {\n if (state.mutationObserver) return;\n\n state.mutationObserver = new MutationObserver((mutations) => {\n mutations.forEach((mutation) => {\n mutation.addedNodes.forEach((node) => {\n if (node instanceof Element) {\n trackElementSubtree(node);\n }\n });\n });\n\n const hasRelevantChange = mutations.some((m) => {\n if (\n m.type === 'attributes' &&\n ['style', 'class', 'width', 'height'].includes(m.attributeName ?? '') &&\n containsTrackedElement(m.target)\n )\n return true;\n if (m.type === 'childList' && containsTrackedElement(m.target)) return true;\n return false;\n });\n if (hasRelevantChange) {\n setTimeout(updateAllOverlayPositions, 50);\n }\n });\n\n state.mutationObserver.observe(document.body, {\n attributes: true,\n childList: true,\n subtree: true,\n attributeFilter: ['style', 'class', 'width', 'height'],\n });\n }\n\n function stopMutationObserver() {\n if (state.mutationObserver) {\n state.mutationObserver.disconnect();\n state.mutationObserver = null;\n }\n }\n\n function containsTrackedElement(node: Node): boolean {\n if (!(node instanceof Element)) return false;\n if (node.closest(`[${AGENT_ATTR}]`)) return false;\n return (\n node.hasAttribute(state.attributeName) ||\n node.hasAttribute('data-visual-selector-id') ||\n !!node.querySelector(trackedSelector)\n );\n }\n\n // --- Sandbox Mount Observer ---\n\n function setupSandboxMountObserver() {\n if (window.self === window.top) return;\n\n const mountObserver = new MutationObserver((mutations) => {\n const hasChanges = mutations.some(\n (m) => m.addedNodes.length > 0 || m.removedNodes.length > 0,\n );\n if (!hasChanges) return;\n\n const hasTrackedElements =\n document.body.querySelectorAll(\n `[${state.attributeName}], [data-dynamic-content], [data-visual-selector-id]`,\n ).length > 0;\n\n try {\n window.parent.postMessage(\n {\n type: hasTrackedElements ? 'sandbox:onMounted' : 'sandbox:onUnmounted',\n },\n state.targetOrigin,\n );\n } catch {\n // 静默忽略\n }\n });\n\n if (document.body) {\n mountObserver.observe(document.body, { childList: true, subtree: true });\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n mountObserver.observe(document.body, { childList: true, subtree: true });\n });\n }\n }\n\n // --- 消息监听器 ---\n\n function selectElementById(id: string) {\n const element = document.querySelector(\n `[${state.attributeName}=\"${id}\"], [data-visual-selector-id=\"${id}\"]`,\n );\n if (element) {\n selectElement(element);\n }\n }\n\n function clearSelectionState() {\n clearAllOverlays(state, () => removeLayerDropdown(state));\n }\n\n const onMessage = (e: MessageEvent) => {\n handleMessage(state, e, {\n enableEditMode,\n updateAllOverlayPositions,\n stopInlineEditing: () => stopInlineEditing(state, updateAllOverlayPositions),\n handleInlineEdit: (data) => handleInlineEdit(state, data, updateAllOverlayPositions),\n selectElementById,\n clearSelectionState,\n });\n };\n\n // --- 初始化 ---\n\n window.addEventListener('message', onMessage);\n setupSandboxMountObserver();\n\n try {\n window.parent.postMessage({ type: 'visual-edit-agent-ready' }, state.targetOrigin);\n } catch {\n // 静默忽略\n }\n\n // --- 返回控制接口 ---\n\n return {\n destroy() {\n window.removeEventListener('message', onMessage);\n if (state.editModeEnabled) {\n enableEditMode(false);\n }\n },\n enableEditMode,\n selectElement,\n clearSelection() {\n clearSelectionState();\n },\n getSelectedId() {\n return state.selectedId;\n },\n };\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -165,7 +165,7 @@ interface PopoverDragStateMessage {
|
|
|
165
165
|
isDragging: boolean;
|
|
166
166
|
};
|
|
167
167
|
}
|
|
168
|
-
/**
|
|
168
|
+
/** iframe ↔ 主页面:下拉菜单状态 */
|
|
169
169
|
interface DropdownStateMessage {
|
|
170
170
|
type: 'dropdown-state';
|
|
171
171
|
data: {
|
|
@@ -180,7 +180,13 @@ interface RefreshPageMessage {
|
|
|
180
180
|
interface RequestElementPositionMessage {
|
|
181
181
|
type: 'request-element-position';
|
|
182
182
|
}
|
|
183
|
-
/**
|
|
183
|
+
/** 主页面 → iframe:根据 ID 选中元素 */
|
|
184
|
+
interface SelectElementByIdMessage {
|
|
185
|
+
type: 'select-element-by-id';
|
|
186
|
+
data: {
|
|
187
|
+
visualSelectorId: string;
|
|
188
|
+
};
|
|
189
|
+
}
|
|
184
190
|
interface LayerItem {
|
|
185
191
|
element: Element;
|
|
186
192
|
tagName: string;
|
|
@@ -201,4 +207,4 @@ interface VisualEditAgentInstance {
|
|
|
201
207
|
*/
|
|
202
208
|
declare function setupVisualEditAgent(options?: VisualEditAgentOptions): VisualEditAgentInstance;
|
|
203
209
|
|
|
204
|
-
export { type AgentReadyMessage as A, type ContentEditingMessage as C, type DropdownStateMessage as D, type ElementPosition as E, type InjectFontImportMessage as I, type LayerItem as L, type PopoverDragStateMessage as P, type RefreshPageMessage as R, type SandboxMountMessage as S, type ToggleInlineEditModeMessage as T, type UnselectElementMessage as U, type VisualSelectorPluginOptions as V, type ElementPositionUpdateMessage as a, type ElementSelectedMessage as b, type ElementUpdateMessage as c, type InlineEditMessage as d, type RequestElementPositionMessage as e, type
|
|
210
|
+
export { type AgentReadyMessage as A, type ContentEditingMessage as C, type DropdownStateMessage as D, type ElementPosition as E, type InjectFontImportMessage as I, type LayerItem as L, type PopoverDragStateMessage as P, type RefreshPageMessage as R, type SandboxMountMessage as S, type ToggleInlineEditModeMessage as T, type UnselectElementMessage as U, type VisualSelectorPluginOptions as V, type ElementPositionUpdateMessage as a, type ElementSelectedMessage as b, type ElementUpdateMessage as c, type InlineEditMessage as d, type RequestElementPositionMessage as e, type SelectElementByIdMessage as f, type ToggleVisualEditModeMessage as g, type UpdateAttributeMessage as h, type UpdateClassesMessage as i, type UpdateContentMessage as j, type UpdateThemeVariablesMessage as k, type VisualEditAgentInstance as l, type VisualEditAgentOptions as m, type VisualSelectorControlMessage as n, setupVisualEditAgent as s };
|
package/dist/runtime.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { s as setupVisualEditAgent } from './runtime-
|
|
1
|
+
export { s as setupVisualEditAgent } from './runtime-D695qvel.js';
|