首页
/ SuperEditor中块节点删除后光标位置处理的Bug分析

SuperEditor中块节点删除后光标位置处理的Bug分析

2025-07-08 23:54:46作者:尤辰城Agatha

问题背景

在SuperEditor富文本编辑器的开发过程中,发现了一个关于块节点删除后光标位置处理的逻辑缺陷。当用户在块节点(如HorizontalRuleNode)上使用折叠选择(collapsed selection)时,系统错误地返回了TextPosition类型的位置信息,而实际上应该返回UpstreamDownstreamNodePosition类型。

问题复现

通过一个简单的测试用例可以复现这个问题:

test("getDocumentPositionAfterExpandedDeletion on block node", () {
  final node = HorizontalRuleNode(id: "1");
  final document = MutableDocument(nodes: [node]);
  final selection = DocumentSelection.collapsed(
    position: DocumentPosition(
      nodeId: node.id,
      nodePosition: node.endPosition,
    ),
  );
  final position = CommonEditorOperations.getDocumentPositionAfterExpandedDeletion(
    document: document,
    selection: selection,
  );
  expect(position is UpstreamDownstreamNodePosition, isTrue);
});

在这个测试中,我们创建了一个水平线节点(HorizontalRuleNode),并在其末尾设置了一个折叠选择。理论上,当尝试删除这个选择时,系统应该返回一个UpstreamDownstreamNodePosition,但实际上却返回了TextPosition。

技术分析

当前实现的问题

当前CommonEditorOperations.getDocumentPositionAfterExpandedDeletion方法的实现存在以下问题:

  1. 类型判断不准确:对于块节点的处理,方法错误地假设所有块节点在被删除时都会被转换为ParagraphNode,因此返回了TextNodePosition。

  2. 折叠选择处理不当:对于折叠选择(即光标位置而非选择范围),方法没有做特殊处理,而是直接按照扩展选择的方式处理,导致返回了错误的位置类型。

正确的处理逻辑

根据富文本编辑器的常规行为,应该遵循以下原则:

  1. 折叠选择处理:当选择是折叠的(即只是一个光标位置),不应该执行任何删除操作,因此应该返回原始选择位置或者null表示不需要改变选择。

  2. 块节点位置类型:对于块节点,正确的位置类型应该是UpstreamDownstreamNodePosition,因为它需要明确表示是在节点的上游还是下游。

解决方案

经过讨论,开发团队确定了两种可能的解决方案:

  1. 返回null方案:修改方法使其在遇到折叠选择或不可删除节点时返回null,表示不需要改变当前选择。这种方案保持了与不可删除节点处理的一致性。

  2. 返回原选择方案:修改方法使其在遇到折叠选择时返回原始选择位置。这种方案更直观,但需要同时修改不可删除节点的处理逻辑以保持一致。

最终团队倾向于第一种方案,因为它更符合方法的设计初衷 - 只在确实发生删除操作时返回新位置,否则返回null表示不需要改变。

影响范围

这个修复会影响以下场景:

  1. 用户在块节点上使用删除键时的光标行为
  2. 程序化删除操作后的光标定位
  3. 与块节点相关的所有删除操作后的位置计算

总结

这个Bug揭示了SuperEditor在处理块节点删除操作时的一个逻辑缺陷。通过分析,我们明确了正确的处理方式应该是:对于折叠选择,不执行删除操作并返回null;对于块节点,返回正确的UpstreamDownstreamNodePosition类型。这个修复将提高编辑器在处理块节点时的行为一致性和用户体验。

登录后查看全文
热门项目推荐
相关项目推荐