Skip to content

feat: 支持安全的 Markdown 块拖拽重排 - #346

Draft
jackson-zhou wants to merge 2 commits into
floatboatai:mainfrom
jackson-zhou:feat/block-reorder
Draft

jackson-zhou wants to merge 2 commits into
floatboatai:mainfrom
jackson-zhou:feat/block-reorder

Conversation

@jackson-zhou

@jackson-zhou jackson-zhou commented Sep 17, 2026 •

Copy link
Copy Markdown

摘要

新增可选的 Markdown 块重排插件:通过拖拽手柄移动一个完整的最外层块,保留原始源码和 Markdown 结构,并支持一步撤销。源码模式和实时预览模式共用同一套移动规划逻辑。

**贡献说明:**实现、测试和文档主要由 AI 生成,已完成代码审查、自动化测试及真实浏览器和 Electron 验证。OpenSpec 提案、仓库贡献政策审核及剩余人工验收仍待完成,暂保留 Draft;AI 使用情况和待确认事项在下方如实列明。

背景与动机

Closes #332。本 PR 基于 main 独立实现,作为与 #331 并列的另一种实现方案供审查。

变更内容

  • packages/plugin-block-drag:提供可选的 legacy 插件工厂和原生生命周期插件;实现拖动启动阈值、源块高亮、插入位置提示、边缘自动滚动、取消、手柄键盘导航,以及只读、输入法组合输入和折叠状态保护。横向滚动长代码时,手柄与提示保持在可视内容区域。原生运行时中的移动命令由宿主命令服务统一管理,支持改键、清除快捷键、冲突处理、当前编辑器路由和卸载。
  • 移动模型:保留原始源码并映射选区;校验完整 Markdown 块语法树,拒绝导致列表合并、内容被代码块或未闭合围栏吞入等结构变化的移动。解析设有时间预算,未能完成解析时不执行移动。
  • packages/core:新增 prepareBlockMove(view),在表格失焦前捕获待提交输入,核实宿主是否原样接受输入,并保留被拒绝的编辑以便重试。多个待提交表格按源码位置从后向前提交。已接受的单元格编辑与块移动拥有独立的撤销边界。如果保存表格改变了块结构,则保留保存结果并取消移动,避免使用失效索引移动错误内容。宿主重建事务时保留历史记录元数据。
  • packages/reference-plugins、apps/electron-demo:增加可选启动开关,在 demo 的两种接入模式下默认启用,并将插件以零权限需求登记到内置插件名单。
  • openspec/ 与文档:补充设计、API 契约、明确的范围限制、可复跑的浏览器/Electron 冒烟测试脚本、验证记录和剩余验收清单。

每次只移动一个最外层块;标题只移动自身,不带走下方章节内容,图片随所属段落移动。首版不支持触屏、多块或跨文档移动,以及列表内部排序和嵌套调整。

测试与验证

  • pnpm test:72 个测试文件、1,043 项测试通过。
  • pnpm typecheck、pnpm check:api、pnpm build、pnpm build:electron-demo 均通过。
  • pnpm --filter @floatboat/nexus-electron-demo smoke:multi-window 通过。
  • pnpm dlx @fission-ai/openspec validate add-markdown-block-reordering --strict 通过。
  • 新增回归覆盖宿主拒绝或替换事务、多个待提交表格、取消后继续编辑、表格输入导致块拆分、独立撤销/重做,以及运行时快捷键管理。
  • 真实 Chrome 冒烟测试:启用截图时完成 92 项文档/滚动断言,另有焦点、可见性和错误检查;覆盖源码与实时预览模式下的九种块内容、首尾移动、撤销/重做、Escape 取消、缩放、连续键盘移动、只读、卸载、自动滚动和表格输入被拒绝后的重试。
  • 扩展浏览器验收:20 项文档断言及几何/生命周期检查,覆盖移出编辑器释放、真实指针捕获丢失、尺寸变化、横向滚动、折叠,以及表格编辑/选择/删除/行列排序/整表移动后继续编辑。
  • runtime 真实键盘验收:40 项检查通过,覆盖默认快捷键、改键、清除、冲突、当前编辑器路由、晚接入、禁用/重启和偏好保留。
  • 实际 Electron demo:legacy 和原生 runtime 两种模式均通过自动化指针拖动、撤销、Escape 取消、默认快捷键、待保存单元格的整表移动,以及一次撤销保留单元格编辑。烟测使用隔离用户数据和隐藏测试窗口,实体设备验证单独记录。
  • 人工验收尚待完成:操作系统原生中文/日文输入法、实体鼠标/触控板、系统触发的指针取消、屏幕阅读器;Electron 中的宿主拒绝表格输入后重试及快捷键配置还需补验。

已知基线限制:连续操作两个编辑器时,第二个编辑器的块移动后选区可能回到文首;纯 CodeMirror(不加载 Nexus 或此插件)同样能复现。本 PR 未修改该行为,runtime 路由验收按独立命令用例显式选择起始块,详细复现与对照见验证记录。

验证环境:macOS 26.6.2 arm64;Chrome 152.0.7977.84;Electron 35.7.5;Playwright 1.55.0;Node 23.7.0;pnpm 9.15.4。以上结果来自本地验证,上游 CI 状态另行确认。

合规自检

  • CLA 已签署:状态待确认,不声明已签署。
  • **AI 披露:本 PR 的功能代码并非主要由 AI 生成。**此项不满足,保留未勾选;功能代码主要由 AI 生成,具体情况见上文。
  • 新增依赖、许可证与用途已列明:
    • 新插件引用仓库已有的 CodeMirror commands/language/state/view 和 Lezer common 依赖,许可证为 MIT,用于解析、事务、视图及历史记录集成;复用工作区内的 core/plugin-api。
    • 根目录新增开发依赖 playwright@1.55.0,许可证为 Apache-2.0,用于可复跑的真实浏览器与 Electron 验收,不加入插件运行时依赖。
  • 未提交编译构建产物、密钥、环境配置文件或个人 Vault 数据;截图仅包含合成的示例文本。

自检清单

  • 标题保留 Conventional Commits 类型前缀;新增公共 API 已补充文档和导出类型。
  • 已核对 12 条 Table Widget 规则并运行 core 回归。主线原有的独立手柄行结构保持不变;本 PR 不声称解决该结构与第 6 条规则之间的基线不一致。
  • 已关联 OpenSpec 提案,功能属于项目定义的编辑器范围。
  • 维护者对提案及贡献方式的批准,以及剩余人工验收。

截图

拖动过程中:第一段高亮,目标插入位置位于第三段之后。

拖动中的源块高亮与目标插入位置

释放后:第一段移动到文末。

完成块重排后的文档

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@jackson-zhou jackson-zhou changed the title feat: add safe Markdown block reordering feat: 支持安全的 Markdown 块拖拽重排 Sep 17, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

期望支持块拖拽,直接调整 Markdown 内容顺序

2 participants