Appearance
ADR-005: 引入 TipTap 作为富文本编辑器
Status
Accepted
Date
2026-03-25
Context
TextNode 需要富文本编辑能力(标题、加粗、斜体、列表、删除线),同时需要满足:
- 与 Vue 3 深度集成 — 响应式内容同步
- 程序化写入 — AI 生成结果通过
editor.commands.setContent填充到编辑器 - 防抖回写 — 避免每次击键触发
syncToCanvas - 与 Vue Flow 节点系统共存 — 编辑器嵌入自定义节点卡片内部
Options Considered
方案 A:原生 contenteditable + 手动格式化
- 优点:零依赖、完全可控
- 缺点:格式化工具栏需要大量实现;跨浏览器行为不一致;程序化写入困难
方案 B:TipTap(@tiptap/vue-3)
- 优点:基于 ProseMirror 的成熟方案;
@tiptap/vue-3提供useEditorcomposable;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 的协同方案,可考虑迁移到其他编辑器。