定位:打开 HTML,直接改,改完导出。AI 生成原型的微调台。 底座:fork 自 html-visual-editor(MIT 协议) 核心改造:Chrome Extension → 独立 Web App(浏览器打开即用)
现状:html-visual-editor 是 Chrome Extension,通过 manifest.json + content_scripts 注入编辑器到当前页面。依赖 chrome.runtime 消息通信、chrome.sidePanel、chrome.storage 等 API。
改造目标:一个独立的 HTML 页面,用户打开后可以导入 HTML 文件进行编辑,编辑完导出。不需要安装任何东西。
| 改造项 | 现状 | 改为 |
|---|---|---|
| 入口 | 点击 Chrome 扩展图标激活 | 打开网页即进入编辑器,默认展示欢迎页 |
| HTML 加载 | 在当前 file:/// 页面上注入编辑器 | 用户通过拖入/选择文件/粘贴加载 HTML 到 iframe 或 shadow DOM |
| 文件保存 | File System Access API(Chrome 扩展权限更大) |
保留 File System Access API,降级用 Blob 下载 |
| 消息通信 | chrome.runtime.sendMessage |
去掉,改为直接函数调用(同页面内不需要跨上下文消息) |
| 侧边栏 | chrome.sidePanel API |
改为页面内右侧固定面板 |
| Popup | chrome.action popup |
改为页面顶部控制栏 |
| 状态存储 | chrome.storage |
localStorage |
| CSS 注入 | styles/inject.css 通过 manifest 注入 |
在页面内直接 <link> 或 <style> 加载 |
具体步骤:
- 创建
index.html作为应用入口,引入所有 JS/CSS - 将
content/下的编辑器脚本改为普通<script>加载 - 编辑区域用
<iframe srcdoc="">承载用户 HTML,编辑器脚本注入到 iframe 内 - 去掉
manifest.json、background/、popup/、sidepanel/中的 Chrome API 调用 - 将
chrome.runtime.onMessage改为直接调用window.HVE_Core.*方法 - 将
chrome.storage改为localStorage - 侧边栏和工具栏改为页面内 DOM 元素
用户编辑的 HTML 需要在一个隔离环境中渲染(避免 CSS/JS 冲突),但编辑器需要能操作 iframe 内的 DOM。
方案:<iframe srcdoc=""> + 同源访问
- iframe 使用
srcdoc属性加载用户 HTML - 主页面和 iframe 同源,可以直接
iframe.contentDocument访问 - 编辑器脚本通过
iframe.contentWindow注入到 iframe 内 - 导出时序列化 iframe 内的 DOM
关键代码改动:
editor-core.js中的document.*调用需要改为iframeDoc.*selector.js中的事件监听需要绑定到 iframe 的contentDocumenttoolbar.js的浮动工具栏仍然挂在主页面(避免被 iframe CSS 污染)history.js操作的元素引用改为 iframe 内元素
┌─────────────────────────────────────────────────────────────────┐
│ 顶部控制栏:[Logo] [打开] [保存] [另存为] [撤销] [重做] | 编辑模式切换 │
├─────────────────────────────────────────────┬───────────────────┤
│ │ │
│ iframe 编辑区 │ 属性面板 │
│ (用户 HTML 在这里渲染和编辑) │ (标签/ID/Class/ │
│ │ 位置/尺寸/文字/ │
│ - 浮动工具栏(选中元素时出现) │ 颜色/外观/间距) │
│ - 选中元素高亮框 │ │
│ - 右键菜单 │ │
│ │ │
├─────────────────────────────────────────────┴───────────────────┤
│ 底部状态栏:元素路径 | 页面信息 | 缩放控制 │
└─────────────────────────────────────────────────────────────────┘
已有能力(selector.js, 926 行):
- ✅ 鼠标悬停紫色虚线高亮
- ✅ 点击选中,显示实线框 + 8 个蓝色拖拽手柄
- ✅ 多选(Ctrl/Cmd + 点击)
- ✅ 框选(Marquee Selection,拖拽矩形区域选择)
- ✅ Escape 取消选择 / 向上选父级
- ✅ 排除不可选元素(HTML/HEAD/SCRIPT 等)
需改造:
- 事件监听从
document改为iframe.contentDocument - 高亮框和拖拽手柄挂在主页面(覆盖在 iframe 上方),坐标需要转换
- 框选矩形同样挂在主页面
需新增:
- 底部状态栏显示选中元素路径(如
body > div.card > h2),点击路径中任一标签可跳选到该层级 - 元素树面板(可选,P1):左侧可折叠的 DOM 树,点击节点选中对应元素
已有能力(drag-move.js, 281 行):
- ✅ 选中元素拖拽移动
- ✅ 拖拽时实时更新位置
- ✅ 历史记录
需改造:
- 事件坐标转换(iframe 内坐标 → 主页面坐标)
需新增:
- 方向键微调位置(已有,1px/10px 步进)✅
- 拖拽时显示位置参考线(与 align-guide 联动)✅ 已有
已有能力(resize.js, 211 行):
- ✅ 8 个蓝色手柄拖拽调整尺寸
- ✅ 保持宽高比(Shift 键)——需确认是否已实现
- ✅ 历史记录
需改造:
- 手柄挂在主页面覆盖层,坐标转换
已有能力(text-edit.js, 316 行):
- ✅ 双击进入文本编辑模式(contenteditable)
- ✅ 支持 Ctrl+B/I/U 富文本格式
- ✅ Escape 退出编辑
需新增:
- 编辑时显示迷你工具栏(选中文字后弹出,类似 Medium/Notion 的选中浮窗)
- 包含:加粗/斜体/下划线/删除线/链接/颜色
- 这比依赖顶部工具栏更直觉
- 文本编辑历史记录粒度优化(当前是整个元素 content,改为 diff 级别,减少 undo 跳跃感)
已有能力(toolbar.js, 1122 行):
- ✅ 浮动工具栏,选中元素时出现在元素上方
- ✅ 分组:文字格式 / 字体字号 / 对齐 / 颜色 / 圆角阴影透明度 / 插入 / 元素操作 / 格式刷 / 页面排序/PDF / 图表排版 / 撤销重做
- ✅ 下拉菜单:字体选择、字号选择、标题级别、圆角/阴影/透明度数值
需改造:
- 工具栏挂在主页面,位置计算基于 iframe 内元素在主页面中的投影位置
- 样式修改通过
iframe.contentDocument找到目标元素再应用
需新增:
- 样式修改时实时预览(当前已有实时预览,确认改造后仍正常)
- 工具栏位置智能调整(当元素靠近页面顶部时,工具栏显示在下方)
已有能力(table-edit.js, 322 行):
- ✅ 右键菜单:增删行/列、合并/拆分单元格
- ✅ 选中单元格高亮
需改造:
- 右键菜单挂在主页面,坐标转换
已有能力(image-handler.js, 457 行):
- ✅ 粘贴图片(Ctrl+V)
- ✅ 替换图片(双击图片弹出选择框)
- ✅ 图片拖拽调整大小
需改造:
- 图片文件选择器从 Chrome Extension API 改为
<input type="file">
已有能力(align-guide.js, 447 行):
- ✅ 拖拽时显示与其他元素的对齐参考线
- ✅ 居中对齐、边缘对齐
需改造:
- 参考线渲染在主页面覆盖层
已有能力(insert-panel.js, 924 行):
- ✅ 插入:容器/文本/标题/表格/图片/按钮/分割线/链接/列表/引用
- ✅ 双击空白区域弹出插入面板
- ✅ 拖拽插入
需改造:
- 面板挂在主页面
已有能力(context-menu.js, 408 行):
- ✅ 复制/粘贴/删除/上移/下移/锁定/解锁
- ✅ 复制样式/粘贴样式
- ✅ 选择父元素/子元素
需改造:
- 菜单挂在主页面
已有能力(history.js, 293 行):
- ✅ 操作历史栈(最多 100 步)
- ✅ 支持 style/attribute/content/dom/move/resize 类型
- ✅ Ctrl+Z 撤销 / Ctrl+Y 重做
需改造:
- 元素选择器在 iframe 内重新查找(
getUniqueSelector生成的选择器需要在 iframe 的 contentDocument 中查询)
已有能力(editor-core.js):
- ✅ Ctrl+G 组合 / Ctrl+Shift+G 取消组合
- ✅ 组合后作为整体拖拽/调整
已有能力(context-menu.js + editor-core.js):
- ✅ Ctrl+L 锁定/解锁
- ✅ 锁定后不可拖拽/删除/调整
| 方式 | 描述 | 优先级 |
|---|---|---|
| 选择文件 | 点击"打开"按钮选择本地 HTML 文件 | P0 |
| 拖入文件 | 将 HTML 文件拖入编辑区 | P0 |
| 粘贴 HTML | Ctrl+V 粘贴 HTML 代码片段 | P1 |
| 从 URL 加载 | 输入 URL 加载远程 HTML(跨域限制可能需要代理) | P2 |
实现要点:
- 使用
File System Access API的showOpenFilePicker(Chrome/Edge 支持) - 降级方案:
<input type="file">选择文件 - 加载后替换 iframe 的
srcdoc - 记录文件句柄,支持 Ctrl+S 直接保存
| 方式 | 描述 | 优先级 |
|---|---|---|
| 保存 | Ctrl+S 保存到原文件(File System Access API) | P0 |
| 另存为 | 另存为新文件 | P0 |
| 下载 | 不支持 File System Access API 时,Blob 下载 | P0 |
| 复制 HTML | 复制编辑后的完整 HTML 到剪贴板 | P1 |
实现要点:
- 序列化时清除所有编辑器注入的元素和属性(已有
html-serializer.js) - 导出的 HTML 干净无污染
已有能力(sidepanel/panel.html + panel.js):
- ✅ 元素信息(标签/ID/Class)
- ✅ 位置 & 尺寸(X/Y/W/H)
- ✅ 文字属性(字号/行高/字重/对齐)
- ✅ 颜色(文字色/背景色)
- ✅ 外观(圆角/透明度)
- ✅ 间距(margin/padding)
需改造:
- 从 Chrome sidePanel 改为页面内右侧固定面板
- 通过
iframe.contentDocument读写元素属性 - 面板宽度可拖拽调整
需新增:
- CSS 类名编辑增强:显示当前 class 列表,支持增删改
- 链接属性编辑(href/target)
- 图片属性编辑(src/alt/宽高)
- 表格属性编辑(边框/间距/对齐)
| 操作 | 快捷键 | 现状 |
|---|---|---|
| 删除元素 | Delete / Backspace | ✅ 已有 |
| 复制元素 | Ctrl+D | ✅ 已有 |
| 撤销 | Ctrl+Z | ✅ 已有 |
| 重做 | Ctrl+Y / Ctrl+Shift+Z | ✅ 已有 |
| 保存 | Ctrl+S | ✅ 已有 |
| 锁定/解锁 | Ctrl+L | ✅ 已有 |
| 组合 | Ctrl+G | ✅ 已有 |
| 取消组合 | Ctrl+Shift+G | ✅ 已有 |
| 微调位置 | 方向键(1px)/ Shift+方向键(10px) | ✅ 已有 |
| 复制样式 | Ctrl+Shift+C | ✅ 已有 |
| 粘贴样式 | Ctrl+Shift+V | ✅ 已有 |
| 页面排序 | Ctrl+Shift+P | ✅ 已有 |
| 选父元素 | Escape | ✅ 已有 |
| 取消选择 | Escape(到 body 时) | ✅ 已有 |
| 全选同级 | Ctrl+A | ❌ 需新增 |
| Tab 切换选中 | Tab / Shift+Tab | ❌ 需新增(切换同级下一个/上一个元素) |
| 上移一层 | Ctrl+] | ❌ 需新增(z-index +1) |
| 下移一层 | Ctrl+[ | ❌ 需新增(z-index -1) |
当用户首次打开应用,没有加载 HTML 时,显示欢迎页:
- 最近编辑的文件列表(localStorage 存储)
- 拖入文件提示区
- 新建空白 HTML 按钮
- 简单的使用说明
| 功能 | 描述 |
|---|---|
| 缩放 | Ctrl+滚轮 / 底部缩放滑块,支持 25%-400% |
| 适配宽度 | 自动缩放到编辑区宽度 |
| 设备预览 | 模拟不同设备宽度(桌面 1440 / 平板 768 / 手机 375) |
实现要点:
- 缩放通过 CSS
transform: scale()应用到 iframe 容器 - 坐标转换需要考虑缩放比例
| 操作 | 描述 |
|---|---|
| 批量改样式 | 多选元素后,在属性面板修改一个属性,同时应用到所有选中元素 |
| 批量删除 | 多选后 Delete 一次性删除 |
| 批量移动 | 多选后拖拽整体移动 |
现状:框选多选已有,批量删除/移动已有。批量改样式需新增。
左侧可折叠的 DOM 树面板:
- 实时同步 iframe 内 DOM 结构
- 点击节点选中对应元素
- 展开高亮当前选中元素的路径
- 支持拖拽重排 DOM 顺序
- 支持右键菜单(删除/复制/隐藏)
已有能力(page-sorter.js + pdf-paginator.js):
- ✅ PPT 风格页面缩略图排序
- ✅ PDF 分页预览
- ✅ 一键导出 PDF(智能避免元素内断页)
需改造:
- 页面缩略图从 iframe 内截取
- PDF 导出在独立页面中运行
已有能力(canvas-mode.js, 1762 行):
- ✅ 类 Figma 自由绘制
- ✅ 文本/矩形/椭圆/线段/箭头
- ✅ 颜色选择器
- ✅ SVG/PNG 导出
MVP 阶段可以先不迁移这个模块。
已有能力(chart-typography.js, 551 行):
- ✅ 预置统计卡片/KPI 网格/图例
- ✅ 精细排版控制
MVP 阶段可以先不迁移。
| 模块 | 工作量 | 难度 | 说明 |
|---|---|---|---|
| 创建 index.html 框架 | 0.5 天 | 低 | 顶部栏 + iframe 区 + 侧边栏 + 底部栏 |
| iframe 承载与脚本注入 | 1 天 | 中 | srcdoc 加载 + 脚本注入 + 坐标转换系统 |
| 去掉 Chrome API 依赖 | 0.5 天 | 低 | 替换 chrome.runtime/storage/sidePanel |
| 坐标转换系统 | 1 天 | 高 | iframe 缩放/滚动下的鼠标坐标映射 |
| 文件导入导出 | 0.5 天 | 低 | 已有 file-manager.js,微调即可 |
| 小计 | 3.5 天 |
| 模块 | 工作量 | 难度 | 说明 |
|---|---|---|---|
| selector.js 适配 | 0.5 天 | 中 | 事件监听改为 iframe.contentDocument |
| drag-move.js 适配 | 0.5 天 | 中 | 坐标转换 |
| resize.js 适配 | 0.5 天 | 中 | 手柄覆盖层 + 坐标转换 |
| text-edit.js 适配 | 0.5 天 | 中 | contenteditable 在 iframe 内工作 |
| toolbar.js 适配 | 0.5 天 | 中 | 工具栏挂在主页面,位置计算 |
| table-edit.js 适配 | 0.5 天 | 低 | 右键菜单坐标转换 |
| image-handler.js 适配 | 0.5 天 | 中 | 文件选择器替换 |
| align-guide.js 适配 | 0.5 天 | 中 | 参考线渲染在覆盖层 |
| insert-panel.js 适配 | 0.5 天 | 中 | 面板位置计算 |
| context-menu.js 适配 | 0.5 天 | 低 | 坐标转换 |
| history.js 适配 | 0.5 天 | 中 | 选择器在 iframe 内查找 |
| editor-core.js 适配 | 0.5 天 | 低 | 消息通信改为直接调用 |
| 小计 | 5.5 天 |
| 功能 | 工作量 | 优先级 | 说明 |
|---|---|---|---|
| 欢迎页 + 最近文件 | 0.5 天 | P0 | |
| 底部状态栏(元素路径) | 0.5 天 | P0 | |
| 全选/Tab 切换/层级调整快捷键 | 0.5 天 | P0 | |
| 属性面板增强 | 1 天 | P1 | 类名编辑/链接/图片/表格属性 |
| 缩放与视口控制 | 1 天 | P1 | |
| 批量改样式 | 0.5 天 | P1 | |
| 元素树面板 | 1.5 天 | P1 | DOM 树 + 同步 + 拖拽重排 |
| 小计 | 5.5 天 |
| 阶段 | 工作日 | 日历天(按每天 3-4 小时有效开发) |
|---|---|---|
| 架构改造 | 3.5 天 | ~5 天 |
| 编辑功能适配 | 5.5 天 | ~8 天 |
| 新增功能(P0) | 1.5 天 | ~2 天 |
| MVP 交付 | 10.5 天 | ~2 周 |
| 新增功能(P1) | 3 天 | ~4 天 |
| 完整版 | 13.5 天 | ~3 周 |
| 天 | 目标 |
|---|---|
| D1 | 创建 index.html 框架(顶栏 + iframe + 侧边栏 + 底栏) |
| D2 | iframe 承载方案实现(srcdoc 加载 + 脚本注入) |
| D3 | 坐标转换系统 + selector.js 适配 |
| D4 | drag-move / resize / text-edit 适配 |
| D5 | toolbar / context-menu / history 适配 |
| 天 | 目标 |
|---|---|
| D6 | 剩余模块适配(table-edit / image-handler / align-guide / insert-panel) |
| D7 | 文件导入导出完善 + 去掉 Chrome API |
| D8 | 欢迎页 + 底部状态栏 + 快捷键补全 |
| D9 | 属性面板改造(从 sidePanel 到页面内) |
| D10 | 整体联调 + dogfooding(拿真实 PRD HTML 测试) |
| 天 | 目标 |
|---|---|
| D11 | 缩放与视口控制 |
| D12 | 元素树面板 |
| D13 | 批量操作 + 属性面板增强 |
| D14 | UI 打磨 + bug 修复 |
| D15 | README + 部署 GitHub Pages |
| 项目 | 选型 | 理由 |
|---|---|---|
| 框架 | 无框架,原生 JS | 继承底座,避免引入额外复杂度 |
| 样式 | 原生 CSS + CSS Variables | 底座风格统一 |
| HTML 承载 | <iframe srcdoc=""> |
隔离用户 HTML,避免 CSS/JS 冲突 |
| 文件 API | File System Access API + Blob 降级 | 现代浏览器直接读写,旧浏览器下载 |
| 构建 | 无构建 | 原生 JS 直接运行,0 依赖 |
| 部署 | GitHub Pages | 静态文件直接部署 |
| 风险 | 概率 | 影响 | 应对 |
|---|---|---|---|
| iframe 坐标转换复杂,缩放/滚动下有 bug | 中 | 高 | 早期建立统一坐标转换函数,所有模块复用 |
| 部分 CSS/JS 在 iframe 内行为不一致 | 低 | 中 | srcdoc 同源无跨域问题,基本不会有 |
| File System Access API 非所有浏览器支持 | 低 | 低 | 已有 Blob 下载降级方案 |
| 编辑器注入的 CSS 污染用户 HTML | 低 | 中 | 序列化时已清除(html-serializer.js) |
| 大型 HTML 文件性能 | 低 | 低 | 内容在 iframe 内渲染,编辑器脚本轻量 |
- AI 辅助编辑 — 核心定位是"手动微调",AI 后续作为可选侧边栏
- 从零搭建 — 不做建站工具,不做组件库搭建器
- Figma 导入/导出 — 不做设计工具转换
- 后端/用户系统 — 纯前端,local-first
- 实时协作 — 单人使用场景
- 代码编辑器 — 不做 VS Code 那种源码编辑
- Canvas 画板模式 — P2,后续移植
- 图表排版组件 — P2,后续移植