Plate 项目 Lexical 测试收割:用可移植测试索引驱动 Slate v2 行为移植
2026/9/14 19:57:47 网站建设 项目流程

Plate 项目 Lexical 测试收割:用可移植测试索引驱动 Slate v2 行为移植

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

导读

本文讲解 plate 仓库中docs/editor-test-harvester/lexical/这套"测试收割"(test harvest)工作流的核心索引——test-index.md:它以文件级分类(category)、行为家族(family)与落地目标(target)三要素,把上游 Lexical 仓库中 137 个可移植测试文件、1996 个test/describe/it行为指针组织成一张可检索、可审计的移植地图。读完本文,你将掌握这份索引的结构与行指针语义、它与全量清单(inventory.md)和处理台账(slate-processing-ledger.md)如何协同,以及如何在本仓库中用它定位"哪些上游行为值得移植、哪些应拒绝、哪些归 Plate 所有",为 Slate v2 的测试基建做 source-read 与 apply 决策。

一、收割工作流的整体布局:三份文档如何分工

在 docs/editor-test-harvester/lexical 目录下共有三份相互引用的文档,构成一条完整流水线:

文档作用与 test-index.md 的关系
inventory.md全量清单:用一条rg命令枚举上游 Lexical 仓库所有测试文件并逐一分类是索引的上游;只有被标记为portableportable-mixed的 runnable 文件才会进入索引
test-index.md可移植测试名称索引:为每个可移植文件提取全部test/describe/it行,给出文件:行号指针本文主体;inventory.md明确声明"portable 与 portable-mixed 的可运行行已收录进 test-name index"
slate-processing-ledger.md处理台账:为每个索引文件给出already-applied/covered/defer/plate-owned/reject等最终裁决是索引的消费端;用索引的行指针做 source-read,再回填裁决

索引头部自带 provenance 元数据:source report: ./report.md(报告文件不在本仓库内,属于上游生成物)、target: ../lexical(指向被收割的上游 Lexical 源码树,同样不在 plate 仓库内)、generated_at: 2026-05-08last_consolidated_at: 2026-05-09。头部还记录了合并校验结果:可运行可移植文件数仍为 137、提取行数仍为 1996,无缺失或过期索引文件——这保证了索引与上游源码的同步性可被持续复核。

二、索引规模与质量底线:137 个文件、1996 个行为指针

test-index.md在头部给出三个关键统计,这是评估移植工作量的第一手数据:

Indexed runnable portable and portable-mixed files: 137. Extracted test/describe/it lines: 1996. Files with zero extracted names: 0.

解读:

  • 137 个文件:全部是inventory.md中判定为portable(124 个)或portable-mixed(13 个)的可运行文件。product-shell(33)、harness(12)、skip(89)三类被排除在索引之外。
  • 1996 行指针:每个指针形如路径:行号+describe/test/it: 标题,粒度到单个测试用例。
  • 0 个空文件:不存在"有文件但未提取到任何测试名"的漏网之鱼,索引完整性有硬性校验。

此外头部特别说明了一个提取器细节:提取器按行指针记录 literal(字面量)、dynamic(动态模板)和 multiline(多行)标题。dynamic 行(如test: testing ${scenario[2]}: ...)仍需在 apply 前阅读本地源码以还原真实语义,但它们不再被"仅按文件名路由"的方式隐藏——也就是说,索引保证了每条动态标题至少有一个可追溯的锚点(文件:行号),读者可以回到源码展开模板变量。索引中大量dynamic or multiline title占位即属于此类,例如AutoLinks.spec.mjs:33Composition.spec.mjs:176LexicalMarkdown.test.ts:818

三、文件条目的三要素元数据:category / family / target

每个文件条目在测试清单之前固定给出三行元数据,这是本索引最有操作价值的部分。以第一个条目为例:

## `../lexical/packages/lexical-code-shiki/src/__tests__/unit/LexicalCodeNodeTabs.test.ts` category: portable family: core package behavior target: .tmp/slate-v2/packages/slate/test; add focused browser proof only when behavior depends on DOM/runtime transport

category:移植可行性等级

索引中实际出现的取值有portableportable-mixed两种(这也是它叫"Portable Test-Name Index"的原因):

  • portable:文件中的行为可在纯模型层验证,优先落入 Slate v2 的packages/slate/test,属于"直接可移植";
  • portable-mixed:文件是产品/插件 e2e 或混合场景,但其中包含可分离的便携不变量(invariant)。例如AutoLinks.spec.mjsAutocomplete.spec.mjsCharacterLimit.spec.mjs等被标为portable-mixed,其 target 通常是"packages/slate/test;仅当行为依赖 DOM/运行时传输时才补充浏览器证明"。

注意:portable-mixed不等于拒绝。台账里对混合文件的做法是"从产品文件中拆分出原始不变量"(split a raw invariant out of a product file)。

family:行为家族

family把 137 个文件归并到少量语义桶,便于按主题批量检索。结合 inventory.md 的完整行表,可以归纳出以下家族及其在索引中的分布:

family代表文件说明
core package behaviorLexicalCodeNode.test.tsLexicalHistory.test.tsxLexicalHtml.test.tsLexicalHeadingNode.test.tsLexicalQuoteNode.test.tslexical-list/src/__tests__/unit/utils.test.ts核心包/编辑器单元行为,多数 target 指向packages/slate/test
serialization-parsing / marks-inlineLexicalListItemNode.test.tsLexicalListNode.test.tsformatList.test.tsLexicalMarkdown.test.tsCodeBlock.spec.mjsTextFormatting.spec.mjsClearFormatting.spec.mjsElementFormat.spec.mjsHeadings*.spec.mjsIndentation.spec.mjsList.spec.mjsMarkdown.spec.mjs序列化/解析/富文本格式,通常同时指向slate/testslate-history/test与 playwrightrichtext.test.ts
clipboard-paste / browser-engineHTMLCopyAndPaste.spec.mjsImageHTMLCopyAndPaste.spec.mjsLinksHTMLCopyAndPaste.spec.mjsListsHTMLCopyAndPaste.spec.mjsTablesHTMLCopyAndPaste.spec.mjsTextFormatHTMLCopyAndPaste.spec.mjsContextMenuCopyAndPaste.spec.mjsCopyAndPaste.spec.mjsListsCopyAndPaste.spec.mjsExtensions.spec.mjsLexicalTabNode.test.ts*HTMLCopyAndPaste.test.ts剪贴板与粘贴,target 指向slate/test/clipboard-contract.tsslate-dom/test/clipboard-boundary.test.ts、playwrightpaste-html.test.ts
selection-dom-mapping / void-atomAutoLinks.spec.mjsHashtags.spec.mjsHorizontalRule.spec.mjsKeywords.spec.mjsLinks.spec.mjsMentions.spec.mjsNavigation.spec.mjsSelection.spec.mjsLexicalSelection.test.*LexicalCaret.test.ts选择/DOM 映射与 void/原子节点,target 增加slate-react/test/editable-behavior.test.tsx
beforeinput-input / browser-engineAutoScroll.spec.mjsEvents.spec.mjsFocus.spec.mjsKeyboard.spec.mjsKeyboardShortcuts.spec.mjsMutations.spec.mjsTextEntry.spec.mjs输入运行时,target 指向slate-react/test/model-input-strategy-contract.test.ts与 playwright stress
ime-composition / history-undo-redoComposition.spec.mjsregression/8153-safari-ime-delete-selection.spec.mjsIME 合成与撤销栈,target 增加slate-browser/src/playwright/ime.tsslate-history/test
collaboration-remote / history-undo-redoCollaboration.spec.mjs协作,target 为slate/test/collab-history-runtime-contract.ts+ 未来 slate-yjs 浏览器车道
tables-grid / selection-dom-mappingTables.spec.mjsLexicalTableCellNode.test.tsLexicalTableNode.test.tsxLexicalTableSelection.test.tsxLexicalTableUtils.test.ts表格,target 指向 playwrighttables.test.tsslate/test/transforms/insertFragment
portable editor behaviorDraggableBlock.spec.mjsImages.spec.mjsPlaceholder.spec.mjsTab.spec.mjs、绝大多数regression/*.spec.mjs通用便携编辑行为,多数仅指向packages/slate/test
mixed portable invariantAutocomplete.spec.mjsCharacterLimit.spec.mjsColumnLayoutBackspaceAtEnd.spec.mjsDateTime.spec.mjsEmoticons.spec.mjsEquationNode.spec.mjsMaxLength.spec.mjsSpecialTexts.spec.mjsToolbar.spec.mjs混合便携不变量,target 为packages/slate/test+ 按需浏览器证明

target:落地坐标

target明确给出"这份文件的行为应该移植到哪里"。它反复出现的几种坐标在 slate-processing-ledger.md 的"Current Slate Owners"一节有完整定义:

Slate 所有者路径
核心模型与查询不变量.tmp/slate-v2/packages/slate/test
剪贴板模型/DOM 契约.tmp/slate-v2/packages/slate/test/clipboard-contract.ts.tmp/slate-v2/packages/slate-dom/test/clipboard-boundary.ts
文本单元.tmp/slate-v2/packages/slate/test/text-units-contract.ts
输入运行时策略.tmp/slate-v2/packages/slate-react/test/model-input-strategy-contract.test.ts
DOM 修复策略.tmp/slate-v2/packages/slate-react/test/dom-repair-policy-contract.ts
浏览器压力行.tmp/slate-v2/playwright/stress/generated-editing.test.ts
粘贴 HTML 浏览器语料.tmp/slate-v2/playwright/integration/examples/paste-html.test.ts
富文本浏览器行为.tmp/slate-v2/playwright/integration/examples/richtext.test.ts
表格浏览器包含性.tmp/slate-v2/playwright/integration/examples/tables.test.ts
协作/历史基座.tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts.tmp/slate-v2/packages/slate-history/test/history-contract.ts

值得注意的规则:默认优先落在模型层packages/slate/test,只有当行为依赖 DOM/运行时传输时才补浏览器证明("add focused browser proof only when behavior depends on DOM/runtime transport")。这是整个收割策略的基石——先锁模型不变量,再按需加浏览器行。

四、行指针的语义与检索方式

索引的每一行测试记录格式统一为:

- `../lexical/<包>/<路径>.test.ts:<行号>` describe/test/it: <标题>

三种前缀分别对应测试框架的三层结构:

  • describe:测试分组(如LexicalCodeNode testsTabsMarkdownListExtension);
  • test/it:具体用例(二者等价,it是 BDD 风格别名,索引同时保留两种原样拼写,例如LexicalListItemNode.test.ts:1296it: indents and outdents list item);
  • 标题可能是 literal、dynamic(含${...}模板)或 multiline(跨行)。

文件:行号指针是关键——它允许任何 Agent 或工程师通过search_in_files或直接read_file回到上游源码做source-read(通读源码),还原 dynamic 标题的真实参数矩阵。例如LexicalCodeNodeTabs.test.ts:96testing ${scenario[2]}: ${scenario[0]} => ${scenario[1]} (${direction}),必须在源码中展开scenario数组才能知道它覆盖了哪些 Tab 缩进方向组合。

五、按家族深入:索引覆盖的行为全貌

以下按家族给出索引中的代表性文件与其核心用例,全部取自test-index.md的真实行指针(行号即索引中记录的上游行号)。

5.1 核心包行为(core package behavior)

  • 代码块 Tab:LexicalCodeNodeTabs.test.ts(code-shiki) 47/49/96 行覆盖 describeLexicalCodeNode tests/Tabs与场景化 Tab 用例;lexical-code包的同名文件结构相同。LexicalCodeNode.test.ts是索引中最长的核心文件之一,覆盖构造、createDOM/updateDOMexportJSONschema、insertNewAfter$createCodeNode,以及大量 Tab/缩进用例:can tab with collapsed/non-collapsed selection(179/215)、单行/多行 indent/outdent(239/279/319/357)、code blocks can shift lines(459/479)、arrowsrtl code lines(513/514)下的MOVE_TO_END/MOVE_TO_START视觉移动(537/559),以及回归can be registered after initial editor state (regression #7014)(1007)。
  • 历史LexicalHistory.test.tsx覆盖after clearingRedo after Quote Nodechange, undo, redo, undo, change序列(352)、undoStack selection points to the same editor(437)、Changes to TextNode leaf are detected properly #6409(481),以及SharedHistoryExtension父编辑器创建(541/542)。
  • HTML 序列化LexicalHtml.test.ts覆盖[Lexical -> HTML]的具名用例(42)、Use provided selection(64)、Default selection (undefined) should serialize entire editor state(111)、段落对齐优先级(186)、DocumentFragment导出(216)。
  • 富文本节点LexicalHeadingNode.test.ts覆盖构造/DOM/insertNewAfter空/中/尾(101/123/147)、setTag(173)、h2 插入段落后(219);LexicalQuoteNode.test.ts覆盖 QuoteNode 全生命周期。
  • 工具lexical-list/src/__tests__/unit/utils.test.ts覆盖 1/2/5 层列表深度(17/35/68)、getTopListNode直接/非直接/深层嵌套(113/144/176)、isLastItemInList四种嵌套组合(214/249/275/310)。LexicalUtilsInsertNodeToNearestRoot.test.tsxLexicalUtilsSplitNode.test.tsx覆盖最近根插入与 split 抛错。

5.2 序列化、解析与标记(serialization-parsing / marks-inline)

  • 列表LexicalListItemNode.test.ts是索引中行数最密集的文件之一,覆盖构造/DOM、replace()首/中/尾/唯一项(239/294/323/354)、remove()的兄弟嵌套矩阵(401/469/549/629/718/828/939)、insertNewAfter()非空列表项(1063-1204)、setIndent()与小数缩进(1296/1356)、列表分割编号重置/保留(1415/1455)。LexicalListNode.test.ts覆盖append()/splice()包装转换(214-308)、checklist 转 bullet(341)、嵌套清理(367)、子类化$config(462)。
  • 列表格式化formatList.test.ts覆盖insertList的空/有子 root 选择(84/106)、shadow root 选择(131)、$handleListInsertParagraph空项退出/空白退出/非空白扩展/装饰器扩展/分割(235-343)、$handleIndent嵌套子表创建(389)、$handleOutdent嵌套移除(424)。
  • MarkdownLexicalMarkdown.test.ts覆盖嵌套代码围栏往返(1044/1080)、动态围栏计算(1117)、list marker 记忆(1146-1217)、Enter 触发(1246-1326)、normalizeMarkdownshouldMergeAdjacentLines两档(1381/1507)、硬换行导入(1601/1641)、空白保留默认模式(1682-1747)。MarkdownTransformers.test.ts覆盖 LINK 前置文本保留(53/68)、贪婪抑制(90)、链接内不建链接(123)。
  • 清除格式ClearFormatting.spec.mjs覆盖 BIU 清除(39)、链接/引文样式保留(60)、hashtag/mention 保留(107)、对齐与缩进清除(188-252)、跨段落清除(279)。
  • 代码块 e2eCodeBlock.spec.mjs覆盖 markdown 建块(36)、已有文本包裹(108)、多段/部分段落转换(173/234)、行内转换(300)、语言切换(351)、缩进保持(423)、Tab 行缩进(515)、多行 (un)indent(603)、option+arrow行移动(924)、边界选择防护(1111)、CMD/Ctrl+Left/Right(1267)。
  • 标题/引用/格式 e2eHeadingsBackspaceAtStart.spec.mjs(19)、HeadingsEnterAtEnd.spec.mjs(18)、HeadingsEnterInMiddle.spec.mjs(23)分别锁定首标题 Backspace 无操作、末尾 Enter 变段落、中间 Enter 分裂;ElementFormat.spec.mjs覆盖链接内缩进/对齐(26)与空段居中(59);Indentation.spec.mjs覆盖最大深度(461-1007)与负缩进回归(1007);List.spec.mjs覆盖 checklist 焦点选项(79/120)、嵌套列表、backspace 出缩进(224/316)、类型互转(1446-1831)、markdown 起始编号(2270)、空项 Enter 出表(2318)等;Markdown.spec.mjs覆盖样式化 markdown 快捷输入(219-333)、undo/redo(308)、内嵌转换(763-1055)、list marker 保持(1055/1069)。
  • 文本格式TextFormatting.spec.mjs覆盖加粗/斜体快捷键(39/93)、选中加粗(147)、三连击不污染下段(203)、字号增减(532-639)、字体族(660)、多段选择格式化(817)、回归 #2439(1093)、工具栏激活态(1144)、#2523(1182)、多行忽略换行(1240)。

5.3 剪贴板与粘贴(clipboard-paste / browser-engine)

索引中有一整组CopyAndPaste语料:

  • HTML 语料CopyAndPaste/html/):HTMLCopyAndPaste.spec.mjs覆盖多行 HTML 额外换行(25)、带 BR 的代码块(53)、段落夹在水平线之间(135)、段落中间贴顶层元素(199);ImageHTMLCopyAndPaste.spec.mjs覆盖 figure+figcaption(31)、图片粘贴(134)、多图粘贴+undo(172);LinksHTMLCopyAndPaste.spec.mjs覆盖 anchor 粘贴(37)、链接前/后粘贴(99)、局部内容选择粘贴(130)、空链接 #3193(166)、文本进链接/链接进文本/格式化文本进链接/链接进链接/多块进链接(213-366);ListsHTMLCopyAndPaste.spec.mjs覆盖列表元素(24)、Lexical 嵌套列表(93)、直接嵌套 ul(129)、li 混合内容(217)、checklist(299)、列表中段中间贴(372)、列表内嵌套 div(425);TablesHTMLCopyAndPaste.spec.mjs覆盖 Google Docs(24/95)、Quip(161)、Google Sheets(233)、Merge Grids(306)、嵌套块与行内 HTML(434)、合并单元格与不等行(534)、空行(691);TextFormatHTMLCopyAndPaste.spec.mjs覆盖 BIU(20)与 highlight(70)。
  • Lexical 原生语料CopyAndPaste/lexical/):ContextMenuCopyAndPaste.spec.mjs(29/56)覆盖右键复制粘贴;CopyAndPaste.spec.mjs覆盖基础复制(35)、标题复制(222)、段落进引用(875)、Google Docs/MS Word 字号(905/933)、剪切空选区保留剪贴板(965);ListsCopyAndPaste.spec.mjs覆盖部分列表项复制(33/139)、列表内粘贴(280-533)、列表末段落(766)。

5.4 IME、合成与输入运行时(ime / beforeinput / input)

  • Composition.spec.mjs是 IME 语料最全的文件:平假名(35)、阿拉伯语变音符(88)、IME 输入平假名(174)、行间(258)、加粗内(371)、emoji 间(445)、mention 尾/中部(636/746)、mention 后打字不破坏(852)、hashtag(920)、撤销取消(1078)、浮动工具栏不显示(1211)、typeahead 不关闭(1276)、韩语多节点替换(1325)。
  • AutoScroll.spec.mjs:输入时自动滚动(17)。
  • Events.spec.mjs:macOS 自动大写(21)、emoji 后双空格句号 #3953(96)。
  • Focus.spec.mjs:Tab 移出编辑器(20)、点击外部保持选择(34)。
  • Keyboard.spec.mjsKeyboardShortcuts.spec.mjs:格式/对齐/字号快捷键、清格式、代码块切换、缩进(186-335)。
  • Mutations.spec.mjs:文本 mutation 观察器管理选择(53)、DOM 恢复(156)。
  • TextEntry.spec.mjs:文本插入替换(49)、段间插段(113)、单词删除(353)、首段 backspace(395)、空段与新行选择(600)。
  • 回归8153-safari-ime-delete-selection.spec.mjs:Safari IME 结束后 Cmd+A 全选删除(39)、Shift+ArrowUp 多段删除(73)。

5.5 选择、内联原子与 void(selection-dom-mapping / void-atom)

  • AutoLinks.spec.mjs:URL 化文本转链接(32)、邮箱(63)、非空格破坏链接(92)、粘贴 URL 建链(156/191)、去重(225)、多链接(263/300)、非法链接拒绝(607/655)、unlink 再 link(694)、标点保留(755)、emoji 破坏(896)、Enter 不插多余段(955)。
  • Hashtags.spec.mjs:单个/相邻/批量 hashtag(30/90/195)、格式继承(269)、无效 hashtag 跳过 #5703(329)、粘贴多匹配(420)、导入导出多匹配(444)。
  • HorizontalRule.spec.mjs:创建并移动选择(37)、文本节点尾加 HR(158)、中间分裂文本(210)、列表内分裂(272/341)、复制粘贴(399)、空段删除保留 HR(489)。
  • Images.spec.mjs:装饰器创建与选择移动(40)、增删(219)、任意 URL 添加(391)、拖放(442/535)、选择同步 #2901(577)、Node selection 多选替换(615)、尺寸计算(770)、SVG 渲染(820)。
  • Keywords.spec.mjsLinks.spec.mjsMentions.spec.mjsNavigation.spec.mjsSelection.spec.mjsSelectionAlwaysOnDisplay.spec.mjs分别覆盖关键词装饰器、链接全生命周期(转换/段落边界插入/Enter/图片链接/属性粘贴,39-2411)、mention 输入删除矩阵、键盘导航(段落/行/词/emoji 逐词)、选择全域(焦点、行删除、RTL 装饰器、表格选择包含、格式持久化)、失焦保留选择。
  • 单元层:LexicalSelection.test.tsxLexicalSelectionHelpers.test.ts$sliceSelectedTextNodeContent.test.tsLexicalCaret.test.tsdocs-traversals.test.ts覆盖选择克隆/切片/rebasing、样式补丁、块类型设置、caret 遍历与点排序。

5.6 表格(tables-grid)

Tables.spec.mjs是索引中最大的单文件(193 行指针),覆盖工具栏插入(93)、单元格输入(137)、首/末格退出(185/231)、嵌套表退出(276/304)、键盘导航(622-761)、Table selection 选择/样式/复制/清除(795-1244)、合并/拆分单元格(2013-3077)、行列插入删除与合并冲突(3222-4263)、列头合并(4521)、粘贴嵌套表开关(5841-7127)、RTL/范围选择包含(7638-7909)。单元层LexicalTableCellNode.test.ts覆盖<th>scope 头推断(285-350)、LexicalTableExtension.test.ts覆盖嵌套表开关(101/141)与colWidths规整(366-410)、LexicalTableMobileSelection.test.tsx覆盖触摸选择、LexicalTableUtils.test.ts覆盖列移动与越界 no-op。

5.7 回归族(regression/*)

索引收录了 20+ 个按 issue 号命名的回归文件,是"历史缺陷即行为资产"的体现:1055-fast-typing-undo1083-backspace-with-element-at-front1113-link-newline-at-end1258-delete-forward1384-insert-nodes1730-delete-backword221-editing-hashtags230-navigation-around-hashtags231-empty-text-nodes3136-insert-nodes-adjacent-to-inline3433-merge-markdown-lists379-backspace-with-mentions399-open-line429-swapping-emoji4661-insert-column-selection4697-repeated-table-selection4872-full-row-span-cell-merge4876-unmerge-cell5251-paste-into-inline-element5583-select-list-followed-by-element-node6870-table-left-arrow-selection6974-delete-character-backward7163-graphemes7246-delete-character-backward-list7266-column-header-merged-cells7319-delete-character-backward-nodeselection7354-firefox-decorator-paste7635-SELECTION_INSERT_CLIPBOARD_NODES_COMMAND8153-safari-ime-delete-selection。这些文件通常在family上归类为portable editor behaviorselection-dom-mapping / void-atomime-composition / history-undo-redo

六、与 inventory.md 的配合:分类如何决定"进不进索引"

inventory.md 的核心是一条可复现的清单命令:

rg --files ../lexical \ | rg '(^|/)(__tests__|test|tests|spec|e2e|integration|playwright|cypress|wdio|fixtures)(/|$)|\\.(test|spec)\\.[cm]?[jt]sx?$' \ | rg -v '(^|/)(dist|build|coverage|node_modules|vendor|fixtures/generated|__snapshots__)(/|$)'

第一段枚举测试路径,第二段匹配测试目录/文件命名,第三段排除构建产物与快照。运行结果给出封闭计数:

Counts: total 271; runnable 196; fixture/support 75; portable 124; portable-mixed 13; product-shell 33; harness 12; skip 89; uncertain 0.

分类决策树(由Reason列可见):

  • portable:包单元行为带便携不变量 → 进入 test-index.md;
  • portable-mixed:产品/插件 e2e 但含便携不变量行 → 进入 test-index.md;
  • product-shell:示例应用/框架集成外壳 → 不进索引,除非日后拆出原始不变量;
  • harness:测试辅助工具 → 只借技术,不借行为;
  • skip:工具链/打包/发布/ESM fixture/eslint 插件等 → 无 Slate target;
  • uncertain:0 行,无争议。

清单还提供Plate-Owned Overlay路由表,例如lexical-link/src/__tests__/*AutoLinks.spec.mjs归 Plate link/autolink 包;lexical-listList.spec.mjs归 Plate list/checklist;lexical-markdownMarkdown.spec.mjs归 Plate markdown 序列化包;Hashtags/Keywords/DateTime/Emoticons/EquationNode/CharacterLimit/Images 归 Plate 特性插件包;React Composer/typeahead/工具栏外壳归 Plate React 人体工学。这条规则与台账的plate-owned状态一一对应。

七、与 processing-ledger 的配合:从索引到裁决的闭环

slate-processing-ledger.md 是索引的消费产物,其状态词汇表(Status Vocabulary)必须与索引配合理解:

状态含义
already-applied所选 apply 车道已添加或加强对应 Slate v2 证明
covered现有 Slate v2 已有足够证明行,除非后续审计发现漂移
refactor-existing加强/拆分/重命名现有 Slate 测试,优先于复制
create-new新增 Slate v2 单元/浏览器行
defer行为有效,但需要真机设备、yjs 浏览器、表格模型或后续 owner
plate-owned行为应归 Plate 而非原始 Slate,需指明 Plate 包/文档/示例/backlog owner
reject非便携的原始 Slate 行为目标

台账的总体裁决(Verdict)与索引完全对齐:271 个清单行、137 个可运行 portable/portable-mixed 文件、1996 个行指针全部被说明,无遗漏、无过期、无未解决行。核心方法论是一句话:"Do not copy Lexical tests one-for-one. Keep the invariant, steal the strongest proof shape, and reject Lexical internals."(不要一对一复制 Lexical 测试;保留不变量、借鉴最强证明形态、拒绝 Lexical 内部实现细节。)

台账用"Row-Level Source Read"子节展示了索引行指针如何被消费:例如LexicalHistory.test.tsx:352change, undo, redo, undo, change)→already-applied,新增证明"undo 后的新编辑清除 redo 历史且 redo 变为 no-op";LexicalHtml.test.ts:64Use provided selection)→covered(现有writeSelection证明已覆盖);CodeBlock.spec.mjs:173(多段转代码块)→covered/refactor-existing(快照 wrap 与浏览器控制已覆盖)。这说明索引不只是目录,而是每一条裁决的追溯依据。

台账末尾给出未来 apply 切片的验证门控命令(verification gates,路径指向外部.tmp/slate-v2工作树,作为说明保留):

cd /Users/zbeyens/git/slate-v2 bun test ./packages/slate/test/text-units-contract.ts bun test ./packages/slate-dom/test/clipboard-boundary.ts bun test ./packages/slate-history/test/history-contract.ts PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/paste-html.test.ts --project=chromium PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/integration/examples/tables.test.ts --project=chromium PLAYWRIGHT_RETRIES=0 bunx playwright test playwright/stress/generated-editing.test.ts --project=chromium -g '<accepted-family>' bun check

以及真机设备证明门控:

cd /Users/zbeyens/git/slate-v2 SLATE_BROWSER_RAW_MOBILE_REQUIRED=1 bun test:mobile-device-proof:raw

八、实操指南:在本仓库中使用这份索引

  1. 按家族检索:若你在为 Slate v2 的"选择/内联原子"层补测试,先用search_in_files在 docs/editor-test-harvester/lexical/test-index.md 中检索family: selection-dom-mapping / void-atom,即可一次性拿到该家族全部候选文件与其target坐标。
  2. 定位具体行为:用文件:行号指针回到上游源码做 source-read,还原 dynamic/multiline 标题的真实参数;把不变量与 Slate 现有契约对比。
  3. 对照裁决:打开 slate-processing-ledger.md,按文件名查该行为的最终状态——already-applied/covered表示已有归属,defer/plate-owned/reject表示不要直接移植。
  4. 校验清单:需要确认上游是否新增测试文件时,重跑 inventory.md 中的rg清单命令,再比对索引头部的 137/1996 统计。
  5. 执行验证:apply 后按台账的验证门控命令跑模型层bun test与 Playwright 浏览器行,最后bun check通过才视为闭环。

结语

test-index.md不是一份普通的测试清单,而是 plate 项目"跨编辑器收割"工程方法的浓缩:用category判断可移植性、用family聚合行为主题、用target指定落地坐标、用文件:行号指针保证每条行为都可回源审计。它与 inventory.md(全量分类)和 slate-processing-ledger.md(逐行裁决)共同构成一条"枚举 → 索引 → source-read → 裁决 → apply → 验证"的完整流水线。对于任何想要为 Slate v2 补齐可移植行为证明、或理解 plate 如何吸收上游编辑器测试资产的开发者,这份索引都是入口,而其背后的方法论同样适用于本仓库对 portabletext、prosemirror、tiptap、yjs-collaboration 等其他编辑器家族的收割工作(见 docs/editor-test-harvester 目录结构)。

【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询