Skip to content

ADR-005: 引入 TipTap 作为富文本编辑器

Status

Accepted

Date

2026-03-25

Context

TextNode 需要富文本编辑能力(标题、加粗、斜体、列表、删除线),同时需要满足:

  1. 与 Vue 3 深度集成 — 响应式内容同步
  2. 程序化写入 — AI 生成结果通过 editor.commands.setContent 填充到编辑器
  3. 防抖回写 — 避免每次击键触发 syncToCanvas
  4. 与 Vue Flow 节点系统共存 — 编辑器嵌入自定义节点卡片内部

Options Considered

方案 A:原生 contenteditable + 手动格式化

  • 优点:零依赖、完全可控
  • 缺点:格式化工具栏需要大量实现;跨浏览器行为不一致;程序化写入困难

方案 B:TipTap(@tiptap/vue-3)

  • 优点:基于 ProseMirror 的成熟方案;@tiptap/vue-3 提供 useEditor composable;StarterKit 涵盖所有基础格式;扩展生态丰富
  • 缺点:ProseMirror 底层复杂,自定义扩展学习曲线陡

方案 C:Quill / Slate

  • 优点:社区成熟
  • 缺点:React 生态为主,Vue 3 集成不理想

Decision

选择 方案 B:TipTap

封装为 useTextEditor(options) composable,处理:

  • 防抖回写:默认 300ms debounce,避免高频触发 store 更新
  • 外部内容同步isExternalUpdate 标志防止 setContent 触发循环更新
  • 编辑器状态响应式editorState 计数器在每次 onTransaction 递增,驱动工具栏 isActive 更新

Consequences

正面影响:

  • 富文本编辑与 AI 结果写入均通过 editor.commands 操作,路径统一
  • StarterKit + Placeholder 即可覆盖 MVP 需要的全部格式

负面影响 / 已知风险:

  • Editor 实例为 ShallowRef,内容不能直接放入 Pinia 深度响应式对象
  • 自定义扩展时需要了解 ProseMirror Schema

替代此决策的条件

若需要支持协同编辑(Collaboration),TipTap 有商业插件支持,但需评估成本。若决定不用 TipTap 的协同方案,可考虑迁移到其他编辑器。