Skip to content

Commit

Permalink
Fix delete line for selections ending with elements
Browse files Browse the repository at this point in the history
  • Loading branch information
DraXu3 committed May 22, 2024
1 parent 53f6f1d commit b3dc8d6
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 2 deletions.
46 changes: 46 additions & 0 deletions packages/lexical-playground/__tests__/e2e/Selection.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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': `
<span class="editor-image" data-lexical-decorator="true" contenteditable="false">
<div draggable="false">
<img src="/assets/yellow-flower-vav9Hsve.jpg" alt="Yellow flower in tilt shift lens" draggable="false" style="height: inherit; max-width: 500px; width: inherit;">
</div>
</span>
`,
});

const deleteLine = async () => {
await keyDownCtrlOrMeta(page);
await page.keyboard.press('Backspace');
await keyUpCtrlOrMeta(page);
};

await deleteLine();
await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span data-lexical-text="true">One</span>
</p>
`,
);
await deleteLine();
await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
`,
);
});

test('Can insert inline element within text and put selection after it', async ({
page,
isPlainText,
Expand Down
16 changes: 14 additions & 2 deletions packages/lexical/src/LexicalSelection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1696,17 +1696,29 @@ 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
const endPoint = isBackward ? this.focus : this.anchor;
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();
}
Expand Down

0 comments on commit b3dc8d6

Please sign in to comment.