diff --git a/packages/lexical-playground/__tests__/e2e/Selection.spec.mjs b/packages/lexical-playground/__tests__/e2e/Selection.spec.mjs
index 22a15388f5e0..20ebff8f39c6 100644
--- a/packages/lexical-playground/__tests__/e2e/Selection.spec.mjs
+++ b/packages/lexical-playground/__tests__/e2e/Selection.spec.mjs
@@ -217,6 +217,52 @@ test.describe('Selection', () => {
);
});
+ test('can delete line which ends with element with CMD+delete', async ({
+ page,
+ isPlainText,
+ }) => {
+ test.skip(isPlainText || !IS_MAC);
+ await focusEditor(page);
+ await page.keyboard.type('One');
+ await page.keyboard.press('Enter');
+ await page.keyboard.type('Two');
+ // sample image
+ await pasteFromClipboard(page, {
+ 'text/html': `
+
+
+
+
+
+ `,
+ });
+
+ const deleteLine = async () => {
+ await keyDownCtrlOrMeta(page);
+ await page.keyboard.press('Backspace');
+ await keyUpCtrlOrMeta(page);
+ };
+
+ await deleteLine();
+ await assertHTML(
+ page,
+ html`
+
+ One
+
+ `,
+ );
+ await deleteLine();
+ await assertHTML(
+ page,
+ html`
+
+ `,
+ );
+ });
+
test('Can insert inline element within text and put selection after it', async ({
page,
isPlainText,
diff --git a/packages/lexical/src/LexicalSelection.ts b/packages/lexical/src/LexicalSelection.ts
index a62cb36e00b2..d6c76af0f201 100644
--- a/packages/lexical/src/LexicalSelection.ts
+++ b/packages/lexical/src/LexicalSelection.ts
@@ -1696,10 +1696,16 @@ export class RangeSelection implements BaseSelection {
*/
deleteLine(isBackward: boolean): void {
if (this.isCollapsed()) {
- if (this.anchor.type === 'text') {
- this.modify('extend', isBackward, 'lineboundary');
+ // Since `domSelection.modify('extend', ..., 'lineboundary')` works well for text selections
+ // but doesn't properly handle selections which end on elements, a space character is added
+ // for such selections transforming their anchor's type to 'text'
+ const anchorIsElement = this.anchor.type === 'element';
+ if (anchorIsElement) {
+ this.insertText(' ');
}
+ this.modify('extend', isBackward, 'lineboundary');
+
// If selection is extended to cover text edge then extend it one character more
// to delete its parent element. Otherwise text content will be deleted but empty
// parent node will remain
@@ -1707,6 +1713,12 @@ export class RangeSelection implements BaseSelection {
if (endPoint.offset === 0) {
this.modify('extend', isBackward, 'character');
}
+
+ // Adjusts selection to include an extra character added for element anchors to remove it
+ if (anchorIsElement) {
+ const startPoint = isBackward ? this.anchor : this.focus;
+ startPoint.set(startPoint.key, startPoint.offset + 1, startPoint.type);
+ }
}
this.removeText();
}