2026/9/15 12:57:40

Plate 项目 basic-styles 与 math 包非 React 测试覆盖实战:从测试计划到源码级验证

Plate 项目 basic-styles 与 math 包非 React 测试覆盖实战:从测试计划到源码级验证 Plate 项目 basic-styles 与 math 包非 React 测试覆盖实战从测试计划到源码级验证【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate导读本文基于 Plateplatejs仓库中的测试覆盖执行计划文档 2026-03-23-basic-styles-and-math-coverage-pass.md完整还原一次针对platejs/basic-styles与platejs/math两个非 React 包的定向测试覆盖行动包括覆盖目标、被测 API 的源码实现原理、聚焦测试用例的断言逻辑以及从bun test到turbo build/typecheck/lint的完整验证链路。读完本文你将掌握这两个包中 9 个核心函数与插件的职责边界与调用方式并了解 Plate 仓库测试覆盖计划 → 聚焦 spec → 多命令验证的标准化执行流程可直接复用到其他包的覆盖工作中。一、背景为什么做这次覆盖 Pass在 Plate 仓库中packages/basic-styles与packages/math是两个纯逻辑non-React功能包分别承载段落级排版样式与 KaTeX 数学公式渲染。随着仓库整体转向bun test测试运行器并推行按包、按函数粒度补齐覆盖的测试策略2026-03-23 的这份计划文档定义了一次小而聚焦的覆盖行动只针对两个包的非 React 部分补写精确到单个函数/插件的 spec并明确延后/react子目录、字体插件整体扫尾与额外的 KaTeX 行为矩阵。其核心策略值得注意先圈定精确的 API 名单Scope再逐一对齐源码实现补 spec最后用一组标准命令验证。这与仓库内其他覆盖计划如 2026-03-23-core-coverage-pass.md、2026-03-23-combobox-coverage-pass.md属于同一套执行模式。二、basic-styles 包的覆盖范围与源码原理本次为platejs/basic-styles圈定 4 个被测目标均位于 packages/basic-styles/src/libReact 版本在 packages/basic-styles/src/react不在本次范围。2.1setLineHeight注入式块级行高变换源码位于 setLineHeight.ts其实现体现了 Plate 的注入inject架构export const setLineHeight ( editor: SlateEditor, value: number, setNodesOptions?: SetNodesOptions ): void { const { defaultNodeValue, nodeKey } editor.getInjectProps(BaseLineHeightPlugin); const match getInjectMatch( editor, editor.getPlugin({ key: KEYS.lineHeight }) ); if (value defaultNodeValue) { editor.tf.unsetNodes(nodeKey!, { match, ...setNodesOptions }); } else { editor.tf.setNodes({ [nodeKey!]: value }, { match: match as any, ...setNodesOptions, }); } };关键行为通过editor.getInjectProps(BaseLineHeightPlugin)读取插件的defaultNodeValue与nodeKey实现单一数据源当传入值等于默认值1.5时走unsetNodes删除lineHeight属性否则用setNodes写入——即回到默认即清理避免文档中堆积冗余属性。对应 spec setLineHeight.spec.tsx 用jsxt构造编辑器状态覆盖三个断言分支对匹配的p块设置lineHeight: 2后节点类型保持p并新增属性已带lineHeight{2}的段落调用setLineHeight(editor, 1.5)后属性被移除回到默认值即清理对h1等非注入目标调用时不产生任何变更——验证了getInjectMatch的匹配边界。2.2toUnitLess单位剥离工具源码位于 toUnitLess.ts实现极简但边界清晰const digitRegex /\d/; // return 0 if value not valid export const toUnitLess (value: string): string { const match digitRegex.exec(value); if (!match) return 0; const num Number(match[0]); if (value.endsWith(rem)) return (num * 16).toString(); return num.toString(); };提取字符串中第一段连续数字无法匹配如空串、auto时返回0rem单位按 16px 基准换算为像素数值2rem → 32px或纯数字则直接剥离单位。对应 toUnitLess.spec.ts 用三组用例锁定了非法值归零、px/纯数字保数值、rem 乘 16三个契约这是后续行高 HTML 反序列化时把 CSS 字符串规范化为数值的前提。2.3BaseLineHeightPlugin块级注入 HTML 反序列化源码位于 BaseLineHeightPlugin.ts通过createSlatePlugin声明key: KEYS.lineHeightinject.isBlock: truetargetPlugins: [KEYS.p]——只注入到段落块nodeProps声明defaultNodeValue: 1.5、nodeKey: lineHeighttargetPluginToInject向目标插件注入 HTML deserializer解析p styleline-height: ...的element.style.lineHeight为节点属性最后extendTransforms暴露绑定编辑器实例的editor.tf.lineHeight.setNodes(value, options)。其 spec BaseLineHeightPlugin.spec.ts 验证了三件事插件暴露的注入契约isBlock、targetPlugins、nodeProps正确注入的 deserializer 能把style.lineHeight转成{[lineHeight type]: 2}通过editor.tf.lineHeight.setNodes(2, { at: [] })应用、再传1.5清除与setLineHeight共用同一变换。2.4BaseFontColorPlugin叶子标记 颜色反序列化源码位于 BaseFontColorPlugin.tsnodeProps声明defaultNodeValue: black、nodeKey: colorHTML deserializer 标记isLeaf: truevalidStyle: { color: * }命中任意颜色样式时把element.style.color解析为叶子 markextendTransforms暴露editor.tf.color.addMark(value)内部转发到editor.tf.addMarks({ [KEYS.color]: value })。其 spec BaseFontColorPlugin.spec.ts 验证了rgb(255, 0, 0)这类颜色字符串会被原样保留为KEYS.colormark并确认addMark正确转发到编辑器级addMarks。这保证了从 HTML 粘贴带色文本时 mark 结构一致。三、math 包的覆盖范围与源码原理platejs/math在 packages/math/src/lib 下实现公式节点模型与 KaTeX 渲染入口React 交互层packages/math/src/react本次明确延后。被测目标共 5 个。3.1insertEquation与insertInlineEquation公式节点插入两个变换均位于 packages/math/src/lib/transforms// insertEquation.ts editor.tf.insertNodesTEquationElement({ children: [{ text: }], texExpression: , type: editor.getType(KEYS.equation), }, options);// insertInlineEquation.ts editor.tf.insertNodesTEquationElement({ children: [{ text: }], texExpression: texExpression ?? editor.api.string(editor.selection), type: editor.getType(KEYS.inlineEquation), }, options);差异点块级insertEquation插入空表达式节点行内insertInlineEquation若未显式传入texExpression会用editor.api.string(editor.selection)把当前选区文本作为初始 TeX 表达式——这是选中文本一键转行内公式的典型入口。两个 specinsertEquation.spec.ts、insertInlineEquation.spec.ts分别断言了空表达式插入与选区文本回填两种路径。3.2BaseEquationPlugin与BaseInlineEquationPlugin节点类型与 HTML 导入两个插件BaseEquationPlugin.ts、BaseInlineEquationPlugin.ts结构一致差别在节点形态块级node: { isElement: true, isVoid: true }行内node: { isElement: true, isInline: true, isVoid: true }两者 HTML deserializer 都从data-slate-tex-expression属性还原texExpression用于复制/粘贴场景均通过.overrideEditor(withEquation)挂载withEquation.internal.ts中的编辑器覆写逻辑并通过extendEditorTransforms暴露editor.tf.insert.equation(...)与editor.tf.insert.inlineEquation(...)块级插件额外import katex/dist/katex.min.css确保公式渲染样式随包自带。withEquation的底层公式归一化逻辑见 withEquation.internal.ts输入规则$$等触发符见 MathRules.ts 与 inputRules.spec.tsx。3.3getEquationHtmlKaTeX 服务端渲染出口源码位于 getEquationHtml.tsexport const getEquationHtml ({ element, options, }: { element: TEquationElement; options?: KatexOptions; }) katex.renderToString(getEquationExpression(element), options);直接调用 KaTeX 的renderToString生成 HTML 字符串可用于 SSR、导出或非浏览器环境表达式经 getEquationExpression.internal.ts 归一化——该工具兼容早期 HTML 导入把数值/布尔属性存为原始类型的历史数据统一String(...)转换无法识别时回退空串options可透传KatexOptions如displayMode、throwOnErrorgetEquationHtml.spec.ts 覆盖了表达式归一化与渲染调用。四、验证计划多命令组合的完整链路原计划文档给出的验证步骤是本次覆盖通过判定的唯一依据逐条如下命令作用bun test针对改动文件快速验证本次新加的聚焦 specbun test packages/basic-styles/src/lib packages/math/src/lib对两个包的全部 lib 目录做完整回归pnpm test:profile -- --top 20 packages/basic-styles/src packages/math/src输出两个包最慢的 20 个用例检查性能回归pnpm test:slowest -- --top 20 packages/basic-styles/src packages/math/src聚焦最慢用例清单识别拖慢 CI 的测试pnpm install重新解析依赖锁文件确保新 spec 依赖可用pnpm turbo build --filter./packages/basic-styles --filter./packages/math构建两个目标包Turbo 增量构建pnpm turbo typecheck --filter./packages/basic-styles --filter./packages/math包级 TypeScript 类型检查pnpm lint:fix修复 lint 问题保持代码风格一致这套组合覆盖了测试运行 → 性能/慢用例体检 → 依赖解析 → 构建 → 类型 → 风格六个维度--filter./packages/name把验证精确限制在改动包内避免全仓构建拖慢反馈速度——这也是仓库内其他覆盖 pass 计划如 2026-03-23-code-block-coverage-pass.md共用的验证模板。五、执行结果与覆盖收获计划文档最终标记为status: completedResult 确认为setLineHeight、toUnitLess、BaseLineHeightPlugin、BaseFontColorPlugin补写了聚焦 spec为insertEquation、insertInlineEquation、BaseEquationPlugin、BaseInlineEquationPlugin、getEquationHtml补写了聚焦 spec上述全部验证命令通过包括定向bun test、lib 目录全量bun test、test:profile/test:slowest体检、pnpm install、turbo build、turbo typecheck 与lint:fix。六、延后项与后续建议原计划明确声明本次不包含的内容可作为后续覆盖工作的候选清单/react子目录如 packages/math/src/react 下的useEquationInput、EquationPlugin等相关交互 spec 已存在于 useEquationInput.spec.tsxbasic-styles 的宽泛字体插件整体扫尾BaseFontFamilyPlugin、BaseFontSizePlugin、BaseFontWeightPlugin、BaseFontBackgroundColorPlugin等仍有独立 spec可另行批量评估额外的 KaTeX 行为矩阵如错误表达式、不同KatexOptions组合的渲染快照。若沿用本计划的方法论可将pnpm test:profile/test:slowest的输出作为后续性能优化见 editor-performance-master-plan.md的输入形成覆盖 → 体检 → 优化闭环。【免费下载链接】plateRich-text editor with AI and shadcn/ui项目地址: https://gitcode.com/GitHub_Trending/pl/plate创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考