Plate Yjs 协作测试收割(Harvest)指南:许可证门控、可移植行为分类与适配层语料映射
Plate Yjs 协作测试收割Harvest指南许可证门控、可移植行为分类与适配层语料映射【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate导读本文围绕 Plate 仓库中的yjs-collaboration-harvest计划docs/plans/2026-05-13-yjs-collaboration-harvest.md展开系统讲解如何以许可证门控license-gated方式从四个上游仓库slate-yjs、lexical-yjs、y-prosemirror、yjs收割 Yjs 协作相关测试建立可运行性清单、按可移植性分类、映射到 Slate v2 与 Plate 的归属方并沉淀为只读证据产物。读完本文你将掌握这套测试收割—行为分类—归属映射的方法论、各上游测试语料的全景盘点约 54 个 slate-yjs 协作 fixture 与数百个 CRDT 层用例以及它在 Plate 仓库内落地为packages/yjs慢速协作测试套件含内存多端连接器CollaborationConnector的具体源码实现与验证命令。一、为什么需要测试收割协作行为证据的复用地基富文本编辑器接入 Yjs 时最大的工程风险不在于 CRDT 本身而在于编辑器操作语义与共享文档模型之间的适配层insertText、splitNode、mergeNode、moveNode、setNode、addMark、removeMark等 Slate 操作需要被可靠地翻译成 Yjs 共享类型Y.XmlText/Y.XmlElement上的增量更新并在远端以Y.Doc镜像的形式收敛。该计划的核心判断是这些行为已经以测试的形式存在于上游生态中例如 slate-yjs 的协作 fixture、y-prosemirror 的 delta/position 不变量、yjs 自身的 CRDT 用例。与其从零设计测试不如对上游测试做一次收割harvest先做许可证门控确认每个目标仓库的许可证允许复用其测试思路与语料再建穷举清点把每个仓库中所有满足测试文件模式的路径找出来逐行分类判断每条用例是可移植行为、混合行为、纯 harness、还是与编辑器行为无关的 CRDT 内部机制最后映射归属把可移植行为指派给 Slate v2 与 Plate 的对应维护方。该计划本身只留下报告类产物inventory / test-index / completion 状态不修改任何上游仓库因此可安全、可追溯地作为后续slate-yjs包与 Plate Yjs 插件的测试语料来源。二、收割目标与授权评估计划声明的目标Goal原文如下Run a license-gated harvest of Yjs collaboration tests from../slate-yjs,../lexical/packages/lexical-yjs,../y-prosemirror, and../yjs; classify portable behavior, map it to Slate v2 and Plate owners, and leave report-only artifacts.四个目标仓库及其收割结论目标仓库许可证结论收割要点slate-yjsMIT/宽松协作操作 fixture 通过适配器重放并与远端Y.Doc镜像比对是适配层行为的最直接语料lexical/packages/lexical-yjsMIT/宽松在收割清点模式下没有任何可运行测试文件仅能做源码级概念扫描y-prosemirrorMIT/宽松delta / position / suggestion / undo 等大量映射与变换不变量测试跨编辑器可移植性高yjsMIT/宽松CRDT 底层语料相对位置、快照、更新合并、undo-redo、共享类型行为许可证结论基于各仓库本地许可证证据得出而非外部声明。这也是许可证门控的含义先确认可复用的法律前提再进入清点环节。三、八阶段执行流程该计划以完成清单checklist形式记录了八个阶段全部处于完成状态[x]Skill 分析与目标设定owner skill 为.agents/skills/editor-test-harvester/SKILL.md解析目标仓库与许可证模式构建穷举测试清点inventory抽取 fixture / 测试名称逐行分类classify every row将行为映射到 Slate v2 与 Plate 归属方撰写报告、清点、测试索引与完成状态校验报告章节与完成检查。这八个阶段构成了一条可复用的收割流水线任何新编辑器适配层例如未来接入其他 CRDT都可以复用同样的清点 → 抽取 → 分类 → 映射 → 沉淀路径。四、清点命令与产物结构4.1 清点命令Inventory Commands计划采用统一的rg管道来发现测试文件模式同时覆盖目录命名与文件命名两类约定rg --files repo | \ 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__)(/|$) | \ sort该模式的关键点包含规则目录名命中__tests__、test、tests、spec、e2e、integration、playwright、cypress、wdio、fixtures或文件名命中.test.*/.spec.*含.cjs、.mjs、.js、.jsx、.ts、.tsx变体排除规则dist、build、coverage、node_modules、vendor、fixtures/generated、__snapshots__等生成物与依赖目录同一命令分别对四个仓库执行保证口径一致、可复跑。4.2 产物结构收割完成后沉淀为三类证据产物status: donelicense_mode: permissiveInventorydocs/editor-test-harvester/yjs-collaboration/inventory.md逐文件的清点总表包含可运行性、类别、判定理由、测试名抽取方式Test Indexdocs/editor-test-harvester/yjs-collaboration/test-index.md逐条测试的精确索引文件路径 行号 测试/导出名完成状态以 completion ledger 形式记录见后文验证与完成检查一节。需要说明计划头部记录了报告路径docs/editor-test-harvester/yjs-collaboration/report.md而在当前仓库快照中可直接验证的产物为上述 inventory 与 test-index 两个文件。五、分类体系可移植性判定清点表对每一行都给出类别Category这是整份收割计划最核心的分析维度类别含义判定示例取自 inventoryportable可移植行为与编辑器适配层直接相关slate-yjs 协作 fixtureSlate operation fixture is replayed through slate-yjs and checked against a remote Y.Doc mirror.portable-mixed可移植不变量与宿主编辑器策略view/plugin/suggestion 等混杂y-prosemirror 的suggestions.test.jsUseful collaboration invariant mixed with ProseMirror view/plugin/suggestion policy.harness仅测试支撑代码无独立行为断言withTestingElements.ts、cohort.js、testHelper.js等skip跳过与 Slate/Plate 编辑器行为目标无关yjs 的IdMap.tests.jsYjs internal storage/encoding compatibility... not a Slate or Plate editor-behavior target.manual需人工介入执行y-prosemirror 的tr.test.js、y-prosemirror.test.js标记为 manual 但仍归类 portable-mixed这个五分类的价值在于收割方可以只把portable行纳入适配层测试设计把portable-mixed拆出通用不变量、丢弃宿主策略部分把skip行留给 CRDT 底层信心而非编辑器行为覆盖。5.1 空目标lexical-yjs清点表专门记录了空目标Empty Target Notes../lexical/packages/lexical-yjshas no test files under the required inventory pattern. Its source was scanned for Yjs collaboration concepts, but there is no runnable upstream test to harvest from that package path.即 lexical-yjs 包在指定清点模式下没有任何可运行测试只有源码级概念扫描记录——这是一个重要的负结果不能因为某仓库有 Yjs 集成包就默认它有可收割的测试语料。六、上游测试语料全景盘点6.1 slate-yjs适配层 fixture 主力54 个 fixture 1 个适配器套件packages/core/test/collaboration/下按 Slate 操作类型组织的 fixture 是适配层行为的最直接证据测试索引test-index.md逐一给出了文件与行号操作族fixture 数量代表性用例addMark5acrossMarks、acrossMarksSame、atBeginningOfDocument、atEndOfDocument、withOtherMarksinsertNode3atBeginningOfDocument、atEndOfDocument、inTheMiddleinsertText11insideMarks、inTheMiddleOfNestedBlock、withEmptyString、withEntities、withUnicode、withMarks等mergeNode5afterADeleteBackward、inSameParent、onMixedNestedNodes、onMixedTypeNodes、withUnicodemoveNode8downward/upward×whenBlockBecomesNested / BecomesNonNested / StaysNested / StaysNonNestedremoveMark3inTheMiddleOfText、withAddMark、withOtherMarksremoveNode4nestedBlock、wrapperBlock、文档首/尾removeText3文档首/尾、withUnicodesetNode6onDataChange、onDataChangeOnInline、onResetBlock、withAChangeOfType等splitNode6onNonDefaultBlock、withMultipleSubNodes、withUnicode等合计54 个 fixture外加一个index.test.ts适配器套件test-index.md 中记录其第 63 行为adaptersuite负责加载全部协作 fixture 并校验本地/远端收敛。辅助文件withTestingElements.ts测试元素与共享根接线与slate.d.ts环境类型被标记为 harness / skip。从命名可以观察出覆盖设计的意图Unicode 贯穿各操作族withUnicode反复出现嵌套结构nested block、mixed nested nodes与格式标记组合withOtherMarks、insideMarks是重点边界。6.2 y-prosemirror映射与变换不变量116 个导出该仓库的测试大多以test*.js形式存在由 lib0 runnerindex.js/index.node.js加载。按测试索引统计文件可移植类别导出数覆盖主题positions.test.jsportable22单/多段落、硬换行、嵌套 blockquote、列表、代码块、深嵌套、storeMapping往返、远端变更后的书签映射undo.test.jsportable-mixed33基本撤销重做、历史分组、光标恢复、跨多撤销组、AddToHistory策略、视图销毁重建、远端变更不可撤销等y-prosemirror.test.jsportable-mixed23插件完整性、重叠标记、文档/XML 片段变换、change origin、空段落、重复插入、版本化、GC、RepeatGenerate压力序列suggestions.test.jsportable-mixed21建议模式下的标记同步、删除/回车/退格加入、双视图发散、cohort 重放收敛delta.test.jsportable12跨部分节点的删除区间、格式化、包裹、复杂 step 序列、带内容的 blockquotepositions相关 harnessharness—cohort.js、complexSchema.js为共享仿真/schema 辅助suggestion-simulation.test.jsportable-mixed4仿真设置收敛、单建议编辑收敛、重复生成建议编辑、长跑 fuzztr.test.jsmanual1testReplaceStepToDelta合计约116 个导出。其中positions与delta两个文件被直接归类为portable是编辑器协作位置与 delta 映射不变量的典范——这类不变量与宿主编辑器无关可直接借鉴到 Slate 适配层。6.3 yjsCRDT 底层语料237 个导出yjs 自身的测试由 lib0 runnertests/index.js加载覆盖共享类型与协议机制文件类别导出数与适配层的关系y-text.tests.jsportable47delta 语义、格式化保留、Unicode/代理对拆分、embed、快照、attribution、大规模分片文档、RepeatGenerate*随机压力y-array.tests.jsportable-mixed41并发插入/删除冲突、晚同步、事件目标、GC、随机压力最高 30000 次迭代y-map.tests.jsportable-mixed40嵌套事件、并发 set、属性冲突、attribution最高 100000 次迭代undo-redo.tests.jsportable25UndoManager作用域、删除过滤器、嵌套撤销问题、连续重做 bug、ignoreRemoteMapChangessnapshot.tests.jsportable12快照恢复、删除项恢复、依赖变更、containsUpdatedoc.tests.jsportable11子文档subdoc加载/同步/undo、客户端 ID 冲突relativePositions.tests.jsportable9相对位置案例 1–7、与 undo 的结合、关联差异updates.tests.jsportable8更新合并、键编码、待处理更新合并、混淆、文档交集attribution.tests.jsportable-mixed7相对位置、attributed 事件、插入到带归属内容中IdMap/IdSet.tests.jsskip77Yjs 内部存储/编码兼容性compatibility.tests.jsskip3V1 编码解码兼容encoding.tests.jsskip3结构引用、state vector 差分y-xml.tests.jsportable-mixed12XML 元素/属性、fragment attributiondelta.tests.jsportable5delta 基础、schema、attribution合计约237 个导出。其中skip行IdMap/IdSet/compatibility/encoding被明确判定为CRDT 底层信心而非编辑器行为目标这正是分类体系避免把无关语料误入适配层测试的有效例证。七、关键发现收割结论的三条主线计划的关键发现Key Findings可归纳为三条分别对应法律前提、负结果与增量机会许可证干净四个目标仓库均为 MIT/宽松基于本地许可证证据lexical-yjs 无料可收没有满足清点模式的可运行测试文件两侧现状差距Slate v2 侧已有较强的协作底层覆盖证据为.tmp/slate-v2/packages/slate/test/collab-history-runtime-contract.ts协作历史运行时契约测试Plate 侧已有有用的 Yjs 慢速 fixture但仍有适配转换缺口计划原文指出可受益于一个紧凑的适配器转换包adapter-conversion pack覆盖unicode、marks、nested moves、split/merge/set-node、cursor projection五类行为。这五类缺口与上文 slate-yjs fixture 表中的高频关键词withUnicode、withMarks、嵌套 move、split/merge/set-node完全对应说明收割语料与缺口分析形成了闭环。八、Plate 侧落地packages/yjs的协作测试源码剖析收割计划在 Plate 仓库内的落地证据位于 packages/yjs/src/lib/tests/collaboration/由三个文件构成fixtures.ts10 个协作场景、harness.ts内存多端连接器与工具函数、index.slow.ts慢速测试入口。8.1 测试入口与运行方式index.slow.ts把fixtures.ts导出的collaborationFixtures逐一注册为用例import { collaborationFixtures } from ./fixtures; describe(yjs collaboration, () { afterEach(() { mock.restore(); }); for (const fixture of collaborationFixtures) { it(fixture.name.replaceAll(_, ), fixture.run); } });文件名后缀.slow.ts与计划中Plate already has useful Yjs slow fixtures的表述相互印证这些用例涉及多端连接、异步收敛与 setTimeout 打桩属于慢速、确定性要求较高的协作测试。8.2 核心装置内存多端CollaborationConnectorharness.ts 用纯内存实现了一个微型多端协作网络避免引入真实 WebSocket/WebRTC 依赖CollaborationConnector维护peers映射与消息队列queueconnect时为新 peer 与已连接 peer 互发全量状态Y.encodeStateAsUpdateenqueue把本地更新广播给其他已连接 peerflushAll({ order: fifo | reverse })批量投递更新Y.applyUpdate(peer.document, update, REMOTE_ORIGIN)reverse模式用于模拟乱序到达TestCollaborationProvider实现UnifiedProvider契约的测试端挂在Y.Doc的update事件上采集本地更新并交给连接器通过registerProviderType(PROVIDER_TYPE, TestCollaborationProvider)注册为动态 provider 类型REMOTE_ORIGIN符号区分本地/远端更新来源避免远端更新被再次广播回声抑制这是收敛正确性的关键细节工具函数createCollaborationEditor用BaseYjsPlugin.configure构造编辑端、createMixedProviderEditor真实 provider passive mock provider 混用、getDocChildren用slate-yjs/core的yTextToSlateElement把Y.XmlText反解为 Slate 节点、initEditor、replaceSharedContent/appendSharedContent通过slateNodesToInsertDelta把 Slate 值写入共享类型、settle双微任务让异步收敛稳定。8.3 十类协作场景fixtures 一览fixtures.ts 定义的 10 个场景覆盖了加入房间—并发—断线重连—乱序—超时—混合 provider的全生命周期fixture验证的行为不变量seed_once_from_empty_doc空文档只播种一次第二个 peer 收敛到同一内容server_content_wins_over_local_value已有服务端内容时本地 draft 不得覆盖远端服务端优先string_value_deserializes_once字符串初始值只反序列化一次spy 断言deserialize调用次数远端不再重复反序列化async_value_waits_then_converges异步初始值在 Promise resolve 前文档保持空resolve 后收敛custom_shared_type_nested_doc嵌套父文档中的Y.XmlTextparentDoc.getMap(editors).get(main)作为共享类型且根content保持为空reconnect_eventually_converges断线期间远端更新重连后两端收敛到更新值concurrent_local_edits_while_disconnected_eventually_converge两端同时断线并各自追加内容重连后两端一致且内容完整hello world peer one peer twoout_of_order_updates_eventually_converge以reverse顺序投递更新最终顺序依然正确timeout_then_late_sync_does_not_reseedrunWithImmediateTimeout模拟超时后迟到的同步不得再次播种覆盖mixed_provider_inputs同一Y.Doc挂载多个 provider真实 passive连接行为正确这些场景与收割计划适配器转换包的五类缺口unicode、marks、nested moves、split/merge/set-node、cursor projection形成互补Plan 侧缺口指向操作级适配而 Plate 现有 fixture 已经覆盖同步生命周期级不变量播种、服务端优先、断线并发、乱序、超时重连。8.4 插件侧的配套实现协作测试所依赖的运行时能力分布在 packages/yjs/src/libBaseYjsPlugin.ts核心绑定逻辑持有Y.Doc、Awareness、sharedType与 providerswithPlateYjs.ts编辑器级集成含withTCursors光标投影、withTYHistory历史、withTYjs共享类型绑定providers/registry.ts 与三个 provider 包装hocuspocus-provider.ts、indexeddb-provider.ts、webrtc-provider.tscreateMockProvider.ts 与 mockFn.ts混合 provider 测试的被动端。React 侧入口 YjsPlugin.tsx 提供YjsPlugin.configure({ options: { providers, ydoc, sharedType } })的声明式配置插件的安装与 provider 参数说明indexeddb/hocuspocus/webrtc及自定义 provider 注册见 packages/yjs/README.md。九、验证与完成检查计划记录了完成验证步骤其中仓库内可复跑的核心命令如下rg -n License Gate|Confidence Score|Pass-State Ledger|Matrix|Skips|Next Slice|Full Inventory Appendix docs/editor-test-harvester/yjs-collaboration/report.md test -f docs/editor-test-harvester/yjs-collaboration/inventory.md test -f docs/editor-test-harvester/yjs-collaboration/test-index.md bun run completion-check -- --id 019e1c53-3e25-78c0-9083-355925be3817第一条用rg验证报告包含全部关键章节许可证门控、置信度评分、通过状态台账、矩阵、跳过、下一切片、完整清点附录第二、三条验证收割产物文件存在当前仓库中inventory.md与test-index.md均可直接确认第四条通过bun run completion-check以稳定 ID 校验完成状态。这套验证方式的特点是可机械复跑任何后续收割都能用同样的命令证明产物齐备、章节完整。十、从收割语料到slate-yjs包的演进脉络计划头部包含三条同步记录Sync note说明了该文档在时间线上的定位——它始终是证据清单evidence inventory而非当前 API 决策2026-05-18包级规划迁至 docs/plans/2026-05-18-slate-yjs-package-readiness-ralplan.md当时packages/slate-yjs尚无源码剩余执行工作为包脚手架、完整仿真示例、包测试与 Playwright 选区覆盖2026-05-24继续以稳定收割产物作为测试语料但不得据此推断当前 API 或包存在性2026-05-28../slate-v2中已出现slate/yjs包源码当前架构与操作矩阵工作迁至 docs/plans/2026-05-28-slate-yjs-current-architecture-operation-matrix.md。后续相关计划还包括 2026-05-25-slate-yjs-structural-operation-coverage-ralplan.md 与 2026-05-29-slate-yjs-from-scratch-operation-matrix.md并有 本地 yjs 别名避免重复安装的解决方案记录。这条脉络展示了测试收割在工程中的正确用法语料沉淀一次、长期复用而 API 与架构决策跟随最新计划演进。十一、方法论复用给其他适配层或未来 CRDT的收割清单把本文内容浓缩为可迁移的步骤任何新的编辑器协作适配层都可以按此执行门控先确认上游许可证本地证据再谈语料复用清点用统一的rg管道对每个上游仓库跑同一套包含/排除规则分类逐文件打portable / portable-mixed / harness / skip / manual标签并为每个标签写下判定理由抽名把每条可运行测试的文件路径、行号、导出名沉淀为 test-index映射把可移植行为指派给编辑器核心、适配层与插件层的具体归属方沉淀只写报告类产物并记录完成状态status / license_mode / completion闭环把缺口清单如 unicode、marks、nested moves、split/merge/set-node、cursor projection回填到自身测试设计用内存多端连接器实现可确定性验证的慢速协作套件。结语Yjs 协作的正确性最终由操作语义翻译 同步生命周期收敛共同保证二者缺一不可。本文所讲解的收割计划给出了前半部分操作级适配的系统化语料来源——54 个 slate-yjs 协作 fixture、116 个 y-prosemirror 映射不变量、237 个 yjs CRDT 用例并明确了哪些可移植、哪些应跳过而 Plate 仓库内的packages/yjs慢速协作套件与内存CollaborationConnector则示范了后半部分生命周期收敛的可确定性验证方式。两者结合构成了一套从上游证据到本地落地、可复跑、可追溯的协作测试方法论。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考