一份持久内容
CodeMirror 文本是编辑器的内容权威。解析器和扩展从源码派生语法范围、字段及呈现;保存时读取当前 Markdown。
| 层 | 负责什么 |
|---|---|
| 编辑器核心 | 文本、选区、事务、历史、模式与生命周期 |
| 语法与字段 | 识别当前源码范围,读取字段,校验并编码精确修改 |
| 命令 | 描述源码操作,在一次事务中提交 |
| 组件与主题 | 显示内容、提供交互,通过受控动作请求修改 |
| 宿主应用 | 文件、存储、权限来源、上传服务和业务界面 |
从组件操作回到源码
以 [[todo]] 为例:语法确认 token 后,read() 派生 { value: 'todo' }。组件请求 { value: 'done' },patch() 只替换括号内部的字段,最终源码成为 [[done]]。
这种操作与键盘输入共用历史,因此用户可以撤销组件按钮造成的修改。见自定义节点的完整实现。
语义与界面分别扩展
Node.create()、Mark.create() 和 Extension.create() 提供声明入口。可以先定义字段和命令,再由应用用 .extend() 添加 Vue、React 或原生 DOM 呈现。
这些声明当前不是 ProseMirror schema。parseHTML、renderHTML、NodeViewContent 等接口不能直接从 Tiptap 示例中搬入;请以 API 参考和支持范围为准。
何时保留源码
未知、未闭合或暂时无法呈现的结构保留原文。自定义语法与资源加载也应明确回退行为,不能以隐藏原文代替解析成功。
与 AST 编辑器集成时的选择
解析树是可重新计算的索引,不能接替文本成为唯一存档。把 Markdown 转成 ProseMirror JSON、编辑后再序列化会改变可表示范围和原始拼写策略;这属于另一条内容管线,不是 MSFE 的透明内核。
若应用同时有富文本视图和源码优先视图,应明确转换边界、损失政策和每个编辑会话的权威来源,不让两份内容同时自动互相覆盖。当前文档只承诺本编辑器内的单一源码事务流。
复杂扩展的一次数据流
- 用户输入进入 CodeMirror 文本与历史。
- 增量解析确认语法范围;未确认部分仍显示源码。
- codec 读取字段,投影描述视觉,组件只呈现收到的属性。
- 组件操作通过命令或字段 patch 请求精确修改。
- 编辑器校验当前意图、权限和范围,接受后通知宿主增量变化。
- 宿主按自己的持久化协议保存 Markdown。
这个分工同时适用于简单状态标记、嵌套容器和异步图表;不同之处在于选择了哪些 扩展入口。