Conversation
📝 WalkthroughWalkthroughThis PR enhances paste handling in the Lexical editor's PlainTextPastePlugin by adding support for multiple clipboard MIME types (text/plain and text/uri-list) with newline and tab parsing logic. It includes comprehensive test coverage, adjusts markdown paragraph spacing, and adds React Query mocking for testing. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/drops/create/lexical/plugins/PlainTextPastePlugin.tsx (1)
70-86:⚠️ Potential issue | 🟠 MajorDon’t consume the paste event when no selection exists.
At Line 70,
preventDefault()runs before the null-check at Line 74. If selection is missing, this handler still returnstrueand the paste is lost.💡 Proposed fix
- event.preventDefault(); - - editor.update(() => { + let handled = false; + editor.update(() => { const selection = $getSelection(); if (!selection) { return; } + handled = true; if ($isRangeSelection(selection)) { insertRangeSelectionText(selection, text); return; } selection.insertRawText(text); }); - - return true; + if (!handled) { + return false; + } + event.preventDefault(); + return true;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@components/drops/create/lexical/plugins/PlainTextPastePlugin.tsx` around lines 70 - 86, The paste handler currently calls event.preventDefault() before checking for a selection, causing the browser paste to be swallowed when $getSelection() is null; move the preventDefault() call so it only executes when a valid selection exists and you're about to handle the paste (i.e., after obtaining selection inside editor.update and confirming selection is truthy), call preventDefault() then perform the existing $isRangeSelection -> insertRangeSelectionText or selection.insertRawText logic and return true; if selection is null do not preventDefault and return false (or allow the handler to fall through) so the native paste proceeds.
🧹 Nitpick comments (1)
__tests__/components/drops/create/lexical/plugins/PlainTextPastePlugin.test.tsx (1)
85-207: Add a null-selection test case to lock in paste fallback behavior.Since the plugin now guards
!selection, add a test that verifies handler return value andpreventDefaultbehavior when$getSelection()returnsnull.✅ Suggested test case
+ it("does not consume paste when selection is missing", () => { + renderPlugin(); + ($getSelection as jest.Mock).mockReturnValue(null); + + const { event, preventDefault } = createClipboardEvent({ text: "hello" }); + const handled = getCommandHandler()(event); + + expect(handled).toBe(false); + expect(preventDefault).not.toHaveBeenCalled(); + });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@__tests__/components/drops/create/lexical/plugins/PlainTextPastePlugin.test.tsx` around lines 85 - 207, Add a new test that mocks ($getSelection as jest.Mock).mockReturnValue(null) and then calls the paste command handler from getCommandHandler() to verify the plugin returns false and does not call event.preventDefault; specifically, in the new it block call renderPlugin(), create a clipboard event via createClipboardEvent({...}) (or empty), pass its event into getCommandHandler()(event), assert handled === false and that preventDefault was not called to lock in the !selection guard. Reference $getSelection and getCommandHandler in the test to locate where to change/add the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@components/drops/create/lexical/plugins/PlainTextPastePlugin.tsx`:
- Around line 70-86: The paste handler currently calls event.preventDefault()
before checking for a selection, causing the browser paste to be swallowed when
$getSelection() is null; move the preventDefault() call so it only executes when
a valid selection exists and you're about to handle the paste (i.e., after
obtaining selection inside editor.update and confirming selection is truthy),
call preventDefault() then perform the existing $isRangeSelection ->
insertRangeSelectionText or selection.insertRawText logic and return true; if
selection is null do not preventDefault and return false (or allow the handler
to fall through) so the native paste proceeds.
---
Nitpick comments:
In
`@__tests__/components/drops/create/lexical/plugins/PlainTextPastePlugin.test.tsx`:
- Around line 85-207: Add a new test that mocks ($getSelection as
jest.Mock).mockReturnValue(null) and then calls the paste command handler from
getCommandHandler() to verify the plugin returns false and does not call
event.preventDefault; specifically, in the new it block call renderPlugin(),
create a clipboard event via createClipboardEvent({...}) (or empty), pass its
event into getCommandHandler()(event), assert handled === false and that
preventDefault was not called to lock in the !selection guard. Reference
$getSelection and getCommandHandler in the test to locate where to change/add
the test.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
__tests__/components/drops/create/lexical/plugins/PlainTextPastePlugin.test.tsx__tests__/components/drops/view/part/DropPartMarkdown.test.tsxcomponents/drops/create/lexical/plugins/PlainTextPastePlugin.tsxcomponents/drops/view/part/dropPartMarkdown/content.tsx

Summary by CodeRabbit
New Features
Style