Skip to content

Commit

Permalink
[lexical-text] Bug Fix: for handling multiple matches on hashtags (#6056
Browse files Browse the repository at this point in the history
)
  • Loading branch information
2wheeh authored May 10, 2024
1 parent 6a33ccf commit 3fc9fb6
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
117 changes: 117 additions & 0 deletions packages/lexical-playground/__tests__/e2e/Hashtags.spec.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import {
import {
assertHTML,
assertSelection,
click,
focusEditor,
html,
initialize,
pasteFromClipboard,
pressToggleBold,
repeat,
test,
Expand Down Expand Up @@ -383,4 +385,119 @@ test.describe('Hashtags', () => {
`,
);
});

test('Can handle hashtags following multiple invalid hashtags', async ({
page,
}) => {
await focusEditor(page);
await page.keyboard.type('#hello');

await page.keyboard.press('Space');

await page.keyboard.type('#world');
await page.keyboard.type('#invalid');
await page.keyboard.type('#invalid');
await page.keyboard.type('#invalid');

await page.keyboard.press('Space');

await page.keyboard.type('#valid');

await page.keyboard.press('Space');

await page.keyboard.type('#valid');
await page.keyboard.type('#invalid');

await page.keyboard.press('Space');
await page.keyboard.type('#valid');

await waitForSelector(page, '.PlaygroundEditorTheme__hashtag');

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#hello
</span>
<span data-lexical-text="true"></span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#world
</span>
<span data-lexical-text="true">#invalid#invalid#invalid</span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#valid
</span>
<span data-lexical-text="true"></span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#valid
</span>
<span data-lexical-text="true">#invalid</span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#valid
</span>
</p>
`,
);
});

test('Should not break when pasting multiple matches', async ({
page,
isPlainText,
}) => {
test.skip(isPlainText);

await focusEditor(page);

const clipboard = {'text/html': '#hello#world'};
await pasteFromClipboard(page, clipboard);

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#hello
</span>
<span data-lexical-text="true">#world</span>
</p>
`,
);
});

test('Should not break while importing and exporting multiple matches', async ({
page,
}) => {
await focusEditor(page);
await page.keyboard.type('```markdown #hello#invalid #a #b');

await click(page, '.action-button .markdown');
await click(page, '.action-button .markdown');
await click(page, '.action-button .markdown');

await assertHTML(
page,
html`
<p
class="PlaygroundEditorTheme__paragraph PlaygroundEditorTheme__ltr"
dir="ltr">
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#hello
</span>
<span data-lexical-text="true">#invalid</span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#a
</span>
<span data-lexical-text="true"></span>
<span class="PlaygroundEditorTheme__hashtag" data-lexical-text="true">
#b
</span>
</p>
`,
);
});
});
8 changes: 8 additions & 0 deletions packages/lexical-text/src/registerLexicalTextEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
LexicalNode,
TextNode,
} from 'lexical';
import invariant from 'shared/invariant';

export type EntityMatch = {end: number; start: number};

Expand Down Expand Up @@ -151,6 +152,13 @@ export function registerLexicalTextEntity<T extends TextNode>(
match.end + prevMatchLengthToSkip,
);
}

invariant(
nodeToReplace !== undefined,
'%s should not be undefined. You may want to check splitOffsets passed to the splitText.',
'nodeToReplace',
);

const replacementNode = createNode(nodeToReplace);
replacementNode.setFormat(nodeToReplace.getFormat());
nodeToReplace.replace(replacementNode);
Expand Down
3 changes: 2 additions & 1 deletion scripts/error-codes/codes.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,6 @@
"161": "Unexpected dirty selection to be null",
"162": "Root element not registered",
"163": "node is not a ListNode",
"164": "Root element count less than 0"
"164": "Root element count less than 0",
"165": "%s should not be undefined. You may want to check splitOffsets passed to the splitText."
}

0 comments on commit 3fc9fb6

Please sign in to comment.