
Plate 仓库 Lexical 测试收割清单全解析271 行测试的便携性分类与 Slate v2 迁移路由【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate本篇技术指南围绕 Plate 仓库中docs/editor-test-harvester/lexical/inventory.mdLexical Test Harvest Full Inventory展开系统讲解如何把上游 Lexical 编辑器的全部测试文件按可移植性分类归档并路由到 Slate v2 测试体系的具体落点。读完本文你将掌握测试收割test harvest的清单命令、五类分类语义、家族family归纳方法、Plate-Owned 所有权叠加层以及从清单到测试索引、再到处理台账的完整加工链路可直接复用于本仓库其他收割目录portabletext、tiptap、prosemirror、yjs-collaboration。一、背景editor-test-harvester 与 Lexical 测试收割Plate 是一个以 AI 与 shadcn/ui 为特色的富文本编辑器项目Rich-text editor with AI and shadcn/ui其底层编辑器内核正朝向 Slate v2 演进。在跨编辑器迁移过程中一个关键问题是上游其他编辑器Lexical、TipTap、ProseMirror、Portable Text、Yjs积累的大量测试哪些行为值得移植、哪些只是内部实现细节docs/editor-test-harvester/目录就是为此设立的测试收割体系按来源编辑器分子目录组织docs/editor-test-harvester/lexical本指南主题包含inventory.md、test-index.md、slate-processing-ledger.md 三个产物docs/editor-test-harvester/portabletext、prosemirror/、tiptap/、yjs-collaboration/同类工作在不同编辑器语料上的复现。本文主角inventory.md是这条流水线的第一道关卡它先用一条命令把上游../lexical仓库本地外部检出的全部测试文件枚举出来再为每一行打上可移植性分类最终形成一份一行一分类、无未决行的全量清单。二、清单头部元信息可追溯的收割账本inventory.md的头部记录了这次收割的元数据这是后续任何加工环节的溯源依据字段值含义source reportreport.md收割主报告上游产出位于../lexical目录不在本仓库内target../lexical被收割的上游仓库本地路径generated_at2026-05-08首次生成时间last_consolidated_at2026-05-09最近一次合并核对时间consolidationlive inventory rerun returned 271 rows; no new or removed rows合并核对结果实时重跑清单命令仍返回 271 行无新增、无删除consolidation字段是这套体系的一个重要设计它不是生成一次就完事而是要求周期性重跑清单命令并与已有账目比对只有增量为零时才允许声称清单保持最新。这与 editor-test-harvester.md 模板 中Existing report, inventory, and test-index read before rerun updates的检查项一致。三、Inventory 命令逐段拆解清单的产生完全依赖一条三段式管道命令这也是整个收割体系可复现性的基石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__)(/|$)三段各自职责第一段rg --files ../lexical枚举上游仓库的所有文件递归、跟随 Git 忽略规则之外的全部物理文件。第二段正向过滤只保留看起来像测试的路径。正则由两个分支组成路径分段匹配任何一层路径段命中__tests__、test、tests、spec、e2e、integration、playwright、cypress、wdio、fixtures之一段边界由(^|/)和(/|$)约束避免把contest这类普通单词误命中扩展名匹配\.(test|spec)\.[cm]?[jt]sx?$覆盖.test.ts、.spec.mjs、.test.tsx、.spec.cts、.test.mjs等常见测试命名。第三段负向过滤排除构建/产物目录dist、build、coverage、node_modules、vendor以及自动生成内容fixtures/generated、__snapshots__快照是断言产物而非测试本体。这套命令的通用性已经得到验证在 portabletext 的清单 中可以看到几乎相同的管道枚举路径换成../portabletext说明只要目标仓库遵循常见的测试目录/命名约定这条命令就能直接复用保证不同编辑器收割之间的口径一致。四、总量账目271 行的勾稽关系清单头部给出了本次收割的完整统计inventory.md第 17 行指标数量说明total271命中清单命令的全部文件runnable196可运行含测试调用的文件fixture/support75纯测试夹具/支撑文件不可单独运行portable124可移植行为不依赖 Lexical 内部架构portable-mixed13可移植与产品策略混合product-shell33产品外壳/框架集成行为harness12测试辅助工具仅借鉴技术skip89明确跳过工具链、发布、ESLint、ESM 夹具等uncertain0无法分类的行这些数字内部是自洽的可以交叉验证portable124 portable-mixed13 137正好等于 test-index.md 记录的Indexed runnable portable and portable-mixed files: 137product-shell33 harness12 skip89 134137 134 271 total。文档明确声明Every row is classified每一行都有分类。uncertain 0意味着收割阶段不留任何悬而未决的行这是模板中nouncertaintest files remain完成阈值的直接落实。五、Category 分类语义五类 一个叠加层清单每一行的Category列决定该文件的行为如何被对待。这是整个收割体系最核心的词汇表分类语义典型落点portable行为是纯编辑器可移植不变量不依赖 Lexical 节点类、命令注册表、Composer 等内部架构转写为 Slate v2 的 package 单测或浏览器行portable-mixed文件整体是产品/插件 e2e但其中一部分行蕴含可移植的编辑器不变量提取不变量行后按 portable 处理其余拒绝product-shellPlayground 产品 UI/应用策略、React Composer/插件集成细节除非后续拆出与框架无关的不变量否则skipharness测试辅助工具或快捷键夹具本身不是编辑器行为仅保留可复用的测试技术skip工具链、打包、发布、ESLint、ESM 夹具行为或纯 Lexical 内部实现无 Slate 落点在分类之上还叠加了一个plate-owned层。清单原文的界定是plate-ownedis an owner-routing overlay on top of the closed counts above. Use it when a residual row is useful for Plate plugins/examples/docs but should not become raw Slate v2 law.——即某行行为有价值但它的正确归宿是Plate 的插件/示例/文档而不是 Slate v2 内核的铁律。六、Family 家族按行为不变量归组Family列把 271 行按行为不变量而非上游文件形状归组这是按不变量家族分组而非按上游文件分组决策原则的落地。清单中出现的主要家族包括家族Family行为关注点清单中的代表行core package behavior包级单元行为含可移植不变量lexical-code的LexicalCodeNode.test.ts、lexical-history、lexical-htmlserialization-parsing / marks-inline序列化/解析、标记与内联元素lexical-list、lexical-markdown、ClearFormatting.spec.mjs、TextFormatting.spec.mjsselection-dom-mapping / void-atom选区-DOM 映射、void/原子节点Selection.spec.mjs93 行、Links.spec.mjs65 行、Hashtags.spec.mjsclipboard-paste / browser-engine剪贴板粘贴与浏览器引擎行为CopyAndPaste/html/*系列、Extensions.spec.mjs、LexicalTabNode系列beforeinput-input / browser-enginebeforeinput/输入运行时AutoScroll.spec.mjs、Events.spec.mjs、Focus.spec.mjs、TextEntry.spec.mjstables-grid / selection-dom-mapping表格网格与表格内选区Tables.spec.mjs193 行、lexical-table单元测试ime-composition / history-undo-redoIME 组合与历史撤销Composition.spec.mjs28 行、回归8153-safari-ime-delete-selectioncollaboration-remote / history-undo-redo远程协作与历史Collaboration.spec.mjsmixed portable invariant产品/插件 e2e 中夹带可移植不变量Autocomplete.spec.mjs、CharacterLimit.spec.mjs、DateTime.spec.mjsportable editor behavior通用的可移植编辑器行为DraggableBlock.spec.mjs、Images.spec.mjs、大量regression/*回归用例product-shell/harness/skip前三类非便携行为React Composer 测试、keyboardShortcuts/index.mjs、eslint 插件与框架夹具家族划分的直接价值体现在后续 slate-processing-ledger.md 的加工台账中台账正是按core package behavior、serialization-parsing / marks-inline、clipboard-paste / browser-engine、ime-composition / input runtime、selection / inline atoms / voids / caret、tables、collaboration等家族分节处理确保同一不变量家族共享同一套 Slate 落点。七、Plate-Owned Overlay所有权路由表清单在总量账目之后给出了 5 行所有权叠加层它决定了残余行residual rows的归属。下表是原文档的核心内容逐行说明Source patternCurrent categoryPlate targetRaw Slate splitlexical-link/src/__tests__/*、AutoLinks.spec.mjs、残余Links*CopyAndPaste行skip、portable、portable-mixedPlate link/autolink 包、示例与文档Slate v2 只保留通用内联边界、粘贴导入与安全链接插入lexical-list/src/__tests__/*、List.spec.mjs、checklist/list 粘贴行portable、portable-mixedPlate list/checklist 包与 list-policy 文档Slate v2 保留结构化列表片段、包裹器与路径/查询行为lexical-markdown/src/__tests__/*、Markdown.spec.mjs残余portable、portable-mixedPlate markdown 序列化/转换包与文档Slate v2 保留 markdown 快捷键示例Hashtags.spec.mjs、Keywords.spec.mjs、DateTime.spec.mjs、Emoticons.spec.mjs、EquationNode.spec.mjs、CharacterLimit.spec.mjs、Images.spec.mjs残余portable、portable-mixedPlate 特性/插件包与示例Slate v2 保留 decoration、inline atom、void、markable-void 基座证明React Composer、菜单、嵌套 composer、typeahead、extension host、toolbar/product shell 行product-shell、skipPlate React/插件人体工学如被接受除非拆出与框架无关的不变量否则无原始 Slate 落点这张表的要点是一份行为可以被同时拆分给两个所有者原始 Slate 只拿走与框架无关的基座级不变量其余产品化语义autolink 语法、checklist ARIA、markdown transformer 语法、装饰器渲染策略全部路由给 Plate 包、示例或 backlog。这也解释了为什么清单中大量lexical-playground/__tests__/e2e/*文件被标为portable-mixed——它们是产品 e2e 文件里藏着可移植编辑器不变量行的混合体。八、Slate target / extraction 字段落点路由与证明分层主表最后一列Slate target / extraction是每一行的落点路由。归纳起来主要有几类写法indexed N test/describe lines; target .tmp/slate-v2/packages/slate/test该行被测试名索引收录了 N 个test/describe/it名称指针行为落点为 Slate v2 的 package 单测目录。例如LexicalCodeNode.test.ts索引 24 行、LexicalEditor.test.tsx索引 88 行。add focused browser proof only when behavior depends on DOM/runtime transport这是证明分层原则的标准句式——只有当行为依赖 DOM/运行时传输时才追加浏览器证明纯模型不变量用 package 单测即可不为此强行上 Playwright。针对特定落点的路由clipboard-contract.ts、slate-dom/test/clipboard-boundary.test.ts、paste-html.test.ts→ 剪贴板/粘贴家族slate-react/test/model-input-strategy-contract.test.ts、editable-behavior.test.tsx→ 输入运行时/可编辑行为slate-history/test、collab-history-runtime-contract.ts→ 历史与协作基座playwright/stress/generated-editing.test.ts、playwright/integration/examples/tables.test.ts→ 浏览器压力/集成行。skip: no Slate target/skip unless a raw editor invariant is split out later非便携或产品外壳行明确无落点或留待将来拆分。另外两种高频路由模式product-shell行统一写skip unless a raw editor invariant is split out later例如 SvelteKit SSR 水合的 e2e、Playground 的Toolbar.spec.mjs、React Composer 相关单测harness行统一写technique only: reuse harness idea if a future test needs it例如lexical-headless的测试工具utils/index.ts、Playground 的keyboardShortcuts/index.mjs。九、典型行深度解读9.1 核心包行为LexicalCodeNode.test.ts| ../lexical/packages/lexical-code/src/__tests__/unit/LexicalCodeNode.test.ts | yes | portable | core package behavior | package unit behavior with portable invariant | indexed 24 test/describe lines; target .tmp/slate-v2/packages/slate/test; ...这是最典型的portable core package behavior组合代码块节点的 Tab 缩进、多行 indent/outdent、RTL 行视觉移动MOVE_TO_END/MOVE_TO_START等行为与 Lexical 内部架构无关是可移植的编辑器不变量。它在 test-index.md 中被展开为 24 个带行号指针的用例名如can indent/outdent one line by forward selecting all line (with tabs)、code blocks can shift multiple lines (with tab)。9.2 剪贴板语料CopyAndPaste/html/*系列HTMLCopyAndPaste.spec.mjs、ImageHTMLCopyAndPaste.spec.mjs、LinksHTMLCopyAndPaste.spec.mjs、ListsHTMLCopyAndPaste.spec.mjs、TablesHTMLCopyAndPaste.spec.mjs、TextFormatHTMLCopyAndPaste.spec.mjs六份文件构成HTML 粘贴语料库全部为portable clipboard-paste / browser-engine统一路由到clipboard-contract.ts、clipboard-boundary.test.ts、paste-html.test.ts、generated-editing.test.ts四个落点。这类行被后续加工台账进一步做行级源码钻孔source-drill例如 Google Docs 表格导入、Quip 表格导入、Google Sheets 导入已落地为paste-html.test.ts的浏览器行而自定义列宽、合并网格、rowspan/colspan 等被显式推迟到未来的表格模型所有者。9.3 高密度选区用例Selection.spec.mjs| ../lexical/packages/lexical-playground/__tests__/e2e/Selection.spec.mjs | yes | portable | selection-dom-mapping / void-atom | browser editor behavior e2e | indexed 93 test/describe lines; ...索引 93 行用例是清单中密度最高的文件之一路由到 slate 单测、slate-react可编辑行为与 Playwright 压力行三层落点。它表明收割体系对高价值浏览器语料采取拆层吸收模型不变量进 package 单测DOM 传输行为进浏览器行。9.4 表格家族Tables.spec.mjs与lexical-tableTables.spec.mjs索引 193 行路由到tables.test.ts与insertFragment单测lexical-table包内 7 个单元测试文件全部标为tables-grid / selection-dom-mapping。但注意其落点标注中多次出现transforms/insertFragment限定结合台账可知当前只接收表格包含/导航证明整表/多格选择模型被显式推迟issue #2558 保持 not-claimed。这是不把表格模型决定隐藏在 DOM 选区工作副作用里的纪律体现。9.5 skip 家族工具链与框架夹具lexical-eslint-plugin/__tests__/integration/*、scripts/__tests__/integration/fixtures/lexical-esm-astro-react/*、lexical-esm-nextjs/*等数十行统一归类为skip理由为tooling, packaging, release, eslint, or ESM fixture behavior。它们虽然以test/fixtures目录或.test.mjs命名命中清单命令但与编辑器行为无关必须显式跳过并保留理由这正是模板中every ... file is ... explicitly skipped with reason的检查项。9.6 回归用例携带 issue 号的便携行为regression/目录下约 30 个文件如1055-fast-typing-undo、1083-backspace-with-element-at-front、221-editing-hashtags、3433-merge-markdown-lists、7163-graphemes大多为portable portable editor behavior它们在 slate-processing-ledger.md 中被逐行钻孔后给出明确结论——例如7163-graphemes转为 Slate 的text-units-contract.ts文本单元证明、3433转为 markdown-shortcuts 示例的相邻列表合并浏览器证明。这类行是历史浏览器/编辑器回归证明价值密度高是后续移植的优先语料。十、下游加工链路test-index、processing-ledger 与 ralplaninventory.md只是流水线第一环它明确定义了与下游产物的衔接关系Portable and portable-mixed runnable rows are indexed in the test-name index。10.1 test-index.md测试名指针索引收录 137 个可运行的 portable/portable-mixed 文件提取 1996 条test/describe/it名称每条按文件行号指针记录对动态/多行标题如testing ${scenario[2]}: ...以dynamic or multiline title占位并要求apply 前需本地阅读但不再隐藏在仅按文件名路由的目录里合并核对保证portable runnable file count still 137; extracted line count still 1996; no missing or stale index files。10.2 slate-processing-ledger.md状态词汇表台账引入 7 个处理状态每个 inventory 行最终必须落到其一状态含义already-applied该行为已在 Slate v2 对应落点新增或强化证明covered当前 Slate v2 已有足够证明除非后续审计发现漂移refactor-existing强化/拆分/重命名现有 Slate 测试优先于复制create-new新增 Slate v2 单元/浏览器行defer行为有效但依赖原始设备、yjs 浏览器、表格模型或后续所有者plate-owned行为有效但应归属 Plate 包/文档/示例/backlogreject不是可移植的原始 Slate 行为目标台账的裁决结论是一条高杠杆原则原文Do not copy Lexical tests one-for-one. Keep the invariant, steal the strongest proof shape, and reject Lexical internals.不要一比一复制 Lexical 测试保留不变量、借鉴最强的证明形态、拒绝 Lexical 内部实现。10.3 2026-05-09-slate-v2-lexical-harvest-test-processing-ralplan.md执行计划这份 ralplan评审计划把收割账目转化为可执行的加工切片核心要点明确收割完成harvest done≠ 处理完成processing done报告关闭于 0.93 分但其余行属于 backlog否决逐条移植全部 Lexical 测试会制造 1996 个一次性测试、淹没实现采用按行为家族执行的切片策略第一个ralph执行切片是文本单元/删除的包级对等来自 Lexical #7163 字素矩阵证明类型分层强制模型不变量用 package 单测浏览器传输用 Playwright原始移动端用真机门禁不允许用单元测试关闭浏览器行为非声明面non-claims被反复固化整表选择、原始移动端、collaboration 浏览器行均不在此计划内关闭。十一、验证门禁如何证明一行真的被吸收清单与台账给出了一套可执行的验证命令见 ralplan 的 Verification Gates核心形态为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_RETRIES0 bunx playwright test playwright/integration/examples/paste-html.test.ts --projectchromium bun check原始移动端行则要求真机门禁SLATE_BROWSER_RAW_MOBILE_REQUIRED1 bun test:mobile-device-proof:raw这套门禁直接呼应清单中反复出现的句式add focused browser proof only when behavior depends on DOM/runtime transport——证明类型必须与行为类型匹配这是整个收割体系防止假证明用单元行关闭浏览器行为的核心护栏。十二、对本仓库开发者的使用建议复跑清单将inventory.md中的三条rg管道照搬把../lexical换成任意目标编辑器检出目录即可重新生成账目并通过consolidation比对判断是否出现新增/删除行。阅读顺序先看inventory.md全量分类账→ 再看 test-index.md可移植用例名指针→ 最后看 slate-processing-ledger.md每行的最终裁决与落点三者结合即可完整追溯任何一条 Lexical 测试行为的归宿。复用方法论docs/editor-test-harvester/下的 portabletext、tiptap、prosemirror、yjs-collaboration 目录沿用同一套清单/索引/台账结构若要新增收割目标可参照 editor-test-harvester.md 模板 的完成阈值score 0.92、无uncertain行、每条可移植行都有 owner/target/proof来界定收割完成。核心结论lexical/inventory.md是一份可复现、全量、逐行分类的测试资产账本。它用一条命令 五类分类 家族归纳 Plate-Owned 叠加层把 271 行上游 Lexical 测试精确切割为Slate v2 可吸收的 137 行便携语料与应留在 Plate 或拒绝的 134 行非便携语料再通过 test-index 与 processing-ledger 完成从有哪些测试到每行归谁、如何证明的完整闭环。对任何想从成熟编辑器移植测试语料的团队而言这套清单-索引-台账-验证门禁的流水线本身就是可复用的工程范式。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考