news 2026/9/15 20:59:09

Slate Browser 的下一个系统级动作:以 openExample 就绪契约为核心,攻克零宽字符与 IME 渲染/输入策略证明赛道

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Slate Browser 的下一个系统级动作:以 openExample 就绪契约为核心,攻克零宽字符与 IME 渲染/输入策略证明赛道

Slate Browser 的下一个系统级动作:以 openExample 就绪契约为核心,攻克零宽字符与 IME 渲染/输入策略证明赛道

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

本文以仓库内 docs/plans/2026-04-04-slate-browser-next-system-move.md 为主干,融合 docs/slate-browser/ 下的配套研究文档,完整还原这次"系统级动作"的决策过程、API 分期、落地清单与验证命令,并给出可供直接引用的源码级依据。

导读

在 Slate v2 /slate-browser的第一个公开包 tranche 落地之后,"下一步做什么"成为决定浏览器证明(browser proof)体系走向的关键问题。本文基于该计划文档,完整梳理其结论:最高杠杆的系统级动作不是跨浏览器、也不是性能,而是先把openExample(...)打磨成真正的"就绪契约"(readiness contract),再用它搭建渲染器/输入策略(renderer/input-policy)证明赛道,专门攻克零宽字符、空状态与 IME 敏感行为。读完本文,你将掌握:slate-browser三阶段 API tranche 的全部落地形态、选择书签(selection bookmark)接缝的设计动机、本地验证命令清单,以及该决策如何服务于"slate-v2管文档真相、slate-browser管浏览器证明、未来plate-v2管投影与产品化"的整体系统目标。

一、文档定位:一份"条件性后续动作指南"

该计划文档在开头就明确了自己的属性:

这是条件性的后续动作指南,而不是 Slate v2 项目当前的默认队列。

换句话说,它不是 roadmap 本身(roadmap 真相见 docs/slate-v2/ 中链接的 master-roadmap 文档体系),而是回答一个更窄的问题:

如果slate-browser工作在第一波公开包 tranche 之后重新开启,最高杠杆的定向动作是什么?

文档同时给出了完整的执行背景(Context)与六个阶段(Phases):

  1. 完成:将原内部文档树迁入docs/,且不丢失已有docs/*内容;
  2. 完成:更新内部文档对docs的引用;
  3. 完成:阅读相关文档与包/测试文件;
  4. 完成:综合出slate-browser/slate-v2的最强下一步;
  5. 完成:为该动作直接修改文档;
  6. 完成:同一轮内验证文档迁移与文档同步。

从后续docs/analysis/editor-global-systems-objective.md、docs/slate-browser/next-api-candidates.md、docs/slate-browser/next-api-candidates-matrix.md、docs/slate-browser/four-way-api-deep-dive.md 等产出物可以看出,这些阶段全部按期闭环。

二、关键发现(Findings):合并而非重命名

文档用一组"Findings"记录了调研结论,其中最重要的几条是:

  • 现有docs/已包含活跃内容(analysis/plans/solutions/performance/table/),原内部文档树还额外带有plans/slate-browser/slate-v2slate-issues与额外的solutions/子树——这是一次合并(merge),不是重命名(rename)
  • 当前slate-browser公共 tranche 已落地在.tmp/slate-v2
  • 最高杠杆的下一步不是跨浏览器,也不是性能优先
  • 最好的下一步是:更强的openExample(...)就绪契约,然后是针对零宽字符与 IME 敏感行为的渲染器/输入策略证明赛道

这些结论并非拍脑袋,而是经过了文档重读、包/测试文件审阅、以及一轮"跨仓库系统扫描"(覆盖 Lexical、edix、rich-textarea、Premirror、Pretext、TanStack DB、urql、VS Code、LSP)之后收敛出来的。

三、更大的图景:三层系统分工

该计划把"下一步动作"放在了一个显式的系统目标之下(详见 docs/analysis/editor-global-systems-objective.md):

  • slate-v2:负责文档真相(document truth)——文档语义、操作、事务、不可变提交快照;
  • slate-browser:负责浏览器证明(browser proof)——分层测试车道、示例挂载真相、把选区与剪贴板当作一等公民、Chromium 优先的 IME 证明;
  • 未来plate-v2:负责投影(projections)、执行管道(pipelines)、托管服务、布局系统与产品化。

系统目标文档还给出了完整的九层"责任分层"栈:文档引擎平面(slate-v2)、运行时与渲染平面(slate-react-v2)、浏览器证明平面(slate-browser)、投影与派生数据平面(未来plate-v2)、执行管道平面(未来plate-v2)、托管特性与协议平面(未来plate-v2)、布局与测量平面(未来plate-v2)、轻量表面平面(未来plate-v2)、产品化平面(未来plate-v2)。

计划文档中记录的最强跨域参照系(cross-domain imports)也与之对应:

参照对象借鉴方向
TanStack DB投影存储(projection stores)
urql执行管道(execution pipelines)
VS Code + LSP托管语义服务(hosted semantic services)
Premirror + Pretext布局与测量系统(layout and measurement)
rich-textarea / edix轻量表面(lightweight surfaces)

文档特别强调一条纪律:"从每个参照仓库偷对的理念,但让每一层待在它的车道上"——这正是判断"下一步该做什么、不该做什么"的总纲。

四、下一批 API 候选的排序与三段式分期

计划文档给出了slate-browser下一批 API 候选的显式排序:

  1. ready契约
  2. editor.selection.select(...)
  3. editor.get.blockTexts()/assert.blockTexts(...)
  4. editor.snapshot()
  5. 容错选区断言(tolerant selection assertions)
  6. HTML 归一化选项(HTML normalization options)
  7. 真实剪贴板读取助手(real clipboard read helpers)
  8. 更晚的路径导向定位器(path-oriented locators)

配套的 docs/slate-browser/next-api-candidates-matrix.md 给出了每个候选的详细评审(状态、候选形态、证据来源、消除的痛点、风险与规则),并据此划出阶段切分:

  • Phase 1readyselection.select(...)blockTextssnapshot()
  • Phase 2:容错选区断言、HTML 归一化选项、可能的get.selectedText()
  • Phase 3:真实剪贴板读取、替代表面作用域(alternate-surface scoping)、路径导向定位器

4.1 当前测试痛点数据:API 存在的理由

矩阵文档统计了当前 Playwright 示例套件中的"重复噪音":

  • page.goto(...):23 处
  • getByRole('textbox'):41 处
  • selectText():7 处
  • 裸 DOM 选区手术(document.createRange/window.getSelection()/addRange(...)):5 处
  • boundingBox()断言:2 处

这套数据正是"下一个 API 应该消除高频噪音设置,而不是再添一个可爱助手名"的量化依据。

4.2 四个"现在就发"的 API 候选形态

ready契约(最强,取自 Lexical 的initialize(...)纪律,但不复制其整体臃肿):

const editor = await openExample(page, "custom-placeholder", { ready: { editor: "visible", placeholder: "visible", text: /Type something/, selection: "settled", selector: "#document-outline", }, });

可选表单(harness 内):

await editor.ready({ selection: { anchor: { path: [0, 0], offset: 0 }, focus: { path: [0, 0], offset: 0 }, }, });

它消除的痛点:临时page.goto(...)、对占位符/文本/额外选择器的一次性等待、隐藏的选区稳定(selection-settle)时序。强规则:优先一个ready对象,而不是更多顶层waitForX布尔值;风险是变成"厨房水槽",规则是"保持狭窄、只做就绪"。

editor.selection.select(...)(最强 Slate 风格候选):

await editor.selection.select({ anchor: { path: [0, 0], offset: 0 }, focus: { path: [0, 0], offset: 5 }, });

以及便捷形态与伴随方法:

await editor.selection.collapse({ path: [0, 0], offset: 0 }); await editor.selection.selectBlock([1]);

它解决的悖论是:当前 harness 能断言语义选区,却不能创建语义选区——测试被迫回退到裸 DOM Range 手术。强规则:选区设置语义优先,鼠标手势留给交互测试而非基础设置。

editor.get.blockTexts()/editor.assert.blockTexts(...)(最佳语义 getter,取自 edix):

expect(await editor.get.blockTexts()).toEqual(["alpha", "beta"]); await editor.assert.blockTexts(["alpha", "beta"]);

伴随窄 getter 与选中文本:

expect(await editor.get.textAt([1])).toBe("beta"); expect(await editor.get.selectedText()).toBe("wise quote");

它优于扁平的get.text()(对许多 Slate 测试而言过于有损),也比裸 HTML 更贴近 Slate 语义、比 DOM 琐碎更稳定。强规则:停在块级文本语义,不要在这里添加伪造的 DOM 到 Slate JSON 反序列化

editor.snapshot()(最高价值的调试 API,灵感来自use-editablegetState()):

const snapshot = await editor.snapshot(); expect(snapshot).toEqual({ text: "Hello", blockTexts: ["Hello"], selection: { anchor: { path: [0, 0], offset: 5 }, focus: { path: [0, 0], offset: 5 }, }, domSelection: { anchorNodeText: "Hello", anchorOffset: 5, focusNodeText: "Hello", focusOffset: 5, }, });

矩阵文档给出的预期载荷还包括selectedTextplaceholderShape。强规则:快照只聚合既有真相,不发明新的隐藏状态——这也是未来 agent-native 产物捕获的燃料。

4.3 第二波候选

容错选区断言(取自 Lexical;offset 可以是精确值或区间[min, max]):

await editor.assert.selection({ anchor: { path: [0, 0], offset: [0, 1] }, focus: { path: [0, 0], offset: [0, 1] }, });

DOM 侧对应:

await editor.assert.domSelection({ anchorOffset: [0, 1], focusOffset: [0, 1], });

HTML 归一化选项(挂在htmlEquals上,而不是新增一堆近似重复方法):

await editor.assert.htmlEquals(expectedHtml, { ignoreClasses: true, ignoreInlineStyles: true, ignoreDir: true, });

4.4 第三波候选

真实剪贴板读取(edix 已证明navigator.clipboard.read()在浏览器测试中有用):

await editor.clipboard.copy(); expect(await editor.clipboard.readText()).toContain("Hello"); expect(await editor.clipboard.readHtml()).toContain("<p");

替代表面作用域(iframe / shadow DOM,当前套件已有 iframe.test.ts 与 shadow-dom.test.ts 所述压力)与路径导向定位器:

const editor = await openExample(page, "iframe", { surface: "iframe" }); await editor.path([1]).click({ clickCount: 3 }); await editor.textNode([0, 0]).click();

4.5 明确拒绝的 API

两份候选文档都列出了"不要加"清单:

  • openFixture(...):没有真实 fixture 车道,示例挂载真相仍是正确接缝;
  • editor.driver():通用驱动逃生舱会摧毁 Slate 风格 API 的意义;
  • 伪造的合成公开粘贴助手:真实浏览器剪贴板写入 + 真实粘贴手势已经存在;
  • 一个巨型EditorDriver抽象:当前后端是 Playwright-first,现在假装不是就是"抽象角色扮演"。

五、四方深度对比:谁还在贡献 API 思想

计划文档记录了"4-way deep dive"(针对 Lexical、ProseMirror、Tiptap、edix 四家的聚焦对照,完整版见 docs/slate-browser/four-way-api-deep-dive.md)。其结论(Bottom Line First):

  • Lexical仍是助手 API 的最强来源(就绪契约、容错选区断言、HTML 归一化选项、剪贴板序列化纪律、人类可读期望选区构建器);
  • ProseMirror是最强的接缝/不变量来源——不提供最漂亮的 API,但提供最好的不变量和一个严肃的后期 API:选区书签(selection bookmarks)
  • edix仍贡献少量高价值语义 getter(getTextgetSelectiongetSelectedRectgetSelectedText);
  • Tiptap主要是 DX 与产品化验证者,不是助手 API 矿藏。

这次深潜"materially changed one thing":ProseMirror 暴露了一个真实的后期候选——editor.selection.bookmark()/capture()——但前提是它必须有真实的 Slate 侧书签/range-ref 接缝支撑,而不是 Playwright 伪造品

六、当前状态盘点:三个 Phase 已全部落地

计划文档的 Findings 明确记录了"已落地在代码里"的清单(对应实现位于.tmp/slate-v2/packages/slate-browser/src/playwright/index.ts,配套 red/green 覆盖在.tmp/slate-v2/playwright/integration/examples/slate-browser-helpers.test.ts;这些路径是计划文档记录的当时状态):

Phase 1 已落地

  • ready契约
  • editor.selection.select(...)
  • editor.selection.collapse(...)
  • editor.get.blockTexts()
  • editor.assert.blockTexts(...)
  • editor.snapshot()

Phase 2 已落地

  • 容错选区断言
  • 容错 DOM 选区断言
  • editor.get.selectedText()
  • 归一化的editor.assert.htmlEquals(..., options?)

Phase 3 已落地

  • 真实剪贴板读取:editor.clipboard.readText()editor.clipboard.readHtml()
  • 替代表面作用域:surface.framesurface.scope
  • 路径导向定位器:editor.locator.block(...)editor.locator.text(...)

选择书签接缝也已落地

  • editor.selection.capture(...)
  • editor.selection.bookmark(...)
  • editor.selection.resolve(...)
  • editor.selection.restore(...)
  • editor.selection.unref(...)

文档特别强调:这个接缝由真实编辑器RangeRef语义支撑(暴露在根表面上),而不是一个伪造的仅限 Playwright 的快照别名——为此还在旧Editable根与slate-dom-v2挂载根上暴露了刻意设计的浏览器测试句柄,让slate-browser能创建真正的RangeRef支撑选区书签。

七、决策标准与五个方向研判

文档 docs/slate-browser/next-system-move.md 给出了下一步动作的决策标准,下一步应:

  1. 直接帮助证明剩余的slate-v2浏览器面向接缝;
  2. 提升测试诚实度,而不是抽象数量;
  3. 让未来的跨浏览器与性能车道更轻松;
  4. 在第二个后端真实存在之前,避免伪造"车道中立"的 API 设计。

基于此,文档对五个候选方向逐一研判:

方向 1:更强的openExample(...)就绪契约——最强动作。理由:每个剩余的浏览器面向证明都以挂载示例为起点;当前openExample(...)有用但仍单薄;就绪状态目前被描述为"几个等待",而不是一个真正的契约。它应该:保持openExample(...)作为唯一路由入口、让就绪显式且有意为之、区分页面导航 / 编辑器根可见性 / 示例特定挂载状态 / 选区敏感就绪。它不应该变成:Lexical 体量的厨房水槽初始化器、通用 runner 抽象、新的公开openFixture(...)强立场:偷 Lexical 的设置纪律,不复制它的整个initialize(...)大块

方向 2:跨浏览器车道——重要,但不是第一。现在做它输的原因:文档已拒绝伪造的跨浏览器 IME 抽象剧场;Chromium 仍是 IME 与剪贴板重负载示例证明的诚实第一车道;没有更锋利的就绪契约,跨浏览器车道只会给你"更宽的 flake"。最佳姿态:就绪契约落地后加test:slate-browser:cross,先从非 IME 证明开始(占位符可见性、语义选区归一化、普通剪贴板行为),不要从 Safari/WebKit IME 英雄主义开始

方向 3:性能/精度车道——应该做,但要等下一个正确性接缝钉死之后。Premirror 与 Pretext 是车道命名与基准诚实度的正确影响源,但正确性目标停止漂移后,性能车道才值钱得多。最佳后期形态:test:slate-browser:perf,可能还有test:slate-browser:accuracy强立场:渲染器/输入策略证明赛道存在之前,不上性能车道。

方向 4:弱化 Playwright 特定公开边界——今天做是错的。理由:当前只有一个真实公开后端slate-browser/playwright;现在构建通用EditorDriver是抽象角色扮演;包已经有正确的切分(core/browser放车道中立名词,playwright放后端特定 harness)。规则:保持 API 名词编辑器形状,在第二个后端真实之前保持后端表面显式

方向 5:发布姿态——此刻最不重要。包形状已经真实;包承诺仍应保守;发布策略不会解锁下一个slate-v2接缝。最佳姿态:在公开 API 之上再落地一个真实证明车道之前,保持包 experimental/private

八、具体动作批次与目标接缝

计划的最终推荐是两个连续动作:

  1. openExample(...)变成真正的就绪契约
  2. 用该契约搭建第一个渲染器/输入策略证明赛道

该赛道应瞄准当前未解决的接缝(这也是本次"系统级动作"最终要钉死的四大目标):

  • 空块占位符策略(empty block placeholder policy)
  • 零宽字符渲染策略(zero-width rendering policy)
  • 哨兵文本周围的选区归一化(selection normalization around sentinel text)
  • 空/零宽敏感起点上的 IME 提交行为(IME commit behavior on empty and zero-width-sensitive starts)

具体 tranche(Do this next):

  1. 收紧OpenExampleOptions,让就绪语义替代临时等待;
  2. 为零宽 / 空状态 / IME 邻近行为添加就绪敏感的浏览器回归;
  3. 只有在那之后,才向外分支到test:slate-browser:crosstest:slate-browser:perf,可能还有test:slate-browser:accuracy

8.1 反规则清单

文档明确列出"不要先做这些":

  • 重新引入openFixture(...)
  • 添加伪造的公开合成粘贴助手
  • 发明车道中立 driver 抽象
  • 从跨浏览器 IME 剧场开始
  • 把发布语义变成主要架构决策

九、分层测试框架与命令体系

该动作植根于 docs/slate-browser/overview.md 确立的分层测试框架世界观:"一个 runner 统治一切是陷阱;速度、保真度与覆盖想要不同的工具":

  • Layer 0 核心快速测试:纯模型/变换/选区/投影语义;
  • Layer 1 DOM 契约测试:浏览器支撑的契约测试(未来方向是 Vitest browser + Playwright provider);
  • Layer 2 示例集成测试:Playwright,断言真实示例表面上的真实编辑器行为;
  • Lane A IME/组合:Chromium Playwright + CDP(jsdom 组合测试不够);
  • Lane B Agent 原生dev-browser/agent-browser,后期扩展接缝;
  • Lane C 性能:显式基准脚本。

slate-browser在该体系中的角色是:master roadmap 的专家测试/证明车道,不拥有 roadmap 真相或队列顺序,但喂养已产出工件义务(proof ledger)。

计划文档记录的可信本地命令包括(均为当时仓库根命令):

  • yarn workspace slate-browser test
  • yarn test:slate-browser:e2e:local
  • yarn test:slate-browser:bookmarks:local
  • PLAYWRIGHT_BASE_URL=http://localhost:3200 yarn test:slate-browser:e2e
  • PLAYWRIGHT_BASE_URL=http://localhost:3200 yarn test:slate-browser:ime
  • PLAYWRIGHT_BASE_URL=http://localhost:3200 yarn test:slate-browser:clipboard
  • PLAYWRIGHT_BASE_URL=http://localhost:3200 yarn test:slate-browser:anchors
  • yarn lint:typescript
  • ROLLUP_PACKAGES=slate-browser,slate-react,slate-dom-v2 yarn build:rollup

其中两条本地置信命令(yarn test:slate-browser:e2e:localyarn test:slate-browser:bookmarks:local)是新接入的:计划文档记录,书签接缝验证时因共享的:3200服务器对应用运行时改动"不是可信目标",因此用全新本地站点服务器http://localhost:3210验证,并修复了本地 Playwright runner 路径(新增scripts/run-slate-browser-local.sh并在.tmp/slate-v2/package.json接入 fresh-server 本地命令)。

十、执行进度:从文档迁移到书签验证的一日闭环

计划文档的 Progress 日志(2026-04-04)完整记录了这次动作从调研到验证的闭环:

  1. 加载tasklearnings-researchergoal workflowmajor-task
  2. 对照当前docs/与原内部文档树,映射迁移前的重叠;
  3. 将原内部文档树迁入docs/并重写过期内部路径引用;
  4. 重读 Slate v2 /slate-browser文档、学习文档、包文件与示例测试;
  5. 新增 docs/slate-browser/next-system-move.md 并从slate-browser/slate-v2概览文档链接它;
  6. 验证旧内部文档树消失、无陈旧路径引用残留;
  7. 运行跨仓库系统扫描(Lexical、edix、rich-textarea、Premirror、Pretext、TanStack DB、urql、VS Code、LSP);
  8. 新增 docs/analysis/editor-global-systems-objective.md 并链接;
  9. 新增 docs/slate-browser/next-api-candidates.md 与 docs/slate-browser/next-api-candidates-matrix.md;
  10. 完成 Lexical / ProseMirror / Tiptap / edix 四方对照,新增 docs/slate-browser/four-way-api-deep-dive.md;
  11. 依次实现 Phase 1、Phase 2、Phase 3 的slate-browserPlaywright tranche,并逐波补充 red/green 覆盖;
  12. 暴露浏览器测试句柄、落地书签接缝,用:3210fresh-server 验证并以yarn test:slate-browser:e2e:local跑完全部 helper 套件。

十一、结论

这份"下一系统级动作"文档的核心判断可以用三句话收束:

  1. 公开包 tranche 已经完成——slate-browser已从一次性 spike 变成带公开拆分的真实 workspace 包(slate-browserslate-browser/coreslate-browser/browserslate-browser/playwright);
  2. 下一步不是"更多表面积",而是两件事:在openExample(...)上建立更锋利的就绪契约,再用该契约搭建渲染器/输入策略证明赛道,钉死空块占位符、零宽渲染、哨兵文本选区归一化与 IME 提交行为这四大接缝;
  3. 这是通往诚实跨浏览器、性能与发布决策的最干净路径——只有当正确性车道停止漂移,test:slate-browser:crosstest:slate-browser:perf才有意义;而只有由真实RangeRef语义支撑的选择书签接缝,才能让选区在历史、注释锚点与 transform 存续测试中成为一等公民。

对任何想要继续深入研究slate-browser体系的人,建议按此顺序阅读:先读 docs/slate-browser/overview.md 建立分层框架观,再读 docs/slate-browser/next-api-candidates.md 与 docs/slate-browser/next-api-candidates-matrix.md 理解 API 排序依据,然后读 docs/slate-browser/four-way-api-deep-dive.md 对照四方结论,最后回到 docs/slate-browser/next-system-move.md 与本文所依据的计划文档,即可完整还原这次"系统级动作"的决策全貌。

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

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 20:57:23

鼎阳SDS7404A H10:重新定义示波器的时频联合分析范式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 20:56:28

CentOS 7安装Git全攻略:yum、源码编译与SSH配置详解

前两天帮一台老服务器重装 Git&#xff0c;本来想着几条命令就能搞定的事&#xff0c;结果前前后后折腾了小半个下午。yum 源慢到像拨号上网、编译依赖缺了好几个、装完以后中文文件名还乱码&#xff0c;整个过程基本把 CentOS 7 上装 Git 能踩的坑都踩了一遍。正好趁着这个经历…

作者头像 李华
网站建设 2026/9/15 20:56:20

社交网站建站图解步骤:备案避坑与部署实战指南

社交网站建站图解步骤:备案避坑与部署实战指南 备案流程一头雾水?别慌。很多甲方对接人在启动社交网站建站项目时,最头疼的不是代码怎么写,而是域名解析后网站打不开,或者上传文件报错。其实,只要理清从域名注册到服务器配置的每一步,这些坑都能避开。今天我们就用图解步骤的方式,把社交网站建站的底层逻辑、域名服…

作者头像 李华