Fix forward word deletion destructing element nodes (#5625)

This commit is contained in:
Ivaylo Pavlov
2024-03-07 16:54:43 +00:00
committed by GitHub
parent 9f84191951
commit 4eb91a8c20
2 changed files with 44 additions and 18 deletions

View File

@ -65,6 +65,10 @@ export class LayoutContainerNode extends ElementNode {
return $createLayoutContainerNode(json.templateColumns); return $createLayoutContainerNode(json.templateColumns);
} }
isShadowRoot(): boolean {
return true;
}
canBeEmpty(): boolean { canBeEmpty(): boolean {
return false; return false;
} }

View File

@ -1537,6 +1537,39 @@ export class RangeSelection implements BaseSelection {
} }
} }
} }
/**
* Helper for handling forward character and word deletion that prevents element nodes
* like a table, columns layout being destroyed
*
* @param anchor the anchor
* @param anchorNode the anchor node in the selection
* @param isBackward whether or not selection is backwards
*/
forwardDeletion(
anchor: PointType,
anchorNode: TextNode | ElementNode,
isBackward: boolean,
): boolean {
if (
!isBackward &&
// Delete forward handle case
((anchor.type === 'element' &&
$isElementNode(anchorNode) &&
anchor.offset === anchorNode.getChildrenSize()) ||
(anchor.type === 'text' &&
anchor.offset === anchorNode.getTextContentSize()))
) {
const parent = anchorNode.getParent();
const nextSibling =
anchorNode.getNextSibling() ||
(parent === null ? null : parent.getNextSibling());
if ($isElementNode(nextSibling) && nextSibling.isShadowRoot()) {
return true;
}
}
return false;
}
/** /**
* Performs one logical character deletion operation on the EditorState based on the current Selection. * Performs one logical character deletion operation on the EditorState based on the current Selection.
@ -1548,27 +1581,13 @@ export class RangeSelection implements BaseSelection {
const wasCollapsed = this.isCollapsed(); const wasCollapsed = this.isCollapsed();
if (this.isCollapsed()) { if (this.isCollapsed()) {
const anchor = this.anchor; const anchor = this.anchor;
const focus = this.focus;
let anchorNode: TextNode | ElementNode | null = anchor.getNode(); let anchorNode: TextNode | ElementNode | null = anchor.getNode();
if ( if (this.forwardDeletion(anchor, anchorNode, isBackward)) {
!isBackward && return;
// Delete forward handle case
((anchor.type === 'element' &&
$isElementNode(anchorNode) &&
anchor.offset === anchorNode.getChildrenSize()) ||
(anchor.type === 'text' &&
anchor.offset === anchorNode.getTextContentSize()))
) {
const parent = anchorNode.getParent();
const nextSibling =
anchorNode.getNextSibling() ||
(parent === null ? null : parent.getNextSibling());
if ($isElementNode(nextSibling) && nextSibling.isShadowRoot()) {
return;
}
} }
// Handle the deletion around decorators. // Handle the deletion around decorators.
const focus = this.focus;
const possibleNode = $getAdjacentNode(focus, isBackward); const possibleNode = $getAdjacentNode(focus, isBackward);
if ($isDecoratorNode(possibleNode) && !possibleNode.isIsolated()) { if ($isDecoratorNode(possibleNode) && !possibleNode.isIsolated()) {
// Make it possible to move selection from range selection to // Make it possible to move selection from range selection to
@ -1689,6 +1708,9 @@ export class RangeSelection implements BaseSelection {
*/ */
deleteWord(isBackward: boolean): void { deleteWord(isBackward: boolean): void {
if (this.isCollapsed()) { if (this.isCollapsed()) {
const anchor = this.anchor;
const anchorNode: TextNode | ElementNode | null = anchor.getNode();
if (this.forwardDeletion(anchor, anchorNode, isBackward)) return;
this.modify('extend', isBackward, 'word'); this.modify('extend', isBackward, 'word');
} }
this.removeText(); this.removeText();