vite-plugin-visual-selector 0.1.1 → 0.1.2

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Plugin } from 'vite';
2
- import { V as VisualSelectorPluginOptions } from './runtime-rRIWQKz-.js';
3
- export { A as AgentReadyMessage, C as ContentEditingMessage, D as DropdownStateMessage, E as ElementPosition, a as ElementPositionUpdateMessage, b as ElementSelectedMessage, c as ElementUpdateMessage, I as InjectFontImportMessage, d as InlineEditMessage, L as LayerItem, P as PopoverDragStateMessage, R as RefreshPageMessage, e as RequestElementPositionMessage, S as SandboxMountMessage, T as ToggleInlineEditModeMessage, f as ToggleVisualEditModeMessage, U as UnselectElementMessage, g as UpdateAttributeMessage, h as UpdateClassesMessage, i as UpdateContentMessage, j as UpdateThemeVariablesMessage, k as VisualEditAgentInstance, l as VisualEditAgentOptions, m as VisualSelectorControlMessage, s as setupVisualEditAgent } from './runtime-rRIWQKz-.js';
2
+ import { V as VisualSelectorPluginOptions } from './runtime-CpZH1D8y.js';
3
+ export { A as AgentReadyMessage, C as ContentEditingMessage, D as DropdownStateMessage, E as ElementPosition, a as ElementPositionUpdateMessage, b as ElementSelectedMessage, c as ElementUpdateMessage, I as InjectFontImportMessage, d as InlineEditMessage, L as LayerItem, P as PopoverDragStateMessage, R as RefreshPageMessage, e as RequestElementPositionMessage, S as SandboxMountMessage, T as ToggleInlineEditModeMessage, f as ToggleVisualEditModeMessage, U as UnselectElementMessage, g as UpdateAttributeMessage, h as UpdateClassesMessage, i as UpdateContentMessage, j as UpdateThemeVariablesMessage, k as VisualEditAgentInstance, l as VisualEditAgentOptions, m as VisualSelectorControlMessage, s as setupVisualEditAgent } from './runtime-CpZH1D8y.js';
4
4
 
5
5
  /**
6
6
  * 创建 Vite 插件:在编译阶段(transform hook)向每个原生 JSX 元素注入
package/dist/index.js CHANGED
@@ -407,7 +407,7 @@ function reportElementSelected(state, element) {
407
407
  tagName,
408
408
  classes: typeof el.className === "string" ? el.className : "",
409
409
  visualSelectorId: getSourceId(element),
410
- content: isTextElement ? el.innerText : void 0,
410
+ content: el.innerText,
411
411
  dataSourceLocation: el.dataset?.sourceLocation,
412
412
  isDynamicContent: el.dataset?.dynamicContent === "true",
413
413
  position: getElementPosition(element),
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: isTextElement ? el.innerText : undefined,\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":";AAAA,SAAS,aAAa;AACtB,OAAO,eAAe;AACtB,YAAY,OAAO;AAOnB,OAAO,iBAAiB;AACxB,OAAO,UAAU;;;ACTV,IAAM,yBAAyB;AAG/B,IAAM,uBAAuB;AAG7B,IAAM,aAAa;;;ADF1B,IAAM,WACJ,OAAO,cAAc,aACjB,YACC,UAA4C;AAYnD,SAAS,mBAAmB,MAAc,UAAkB;AAC1D,SAAO,KAAK,SAAS,MAAM,QAAQ,EAAE,MAAM,KAAK,GAAG,EAAE,KAAK,GAAG;AAC/D;AAMA,SAAS,mBAAmB,MAA2B;AACrD,SAAS,kBAAgB,KAAK,IAAI,KAAK,SAAS,KAAK,KAAK,KAAK,IAAI;AACrE;AAKA,SAAS,2BAA2B,MAA2B,eAAuB;AACpF,SAAO,KAAK,WAAW;AAAA,IACrB,CAAC,cACG,iBAAe,SAAS,KACxB,kBAAgB,UAAU,IAAI,KAChC,UAAU,KAAK,SAAS;AAAA,EAC5B;AACF;AAMO,SAAS,qBAAqB,UAAuC,CAAC,GAAW;AACtF,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,OAAO,QAAQ,QAAQ,QAAQ,IAAI;AAEzC,QAAM,UAAU,QAAQ,WAAW,CAAC,WAAW;AAE/C,QAAM,UAAU,QAAQ,WAAW,CAAC,cAAc;AAElD,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA;AAAA,IACT,UAAU,MAAM,IAAI;AAElB,UAAI,CAAC,QAAQ,KAAK,CAAC,YAAY,QAAQ,KAAK,EAAE,CAAC,GAAG;AAChD,eAAO;AAAA,MACT;AAGA,UAAI,QAAQ,KAAK,CAAC,YAAY,QAAQ,KAAK,EAAE,CAAC,GAAG;AAC/C,eAAO;AAAA,MACT;AAEA,UAAI;AACJ,UAAI;AACF,cAAM,MAAM,MAAM;AAAA,UAChB,YAAY;AAAA,UACZ,SAAS,CAAC,OAAO,YAAY;AAAA,QAC/B,CAAC;AAAA,MACH,QAAQ;AAEN,eAAO;AAAA,MACT;AAEA,YAAM,cAAc,IAAI,YAAY,IAAI;AACxC,UAAI,UAAU;AAEd,eAAS,KAAK;AAAA;AAAA,QAEZ,kBAAkB,SAAS;AACzB,gBAAM,OAAO,QAAQ;AAGrB,cAAI,CAAC,mBAAmB,IAAI,GAAG;AAC7B;AAAA,UACF;AAGA,cAAI,2BAA2B,MAAM,aAAa,GAAG;AACnD;AAAA,UACF;AAGA,cAAI,CAAC,KAAK,OAAO,KAAK,KAAK,OAAO,MAAM;AACtC;AAAA,UACF;AAGA,gBAAM,WAAW,GAAG,mBAAmB,MAAM,EAAE,CAAC,IAAI,KAAK,IAAI,MAAM,IAAI,IAAI,KAAK,IAAI,MAAM,SAAS,CAAC;AAEpG,sBAAY,WAAW,KAAK,KAAK,KAAK,IAAI,aAAa,KAAK,QAAQ,GAAG;AACvE,oBAAU;AAAA,QACZ;AAAA,MACF,CAAC;AAGD,UAAI,CAAC,SAAS;AACZ,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,QACL,MAAM,YAAY,SAAS;AAAA,QAC3B,KAAK,YAAY,YAAY,EAAE,OAAO,KAAK,CAAC;AAAA;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACF;;;AExHO,SAAS,SAAiD,IAAO,IAAe;AACrF,MAAI,QAA8C;AAClD,UAAQ,IAAI,SAAoB;AAC9B,QAAI,MAAO,cAAa,KAAK;AAC7B,YAAQ,WAAW,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE;AAAA,EAC1C;AACF;AAGO,SAAS,YAAY,SAAiC;AAC3D,SACG,QAAwB,SAAS,kBACjC,QAAwB,SAAS,oBAClC;AAEJ;AAGO,SAAS,oBAAoB,IAAuB;AACzD,MAAI,WAAW,MAAM,KAAK,SAAS,iBAAiB,0BAA0B,EAAE,IAAI,CAAC;AACrF,MAAI,SAAS,WAAW,GAAG;AACzB,eAAW,MAAM,KAAK,SAAS,iBAAiB,6BAA6B,EAAE,IAAI,CAAC;AAAA,EACtF;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,IAAsB;AACtD,SAAO,GAAG,aAAa,sBAAsB,KAAK,GAAG,aAAa,yBAAyB;AAC7F;AAGO,SAAS,mBAAmB,SAAmC;AACpE,QAAM,OAAO,QAAQ,sBAAsB;AAC3C,SAAO;AAAA,IACL,KAAK,KAAK;AAAA,IACV,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,OAAO,KAAK,QAAQ;AAAA,IAClC,SAAS,KAAK,MAAM,KAAK,SAAS;AAAA,EACpC;AACF;AAGO,IAAM,YAAY,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK,OAAO;AAGhF,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC5DO,SAAS,cAAc,SAA+B;AAC3D,SACE,iBAAiB,SAAS,QAAQ,QAAQ,YAAY,CAAC,KACvD,CAAC,CAAC,QAAQ,aAAa,KAAK,KAC5B,CAAC,QAAQ,cAAc,yBAAyB,KAChD,QAAQ,SAAS,WAAW;AAEhC;AAEO,SAAS,mBAAmB,OAAmB,SAAsB;AAC1E,MAAI,CAAC,cAAc,OAAO,EAAG;AAE7B,QAAM,iBAAiB;AACvB,UAAQ,QAAQ,sBAAsB,QAAQ,eAAe;AAC7D,UAAQ,kBAAkB;AAC1B,UAAQ,aAAa,YAAY,EAAE;AACnC,UAAQ,MAAM,SAAS;AAEvB,QAAM,QAAQ,SAAS,YAAY;AACnC,QAAM,mBAAmB,OAAO;AAChC,QAAM,MAAM,OAAO,aAAa;AAChC,OAAK,gBAAgB;AACrB,OAAK,SAAS,KAAK;AACnB,UAAQ,MAAM;AAEd,QAAM,kBAAkB,QAAQ,CAAC,MAAO,EAAE,MAAM,UAAU,MAAO;AAEjE,QAAM,kBAAkB,SAAS,MAAM;AACrC,QAAI;AACF,aAAO,OAAO;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,aAAa;AAAA,YACX,SAAS,QAAQ;AAAA,YACjB,kBAAkB,MAAM;AAAA,YACxB,oBAAoB,QAAQ,SAAS;AAAA,UACvC;AAAA,UACA,iBAAiB,QAAQ,QAAQ,uBAAuB;AAAA,UACxD,YAAY,QAAQ,eAAe;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,GAAG;AAEN,UAAQ,iBAAiB,SAAS,eAAe;AACjD,EAAC,QAAkE,sBACjE;AAEF,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,kBAAkB,OAAmB,iBAA6B;AAChF,MAAI,CAAC,MAAM,eAAgB;AAE3B,QAAM,eAAe,kBAAkB;AACvC,QAAM,eAAe,gBAAgB,UAAU;AAC/C,QAAM,eAAe,MAAM,SAAS;AAEpC,QAAM,UAAW,MAAM,eACpB;AACH,MAAI,SAAS;AACX,UAAM,eAAe,oBAAoB,SAAS,OAAO;AACzD,WAAQ,MAAM,eACX;AAAA,EACL;AAEA,QAAM,kBAAkB,QAAQ,CAAC,MAAO,EAAE,MAAM,UAAU,EAAG;AAC7D,kBAAgB;AAEhB,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,iBAAiB;AACzB;AAEO,SAAS,iBACd,OACA,MACA,iBACA;AACA,MAAI,KAAK,mBAAmB;AAC1B,UAAM,KAAK,SAAS;AAAA,MAClB,0BAA0B,KAAK,kBAAkB;AAAA,IACnD;AACA,QAAI,IAAI;AACN,yBAAmB,OAAO,EAAE;AAAA,IAC9B;AAAA,EACF,OAAO;AACL,sBAAkB,OAAO,eAAe;AAAA,EAC1C;AACF;;;AC/GO,SAAS,eAAe,SAA+B;AAC5D,QAAM,OAAoB,CAAC;AAE3B,QAAM,YAAuB,CAAC;AAC9B,MAAI,SAAS,QAAQ;AACrB,SAAO,UAAU,WAAW,SAAS,MAAM;AACzC,QAAI,kBAAkB,MAAM,GAAG;AAC7B,gBAAU,KAAK,MAAM;AAAA,IACvB;AACA,aAAS,OAAO;AAAA,EAClB;AACA,YAAU,QAAQ;AAElB,YAAU,QAAQ,CAAC,OAAO;AACxB,SAAK,KAAK,EAAE,SAAS,IAAI,SAAS,GAAG,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAAA,EACxE,CAAC;AAED,OAAK,KAAK,EAAE,SAAS,SAAS,QAAQ,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAEvE,WAAS,IAAI,GAAG,IAAI,QAAQ,SAAS,QAAQ,KAAK;AAChD,UAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,QAAI,kBAAkB,KAAK,GAAG;AAC5B,WAAK,KAAK,EAAE,SAAS,OAAO,SAAS,MAAM,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB,OAAmB;AACrD,MAAI,MAAM,eAAe;AACvB,UAAM,gBAAgB,MAAM,cAAc;AAC1C,QAAI,eAAe;AACjB,YAAM,UAAU,cAAc,cAAc,kBAAkB;AAC9D,UAAI,QAAS,SAAQ,cAAc;AAAA,IACrC;AACA,UAAM,cAAc,OAAO;AAC3B,UAAM,gBAAgB;AACtB,aAAS,oBAAoB,WAAW,mBAAmB;AAAA,EAC7D;AACF;AAEO,SAAS,oBACd,OACA,SACA,QACA,iBACA;AACA,MAAI,MAAM,eAAe;AACvB,wBAAoB,KAAK;AACzB;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,OAAO;AACrC,sBAAoB,OAAO,QAAQ,QAAQ,SAAS,eAAe;AACrE;AAEA,SAAS,oBACP,OACA,QACA,QACA,gBACA,iBACA;AACA,QAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,WAAS,aAAa,uBAAuB,MAAM;AACnD,WAAS,aAAa,YAAY,EAAE;AACpC,SAAO,OAAO,SAAS,OAAO;AAAA,IAC5B,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,MAAI,eAAe;AACnB,QAAM,QAA0B,CAAC;AAEjC,SAAO,QAAQ,CAAC,OAAO,QAAQ;AAC7B,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,aAAa,YAAY,EAAE;AAChC,SAAK,cAAc,MAAM;AACzB,SAAK,MAAM,UAAU;AACrB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,aAAa;AAExB,QAAI,MAAM,YAAY,gBAAgB;AACpC,WAAK,MAAM,QAAQ;AACnB,WAAK,MAAM,kBAAkB;AAC7B,WAAK,MAAM,aAAa;AACxB,qBAAe;AAAA,IACjB,OAAO;AACL,WAAK,MAAM,QAAQ;AAAA,IACrB;AAEA,SAAK,iBAAiB,SAAS,CAAC,MAAM;AACpC,QAAE,gBAAgB;AAClB,0BAAoB,KAAK;AACzB,sBAAgB,MAAM,OAAO;AAAA,IAC/B,CAAC;AAED,SAAK,iBAAiB,cAAc,MAAM;AACxC,UAAI,MAAM,YAAY,gBAAgB;AACpC,aAAK,MAAM,kBAAkB;AAC7B,aAAK,MAAM,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AAED,SAAK,iBAAiB,cAAc,MAAM;AACxC,UAAI,MAAM,YAAY,gBAAgB;AACpC,aAAK,MAAM,kBAAkB;AAC7B,aAAK,MAAM,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AAED,UAAM,KAAK,IAAI;AACf,aAAS,YAAY,IAAI;AAAA,EAC3B,CAAC;AAED,WAAS,KAAK,YAAY,QAAQ;AAElC,QAAM,aAAa,OAAO,sBAAsB;AAChD,WAAS,MAAM,MAAM,GAAG,WAAW,SAAS,OAAO,UAAU,CAAC;AAC9D,WAAS,MAAM,OAAO,GAAG,WAAW,OAAO,OAAO,OAAO;AAEzD,wBAAsB,MAAM;AAC1B,UAAM,SAAS,SAAS,sBAAsB;AAC9C,QAAI,OAAO,QAAQ,OAAO,aAAa,GAAG;AACxC,eAAS,MAAM,OAAO,GAAG,OAAO,aAAa,OAAO,QAAQ,IAAI,OAAO,OAAO;AAAA,IAChF;AACA,QAAI,OAAO,OAAO,GAAG;AACnB,eAAS,MAAM,OAAO,GAAG,IAAI,OAAO,OAAO;AAAA,IAC7C;AACA,QAAI,OAAO,SAAS,OAAO,aAAa;AACtC,eAAS,MAAM,MAAM,GAAG,WAAW,MAAM,OAAO,UAAU,OAAO,SAAS,CAAC;AAAA,IAC7E;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB;AAEtB,QAAM,gBAAgB,CAAC,MAAqB;AAC1C,QAAI,CAAC,MAAM,cAAe;AAE1B,YAAQ,EAAE,KAAK;AAAA,MACb,KAAK;AACH,UAAE,eAAe;AACjB,uBAAe,KAAK,IAAI,eAAe,GAAG,MAAM,SAAS,CAAC;AAC1D,sBAAc,OAAO,cAAc,QAAQ,cAAc;AACzD;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,uBAAe,KAAK,IAAI,eAAe,GAAG,CAAC;AAC3C,sBAAc,OAAO,cAAc,QAAQ,cAAc;AACzD;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,YAAI,gBAAgB,KAAK,eAAe,OAAO,QAAQ;AACrD,8BAAoB,KAAK;AACzB,0BAAgB,OAAO,YAAY,EAAE,OAAO;AAAA,QAC9C;AACA;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,4BAAoB,KAAK;AACzB;AAAA,IACJ;AAAA,EACF;AAEA,EAAC,oBAAiE,UAAU;AAC5E,WAAS,iBAAiB,WAAW,mBAAmB;AAC1D;AAEA,SAAS,oBAAoB,GAAkB;AAC7C,QAAM,UAAW,oBAAiE;AAClF,MAAI,QAAS,SAAQ,CAAC;AACxB;AAEA,SAAS,cACP,OACA,OACA,QACA,gBACA;AACA,QAAM,QAAQ,CAAC,MAAM,MAAM;AACzB,QAAI,OAAO,CAAC,EAAE,YAAY,gBAAgB;AACxC,WAAK,MAAM,QAAQ;AACnB,WAAK,MAAM,kBACT,MAAM,QAAQ,4BAA4B;AAC5C,WAAK,MAAM,aAAa;AAAA,IAC1B,OAAO;AACL,WAAK,MAAM,kBAAkB,MAAM,QAAQ,YAAY;AACvD,WAAK,MAAM,QAAQ,MAAM,QAAQ,YAAY;AAC7C,WAAK,MAAM,aAAa;AAAA,IAC1B;AAAA,EACF,CAAC;AACH;;;AC1MO,SAAS,sBAAsB,OAAmB,SAAkB;AACzE,QAAM,KAAK;AACX,QAAM,UAAU,QAAQ;AACxB,QAAM,gBAAgB,UAAU,SAAS,OAAO;AAEhD,QAAM,WAAW,OAAO,iBAAiB,EAAE;AAC3C,QAAM,iBAAyC;AAAA,IAC7C,YAAY,SAAS;AAAA,IACrB,UAAU,SAAS;AAAA,IACnB,YAAY,SAAS;AAAA,IACrB,WAAW,SAAS;AAAA,IACpB,gBAAgB,SAAS;AAAA,IACzB,oBAAoB,SAAS;AAAA,IAC7B,OAAO,SAAS;AAAA,IAChB,iBAAiB,SAAS;AAAA,IAC1B,YAAY,SAAS;AAAA,IACrB,eAAe,SAAS;AAAA,IACxB,SAAS,SAAS;AAAA,EACpB;AAEA,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN;AAAA,QACA,SAAS,OAAO,GAAG,cAAc,WAAW,GAAG,YAAY;AAAA,QAC3D,kBAAkB,YAAY,OAAO;AAAA,QACrC,SAAS,gBAAgB,GAAG,YAAY;AAAA,QACxC,oBAAoB,GAAG,SAAS;AAAA,QAChC,kBAAkB,GAAG,SAAS,mBAAmB;AAAA,QACjD,UAAU,mBAAmB,OAAO;AAAA,QACpC,YAAY,CAAC;AAAA,QACb;AAAA,QACA,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,MACF;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAAqB,OAAmB;AACtD,MAAI,CAAC,MAAM,cAAc,CAAC,MAAM,iBAAiB,YAAa;AAE9D,QAAM,OAAO,MAAM,gBAAgB,sBAAsB;AACzD,QAAM,eACJ,KAAK,MAAM,OAAO,eAClB,KAAK,SAAS,KACd,KAAK,OAAO,OAAO,cACnB,KAAK,QAAQ;AAEf,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,UAAU,mBAAmB,MAAM,eAAe;AAAA,QAClD;AAAA,QACA,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAaO,SAAS,cACd,OACA,GACA,WACA;AACA,MAAI,MAAM,iBAAiB,OAAO,EAAE,WAAW,MAAM,aAAc;AAEnE,QAAM,MAAM,EAAE;AACd,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,CAAC,IAAI,KAAM;AAElD,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AACH,gBAAU,eAAe,IAAI,MAAM,WAAW,OAAO,IAAI,MAAM,KAAK;AACpE;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,OAAO,IAAI,MAAM,YAAY,UAAU;AACvE,4BAAoB,IAAI,KAAK,gBAAgB,EAAE;AAAA,UAAQ,CAAC,OACtD,GAAG,aAAa,SAAS,IAAI,KAAK,OAAO;AAAA,QAC3C;AACA,mBAAW,UAAU,2BAA2B,EAAE;AAAA,MACpD;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,IAAI,MAAM,aAAa,IAAI,MAAM,UAAU,QAAW;AACtF,4BAAoB,IAAI,KAAK,gBAAgB,EAAE;AAAA,UAAQ,CAAC,OACtD,GAAG,aAAa,IAAI,KAAK,WAAW,IAAI,KAAK,KAAK;AAAA,QACpD;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,IAAI,MAAM,YAAY,QAAW;AACjE,4BAAoB,IAAI,KAAK,gBAAgB,EAAE,QAAQ,CAAC,OAAO;AAC7D,UAAC,GAAmB,YAAY,IAAI,KAAK;AAAA,QAC3C,CAAC;AACD,mBAAW,UAAU,2BAA2B,EAAE;AAAA,MACpD;AACA;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,eAAgB,WAAU,kBAAkB;AAEtD,YAAM,kBAAkB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AACjD,YAAM,oBAAoB,CAAC;AAC3B,YAAM,aAAa;AACnB,YAAM,kBAAkB;AACxB;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,WAAW;AACvB,cAAM,OACJ,IAAI,KAAK,SAAS,SAAS,SAAS,cAAc,OAAO,IAAI,SAAS;AACxE,YAAI,MAAM;AACR,qBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,KAAK,SAAS,GAAG;AAC9D,YAAC,KAAqB,MAAM,YAAY,MAAM,KAAe;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM;AACZ,kBAAU,iBAAiB,IAAI,IAAI;AAAA,MACrC;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,WAAW,eAAe,KAAK,IAAI,KAAK,OAAO,GAAG;AAC9D,cAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,aAAK,MAAM;AACX,aAAK,OAAO,IAAI,KAAK;AACrB,aAAK,aAAa,YAAY,EAAE;AAChC,iBAAS,KAAK,YAAY,IAAI;AAAA,MAChC;AACA;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IAEF,KAAK;AACH,aAAO,SAAS,OAAO;AACvB;AAAA,IAEF,KAAK;AACH,2BAAqB,KAAK;AAC1B;AAAA,IAEF,KAAK,sBAAsB;AACzB,YAAM,aAAa;AACnB,UAAI,OAAO,WAAW,WAAW,WAAW;AAC1C,kBAAU,eAAe,WAAW,MAAM;AAAA,MAC5C;AACA;AAAA,IACF;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,gCAA0B,OAAO,GAA2B;AAC5D;AAAA,EACJ;AACF;AAEA,SAAS,0BAA0B,OAAmB,KAA2B;AAC/E,MAAI,CAAC,IAAI,mBAAoB;AAE7B,QAAM,KAAK,SAAS;AAAA,IAClB,IAAI,MAAM,aAAa,KAAK,IAAI,kBAAkB;AAAA,EACpD;AACA,MAAI,CAAC,GAAI;AAET,MAAI,IAAI,SAAS,0BAA0B,IAAI,QAAQ;AACrD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACtD,SAAG,MAAM;AAAA,QACP,KAAK,QAAQ,UAAU,CAAC,MAAM,IAAI,EAAE,YAAY,CAAC,EAAE;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,IAAI,SAAS,yBAAyB,OAAO,IAAI,SAAS,UAAU;AAC7E,OAAG,cAAc,IAAI;AAAA,EACvB,WAAW,IAAI,SAAS,0BAA0B,OAAO,IAAI,cAAc,UAAU;AACnF,OAAG,YAAY,IAAI;AAAA,EACrB;AACF;;;AChNO,SAAS,cAAc,MAA6C;AACzE,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,aAAa,YAAY,EAAE;AACnC,UAAQ,MAAM,WAAW;AACzB,UAAQ,MAAM,gBAAgB;AAC9B,UAAQ,MAAM,SAAS;AACvB,UAAQ,MAAM,YAAY;AAE1B,MAAI,KAAK,UAAU;AACjB,YAAQ,MAAM,YAAY;AAAA,EAC5B,OAAO;AACL,YAAQ,MAAM,YAAY;AAC1B,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEA,SAAO;AACT;AAEO,SAAS,gBACd,SACA,QACA,UAAyC,QACzC,WAGA;AACA,QAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAQ,MAAM,MAAM,GAAG,KAAK,MAAM,OAAO,OAAO;AAChD,UAAQ,MAAM,OAAO,GAAG,KAAK,OAAO,OAAO,OAAO;AAClD,UAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK;AACnC,UAAQ,MAAM,SAAS,GAAG,KAAK,MAAM;AAErC,MAAI,YAAY,QAAQ;AACtB,QAAI,MAAM,QAAQ,cAAc,kBAAkB;AAClD,QAAI,CAAC,KAAK;AACR,YAAM,SAAS,cAAc,KAAK;AAClC,UAAI,aAAa,YAAY,EAAE;AAC/B,UAAI,aAAa,kBAAkB,EAAE;AACrC,aAAO,OAAO,IAAI,OAAO;AAAA,QACvB,UAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,YAAY;AAAA,MACd,CAAC;AAED,UAAI,YAAY,YAAY;AAC1B,YAAI,MAAM,kBAAkB;AAC5B,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,SAAS;AACnB,YAAI,MAAM,gBAAgB;AAE1B,cAAM,WAAW,SAAS,cAAc,MAAM;AAC9C,iBAAS,cAAc,OAAO,QAAQ,YAAY;AAClD,YAAI,YAAY,QAAQ;AAExB,cAAM,QAAQ,SAAS,cAAc,MAAM;AAC3C,cAAM,aAAa,kBAAkB,EAAE;AACvC,cAAM,cAAc;AACpB,cAAM,MAAM,WAAW;AACvB,cAAM,MAAM,aAAa;AACzB,YAAI,YAAY,KAAK;AAErB,YAAI,WAAW,YAAY;AACzB,gBAAM,aAAa,UAAU;AAC7B,cAAI,iBAAiB,SAAS,CAAC,MAAM;AACnC,cAAE,gBAAgB;AAClB,uBAAW,QAAQ,GAAqB;AAAA,UAC1C,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,YAAI,MAAM,kBAAkB;AAC5B,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,gBAAgB;AAC1B,YAAI,cAAc,OAAO,QAAQ,YAAY;AAAA,MAC/C;AAEA,cAAQ,YAAY,GAAG;AAAA,IACzB;AACA,gBAAY,KAAK,IAAI;AAAA,EACvB;AACF;AAEA,SAAS,YAAY,KAAkB,MAAe;AACpD,QAAM,YAAY,KAAK,MAAM;AAC7B,QAAM,eAAe,KAAK,UAAU;AACpC,QAAM,cAAc,KAAK,SAAS,OAAO,aAAa;AACtD,QAAM,aAAa,cAAc,IAAI;AAErC,MAAI,aAAa,cAAc;AAC7B,QAAI,MAAM,MAAM;AAAA,EAClB,WAAW,WAAW;AACpB,QAAI,MAAM,MAAM,GAAG,KAAK,SAAS,CAAC;AAAA,EACpC,OAAO;AACL,QAAI,MAAM,MAAM;AAAA,EAClB;AAEA,MAAI,MAAM,OAAO,GAAG,UAAU;AAE9B,wBAAsB,MAAM;AAC1B,UAAM,UAAU,IAAI,sBAAsB;AAC1C,QAAI,QAAQ,QAAQ,OAAO,aAAa,GAAG;AACzC,YAAM,QAAQ,QAAQ,QAAQ,OAAO,aAAa;AAClD,UAAI,MAAM,OAAO,GAAG,aAAa,KAAK;AAAA,IACxC;AACA,QAAI,QAAQ,OAAO,GAAG;AACpB,YAAM,QAAQ,IAAI,QAAQ;AAC1B,UAAI,MAAM,OAAO,GAAG,aAAa,KAAK;AAAA,IACxC;AAAA,EACF,CAAC;AACH;AAMO,SAAS,mBAAmB,OAAmB;AACpD,QAAM,cAAc,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAC7C,QAAM,gBAAgB,CAAC;AACvB,QAAM,iBAAiB;AACzB;AAEO,SAAS,uBAAuB,OAAmB,gBAA4B;AACpF,QAAM,kBAAkB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AACjD,QAAM,oBAAoB,CAAC;AAC3B,iBAAe;AACjB;AAEO,SAAS,iBAAiB,OAAmB,gBAA4B;AAC9E,qBAAmB,KAAK;AACxB,yBAAuB,OAAO,cAAc;AAC5C,QAAM,aAAa;AACnB,QAAM,kBAAkB;AAC1B;AAMO,SAAS,mBAAmB;AACjC,WAAS,gBAAgB,aAAa,2BAA2B,EAAE;AAEnE,MAAI,CAAC,SAAS,eAAe,mBAAmB,GAAG;AACjD,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,aAAa,YAAY,EAAE;AACjC,UAAM,cAAc;AAAA,yCACiB,UAAU,WAAW,UAAU;AAAA,yCAC/B,UAAU,WAAW,UAAU;AAAA,yCAC/B,UAAU,WAAW,UAAU;AAAA;AAAA;AAAA;AAAA;AAKpE,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,MAAI,CAAC,SAAS,eAAe,iBAAiB,GAAG;AAC/C,UAAM,gBAAgB,SAAS,cAAc,OAAO;AACpD,kBAAc,KAAK;AACnB,kBAAc,aAAa,YAAY,EAAE;AACzC,kBAAc,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAM5B,aAAS,KAAK,YAAY,aAAa;AAAA,EACzC;AAEA,MAAI,CAAC,SAAS,eAAe,uBAAuB,GAAG;AACrD,UAAM,eAAe,SAAS,cAAc,OAAO;AACnD,iBAAa,KAAK;AAClB,iBAAa,aAAa,YAAY,EAAE;AACxC,iBAAa,cAAc;AAAA;AAAA,SAEtB,UAAU,OAAO,UAAU;AAAA;AAEhC,aAAS,KAAK,YAAY,YAAY;AAAA,EACxC;AAEA,MAAI;AACF,aAAS,cAAc,EAAE,QAAQ,CAAC,SAAS;AACzC,YAAM,SAAS,KAAK;AACpB,YAAM,SAAS,QAAQ;AACvB,UAAI,kBAAkB,WAAW,OAAO,QAAQ,IAAI,UAAU,GAAG,EAAG;AACpE,UAAI;AACF,aAAK,OAAO;AAAA,MACd,QAAQ;AACN,aAAK,MAAM;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAAqB;AACnC,WAAS,gBAAgB,gBAAgB,yBAAyB;AAElE,QAAM,cAAc,SAAS,eAAe,mBAAmB;AAC/D,MAAI,YAAa,aAAY,OAAO;AAEpC,QAAM,eAAe,SAAS,eAAe,uBAAuB;AACpE,MAAI,aAAc,cAAa,OAAO;AAEtC,QAAM,gBAAgB,SAAS,eAAe,iBAAiB;AAC/D,MAAI,cAAe,eAAc,OAAO;AAC1C;;;AC3MO,SAAS,iBAAiB,UAAkC,CAAC,GAAe;AACjF,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe,CAAC;AAAA,IAChB,mBAAmB,CAAC;AAAA,IACpB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe,QAAQ,iBAAiB;AAAA,IACxC,cAAc,QAAQ,gBAAgB;AAAA,EACxC;AACF;;;ACVO,SAAS,qBACd,UAAkC,CAAC,GACV;AACzB,QAAM,QAAQ,iBAAiB,OAAO;AAItC,WAAS,4BAA4B;AACnC,QAAI,MAAM,cAAc,MAAM,iBAAiB,aAAa;AAC1D,YAAM,WAAW,oBAAoB,MAAM,UAAU;AACrD,YAAM,kBAAkB,QAAQ,CAAC,SAAS,MAAM;AAC9C,YAAI,SAAS,CAAC,GAAG;AACf,0BAAgB,SAAS,SAAS,CAAC,GAAG,MAAM,IAAI,aAAa,QAAQ;AAAA,YACnE;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AACA,yBAAqB,KAAK;AAAA,EAC5B;AAIA,WAAS,WAAW,QAAiB,KAAqB;AACxD,UAAM,UAAU,IAAI,cAAc,kBAAkB;AACpD,QAAI,SAAS;AACX,cAAQ,cAAc,MAAM,gBAAgB,WAAW;AAAA,IACzD;AACA,wBAAoB,OAAO,QAAQ,KAAK,aAAa;AAAA,EACvD;AAIA,WAAS,mBAAmB,GAAW,GAA2B;AAChE,UAAM,cAAc,SAAS,eAAe,uBAAuB;AACnE,QAAI,YAAa,aAAY,WAAW;AAExC,UAAM,UAAU,SAAS,iBAAiB,GAAG,CAAC;AAE9C,QAAI,YAAa,aAAY,WAAW;AAExC,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI,QAAQ,QAAQ,IAAI,UAAU,GAAG,EAAG,QAAO;AAE/C,WAAO,QAAQ,QAAQ,IAAI,MAAM,aAAa,8BAA8B,KAAK;AAAA,EACnF;AAEA,WAAS,gBAAgB,GAAW,GAAW,WAAyC;AACtF,UAAM,UAAU,mBAAmB,GAAG,CAAC;AACvC,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,KAAK,YAAY,OAAO;AAC9B,QAAI,CAAC,MAAM,OAAO,UAAW,QAAO;AAEpC,WAAO;AAAA,EACT;AAIA,WAAS,YAAY,GAAe;AAClC,QAAI,CAAC,MAAM,gBAAiB;AAE5B,0BAAsB,MAAM;AAC1B,YAAM,KAAK,gBAAgB,EAAE,SAAS,EAAE,SAAS,MAAM,UAAU;AACjE,UAAI,CAAC,IAAI;AACP,2BAAmB,KAAK;AACxB;AAAA,MACF;AACA,UAAI,OAAO,MAAM,eAAgB;AAEjC,yBAAmB,KAAK;AAExB,YAAM,WAAW,oBAAoB,EAAE;AACvC,eAAS,QAAQ,CAAC,IAAI,MAAM;AAC1B,cAAM,UAAU,cAAc,EAAE,UAAU,MAAM,CAAC;AACjD,gBAAQ,aAAa,YAAY,EAAE;AACnC,iBAAS,KAAK,YAAY,OAAO;AACjC,wBAAgB,SAAS,IAAI,MAAM,IAAI,UAAU,MAAM;AACvD,cAAM,cAAc,KAAK,OAAO;AAAA,MAClC,CAAC;AAED,YAAM,iBAAiB;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,WAAS,eAAe;AACtB,uBAAmB,KAAK;AAAA,EAC1B;AAIA,WAAS,QAAQ,GAAe;AAC9B,QAAI,CAAC,MAAM,gBAAiB;AAE5B,UAAM,SAAS,EAAE;AAEjB,QAAI,QAAQ,UAAU,uBAAuB,EAAG;AAChD,QACE,QAAQ,UAAU,kBAAkB,KACpC,MAAM,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC;AAEtD;AAEF,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,MAAE,yBAAyB;AAE3B,uBAAmB,KAAK;AAExB,UAAM,UAAU,mBAAmB,EAAE,SAAS,EAAE,OAAO;AACvD,QAAI,CAAC,QAAS;AAEd,kBAAc,OAAO;AAAA,EACvB;AAEA,WAAS,cAAc,SAAkB;AACvC,UAAM,KAAK,YAAY,OAAO;AAC9B,QAAI,CAAC,GAAI;AAET,QAAI,MAAM,gBAAgB;AACxB,wBAAkB,OAAO,yBAAyB;AAAA,IACpD;AAEA,2BAAuB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAE9D,UAAM,WAAW,oBAAoB,EAAE;AACvC,aAAS,QAAQ,CAAC,IAAI,MAAM;AAC1B,YAAM,UAAU,cAAc,EAAE,UAAU,KAAK,CAAC;AAChD,cAAQ,aAAa,YAAY,EAAE;AACnC,eAAS,KAAK,YAAY,OAAO;AACjC,sBAAgB,SAAS,IAAI,MAAM,IAAI,aAAa,QAAQ;AAAA,QAC1D;AAAA,MACF,CAAC;AACD,YAAM,kBAAkB,KAAK,OAAO;AAAA,IACtC,CAAC;AAED,UAAM,aAAa;AACnB,UAAM,kBAAkB;AAExB,uBAAmB,KAAK;AACxB,0BAAsB,OAAO,OAAO;AAAA,EACtC;AAIA,MAAI,aAAa;AACjB,QAAM,0BAA0B,MAAM;AACpC,QAAI,WAAY;AAChB,iBAAa;AACb,0BAAsB,MAAM;AAC1B,mBAAa;AACb,2BAAqB,KAAK;AAAA,IAC5B,CAAC;AAAA,EACH;AAIA,WAAS,eAAe,SAAkB,QAA6C;AACrF,UAAM,kBAAkB;AAExB,QAAI,SAAS;AACX,eAAS,KAAK,MAAM,SAAS;AAC7B,uBAAiB;AACjB,eAAS,iBAAiB,aAAa,WAAW;AAClD,eAAS,iBAAiB,cAAc,YAAY;AACpD,eAAS,iBAAiB,SAAS,SAAS,IAAI;AAChD,aAAO,iBAAiB,UAAU,yBAAyB,IAAI;AAC/D,eAAS,iBAAiB,UAAU,yBAAyB,IAAI;AACjE,aAAO,iBAAiB,UAAU,yBAAyB;AAE3D,4BAAsB;AAAA,IACxB,OAAO;AACL,eAAS,KAAK,MAAM,SAAS;AAC7B,yBAAmB;AACnB,uBAAiB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAExD,UAAI,MAAM,gBAAgB;AACxB,0BAAkB,OAAO,yBAAyB;AAAA,MACpD;AAEA,eAAS,oBAAoB,aAAa,WAAW;AACrD,eAAS,oBAAoB,cAAc,YAAY;AACvD,eAAS,oBAAoB,SAAS,SAAS,IAAI;AACnD,aAAO,oBAAoB,UAAU,yBAAyB,IAAI;AAClE,eAAS,oBAAoB,UAAU,yBAAyB,IAAI;AACpE,aAAO,oBAAoB,UAAU,yBAAyB;AAE9D,2BAAqB;AAAA,IACvB;AAAA,EACF;AAIA,WAAS,wBAAwB;AAC/B,QAAI,MAAM,iBAAkB;AAE5B,UAAM,mBAAmB,IAAI,iBAAiB,CAAC,cAAc;AAC3D,YAAM,oBAAoB,UAAU,KAAK,CAAC,MAAM;AAC9C,YACE,EAAE,SAAS,gBACX,CAAC,SAAS,SAAS,SAAS,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,KACpE,uBAAuB,EAAE,MAAM;AAE/B,iBAAO;AACT,YAAI,EAAE,SAAS,eAAe,uBAAuB,EAAE,MAAM,EAAG,QAAO;AACvE,eAAO;AAAA,MACT,CAAC;AACD,UAAI,mBAAmB;AACrB,mBAAW,2BAA2B,EAAE;AAAA,MAC1C;AAAA,IACF,CAAC;AAED,UAAM,iBAAiB,QAAQ,SAAS,MAAM;AAAA,MAC5C,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS,SAAS,SAAS,QAAQ;AAAA,IACvD,CAAC;AAAA,EACH;AAEA,WAAS,uBAAuB;AAC9B,QAAI,MAAM,kBAAkB;AAC1B,YAAM,iBAAiB,WAAW;AAClC,YAAM,mBAAmB;AAAA,IAC3B;AAAA,EACF;AAEA,WAAS,uBAAuB,MAAqB;AACnD,QAAI,EAAE,gBAAgB,SAAU,QAAO;AACvC,QAAI,KAAK,aAAa,UAAU,EAAG,QAAO;AAC1C,WAAO,kBAAkB,IAAI,KAAK,CAAC,CAAC,KAAK,cAAc,IAAI,MAAM,aAAa,GAAG;AAAA,EACnF;AAIA,WAAS,4BAA4B;AACnC,QAAI,OAAO,SAAS,OAAO,IAAK;AAEhC,UAAM,gBAAgB,IAAI,iBAAiB,CAAC,cAAc;AACxD,YAAM,aAAa,UAAU;AAAA,QAC3B,CAAC,MAAM,EAAE,WAAW,SAAS,KAAK,EAAE,aAAa,SAAS;AAAA,MAC5D;AACA,UAAI,CAAC,WAAY;AAEjB,YAAM,qBACJ,SAAS,KAAK,iBAAiB,gDAAgD,EAAE,SAAS;AAE5F,UAAI;AACF,eAAO,OAAO;AAAA,UACZ;AAAA,YACE,MAAM,qBAAqB,sBAAsB;AAAA,UACnD;AAAA,UACA,MAAM;AAAA,QACR;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAED,QAAI,SAAS,MAAM;AACjB,oBAAc,QAAQ,SAAS,MAAM,EAAE,WAAW,MAAM,SAAS,KAAK,CAAC;AAAA,IACzE,OAAO;AACL,eAAS,iBAAiB,oBAAoB,MAAM;AAClD,sBAAc,QAAQ,SAAS,MAAM,EAAE,WAAW,MAAM,SAAS,KAAK,CAAC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,YAAY,CAAC,MAAoB;AACrC,kBAAc,OAAO,GAAG;AAAA,MACtB;AAAA,MACA;AAAA,MACA,mBAAmB,MAAM,kBAAkB,OAAO,yBAAyB;AAAA,MAC3E,kBAAkB,CAAC,SAAS,iBAAiB,OAAO,MAAM,yBAAyB;AAAA,IACrF,CAAC;AAAA,EACH;AAIA,SAAO,iBAAiB,WAAW,SAAS;AAC5C,4BAA0B;AAE1B,MAAI;AACF,WAAO,OAAO,YAAY,EAAE,MAAM,0BAA0B,GAAG,MAAM,YAAY;AAAA,EACnF,QAAQ;AAAA,EAER;AAIA,SAAO;AAAA,IACL,UAAU;AACR,aAAO,oBAAoB,WAAW,SAAS;AAC/C,UAAI,MAAM,iBAAiB;AACzB,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AACf,uBAAiB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAAA,IAC1D;AAAA,IACA,gBAAgB;AACd,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;","names":[]}
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":[]}
@@ -54,7 +54,7 @@ interface ElementSelectedMessage {
54
54
  tagName: string;
55
55
  classes: string;
56
56
  visualSelectorId: string | null;
57
- content?: string;
57
+ content: string;
58
58
  dataSourceLocation?: string;
59
59
  isDynamicContent?: boolean;
60
60
  position: ElementPosition;
package/dist/runtime.d.ts CHANGED
@@ -1 +1 @@
1
- export { s as setupVisualEditAgent } from './runtime-rRIWQKz-.js';
1
+ export { s as setupVisualEditAgent } from './runtime-CpZH1D8y.js';
package/dist/runtime.js CHANGED
@@ -330,7 +330,7 @@ function reportElementSelected(state, element) {
330
330
  tagName,
331
331
  classes: typeof el.className === "string" ? el.className : "",
332
332
  visualSelectorId: getSourceId(element),
333
- content: isTextElement ? el.innerText : void 0,
333
+ content: el.innerText,
334
334
  dataSourceLocation: el.dataset?.sourceLocation,
335
335
  isDynamicContent: el.dataset?.dynamicContent === "true",
336
336
  position: getElementPosition(element),
@@ -1 +1 @@
1
- {"version":3,"sources":["../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":["// 注入到 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: isTextElement ? el.innerText : undefined,\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":";AACO,IAAM,yBAAyB;AAG/B,IAAM,uBAAuB;AAG7B,IAAM,aAAa;;;ACJnB,SAAS,SAAiD,IAAO,IAAe;AACrF,MAAI,QAA8C;AAClD,UAAQ,IAAI,SAAoB;AAC9B,QAAI,MAAO,cAAa,KAAK;AAC7B,YAAQ,WAAW,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE;AAAA,EAC1C;AACF;AAGO,SAAS,YAAY,SAAiC;AAC3D,SACG,QAAwB,SAAS,kBACjC,QAAwB,SAAS,oBAClC;AAEJ;AAGO,SAAS,oBAAoB,IAAuB;AACzD,MAAI,WAAW,MAAM,KAAK,SAAS,iBAAiB,0BAA0B,EAAE,IAAI,CAAC;AACrF,MAAI,SAAS,WAAW,GAAG;AACzB,eAAW,MAAM,KAAK,SAAS,iBAAiB,6BAA6B,EAAE,IAAI,CAAC;AAAA,EACtF;AACA,SAAO;AACT;AAGO,SAAS,kBAAkB,IAAsB;AACtD,SAAO,GAAG,aAAa,sBAAsB,KAAK,GAAG,aAAa,yBAAyB;AAC7F;AAGO,SAAS,mBAAmB,SAAmC;AACpE,QAAM,OAAO,QAAQ,sBAAsB;AAC3C,SAAO;AAAA,IACL,KAAK,KAAK;AAAA,IACV,MAAM,KAAK;AAAA,IACX,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,IACb,SAAS,KAAK,OAAO,KAAK,QAAQ;AAAA,IAClC,SAAS,KAAK,MAAM,KAAK,SAAS;AAAA,EACpC;AACF;AAGO,IAAM,YAAY,CAAC,KAAK,MAAM,MAAM,MAAM,MAAM,MAAM,MAAM,QAAQ,KAAK,OAAO;AAGhF,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;;;AC5DO,SAAS,cAAc,SAA+B;AAC3D,SACE,iBAAiB,SAAS,QAAQ,QAAQ,YAAY,CAAC,KACvD,CAAC,CAAC,QAAQ,aAAa,KAAK,KAC5B,CAAC,QAAQ,cAAc,yBAAyB,KAChD,QAAQ,SAAS,WAAW;AAEhC;AAEO,SAAS,mBAAmB,OAAmB,SAAsB;AAC1E,MAAI,CAAC,cAAc,OAAO,EAAG;AAE7B,QAAM,iBAAiB;AACvB,UAAQ,QAAQ,sBAAsB,QAAQ,eAAe;AAC7D,UAAQ,kBAAkB;AAC1B,UAAQ,aAAa,YAAY,EAAE;AACnC,UAAQ,MAAM,SAAS;AAEvB,QAAM,QAAQ,SAAS,YAAY;AACnC,QAAM,mBAAmB,OAAO;AAChC,QAAM,MAAM,OAAO,aAAa;AAChC,OAAK,gBAAgB;AACrB,OAAK,SAAS,KAAK;AACnB,UAAQ,MAAM;AAEd,QAAM,kBAAkB,QAAQ,CAAC,MAAO,EAAE,MAAM,UAAU,MAAO;AAEjE,QAAM,kBAAkB,SAAS,MAAM;AACrC,QAAI;AACF,aAAO,OAAO;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,aAAa;AAAA,YACX,SAAS,QAAQ;AAAA,YACjB,kBAAkB,MAAM;AAAA,YACxB,oBAAoB,QAAQ,SAAS;AAAA,UACvC;AAAA,UACA,iBAAiB,QAAQ,QAAQ,uBAAuB;AAAA,UACxD,YAAY,QAAQ,eAAe;AAAA,QACrC;AAAA,QACA,MAAM;AAAA,MACR;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,GAAG;AAEN,UAAQ,iBAAiB,SAAS,eAAe;AACjD,EAAC,QAAkE,sBACjE;AAEF,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,kBAAkB,OAAmB,iBAA6B;AAChF,MAAI,CAAC,MAAM,eAAgB;AAE3B,QAAM,eAAe,kBAAkB;AACvC,QAAM,eAAe,gBAAgB,UAAU;AAC/C,QAAM,eAAe,MAAM,SAAS;AAEpC,QAAM,UAAW,MAAM,eACpB;AACH,MAAI,SAAS;AACX,UAAM,eAAe,oBAAoB,SAAS,OAAO;AACzD,WAAQ,MAAM,eACX;AAAA,EACL;AAEA,QAAM,kBAAkB,QAAQ,CAAC,MAAO,EAAE,MAAM,UAAU,EAAG;AAC7D,kBAAgB;AAEhB,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,QAAM,iBAAiB;AACzB;AAEO,SAAS,iBACd,OACA,MACA,iBACA;AACA,MAAI,KAAK,mBAAmB;AAC1B,UAAM,KAAK,SAAS;AAAA,MAClB,0BAA0B,KAAK,kBAAkB;AAAA,IACnD;AACA,QAAI,IAAI;AACN,yBAAmB,OAAO,EAAE;AAAA,IAC9B;AAAA,EACF,OAAO;AACL,sBAAkB,OAAO,eAAe;AAAA,EAC1C;AACF;;;AC/GO,SAAS,eAAe,SAA+B;AAC5D,QAAM,OAAoB,CAAC;AAE3B,QAAM,YAAuB,CAAC;AAC9B,MAAI,SAAS,QAAQ;AACrB,SAAO,UAAU,WAAW,SAAS,MAAM;AACzC,QAAI,kBAAkB,MAAM,GAAG;AAC7B,gBAAU,KAAK,MAAM;AAAA,IACvB;AACA,aAAS,OAAO;AAAA,EAClB;AACA,YAAU,QAAQ;AAElB,YAAU,QAAQ,CAAC,OAAO;AACxB,SAAK,KAAK,EAAE,SAAS,IAAI,SAAS,GAAG,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAAA,EACxE,CAAC;AAED,OAAK,KAAK,EAAE,SAAS,SAAS,QAAQ,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAEvE,WAAS,IAAI,GAAG,IAAI,QAAQ,SAAS,QAAQ,KAAK;AAChD,UAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,QAAI,kBAAkB,KAAK,GAAG;AAC5B,WAAK,KAAK,EAAE,SAAS,OAAO,SAAS,MAAM,QAAQ,YAAY,GAAG,OAAO,EAAE,CAAC;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,oBAAoB,OAAmB;AACrD,MAAI,MAAM,eAAe;AACvB,UAAM,gBAAgB,MAAM,cAAc;AAC1C,QAAI,eAAe;AACjB,YAAM,UAAU,cAAc,cAAc,kBAAkB;AAC9D,UAAI,QAAS,SAAQ,cAAc;AAAA,IACrC;AACA,UAAM,cAAc,OAAO;AAC3B,UAAM,gBAAgB;AACtB,aAAS,oBAAoB,WAAW,mBAAmB;AAAA,EAC7D;AACF;AAEO,SAAS,oBACd,OACA,SACA,QACA,iBACA;AACA,MAAI,MAAM,eAAe;AACvB,wBAAoB,KAAK;AACzB;AAAA,EACF;AAEA,QAAM,SAAS,eAAe,OAAO;AACrC,sBAAoB,OAAO,QAAQ,QAAQ,SAAS,eAAe;AACrE;AAEA,SAAS,oBACP,OACA,QACA,QACA,gBACA,iBACA;AACA,QAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,WAAS,aAAa,uBAAuB,MAAM;AACnD,WAAS,aAAa,YAAY,EAAE;AACpC,SAAO,OAAO,SAAS,OAAO;AAAA,IAC5B,UAAU;AAAA,IACV,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,WAAW;AAAA,IACX,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,eAAe;AAAA,IACf,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW;AAAA,IACX,WAAW;AAAA,EACb,CAAC;AAED,MAAI,eAAe;AACnB,QAAM,QAA0B,CAAC;AAEjC,SAAO,QAAQ,CAAC,OAAO,QAAQ;AAC7B,UAAM,OAAO,SAAS,cAAc,KAAK;AACzC,SAAK,aAAa,YAAY,EAAE;AAChC,SAAK,cAAc,MAAM;AACzB,SAAK,MAAM,UAAU;AACrB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,aAAa;AAExB,QAAI,MAAM,YAAY,gBAAgB;AACpC,WAAK,MAAM,QAAQ;AACnB,WAAK,MAAM,kBAAkB;AAC7B,WAAK,MAAM,aAAa;AACxB,qBAAe;AAAA,IACjB,OAAO;AACL,WAAK,MAAM,QAAQ;AAAA,IACrB;AAEA,SAAK,iBAAiB,SAAS,CAAC,MAAM;AACpC,QAAE,gBAAgB;AAClB,0BAAoB,KAAK;AACzB,sBAAgB,MAAM,OAAO;AAAA,IAC/B,CAAC;AAED,SAAK,iBAAiB,cAAc,MAAM;AACxC,UAAI,MAAM,YAAY,gBAAgB;AACpC,aAAK,MAAM,kBAAkB;AAC7B,aAAK,MAAM,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AAED,SAAK,iBAAiB,cAAc,MAAM;AACxC,UAAI,MAAM,YAAY,gBAAgB;AACpC,aAAK,MAAM,kBAAkB;AAC7B,aAAK,MAAM,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AAED,UAAM,KAAK,IAAI;AACf,aAAS,YAAY,IAAI;AAAA,EAC3B,CAAC;AAED,WAAS,KAAK,YAAY,QAAQ;AAElC,QAAM,aAAa,OAAO,sBAAsB;AAChD,WAAS,MAAM,MAAM,GAAG,WAAW,SAAS,OAAO,UAAU,CAAC;AAC9D,WAAS,MAAM,OAAO,GAAG,WAAW,OAAO,OAAO,OAAO;AAEzD,wBAAsB,MAAM;AAC1B,UAAM,SAAS,SAAS,sBAAsB;AAC9C,QAAI,OAAO,QAAQ,OAAO,aAAa,GAAG;AACxC,eAAS,MAAM,OAAO,GAAG,OAAO,aAAa,OAAO,QAAQ,IAAI,OAAO,OAAO;AAAA,IAChF;AACA,QAAI,OAAO,OAAO,GAAG;AACnB,eAAS,MAAM,OAAO,GAAG,IAAI,OAAO,OAAO;AAAA,IAC7C;AACA,QAAI,OAAO,SAAS,OAAO,aAAa;AACtC,eAAS,MAAM,MAAM,GAAG,WAAW,MAAM,OAAO,UAAU,OAAO,SAAS,CAAC;AAAA,IAC7E;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB;AAEtB,QAAM,gBAAgB,CAAC,MAAqB;AAC1C,QAAI,CAAC,MAAM,cAAe;AAE1B,YAAQ,EAAE,KAAK;AAAA,MACb,KAAK;AACH,UAAE,eAAe;AACjB,uBAAe,KAAK,IAAI,eAAe,GAAG,MAAM,SAAS,CAAC;AAC1D,sBAAc,OAAO,cAAc,QAAQ,cAAc;AACzD;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,uBAAe,KAAK,IAAI,eAAe,GAAG,CAAC;AAC3C,sBAAc,OAAO,cAAc,QAAQ,cAAc;AACzD;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,YAAI,gBAAgB,KAAK,eAAe,OAAO,QAAQ;AACrD,8BAAoB,KAAK;AACzB,0BAAgB,OAAO,YAAY,EAAE,OAAO;AAAA,QAC9C;AACA;AAAA,MACF,KAAK;AACH,UAAE,eAAe;AACjB,4BAAoB,KAAK;AACzB;AAAA,IACJ;AAAA,EACF;AAEA,EAAC,oBAAiE,UAAU;AAC5E,WAAS,iBAAiB,WAAW,mBAAmB;AAC1D;AAEA,SAAS,oBAAoB,GAAkB;AAC7C,QAAM,UAAW,oBAAiE;AAClF,MAAI,QAAS,SAAQ,CAAC;AACxB;AAEA,SAAS,cACP,OACA,OACA,QACA,gBACA;AACA,QAAM,QAAQ,CAAC,MAAM,MAAM;AACzB,QAAI,OAAO,CAAC,EAAE,YAAY,gBAAgB;AACxC,WAAK,MAAM,QAAQ;AACnB,WAAK,MAAM,kBACT,MAAM,QAAQ,4BAA4B;AAC5C,WAAK,MAAM,aAAa;AAAA,IAC1B,OAAO;AACL,WAAK,MAAM,kBAAkB,MAAM,QAAQ,YAAY;AACvD,WAAK,MAAM,QAAQ,MAAM,QAAQ,YAAY;AAC7C,WAAK,MAAM,aAAa;AAAA,IAC1B;AAAA,EACF,CAAC;AACH;;;AC1MO,SAAS,sBAAsB,OAAmB,SAAkB;AACzE,QAAM,KAAK;AACX,QAAM,UAAU,QAAQ;AACxB,QAAM,gBAAgB,UAAU,SAAS,OAAO;AAEhD,QAAM,WAAW,OAAO,iBAAiB,EAAE;AAC3C,QAAM,iBAAyC;AAAA,IAC7C,YAAY,SAAS;AAAA,IACrB,UAAU,SAAS;AAAA,IACnB,YAAY,SAAS;AAAA,IACrB,WAAW,SAAS;AAAA,IACpB,gBAAgB,SAAS;AAAA,IACzB,oBAAoB,SAAS;AAAA,IAC7B,OAAO,SAAS;AAAA,IAChB,iBAAiB,SAAS;AAAA,IAC1B,YAAY,SAAS;AAAA,IACrB,eAAe,SAAS;AAAA,IACxB,SAAS,SAAS;AAAA,EACpB;AAEA,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN;AAAA,QACA,SAAS,OAAO,GAAG,cAAc,WAAW,GAAG,YAAY;AAAA,QAC3D,kBAAkB,YAAY,OAAO;AAAA,QACrC,SAAS,gBAAgB,GAAG,YAAY;AAAA,QACxC,oBAAoB,GAAG,SAAS;AAAA,QAChC,kBAAkB,GAAG,SAAS,mBAAmB;AAAA,QACjD,UAAU,mBAAmB,OAAO;AAAA,QACpC,YAAY,CAAC;AAAA,QACb;AAAA,QACA,iBAAiB;AAAA,QACjB,cAAc;AAAA,QACd;AAAA,MACF;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAAqB,OAAmB;AACtD,MAAI,CAAC,MAAM,cAAc,CAAC,MAAM,iBAAiB,YAAa;AAE9D,QAAM,OAAO,MAAM,gBAAgB,sBAAsB;AACzD,QAAM,eACJ,KAAK,MAAM,OAAO,eAClB,KAAK,SAAS,KACd,KAAK,OAAO,OAAO,cACnB,KAAK,QAAQ;AAEf,MAAI;AACF,WAAO,OAAO;AAAA,MACZ;AAAA,QACE,MAAM;AAAA,QACN,UAAU,mBAAmB,MAAM,eAAe;AAAA,QAClD;AAAA,QACA,kBAAkB,MAAM;AAAA,MAC1B;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF,QAAQ;AAAA,EAER;AACF;AAaO,SAAS,cACd,OACA,GACA,WACA;AACA,MAAI,MAAM,iBAAiB,OAAO,EAAE,WAAW,MAAM,aAAc;AAEnE,QAAM,MAAM,EAAE;AACd,MAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,CAAC,IAAI,KAAM;AAElD,UAAQ,IAAI,MAAM;AAAA,IAChB,KAAK;AACH,gBAAU,eAAe,IAAI,MAAM,WAAW,OAAO,IAAI,MAAM,KAAK;AACpE;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,OAAO,IAAI,MAAM,YAAY,UAAU;AACvE,4BAAoB,IAAI,KAAK,gBAAgB,EAAE;AAAA,UAAQ,CAAC,OACtD,GAAG,aAAa,SAAS,IAAI,KAAK,OAAO;AAAA,QAC3C;AACA,mBAAW,UAAU,2BAA2B,EAAE;AAAA,MACpD;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,IAAI,MAAM,aAAa,IAAI,MAAM,UAAU,QAAW;AACtF,4BAAoB,IAAI,KAAK,gBAAgB,EAAE;AAAA,UAAQ,CAAC,OACtD,GAAG,aAAa,IAAI,KAAK,WAAW,IAAI,KAAK,KAAK;AAAA,QACpD;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,oBAAoB,IAAI,MAAM,YAAY,QAAW;AACjE,4BAAoB,IAAI,KAAK,gBAAgB,EAAE,QAAQ,CAAC,OAAO;AAC7D,UAAC,GAAmB,YAAY,IAAI,KAAK;AAAA,QAC3C,CAAC;AACD,mBAAW,UAAU,2BAA2B,EAAE;AAAA,MACpD;AACA;AAAA,IAEF,KAAK;AACH,UAAI,MAAM,eAAgB,WAAU,kBAAkB;AAEtD,YAAM,kBAAkB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AACjD,YAAM,oBAAoB,CAAC;AAC3B,YAAM,aAAa;AACnB,YAAM,kBAAkB;AACxB;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,WAAW;AACvB,cAAM,OACJ,IAAI,KAAK,SAAS,SAAS,SAAS,cAAc,OAAO,IAAI,SAAS;AACxE,YAAI,MAAM;AACR,qBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,KAAK,SAAS,GAAG;AAC9D,YAAC,KAAqB,MAAM,YAAY,MAAM,KAAe;AAAA,UAC/D;AAAA,QACF;AAAA,MACF;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM;AACZ,kBAAU,iBAAiB,IAAI,IAAI;AAAA,MACrC;AACA;AAAA,IAEF,KAAK;AACH,UAAI,IAAI,MAAM,WAAW,eAAe,KAAK,IAAI,KAAK,OAAO,GAAG;AAC9D,cAAM,OAAO,SAAS,cAAc,MAAM;AAC1C,aAAK,MAAM;AACX,aAAK,OAAO,IAAI,KAAK;AACrB,aAAK,aAAa,YAAY,EAAE;AAChC,iBAAS,KAAK,YAAY,IAAI;AAAA,MAChC;AACA;AAAA,IAEF,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IAEF,KAAK;AACH,aAAO,SAAS,OAAO;AACvB;AAAA,IAEF,KAAK;AACH,2BAAqB,KAAK;AAC1B;AAAA,IAEF,KAAK,sBAAsB;AACzB,YAAM,aAAa;AACnB,UAAI,OAAO,WAAW,WAAW,WAAW;AAC1C,kBAAU,eAAe,WAAW,MAAM;AAAA,MAC5C;AACA;AAAA,IACF;AAAA,IAEA,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,gCAA0B,OAAO,GAA2B;AAC5D;AAAA,EACJ;AACF;AAEA,SAAS,0BAA0B,OAAmB,KAA2B;AAC/E,MAAI,CAAC,IAAI,mBAAoB;AAE7B,QAAM,KAAK,SAAS;AAAA,IAClB,IAAI,MAAM,aAAa,KAAK,IAAI,kBAAkB;AAAA,EACpD;AACA,MAAI,CAAC,GAAI;AAET,MAAI,IAAI,SAAS,0BAA0B,IAAI,QAAQ;AACrD,eAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,IAAI,MAAM,GAAG;AACtD,SAAG,MAAM;AAAA,QACP,KAAK,QAAQ,UAAU,CAAC,MAAM,IAAI,EAAE,YAAY,CAAC,EAAE;AAAA,QACnD;AAAA,MACF;AAAA,IACF;AAAA,EACF,WAAW,IAAI,SAAS,yBAAyB,OAAO,IAAI,SAAS,UAAU;AAC7E,OAAG,cAAc,IAAI;AAAA,EACvB,WAAW,IAAI,SAAS,0BAA0B,OAAO,IAAI,cAAc,UAAU;AACnF,OAAG,YAAY,IAAI;AAAA,EACrB;AACF;;;AChNO,SAAS,cAAc,MAA6C;AACzE,QAAM,UAAU,SAAS,cAAc,KAAK;AAC5C,UAAQ,aAAa,YAAY,EAAE;AACnC,UAAQ,MAAM,WAAW;AACzB,UAAQ,MAAM,gBAAgB;AAC9B,UAAQ,MAAM,SAAS;AACvB,UAAQ,MAAM,YAAY;AAE1B,MAAI,KAAK,UAAU;AACjB,YAAQ,MAAM,YAAY;AAAA,EAC5B,OAAO;AACL,YAAQ,MAAM,YAAY;AAC1B,YAAQ,MAAM,kBAAkB;AAAA,EAClC;AAEA,SAAO;AACT;AAEO,SAAS,gBACd,SACA,QACA,UAAyC,QACzC,WAGA;AACA,QAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAQ,MAAM,MAAM,GAAG,KAAK,MAAM,OAAO,OAAO;AAChD,UAAQ,MAAM,OAAO,GAAG,KAAK,OAAO,OAAO,OAAO;AAClD,UAAQ,MAAM,QAAQ,GAAG,KAAK,KAAK;AACnC,UAAQ,MAAM,SAAS,GAAG,KAAK,MAAM;AAErC,MAAI,YAAY,QAAQ;AACtB,QAAI,MAAM,QAAQ,cAAc,kBAAkB;AAClD,QAAI,CAAC,KAAK;AACR,YAAM,SAAS,cAAc,KAAK;AAClC,UAAI,aAAa,YAAY,EAAE;AAC/B,UAAI,aAAa,kBAAkB,EAAE;AACrC,aAAO,OAAO,IAAI,OAAO;AAAA,QACvB,UAAU;AAAA,QACV,SAAS;AAAA,QACT,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,cAAc;AAAA,QACd,UAAU;AAAA,QACV,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,YAAY;AAAA,MACd,CAAC;AAED,UAAI,YAAY,YAAY;AAC1B,YAAI,MAAM,kBAAkB;AAC5B,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,SAAS;AACnB,YAAI,MAAM,gBAAgB;AAE1B,cAAM,WAAW,SAAS,cAAc,MAAM;AAC9C,iBAAS,cAAc,OAAO,QAAQ,YAAY;AAClD,YAAI,YAAY,QAAQ;AAExB,cAAM,QAAQ,SAAS,cAAc,MAAM;AAC3C,cAAM,aAAa,kBAAkB,EAAE;AACvC,cAAM,cAAc;AACpB,cAAM,MAAM,WAAW;AACvB,cAAM,MAAM,aAAa;AACzB,YAAI,YAAY,KAAK;AAErB,YAAI,WAAW,YAAY;AACzB,gBAAM,aAAa,UAAU;AAC7B,cAAI,iBAAiB,SAAS,CAAC,MAAM;AACnC,cAAE,gBAAgB;AAClB,uBAAW,QAAQ,GAAqB;AAAA,UAC1C,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,YAAI,MAAM,kBAAkB;AAC5B,YAAI,MAAM,QAAQ;AAClB,YAAI,MAAM,gBAAgB;AAC1B,YAAI,cAAc,OAAO,QAAQ,YAAY;AAAA,MAC/C;AAEA,cAAQ,YAAY,GAAG;AAAA,IACzB;AACA,gBAAY,KAAK,IAAI;AAAA,EACvB;AACF;AAEA,SAAS,YAAY,KAAkB,MAAe;AACpD,QAAM,YAAY,KAAK,MAAM;AAC7B,QAAM,eAAe,KAAK,UAAU;AACpC,QAAM,cAAc,KAAK,SAAS,OAAO,aAAa;AACtD,QAAM,aAAa,cAAc,IAAI;AAErC,MAAI,aAAa,cAAc;AAC7B,QAAI,MAAM,MAAM;AAAA,EAClB,WAAW,WAAW;AACpB,QAAI,MAAM,MAAM,GAAG,KAAK,SAAS,CAAC;AAAA,EACpC,OAAO;AACL,QAAI,MAAM,MAAM;AAAA,EAClB;AAEA,MAAI,MAAM,OAAO,GAAG,UAAU;AAE9B,wBAAsB,MAAM;AAC1B,UAAM,UAAU,IAAI,sBAAsB;AAC1C,QAAI,QAAQ,QAAQ,OAAO,aAAa,GAAG;AACzC,YAAM,QAAQ,QAAQ,QAAQ,OAAO,aAAa;AAClD,UAAI,MAAM,OAAO,GAAG,aAAa,KAAK;AAAA,IACxC;AACA,QAAI,QAAQ,OAAO,GAAG;AACpB,YAAM,QAAQ,IAAI,QAAQ;AAC1B,UAAI,MAAM,OAAO,GAAG,aAAa,KAAK;AAAA,IACxC;AAAA,EACF,CAAC;AACH;AAMO,SAAS,mBAAmB,OAAmB;AACpD,QAAM,cAAc,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AAC7C,QAAM,gBAAgB,CAAC;AACvB,QAAM,iBAAiB;AACzB;AAEO,SAAS,uBAAuB,OAAmB,gBAA4B;AACpF,QAAM,kBAAkB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;AACjD,QAAM,oBAAoB,CAAC;AAC3B,iBAAe;AACjB;AAEO,SAAS,iBAAiB,OAAmB,gBAA4B;AAC9E,qBAAmB,KAAK;AACxB,yBAAuB,OAAO,cAAc;AAC5C,QAAM,aAAa;AACnB,QAAM,kBAAkB;AAC1B;AAMO,SAAS,mBAAmB;AACjC,WAAS,gBAAgB,aAAa,2BAA2B,EAAE;AAEnE,MAAI,CAAC,SAAS,eAAe,mBAAmB,GAAG;AACjD,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,aAAa,YAAY,EAAE;AACjC,UAAM,cAAc;AAAA,yCACiB,UAAU,WAAW,UAAU;AAAA,yCAC/B,UAAU,WAAW,UAAU;AAAA,yCAC/B,UAAU,WAAW,UAAU;AAAA;AAAA;AAAA;AAAA;AAKpE,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAEA,MAAI,CAAC,SAAS,eAAe,iBAAiB,GAAG;AAC/C,UAAM,gBAAgB,SAAS,cAAc,OAAO;AACpD,kBAAc,KAAK;AACnB,kBAAc,aAAa,YAAY,EAAE;AACzC,kBAAc,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAM5B,aAAS,KAAK,YAAY,aAAa;AAAA,EACzC;AAEA,MAAI,CAAC,SAAS,eAAe,uBAAuB,GAAG;AACrD,UAAM,eAAe,SAAS,cAAc,OAAO;AACnD,iBAAa,KAAK;AAClB,iBAAa,aAAa,YAAY,EAAE;AACxC,iBAAa,cAAc;AAAA;AAAA,SAEtB,UAAU,OAAO,UAAU;AAAA;AAEhC,aAAS,KAAK,YAAY,YAAY;AAAA,EACxC;AAEA,MAAI;AACF,aAAS,cAAc,EAAE,QAAQ,CAAC,SAAS;AACzC,YAAM,SAAS,KAAK;AACpB,YAAM,SAAS,QAAQ;AACvB,UAAI,kBAAkB,WAAW,OAAO,QAAQ,IAAI,UAAU,GAAG,EAAG;AACpE,UAAI;AACF,aAAK,OAAO;AAAA,MACd,QAAQ;AACN,aAAK,MAAM;AAAA,MACb;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,qBAAqB;AACnC,WAAS,gBAAgB,gBAAgB,yBAAyB;AAElE,QAAM,cAAc,SAAS,eAAe,mBAAmB;AAC/D,MAAI,YAAa,aAAY,OAAO;AAEpC,QAAM,eAAe,SAAS,eAAe,uBAAuB;AACpE,MAAI,aAAc,cAAa,OAAO;AAEtC,QAAM,gBAAgB,SAAS,eAAe,iBAAiB;AAC/D,MAAI,cAAe,eAAc,OAAO;AAC1C;;;AC3MO,SAAS,iBAAiB,UAAkC,CAAC,GAAe;AACjF,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,iBAAiB;AAAA,IACjB,eAAe,CAAC;AAAA,IAChB,mBAAmB,CAAC;AAAA,IACpB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe,QAAQ,iBAAiB;AAAA,IACxC,cAAc,QAAQ,gBAAgB;AAAA,EACxC;AACF;;;ACVO,SAAS,qBACd,UAAkC,CAAC,GACV;AACzB,QAAM,QAAQ,iBAAiB,OAAO;AAItC,WAAS,4BAA4B;AACnC,QAAI,MAAM,cAAc,MAAM,iBAAiB,aAAa;AAC1D,YAAM,WAAW,oBAAoB,MAAM,UAAU;AACrD,YAAM,kBAAkB,QAAQ,CAAC,SAAS,MAAM;AAC9C,YAAI,SAAS,CAAC,GAAG;AACf,0BAAgB,SAAS,SAAS,CAAC,GAAG,MAAM,IAAI,aAAa,QAAQ;AAAA,YACnE;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AACA,yBAAqB,KAAK;AAAA,EAC5B;AAIA,WAAS,WAAW,QAAiB,KAAqB;AACxD,UAAM,UAAU,IAAI,cAAc,kBAAkB;AACpD,QAAI,SAAS;AACX,cAAQ,cAAc,MAAM,gBAAgB,WAAW;AAAA,IACzD;AACA,wBAAoB,OAAO,QAAQ,KAAK,aAAa;AAAA,EACvD;AAIA,WAAS,mBAAmB,GAAW,GAA2B;AAChE,UAAM,cAAc,SAAS,eAAe,uBAAuB;AACnE,QAAI,YAAa,aAAY,WAAW;AAExC,UAAM,UAAU,SAAS,iBAAiB,GAAG,CAAC;AAE9C,QAAI,YAAa,aAAY,WAAW;AAExC,QAAI,CAAC,QAAS,QAAO;AACrB,QAAI,QAAQ,QAAQ,IAAI,UAAU,GAAG,EAAG,QAAO;AAE/C,WAAO,QAAQ,QAAQ,IAAI,MAAM,aAAa,8BAA8B,KAAK;AAAA,EACnF;AAEA,WAAS,gBAAgB,GAAW,GAAW,WAAyC;AACtF,UAAM,UAAU,mBAAmB,GAAG,CAAC;AACvC,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,KAAK,YAAY,OAAO;AAC9B,QAAI,CAAC,MAAM,OAAO,UAAW,QAAO;AAEpC,WAAO;AAAA,EACT;AAIA,WAAS,YAAY,GAAe;AAClC,QAAI,CAAC,MAAM,gBAAiB;AAE5B,0BAAsB,MAAM;AAC1B,YAAM,KAAK,gBAAgB,EAAE,SAAS,EAAE,SAAS,MAAM,UAAU;AACjE,UAAI,CAAC,IAAI;AACP,2BAAmB,KAAK;AACxB;AAAA,MACF;AACA,UAAI,OAAO,MAAM,eAAgB;AAEjC,yBAAmB,KAAK;AAExB,YAAM,WAAW,oBAAoB,EAAE;AACvC,eAAS,QAAQ,CAAC,IAAI,MAAM;AAC1B,cAAM,UAAU,cAAc,EAAE,UAAU,MAAM,CAAC;AACjD,gBAAQ,aAAa,YAAY,EAAE;AACnC,iBAAS,KAAK,YAAY,OAAO;AACjC,wBAAgB,SAAS,IAAI,MAAM,IAAI,UAAU,MAAM;AACvD,cAAM,cAAc,KAAK,OAAO;AAAA,MAClC,CAAC;AAED,YAAM,iBAAiB;AAAA,IACzB,CAAC;AAAA,EACH;AAEA,WAAS,eAAe;AACtB,uBAAmB,KAAK;AAAA,EAC1B;AAIA,WAAS,QAAQ,GAAe;AAC9B,QAAI,CAAC,MAAM,gBAAiB;AAE5B,UAAM,SAAS,EAAE;AAEjB,QAAI,QAAQ,UAAU,uBAAuB,EAAG;AAChD,QACE,QAAQ,UAAU,kBAAkB,KACpC,MAAM,kBAAkB,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC;AAEtD;AAEF,MAAE,eAAe;AACjB,MAAE,gBAAgB;AAClB,MAAE,yBAAyB;AAE3B,uBAAmB,KAAK;AAExB,UAAM,UAAU,mBAAmB,EAAE,SAAS,EAAE,OAAO;AACvD,QAAI,CAAC,QAAS;AAEd,kBAAc,OAAO;AAAA,EACvB;AAEA,WAAS,cAAc,SAAkB;AACvC,UAAM,KAAK,YAAY,OAAO;AAC9B,QAAI,CAAC,GAAI;AAET,QAAI,MAAM,gBAAgB;AACxB,wBAAkB,OAAO,yBAAyB;AAAA,IACpD;AAEA,2BAAuB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAE9D,UAAM,WAAW,oBAAoB,EAAE;AACvC,aAAS,QAAQ,CAAC,IAAI,MAAM;AAC1B,YAAM,UAAU,cAAc,EAAE,UAAU,KAAK,CAAC;AAChD,cAAQ,aAAa,YAAY,EAAE;AACnC,eAAS,KAAK,YAAY,OAAO;AACjC,sBAAgB,SAAS,IAAI,MAAM,IAAI,aAAa,QAAQ;AAAA,QAC1D;AAAA,MACF,CAAC;AACD,YAAM,kBAAkB,KAAK,OAAO;AAAA,IACtC,CAAC;AAED,UAAM,aAAa;AACnB,UAAM,kBAAkB;AAExB,uBAAmB,KAAK;AACxB,0BAAsB,OAAO,OAAO;AAAA,EACtC;AAIA,MAAI,aAAa;AACjB,QAAM,0BAA0B,MAAM;AACpC,QAAI,WAAY;AAChB,iBAAa;AACb,0BAAsB,MAAM;AAC1B,mBAAa;AACb,2BAAqB,KAAK;AAAA,IAC5B,CAAC;AAAA,EACH;AAIA,WAAS,eAAe,SAAkB,QAA6C;AACrF,UAAM,kBAAkB;AAExB,QAAI,SAAS;AACX,eAAS,KAAK,MAAM,SAAS;AAC7B,uBAAiB;AACjB,eAAS,iBAAiB,aAAa,WAAW;AAClD,eAAS,iBAAiB,cAAc,YAAY;AACpD,eAAS,iBAAiB,SAAS,SAAS,IAAI;AAChD,aAAO,iBAAiB,UAAU,yBAAyB,IAAI;AAC/D,eAAS,iBAAiB,UAAU,yBAAyB,IAAI;AACjE,aAAO,iBAAiB,UAAU,yBAAyB;AAE3D,4BAAsB;AAAA,IACxB,OAAO;AACL,eAAS,KAAK,MAAM,SAAS;AAC7B,yBAAmB;AACnB,uBAAiB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAExD,UAAI,MAAM,gBAAgB;AACxB,0BAAkB,OAAO,yBAAyB;AAAA,MACpD;AAEA,eAAS,oBAAoB,aAAa,WAAW;AACrD,eAAS,oBAAoB,cAAc,YAAY;AACvD,eAAS,oBAAoB,SAAS,SAAS,IAAI;AACnD,aAAO,oBAAoB,UAAU,yBAAyB,IAAI;AAClE,eAAS,oBAAoB,UAAU,yBAAyB,IAAI;AACpE,aAAO,oBAAoB,UAAU,yBAAyB;AAE9D,2BAAqB;AAAA,IACvB;AAAA,EACF;AAIA,WAAS,wBAAwB;AAC/B,QAAI,MAAM,iBAAkB;AAE5B,UAAM,mBAAmB,IAAI,iBAAiB,CAAC,cAAc;AAC3D,YAAM,oBAAoB,UAAU,KAAK,CAAC,MAAM;AAC9C,YACE,EAAE,SAAS,gBACX,CAAC,SAAS,SAAS,SAAS,QAAQ,EAAE,SAAS,EAAE,iBAAiB,EAAE,KACpE,uBAAuB,EAAE,MAAM;AAE/B,iBAAO;AACT,YAAI,EAAE,SAAS,eAAe,uBAAuB,EAAE,MAAM,EAAG,QAAO;AACvE,eAAO;AAAA,MACT,CAAC;AACD,UAAI,mBAAmB;AACrB,mBAAW,2BAA2B,EAAE;AAAA,MAC1C;AAAA,IACF,CAAC;AAED,UAAM,iBAAiB,QAAQ,SAAS,MAAM;AAAA,MAC5C,YAAY;AAAA,MACZ,WAAW;AAAA,MACX,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS,SAAS,SAAS,QAAQ;AAAA,IACvD,CAAC;AAAA,EACH;AAEA,WAAS,uBAAuB;AAC9B,QAAI,MAAM,kBAAkB;AAC1B,YAAM,iBAAiB,WAAW;AAClC,YAAM,mBAAmB;AAAA,IAC3B;AAAA,EACF;AAEA,WAAS,uBAAuB,MAAqB;AACnD,QAAI,EAAE,gBAAgB,SAAU,QAAO;AACvC,QAAI,KAAK,aAAa,UAAU,EAAG,QAAO;AAC1C,WAAO,kBAAkB,IAAI,KAAK,CAAC,CAAC,KAAK,cAAc,IAAI,MAAM,aAAa,GAAG;AAAA,EACnF;AAIA,WAAS,4BAA4B;AACnC,QAAI,OAAO,SAAS,OAAO,IAAK;AAEhC,UAAM,gBAAgB,IAAI,iBAAiB,CAAC,cAAc;AACxD,YAAM,aAAa,UAAU;AAAA,QAC3B,CAAC,MAAM,EAAE,WAAW,SAAS,KAAK,EAAE,aAAa,SAAS;AAAA,MAC5D;AACA,UAAI,CAAC,WAAY;AAEjB,YAAM,qBACJ,SAAS,KAAK,iBAAiB,gDAAgD,EAAE,SAAS;AAE5F,UAAI;AACF,eAAO,OAAO;AAAA,UACZ;AAAA,YACE,MAAM,qBAAqB,sBAAsB;AAAA,UACnD;AAAA,UACA,MAAM;AAAA,QACR;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAED,QAAI,SAAS,MAAM;AACjB,oBAAc,QAAQ,SAAS,MAAM,EAAE,WAAW,MAAM,SAAS,KAAK,CAAC;AAAA,IACzE,OAAO;AACL,eAAS,iBAAiB,oBAAoB,MAAM;AAClD,sBAAc,QAAQ,SAAS,MAAM,EAAE,WAAW,MAAM,SAAS,KAAK,CAAC;AAAA,MACzE,CAAC;AAAA,IACH;AAAA,EACF;AAIA,QAAM,YAAY,CAAC,MAAoB;AACrC,kBAAc,OAAO,GAAG;AAAA,MACtB;AAAA,MACA;AAAA,MACA,mBAAmB,MAAM,kBAAkB,OAAO,yBAAyB;AAAA,MAC3E,kBAAkB,CAAC,SAAS,iBAAiB,OAAO,MAAM,yBAAyB;AAAA,IACrF,CAAC;AAAA,EACH;AAIA,SAAO,iBAAiB,WAAW,SAAS;AAC5C,4BAA0B;AAE1B,MAAI;AACF,WAAO,OAAO,YAAY,EAAE,MAAM,0BAA0B,GAAG,MAAM,YAAY;AAAA,EACnF,QAAQ;AAAA,EAER;AAIA,SAAO;AAAA,IACL,UAAU;AACR,aAAO,oBAAoB,WAAW,SAAS;AAC/C,UAAI,MAAM,iBAAiB;AACzB,uBAAe,KAAK;AAAA,MACtB;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB;AACf,uBAAiB,OAAO,MAAM,oBAAoB,KAAK,CAAC;AAAA,IAC1D;AAAA,IACA,gBAAgB;AACd,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../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":["// 注入到 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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-plugin-visual-selector",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",