Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 81 additions & 25 deletions packages/lexical-playground/__tests__/e2e/Composition.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
moveLeft,
moveToLineBeginning,
pressBackspace,
selectAll,
selectCharacters,
toggleBold,
} from '../keyboardShortcuts/index.mjs';
import {
assertHTML,
Expand Down Expand Up @@ -830,34 +832,19 @@ test.describe('Composition', () => {
text: 'もじあ',
});

if (browserName === 'webkit') {
await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph" dir="auto">
<span data-lexical-text="true">
Luke &nbsp;すし もじあSkywalker
</span>
</p>
`,
);
}
/* eslint-disable no-irregular-whitespace */
if (browserName === 'chromium') {
await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph" dir="auto">
<span data-lexical-text="true">Luke ​すし もじあSkywalker</span>
</p>
`,
);
}
await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph" dir="auto">
<span data-lexical-text="true">Luke すし もじあSkywalker</span>
</p>
`,
);

await assertSelection(page, {
anchorOffset: 12,
anchorOffset: 11,
anchorPath: [0, 0, 0],
focusOffset: 12,
focusOffset: 11,
focusPath: [0, 0, 0],
});
});
Expand Down Expand Up @@ -1334,6 +1321,75 @@ test.describe('Composition', () => {

expect(isTypeaheadMenuDisplayedDuringIMEComposition).toBe(true);
});

test('Can replace multiple formatted text nodes with IME composition (Korean)', async ({
page,
browserName,
isPlainText,
}) => {
// We don't yet support FF.
test.skip(browserName !== 'chromium' || isPlainText);

await focusEditor(page);
await enableCompositionKeyEvents(page);

await page.keyboard.type('helloworld');

await moveLeft(page, 10);
await selectCharacters(page, 'right', 5);
await toggleBold(page);

await selectAll(page);

const client = await page.context().newCDPSession(page);

await client.send('Input.imeSetComposition', {
selectionEnd: 1,
selectionStart: 1,
text: 'ㄱ',
});
await client.send('Input.imeSetComposition', {
selectionEnd: 1,
selectionStart: 1,
text: '가',
});
await client.send('Input.imeSetComposition', {
selectionEnd: 2,
selectionStart: 2,
text: '가ㄴ',
});
await client.send('Input.imeSetComposition', {
selectionEnd: 2,
selectionStart: 2,
text: '가나',
});
await client.send('Input.imeSetComposition', {
selectionEnd: 3,
selectionStart: 3,
text: '가나ㄷ',
});
await client.send('Input.imeSetComposition', {
selectionEnd: 3,
selectionStart: 3,
text: '가나다',
});
await client.send('Input.insertText', {
text: '가나다',
});

await assertHTML(
page,
html`
<p class="PlaygroundEditorTheme__paragraph" dir="auto">
<strong
class="PlaygroundEditorTheme__textBold"
data-lexical-text="true">
가나다
</strong>
</p>
`,
);
});
});
/* eslint-enable sort-keys-fix/sort-keys-fix */
});
Original file line number Diff line number Diff line change
Expand Up @@ -342,13 +342,15 @@ test.describe('HTML Tables CopyAndPaste', () => {
</colgroup>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader PlaygroundEditorTheme__tableCellSelected">
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
style="background-color: rgb(242, 243, 245)">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">a</span>
</p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader PlaygroundEditorTheme__tableCellSelected">
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
style="background-color: rgb(242, 243, 245)">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">b</span>
</p>
Expand All @@ -364,7 +366,8 @@ test.describe('HTML Tables CopyAndPaste', () => {
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader PlaygroundEditorTheme__tableCellSelected">
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader"
style="background-color: rgb(242, 243, 245)">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">c</span>
</p>
Expand Down Expand Up @@ -425,89 +428,6 @@ test.describe('HTML Tables CopyAndPaste', () => {
</table>
<p class="PlaygroundEditorTheme__paragraph" dir="auto"><br /></p>
`,
html`
<p class="PlaygroundEditorTheme__paragraph" dir="auto"><br /></p>
<table class="PlaygroundEditorTheme__table" dir="auto">
<colgroup>
<col style="width: 92px" />
<col style="width: 92px" />
<col style="width: 92px" />
<col style="width: 92px" />
</colgroup>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">a</span>
</p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">b</span>
</p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">c</span>
</p>
</th>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph">
<span data-lexical-text="true">d</span>
</p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
<tr>
<th
class="PlaygroundEditorTheme__tableCell PlaygroundEditorTheme__tableCellHeader">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</th>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
<td class="PlaygroundEditorTheme__tableCell">
<p class="PlaygroundEditorTheme__paragraph"><br /></p>
</td>
</tr>
</table>
<p class="PlaygroundEditorTheme__paragraph" dir="auto"><br /></p>
`,
);
});

Expand Down
4 changes: 4 additions & 0 deletions packages/lexical-table/src/LexicalTablePluginHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,10 @@ function $insertTableIntoGrid(
}

const {cell} = interimGridMap[row][col];
const backgroundColor = templateCell.getBackgroundColor();
if (backgroundColor !== null && backgroundColor !== undefined) {
cell.setBackgroundColor(backgroundColor);
}
const originalChildren = cell.getChildren();
templateCell.getChildren().forEach((child) => {
if ($isTextNode(child)) {
Expand Down
40 changes: 27 additions & 13 deletions packages/lexical/src/LexicalEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
$getSelection,
$isDecoratorNode,
$isElementNode,
$isNodeSelection,
$isRangeSelection,
$isRootNode,
$isTextNode,
Expand All @@ -47,6 +48,7 @@ import {
DROP_COMMAND,
FOCUS_COMMAND,
FORMAT_TEXT_COMMAND,
HISTORY_MERGE_TAG,
INSERT_LINE_BREAK_COMMAND,
INSERT_PARAGRAPH_COMMAND,
KEY_ARROW_DOWN_COMMAND,
Expand Down Expand Up @@ -87,6 +89,7 @@ import {
} from './LexicalSelection';
import {getActiveEditor, updateEditorSync} from './LexicalUpdates';
import {
$addUpdateTag,
$findMatchingParent,
$flushMutations,
$getAdjacentNode,
Expand Down Expand Up @@ -1006,6 +1009,9 @@ function $handleInput(event: InputEvent): boolean {
getAnchorTextFromDOM(domSelection.anchorNode)
) {
dispatchCommand(editor, CONTROLLED_TEXT_INSERTION_COMMAND, data);
if (editor.isComposing()) {
$addUpdateTag(HISTORY_MERGE_TAG);
}
}

const textLength = data.length;
Expand All @@ -1022,7 +1028,7 @@ function $handleInput(event: InputEvent): boolean {
}

// This ensures consistency on Android.
if (!IS_SAFARI && !IS_IOS && !IS_APPLE_WEBKIT && editor.isComposing()) {
if (IS_ANDROID_CHROME && editor.isComposing()) {
lastKeyDownTimeStamp = 0;
$setCompositionKey(null);
}
Expand Down Expand Up @@ -1090,6 +1096,7 @@ function $handleCompositionStart(event: CompositionEvent): boolean {
function $handleCompositionEnd(event: CompositionEvent): boolean {
const editor = getActiveEditor();
$onCompositionEndImpl(editor, event.data);
$addUpdateTag(HISTORY_MERGE_TAG);
return true;
}

Expand All @@ -1103,35 +1110,42 @@ function $onCompositionEndImpl(editor: LexicalEditor, data?: string): void {
// So check for the empty case.
if (data === '') {
const node = $getNodeByKey(compositionKey);
const textNode = getDOMTextNode(editor.getElementByKey(compositionKey));
const domElement = editor.getElementByKey(compositionKey);
const textNode = getDOMTextNode(domElement);

if (
textNode !== null &&
textNode.nodeValue !== null &&
$isTextNode(node)
) {
const domSelection = getDOMSelection(getWindow(editor));
let anchorOffset = null;
let focusOffset = null;

if (domSelection !== null && domSelection.anchorNode === textNode) {
anchorOffset = domSelection.anchorOffset;
focusOffset = domSelection.focusOffset;
}

$updateTextNodeFromDOMContent(
node,
textNode.nodeValue,
null,
null,
anchorOffset,
focusOffset,
true,
);
}

return;
}

// Composition can sometimes be that of a new line. In which case, we need to
// handle that accordingly.
if (data[data.length - 1] === '\n') {
} else if (data[data.length - 1] === '\n') {
const selection = $getSelection();

if ($isRangeSelection(selection)) {
if ($isRangeSelection(selection) || $isNodeSelection(selection)) {
// If the last character is a line break, we also need to insert
// a line break.
const focus = selection.focus;
selection.anchor.set(focus.key, focus.offset, focus.type);
if ($isRangeSelection(selection)) {
const focus = selection.focus;
selection.anchor.set(focus.key, focus.offset, focus.type);
}
dispatchCommand(editor, KEY_ENTER_COMMAND, null);
return;
}
Expand Down
Loading
Loading