# vite-plugin-design-mode **Repository Path**: fengfei/vite-plugin-design-mode ## Basic Information - **Project Name**: vite-plugin-design-mode - **Description**: 网页应用可视化编辑 Vite 插件 - **Primary Language**: TypeScript - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-24 - **Last Updated**: 2026-03-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Vite Plugin Design Mode 一个为AppDev启用设计模式功能的Vite插件,为React组件提供源码映射和可视化编辑功能。 ## 特性 - **源码映射**: 在编译时自动向DOM元素注入源码位置信息(使用紧凑的 `data-xagi-info` JSON 属性) - **可视化编辑**: 提供直观的设计模式UI,支持实时样式编辑 - **双击编辑**: 双击静态文本元素即可进入编辑模式,实时预览并自动保存到源码 - **静态内容检测**: 智能识别纯静态文本(无变量、表达式或子元素),只有静态内容才能直接编辑 - **列表项同步**: 编辑列表项时自动同步所有相关实例(内容或样式) - **组件识别**: 识别组件名称、导入路径,区分组件使用位置和定义位置 - **实时修改**: 支持实时编辑样式和内容,并自动持久化到源码文件 - **Tailwind CSS集成**: 内置Tailwind CSS预设,提供快速样式编辑 - **桥接通信**: 提供消息桥接机制,支持与外部工具和设计系统集成(支持 iframe 模式) - **开发服务器集成**: 无缝集成Vite开发服务器,支持热重载 - **零配置**: 开箱即用,无需复杂配置即可开始使用 ## Installation ### 一键安装(推荐) 使用 CLI 工具一键配置插件: ```bash npx @xagi/vite-plugin-design-mode install # 或 pnpm dlx @xagi/vite-plugin-design-mode install ``` 这个命令会: - 在 `package.json` 的 `devDependencies` 中添加插件依赖 - 自动在 `vite.config.ts/js/mjs` 中添加插件配置 - 使用默认配置,无需手动传参 **注意:** CLI 只会在配置文件中添加配置,不会执行包管理器安装命令。配置完成后,请手动运行包管理器安装命令来安装依赖: ```bash pnpm install # 或 npm install # 或 yarn install ``` ### 一键卸载 使用 CLI 工具一键卸载插件并清理配置: ```bash npx @xagi/vite-plugin-design-mode uninstall # 或 pnpm dlx @xagi/vite-plugin-design-mode uninstall ``` 这个命令会: - 从 `package.json` 中移除插件依赖 - 从 `vite.config.ts/js/mjs` 中移除 import 和插件配置 - 自动清理所有相关配置 **注意:** CLI 只会在配置文件中移除配置,不会执行包管理器卸载命令。配置清理完成后,请手动运行包管理器卸载命令来移除依赖: ```bash pnpm remove @xagi/vite-plugin-design-mode # 或 npm uninstall @xagi/vite-plugin-design-mode # 或 yarn remove @xagi/vite-plugin-design-mode ``` ### 手动安装 如果需要手动安装: ```bash npm install @xagi/vite-plugin-design-mode --save-dev # or yarn add @xagi/vite-plugin-design-mode --dev # or pnpm add @xagi/vite-plugin-design-mode -D ``` ## Basic Usage 使用一键安装后,插件已自动配置,`vite.config.ts` 中会包含: ```typescript // vite.config.ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import appdevDesignMode from '@xagi/vite-plugin-design-mode'; export default defineConfig({ plugins: [ react(), appdevDesignMode() // 使用默认配置,无需传参 ] }); ``` **默认配置说明:** - `enabled: true` - 启用插件 - `enableInProduction: false` - 仅在开发环境生效,生产构建时自动禁用 - `verbose: true` - 启用详细日志 - `attributePrefix: 'data-xagi'` - 源码映射属性的前缀 - `include: ['src/**/*.{ts,js,tsx,jsx}']` - 处理 src 目录下的 TypeScript/JavaScript/TSX/JSX 文件 - `exclude: ['node_modules', 'dist']` - 排除指定目录 - `enableBackup: false` - 是否启用备份功能 - `enableHistory: false` - 是否启用历史记录功能 ## Advanced Usage ```typescript // vite.config.ts import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; import appdevDesignMode from '@xagi/vite-plugin-design-mode'; export default defineConfig({ plugins: [ react(), appdevDesignMode({ enabled: true, enableInProduction: false, attributePrefix: 'data-appdev', verbose: true, exclude: ['node_modules', '.git'], include: ['**/*.{js,jsx,ts,tsx}'] }) ] }); ``` ## 工作原理 1. **编译时转换**: 插件在编译时使用Babel AST转换JSX/TSX/JS文件 2. **抽象语法树分析**: 分析AST识别React组件和DOM元素 - 追踪 ImportDeclaration 以解析组件定义和导入路径 - 静态分析确定内容是否为纯静态文本(`isStaticContent`) - 识别 UI 组件(components/ui 目录下的组件) 3. **源码映射数据注入**: 将源码位置信息作为紧凑的`data-*`属性(默认前缀 `data-xagi`)注入到DOM元素 - 主要信息存储在 `data-xagi-info` JSON 属性中(减少 DOM 体积) - 添加 `data-xagi-element-id` 用于唯一标识和列表项同步 - 添加 `data-xagi-static-content` 标记可编辑的静态内容 4. **虚拟模块加载**: 通过Vite虚拟模块机制动态加载客户端代码 5. **运行时通信**: 设计模式UI通过桥接系统与外部工具通信,支持实时编辑 - 支持 iframe 模式,通过 `postMessage` 与父窗口通信 - 支持元素选择、样式更新、内容更新等消息类型 6. **源码持久化**: 修改的样式和内容通过API端点实时写入源码文件 - 使用智能文本替换算法,基于行/列信息安全修改源码 - 支持样式(className)、内容(innerText)、属性更新 7. **列表项同步**: 使用 `element-id` 识别相关列表项,编辑一个实例自动同步到所有实例 8. **批量更新**: 支持批量更新多个元素,通过防抖机制优化性能 9. **备份与历史**: 可选启用备份和历史记录功能,支持撤销操作 ## API 端点 插件提供以下API端点: ### 基础端点 - `GET /__appdev_design_mode/get-source?elementId=xxx` - 获取指定元素的源码信息和文件内容(增强版,包含更多元数据) - `POST /__appdev_design_mode/modify-source` - 修改源码文件中的样式或内容(兼容旧版本) - `POST /__appdev_design_mode/update` - 统一更新接口,支持样式、内容、属性更新 - `GET /__appdev_design_mode/health` - 健康检查,返回插件运行状态 ### 批量操作端点 - `POST /__appdev_design_mode/batch-update` - 批量更新多个元素的源码(需要 `enableHistory: true` 以保存会话) - `GET /__appdev_design_mode/batch-update-status?batchId=xxx` - 查询批量更新会话状态(需要 `enableHistory: true`) ### 历史记录端点(需要 `enableHistory: true`) - `GET /__appdev_design_mode/get-history` - 获取更新历史记录 - `POST /__appdev_design_mode/undo` - 撤销操作(需要 `enableBackup: true`) - `POST /__appdev_design_mode/redo` - 重做操作(暂未实现) ### 验证端点 - `POST /__appdev_design_mode/validate-update` - 验证更新请求的有效性 ## 生成属性 插件处理的元素将具有以下属性(默认前缀为 `data-xagi`,可通过 `attributePrefix` 配置项自定义): ### 核心属性(实际注入) - **`{prefix}-info`**: 包含完整源码映射信息的 JSON 字符串,包含以下字段: - `fileName`: 源码文件路径 - `lineNumber`: 源码行号 - `columnNumber`: 源码列号 - `elementType`: 元素类型(标签名) - `componentName`: 组件名称(如果适用) - `functionName`: 函数名称(如果适用) - `elementId`: 唯一元素标识符 - `importPath`: 组件导入路径(用于区分组件使用位置和定义位置) - `isUIComponent`: 是否是 UI 组件(components/ui 目录下的组件) - **`{prefix}-element-id`**: 唯一元素标识符,格式为 `文件路径:行号:列号_标签名#ID`(如果有 id 属性)或 `文件路径:行号:列号_标签名`(如果没有 id 属性)。用于列表项同步和元素识别。 - **`{prefix}-position`**: 位置信息,格式为 `行号:列号`(简化版位置信息) - **`{prefix}-static-content`**: 标记元素是否包含纯静态内容(值为 `'true'`),用于判断元素是否可以直接编辑。只有包含纯静态文本(无变量、表达式或子元素)的元素才会被标记。 - **`{prefix}-static-class`**: 标记 className 是否为纯静态字符串(值为 `'true'`),用于判断样式是否可以直接编辑。 - **`{prefix}-children-source`**: 子元素的源码位置信息,格式为 `文件路径:行号:列号`(用于透传组件追踪静态文本子元素的来源位置) ### 优化说明 为了减少 DOM 体积,插件采用了紧凑的属性策略: - **所有主要信息都包含在 `{prefix}-info` 中**,不再单独注入 `{prefix}-file`、`{prefix}-line`、`{prefix}-column`、`{prefix}-component`、`{prefix}-function`、`{prefix}-import` 等属性 - 这些信息可以通过解析 `{prefix}-info` JSON 字符串获取 **注意**:这些属性使用可配置的前缀,默认值为 `data-xagi`。通过设置 `attributePrefix` 选项,可以避免与用户自定义的 `data-*` 属性冲突。例如,设置 `attributePrefix: 'data-appdev'` 后,属性名将变为 `data-appdev-info`、`data-appdev-element-id`、`data-appdev-static-content` 等。 ## 浏览器集成 ### 直接DOM访问 在浏览器开发者工具或外部应用中: ```javascript // 获取元素源码信息(注意:默认前缀已改为 data-xagi) const element = document.querySelector('.my-element'); // 从全局配置获取前缀,或使用默认值 'data-xagi' const prefix = window.__APPDEV_DESIGN_MODE_CONFIG__?.attributePrefix || 'data-xagi'; const sourceInfo = element.getAttribute(`${prefix}-info`); const sourceData = JSON.parse(sourceInfo); console.log(sourceData); // { // fileName: 'src/App.tsx', // lineNumber: 10, // columnNumber: 5, // elementType: 'div', // componentName: 'App', // functionName: 'App', // elementId: 'src/App.tsx:10:5_div', // importPath: undefined, // 如果是组件,会显示导入路径 // isUIComponent: false // 是否是 UI 组件 // } // 检查元素是否可以直接编辑(静态内容) const isEditable = element.getAttribute(`${prefix}-static-content`) === 'true'; if (isEditable) { // 双击元素即可编辑 element.addEventListener('dblclick', () => { element.contentEditable = 'true'; }); } ``` ### 桥接通信 使用内置桥接系统与设计模式UI交互: ```javascript // 监听元素选择变化 window.addEventListener('message', (event) => { const { type, payload } = event.data; if (type === 'SELECTION_CHANGED') { console.log('选中的元素:', payload); // payload 包含: tagName, id, className, innerText, source } }); // 发送样式更新命令 window.parent.postMessage({ type: 'UPDATE_STYLE', payload: { newClass: 'bg-blue-500 text-white p-4 rounded-lg' } }, '*'); // 发送内容更新命令 window.parent.postMessage({ type: 'UPDATE_CONTENT', payload: { newContent: '更新后的文本内容' } }, '*'); ``` ## 配置选项 | 选项 | 类型 | 默认值 | 描述 | |------|------|--------|------| | `enabled` | boolean | `true` | 是否启用设计模式插件 | | `enableInProduction` | boolean | `false` | 是否在生产环境启用,通常保持false | | `attributePrefix` | string | `'data-xagi'` | 自定义源码映射属性的前缀 | | `verbose` | boolean | `true` | 是否启用详细日志输出,便于调试 | | `exclude` | string[] | `['node_modules', 'dist']` | 排除处理的文件模式和目录 | | `include` | string[] | `['src/**/*.{ts,js,tsx,jsx}']` | 包含处理的文件模式,支持glob语法 | | `enableBackup` | boolean | `false` | 是否启用备份功能,启用后会在修改源码前创建备份文件 | | `enableHistory` | boolean | `false` | 是否启用历史记录功能,启用后会保存批量更新会话和历史记录 | ### 配置示例 ```typescript // vite.config.ts export default defineConfig({ plugins: [ react(), appdevDesignMode({ enabled: true, enableInProduction: false, attributePrefix: 'data-appdev', verbose: true, exclude: ['node_modules', '.git', 'dist'], include: ['src/**/*.{ts,js,tsx,jsx}', 'pages/**/*.{ts,js,tsx,jsx}'], enableBackup: true, // 启用备份功能 enableHistory: true // 启用历史记录功能 }) ] }); ``` ## 使用场景 ### 1. 设计与开发协作 - 设计师可以直接在浏览器中调整组件样式 - 实时预览设计效果,所见即所得 - 自动生成样式代码,无需手动编写 ### 2. 组件库开发 - 快速迭代组件样式和变体 - 可视化调整组件参数和样式 - 生成一致的设计语言 ### 3. 原型开发 - 快速构建和调整页面布局 - 实时验证设计想法 - 加速从原型到代码的转换 ### 4. 团队协作 - 统一设计系统和代码规范 - 减少设计师和开发者的沟通成本 - 提高开发效率和代码质量 ## Tailwind CSS 预设 插件内置了常用的Tailwind CSS类预设: ### 背景颜色预设 - `bg-white` - 白色背景 - `bg-slate-50` - 浅灰色背景 - `bg-blue-50` - 浅蓝色背景 - `bg-blue-100` - 中浅蓝色背景 - `bg-blue-600` - 深蓝色背景 - `bg-red-50` - 浅红色背景 - `bg-green-50` - 浅绿色背景 ### 文字颜色预设 - `text-slate-900` - 深灰色文字 - `text-slate-600` - 中灰色文字 - `text-blue-600` - 蓝色文字 - `text-white` - 白色文字 - `text-red-600` - 红色文字 ### 间距预设 - `p-0` - 无内边距 - `p-2` - 小内边距 - `p-4` - 中等内边距 - `p-6` - 大内边距 - `p-8` - 特大内边距 - `p-12` - 超大内边距 ### 圆角预设 - `rounded-none` - 无圆角 - `rounded-sm` - 小圆角 - `rounded-md` - 中等圆角 - `rounded-lg` - 大圆角 - `rounded-full` - 完全圆角 ## 设计模式UI使用指南 ### 启动设计模式 1. 在页面右下角找到设计模式开关 2. 点击开关启用设计模式 3. 开始选择和编辑页面元素 ### 编辑元素样式 1. 点击页面中的任意元素 2. 在右侧编辑面板中选择预设样式 3. 实时预览样式效果 4. 修改会自动保存到源码文件 5. 对于列表项,修改一个实例会自动同步到所有相关实例 ### 编辑元素内容 1. **双击**包含静态文本的元素(只有标记了 `data-xagi-static-content="true"` 的元素才能编辑) 2. 进入 `contentEditable` 模式,直接编辑文本 3. 失去焦点时自动保存到源码文件 4. 对于列表项,编辑一个实例会自动同步到所有相关实例 ### 重置修改 - 点击“重置所有修改”按钮撤销所有更改 - 页面将重新加载并恢复原始状态 - 如果启用了备份功能(`enableBackup: true`),可以使用撤销功能恢复之前的版本 - 如果启用了历史记录功能(`enableHistory: true`),可以查看和恢复历史更新会话 ## 故障排除 ### 常见问题 **Q: 设计模式UI没有显示** A: 检查插件是否正确配置,确保在开发模式下运行 **Q: 点击元素没有反应** A: 确认已经启用设计模式,检查浏览器控制台是否有错误信息 **Q: 样式修改没有保存** A: 检查文件权限,确保有写入权限,或者检查开发服务器状态 **Q: 源码映射不准确** A: 检查是否正确配置了include模式,确保源文件被正确处理 ### 调试技巧 1. 启用verbose模式查看详细日志 2. 检查浏览器开发者工具的网络面板,确认API请求状态 3. 查看元素是否正确生成了源码映射属性 4. 使用健康检查端点验证插件运行状态 ```bash # 检查插件状态 curl http://localhost:3000/__appdev_design_mode/health ``` ## 开发指南 ### 本地开发 ```bash # 克隆项目 git clone cd vite-plugin-design-mode # 安装依赖 npm install # 运行示例 cd examples/advanced npm install npm run dev ``` ### 自定义预设 如需自定义样式预设,可以修改客户端配置: ```typescript // 在 DesignModeUI.tsx 中自定义预设 const CUSTOM_PRESETS = { bgColors: [ { label: 'Primary', value: 'bg-blue-600' }, { label: 'Secondary', value: 'bg-gray-600' }, // 添加更多自定义颜色 ] }; ``` ## 贡献指南 欢迎提交Issue和Pull Request来改进这个插件! ### 开发流程 1. Fork项目 2. 创建功能分支 3. 提交更改 4. 创建Pull Request ### 代码规范 - 使用TypeScript - 遵循ESLint规则 - 添加适当的测试 - 更新相关文档 ## 更新日志 ### v1.0.36 - 更新默认属性前缀为 `data-xagi` - 新增批量更新功能(`/batch-update` 端点) - 新增历史记录功能(`enableHistory` 配置项) - 新增备份功能(`enableBackup` 配置项) - 新增撤销/重做功能(需要启用备份和历史记录) - 增强 `/get-source` 端点,返回更多元数据 - 新增 `/validate-update` 端点用于验证更新请求 - 支持 TypeScript/JavaScript/TSX/JSX 文件处理 - 优化默认文件包含模式,支持更多文件类型 - 改进CLI工具,支持一键安装和卸载 ### v1.0.0 - 初始版本发布 - 实现基本的源码映射功能 - 添加可视化设计模式UI - 支持实时样式编辑和源码修改 - 集成Tailwind CSS预设 ## License MIT