﻿# 一次 Markdown 编辑器换内核的尝试

Next Token 博客

渲染层和源码是两套状态，是所见即所得编辑器一类顽固问题的根源。一次从 Milkdown 迁到 CodeMirror 6 的重构，说明修改已有系统的机会在哪里、验收的责任在谁。

发布：2026-10-09
更新：2026-10-10

所见即所得的编辑器里藏着一个隐蔽的问题：你看到的，和文件里实际存的，可能不是同一份数据。一次把 Markdown 编辑器从 [Milkdown](https://nexttoken.tv/wiki/products/milkdown) 迁移到 [CodeMirror 6](https://nexttoken.tv/wiki/products/codemirror) 内核的重构，就是从这个根源动刀的。

## 两份状态，数不清的细节

原来的内核里，渲染出来的内容和原始源码是两套状态。改东西的时候，界面上看起来已经改了，源码里可能并没有改。这不是一个孤立的 Bug，而是一类问题的温床：两份表示之间需要同步，同步就有时机、粒度和冲突处理的问题，细节多到数不清，修掉一个又冒出一个。

目标因此很明确：让源码成为唯一的事实，渲染从源码派生。这也是 [Typora](https://nexttoken.tv/wiki/products/typora) 等主流编辑器已经验证过的路线。做到这一点最直接的办法，就是把底层内核换掉——在旧的架构上继续修补，等于不断为两份状态之间的缝隙打补丁。

## 方案是模型提的，工期也由它估

这次重构连方案都来自模型。开发者并不熟悉内核选型，是模型提出换内核、列举了换完能解决的一串问题，并估计工作量"可能需要一周"。开发者反复确认"这个事情我能 Hold 住吗"，得到肯定答复后才动手，使用的模型是当时的 DeepSeek Flash。

一周是按人类的节奏估的。开发者提醒它"你是 AI，一天差不多了"，结果模型一次性写出了迁移的主体，有一些 Bug，但骨架一次成型。预估和执行的落差本身说明了一个变化：过去拦住这类重构的，主要是逐文件改写的工作量；这部分被压缩之后，真正稀缺的变成了判断——要不要迁、迁到哪、怎么算迁完。

## "写完了"不等于迁移完成

迁移最容易省略的环节是验收。一次性生成的代码会有 Bug；换完内核后编辑器"巨爽"、解决了一堆旧问题，是使用层面的感受。编辑器质量最终仍要靠长期使用和回归情况说话：旧的编辑行为有没有逐项保留，嵌套结构、粘贴、撤销、表格这些 Markdown 的老大难场景有没有回归。这次尝试没有展示完整的测试覆盖，所以它能支持的结论是"迁移主体完成、使用体验明显改善"，而不是"内核迁移从此很轻松"。

同一晚的讨论里还有一个可以对照的案例：一个游戏项目在更换实现语言之前，先让单元测试把既有逻辑锁住，替换才变得"轻轻松松"。两个案例指向同一件事——行为约束和回归检查，比"重写完了"更能定义迁移是否完成。迁移的产出不只是新代码，还有一套能证明旧行为没有被破坏的依据。

## 这次经验适用到哪里

同一段讨论里还有另一个迁移：把一整套 [Obsidian](https://nexttoken.tv/wiki/products/obsidian) 插件搬进另一个运行环境，交代方式是让模型自己判断哪些功能与笔记无关并去掉，一次迁完。可见模型能承担的不只是机械改写，还包括迁移中的裁剪判断——前提是把"什么算相关"的范围交代清楚。

讨论中也出现了更激进的感叹，认为不少跨平台技术栈"已经没有市场了"。这句话需要谨慎对待。一个编辑器换内核成功，说明在"双份状态"这个具体病灶上，换掉内核比继续修补更划算；它不能推广成所有框架失去价值。某个框架值不值得用，取决于它解决的问题在当前项目里是否还存在、留在原架构和迁走的成本谁高谁低——这些要按项目逐个算，一次尝试定不了论。

迁移的发起和执行可以交给模型，"什么叫做完"仍然由人定义。这个责任没有因为执行变快而消失，反而因为执行变快，更容易被人忽略。

## 相关资料

- [渲染与源码两套状态的问题](https://nexttoken.tv/weekly/005/transcript#quote-3ac4fb63746949f2b615)及[换完内核后的体验变化](https://nexttoken.tv/weekly/005/transcript#quote-fd54e601316b1e0d9ada)
- [从 Milkdown 迁到 CodeMirror 6 的方案与工期估计](https://nexttoken.tv/weekly/005/transcript#quote-a26a210c2315f9a66446)
- [对换内核方案的反复确认](https://nexttoken.tv/weekly/005/transcript#quote-916e94a44b29557c3c43)
- [单元测试锁住逻辑、替换实现语言的经验](https://nexttoken.tv/weekly/005/transcript#quote-7958f61026c7f81e12fb)
- [Obsidian 插件的迁移](https://nexttoken.tv/weekly/005/transcript#quote-4aee9820b94a95b919f3)与[对跨平台技术栈的讨论](https://nexttoken.tv/weekly/005/transcript#quote-bdab45c311bcbd6bf8f6)

## 来源与相关链接

- [网页版文章](https://nexttoken.tv/blog/markdown-editor-kernel-migration)
- [Weekly #005 完整文字稿](https://nexttoken.tv/weekly/005/transcript)
