Skip to content

Commit

Permalink
Fix $patchStyleText when the selection is anchored to the end of a te…
Browse files Browse the repository at this point in the history
…xt node (facebook#3116)

Specifically when the next sibling is not a text node or there is no
next sibling.

Without the code changes in this patch, the two test cases will throw
errors when trying to use the updated `firstNode`.
  • Loading branch information
birtles authored Oct 18, 2022
1 parent 08f7f25 commit c2e4456
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import {$createLinkNode} from '@lexical/link';
import {$createHeadingNode} from '@lexical/rich-text';
import {$cloneContents} from '@lexical/selection';
import {$cloneContents, $patchStyleText} from '@lexical/selection';
import {
$createParagraphNode,
$createTextNode,
Expand All @@ -17,6 +17,7 @@ import {
$getSelection,
$isNodeSelection,
$isRangeSelection,
RangeSelection,
TextNode,
} from 'lexical';
import {
Expand Down Expand Up @@ -2830,3 +2831,105 @@ describe('insertNodes', () => {
);
});
});

describe('$patchStyleText', () => {
test('can patch a selection anchored to the end of a TextNode before an inline element', async () => {
const editor = createTestEditor();
const element = document.createElement('div');
editor.setRootElement(element);

await editor.update(() => {
const root = $getRoot();

const paragraph = createParagraphWithNodes(editor, [
{
key: 'a',
mergeable: false,
text: 'a',
},
{
key: 'b',
mergeable: false,
text: 'b',
},
]);

root.append(paragraph);

const link = $createLinkNode('https://');
link.append($createTextNode('link'));

const a = $getNodeByKey('a');
a.insertAfter(link);

setAnchorPoint({
key: 'a',
offset: 1,
type: 'text',
});
setFocusPoint({
key: 'b',
offset: 1,
type: 'text',
});

const selection = $getSelection() as RangeSelection;
$patchStyleText(selection, {'text-emphasis': 'filled'});
});

expect(element.innerHTML).toBe(
'<p dir="ltr"><span data-lexical-text="true">a</span>' +
'<a href="https://" dir="ltr">' +
'<span style="text-emphasis: filled;" data-lexical-text="true">link</span>' +
'</a>' +
'<span style="text-emphasis: filled;" data-lexical-text="true">b</span></p>',
);
});

test('can patch a selection anchored to the end of a TextNode at the end of a paragraph', async () => {
const editor = createTestEditor();
const element = document.createElement('div');
editor.setRootElement(element);

await editor.update(() => {
const root = $getRoot();

const paragraph1 = createParagraphWithNodes(editor, [
{
key: 'a',
mergeable: false,
text: 'a',
},
]);
const paragraph2 = createParagraphWithNodes(editor, [
{
key: 'b',
mergeable: false,
text: 'b',
},
]);

root.append(paragraph1);
root.append(paragraph2);

setAnchorPoint({
key: 'a',
offset: 1,
type: 'text',
});
setFocusPoint({
key: 'b',
offset: 1,
type: 'text',
});

const selection = $getSelection() as RangeSelection;
$patchStyleText(selection, {'text-emphasis': 'filled'});
});

expect(element.innerHTML).toBe(
'<p dir="ltr"><span data-lexical-text="true">a</span></p>' +
'<p dir="ltr"><span style="text-emphasis: filled;" data-lexical-text="true">b</span></p>',
);
});
});
5 changes: 4 additions & 1 deletion packages/lexical-selection/src/lexical-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,10 @@ export function $patchStyleText(
}
} // multiple nodes selected.
} else {
if ($isTextNode(firstNode)) {
if (
$isTextNode(firstNode) &&
startOffset < firstNode.getTextContentSize()
) {
if (startOffset !== 0) {
// the entire first node isn't selected, so split it
firstNode = firstNode.splitText(startOffset)[1];
Expand Down

0 comments on commit c2e4456

Please sign in to comment.