Slate v2 源码删除族闭合(Slate React Source Deleted-Family Closure)实践指南
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
本文基于 plate 仓库中 docs/plans/2026-04-09-slate-v2-slate-react-source-deleted-family-closure.md 这一计划文档,深入解析在 Slate v2 迁移与重构过程中,如何系统性地核对、分类并"闭合"(closure)
slate-react包中被删除的源码族。文章涵盖:删除源码的完整盘点方法、镜像/显式跳过二分类闭合矩阵、包父级树的闭合判定逻辑,以及闭合操作前后必须执行的新鲜验证命令。读者将掌握一套可复用的"源码删除族闭合"工作流,适用于任何大型编辑器重构中对历史源码残骸的清算与证明。
1. 背景:为什么需要"源码删除族闭合"
在 Slate v2 的大规模重构中,旧版slate-react包的大量内部源码被移除或重写。删除源码本身不是问题,问题在于:这些被删除的文件是否被新架构完整承接?如果某些功能被删除后没有替代实现,就会形成"静默功能丢失";反之,如果某些删除只是内部实现换血,而公共能力仍在,则需要用证据证明"能力无损"。
该计划文档(docs/plans/2026-04-09-slate-v2-slate-react-source-deleted-family-closure.md)就是这一清算过程的产物。它的核心思想是:
- 逐一盘点被删除的源码文件(frozen source inventory);
- 逐类判定每个删除族是"已被镜像承接"(
mirrored now)还是"显式跳过"(explicit skip); - 收敛闭合整个
packages/slate-react/**作用域,并给出可执行的新鲜验证清单。
2. 作用域与盘点方法
2.1 闭合作用域
文档明确的闭合作用域为:
packages/slate-react/src/**即本次闭合只针对slate-react包的src目录,不涉及测试目录(test/**已在另一份文档中单独闭合)、CHANGELOG.md包根残渣、以及未来大文档运行时工作(如 semantic islands、更深的slate-react优化)。
2.2 冻结源码清单的生成命令
删除文件的精确清单通过 git diff 生成,仅筛选删除(--diff-filter=D)且限定在packages/slate-react/src下的路径:
git -C /path/to/repo diff --diff-filter=D --name-only -- packages/slate-react/src该命令的核心要点:
| 参数 | 作用 |
|---|---|
git diff | 对比工作区与索引/HEAD 的差异 |
--diff-filter=D | 只列出被删除(Deleted)的文件,忽略新增、修改、重命名 |
--name-only | 只输出文件路径,不输出 diff 正文 |
-- packages/slate-react/src | 路径限定,只统计该目录下的删除 |
执行后得到精确删除路径数为 30 个。这 30 个文件是闭合工作的事实起点,任何未被清单覆盖的删除都不属于本次闭合范围。
3. 冻结源码清单:30 个被删除文件全录
以下为文档记录的完整删除清单,按目录分组:
类型与常量残渣
packages/slate-react/src/@types/direction.d.tspackages/slate-react/src/custom-types.tspackages/slate-react/src/utils/environment.ts
chunking(子块化)内部实现
packages/slate-react/src/chunking/children-helper.tspackages/slate-react/src/chunking/chunk-tree-helper.tspackages/slate-react/src/chunking/get-chunk-tree-for-node.tspackages/slate-react/src/chunking/index.tspackages/slate-react/src/chunking/reconcile-children.tspackages/slate-react/src/chunking/types.tspackages/slate-react/src/components/chunk-tree.tsx
渲染器原语组件
packages/slate-react/src/components/element.tsxpackages/slate-react/src/components/leaf.tsxpackages/slate-react/src/components/string.tsxpackages/slate-react/src/components/text.tsx
restore-dom(DOM 回滚)机制
packages/slate-react/src/components/restore-dom/restore-dom-manager.tspackages/slate-react/src/components/restore-dom/restore-dom.tsx
hooks(公共钩子面)
packages/slate-react/src/hooks/android-input-manager/android-input-manager.tspackages/slate-react/src/hooks/android-input-manager/use-android-input-manager.tspackages/slate-react/src/hooks/use-children.tsxpackages/slate-react/src/hooks/use-composing.tspackages/slate-react/src/hooks/use-decorations.tspackages/slate-react/src/hooks/use-editor.tsxpackages/slate-react/src/hooks/use-element.tspackages/slate-react/src/hooks/use-focused.tspackages/slate-react/src/hooks/use-generic-selector.tsxpackages/slate-react/src/hooks/use-is-mounted.tsxpackages/slate-react/src/hooks/use-mutation-observer.tspackages/slate-react/src/hooks/use-read-only.tspackages/slate-react/src/hooks/use-selected.tspackages/slate-react/src/hooks/use-track-user-input.ts
这份清单本身就是一张核对表:在闭合评审时,逐个文件对照"是否还有替代实现"即可快速定位风险点。
4. 源码族闭合矩阵:两分类判定法
文档将 30 个删除路径划分为 7 个簇,逐一给出状态、证据所有者和解决方案。这是全文最核心的决策表:
| 簇(Cluster) | 删除数 | 状态 | 当前证据所有者 / 替代实现 | 解决方案 |
|---|---|---|---|---|
公共 hook 拆分面(use-composing、use-editor、use-element、use-focused、use-read-only、use-selected) | 6 | mirrored now | true-slate-rc-proof-ledger.md,当前 hooks 位于packages/slate-react/src/hooks/*.tsx | 被删除的拆分式 hook 文件由当前的.tsxhook 面 + 既有运行时/表层证据承接 |
渲染器原语拆分面(element、leaf、text、string) | 4 | mirrored now | 同上,当前原语位于slate-element.tsx、slate-leaf.tsx、slate-text.tsx、text-string.tsx、zero-width-string.tsx | 旧原语拆分由当前渲染器原语与结构化文本表层恢复 |
chunking / 运行时广度内部实现(src/chunking/**、components/chunk-tree.tsx、hooks/use-children.tsx) | 8 | explicit skip | chunking-review.md、architecture-contract.md | 子计数 chunking 在 v2 中不是基础能力;语义孤岛(semantic islands)与选择器局部失效才是真正的故事 |
restore-dom 回滚内部实现(components/restore-dom/**、use-track-user-input.ts、use-is-mounted.tsx、use-mutation-observer.ts) | 5 | explicit skip | editable.tsx、runtime.tsx | 旧 DOM 回滚架构被 mounted 桥接 + 当前Editable的选择/输入所有权取代 |
旧 decorate 订阅内部实现(use-decorations.ts、use-generic-selector.tsx) | 2 | explicit skip | surface-contract.tsx、true-slate-rc-proof-ledger.md | 旧 decorate 机制在现行契约之外;当前价值经由投影局部渲染与恢复的公共表层存续 |
Android 专用助手内部实现(hooks/android-input-manager/**) | 2 | explicit skip | proof-lane-matrix.md,当前合成路径在editable.tsx | Android 助手内部实现不属于现行公共/包声明;当前 IME 事实由专用浏览器通道负责 |
src/custom-types.ts | 1 | explicit skip | 2026-04-09-slate-v2-interfaces-family-deleted-test-closure.md | 声明合并式CustomTypes不在现行结构化类型契约内 |
src/@types/direction.d.ts | 1 | explicit skip | 无 | 已删除的类型残渣,非面向贡献者的现行证明 |
src/utils/environment.ts | 1 | explicit skip | 无 | 已删除的 React 大版本辅助函数不属于现行公共或证明表层 |
4.1 汇总统计
mirrored now(已镜像承接):10个explicit skip(显式跳过):20个- 已对账的源码删除路径:30个
两个分类的语义差异需要重点区分:
mirrored now:功能仍存在于新架构中,只是文件位置、形态或拆分方式变了(如.ts拆分文件合并进.tsxhook 面)。这类删除必须给出替代实现路径,否则视为功能丢失;explicit skip:该功能经评审认定"在新架构中不再必要",且给出了明确理由(架构契约、证明通道、声明范围)。这类删除必须给出理由与证据所有者,不允许无理由跳过。
5. 关键决策的架构依据:"为什么难啃的骨头被更好地切掉了"
文档用三个独立小节解释了最棘手的三块删除为何选择"显式跳过"而非"费力恢复",这些理由对理解 Slate v2 架构方向至关重要。
5.1 Chunking(子计数分块)为何放弃
- 现行文档已声明 chunking 在 v2 中不是基础能力(not foundational);
- 当前源码已不再携带旧的子计数 chunking 树;
- 恢复它等于"复活一个运行时广度拐杖",而非闭合现行契约。
替代方案是语义孤岛(semantic islands)与选择器局部失效(selector-local invalidation)——即通过更精细的依赖切分减少重渲染范围,而不是依赖旧的按子节点数量分块策略。
5.2 Restore DOM(DOM 回滚)为何放弃
- 旧的基于 class 的 DOM 回滚管理器不再是当前接缝(seam);
- 当前
Editable直接拥有 mounted 根的选择与输入行为; - 恢复旧回滚层会产生"竞争性 DOM 事实路径"(competing DOM truth paths),反而引入状态不一致风险。
这一决策体现了 v2 "单一所有权"的设计倾向:DOM 事实由Editable集中持有,而不是分散在多个回滚/恢复辅助层中。
5.3 Android 输入管理器为何放弃
- 当前 IME(输入法)事实由专用浏览器证明通道承载,而不是包内 Android 辅助状态;
- 如果现行契约真的需要这些助手,包/浏览器证明早已暴露该需求——即"未被证明需要的代码不恢复"。
5.4 设计方法论提炼
从这三节可以提炼出 v2 源码删除族的统一判定原则:
- 契约优先:只闭合"现行契约"相关的删除,内部实现细节不构成闭合义务;
- 证据驱动:每个删除族必须有证据所有者(证明文档或测试文件),"无证据 = 不恢复";
- 拒绝竞争路径:如果恢复旧实现会与现代架构产生重复的事实来源(DOM、输入、选择),宁可显式跳过;
- 文档先行:架构契约文档(
architecture-contract.md)与评审文档(chunking-review.md)先行声明"什么不是基础能力",删除时才有依据可依。
6. 包父级树的闭合传播
删除族闭合完成后,还要在包父级树上验证闭合状态向上传播是否正确:
| 作用域 | 状态 | 说明 |
|---|---|---|
packages/slate-react/** | closed | 父级闭合,因为每个子行均已闭合或显式跳过 |
packages/slate-react/test/** | closed | 已在 2026-04-09-slate-v2-slate-react-deleted-test-family-closure.md 中闭合 |
packages/slate-react/src/** | closed | 由本文档闭合 |
packages/slate-react/CHANGELOG.md | explicit skip | 包根残渣,非发布证明 |
闭合传播的逻辑是自底向上的:只有当所有子作用域(src/**、test/**)都达到closed或explicit skip时,父作用域packages/slate-react/**才能标记为closed。任何一个子行悬而未决,父级都不能闭合。
值得注意的是,该文档同时声明:packages/slate-react/**内部已无开放的兄弟桶(sibling buckets still open: none),这意味着本次闭合是一次完整收敛。
7. 本次闭合不覆盖的范围(边界声明)
闭合文档明确列出了不在此次闭合范围内的内容,防止后续工作产生误判:
packages/slate-history/test/**(历史包测试族,另行处理);- 支撑性的示例 / 浏览器删除族(supporting example/browser deletion families);
- 未来的大文档运行时工作,例如语义孤岛、更深的
slate-react优化(这些属于运行时隔离区,即 runtime quarantine,不在本次闭合讨论之列)。
边界声明的作用是责任划分:闭合矩阵只对声明的作用域负责,未声明的工作由后续专项计划承接。
8. 闭合必须的新鲜验证命令
文档末尾给出了本次闭合生效前必须执行的新鲜验证(fresh verification)命令集,它们是闭合结论的"可执行证据":
yarn workspace slate-react run test # slate-react 包测试 yarn test:custom # 自定义测试集 yarn lint:typescript # TypeScript 类型与 lint yarn test:slate-browser:ime:local # 本地 IME(输入法)浏览器通道 yarn test:slate-browser:dom # DOM 浏览器通道各命令的验证目标:
| 命令 | 验证目标 |
|---|---|
yarn workspace slate-react run test | 确认当前slate-react测试面全绿,证明镜像承接的 hook/原语没有破坏行为 |
yarn test:custom | 自定义回归集,覆盖仓库特定功能组合 |
yarn lint:typescript | 类型系统层面确认删除旧文件后无悬空引用、无类型断裂 |
yarn test:slate-browser:ime:local | 印证"IME 事实由浏览器通道负责"的声明(对应 Android 输入管理器删除族的证据) |
yarn test:slate-browser:dom | 印证"DOM 事实由Editable持有"的声明(对应 restore-dom 删除族的证据) |
这 5 条命令与闭合矩阵形成了闭环:矩阵中每个explicit skip的声明,都能在对应的浏览器/测试通道中找到独立证据,而不是仅靠文档自证。
9. 方法论总结:如何复刻这套闭合工作流
基于本文档,可以提炼出一个可复用的"源码删除族闭合"工作流,适用于任何大型编辑器或前端框架重构:
- 冻结清单:用
git diff --diff-filter=D --name-only -- <scope>精确导出删除文件清单,作为唯一事实来源; - 聚类分组:按目录与功能语义将被删除文件分成簇(公共面 / 内部实现 / 类型残渣 / 平台专用);
- 逐簇判定:对每个簇回答两个问题——"功能是否仍被需要?"与"现行架构是否已承接?",据此分入
mirrored now或explicit skip; - 给出证据:
mirrored now必须指向替代实现路径;explicit skip必须给出架构理由与证明所有者,杜绝无理由跳过; - 传播闭合:自底向上验证子作用域全部收敛后,父作用域才能标记
closed,并声明不覆盖范围; - 新鲜验证:以命令清单作为最终闸门,让测试与类型检查成为删除结论的独立证据。
这套流程的本质是:用文档记录架构决策,用 git 历史锚定事实,用测试命令提供证据,三者缺一不可。对于正在经历大规模重构的编辑器项目,这比"凭感觉删除"或"全量保留"都更可审计、更可追溯。
10. 深入阅读
- 2026-04-09-slate-v2-slate-react-source-deleted-family-closure.md:本文档原文,含 30 个删除路径的完整清单;
- 2026-04-09-slate-v2-slate-react-deleted-test-family-closure.md:测试删除族的姊妹闭合文档;
- 2026-04-09-slate-v2-interfaces-family-deleted-test-closure.md:interfaces 族删除测试闭合,
custom-types.ts跳过的证据依据; - true-slate-rc-proof-ledger.md:Slate v2 运行时证明账本,镜像承接族的证据所有者;
- chunking-review.md 与 architecture-contract.md:chunking 跳过决策的架构依据;
- proof-lane-matrix.md:浏览器证明通道矩阵,Android 输入管理器删除族的证据依据。
【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考