diff --git a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts index 739944f8c7..a232f97a88 100644 --- a/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts +++ b/services/web/frontend/js/features/source-editor/extensions/visual/paste-html.ts @@ -581,8 +581,19 @@ const selectors = [ }), createSelector({ selector: 'p', - match: element => - element.nextElementSibling?.nodeName === 'P' && hasContent(element), + match: element => { + // must have content + if (!hasContent(element)) { + return false + } + + // inside lists and tables, must precede another paragraph + if (element.closest('li') || element.closest('table')) { + return element.nextElementSibling?.nodeName === 'P' + } + + return true + }, end: () => '\n\n', }), createSelector({ diff --git a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx index ba78917323..651c97bc14 100644 --- a/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx +++ b/services/web/test/frontend/features/source-editor/components/codemirror-editor-visual-paste-html.spec.tsx @@ -270,6 +270,48 @@ describe(' paste HTML in Visual mode', function () { ) }) + it('handles pasted paragraphs', function () { + mountEditor() + + const data = [ + 'test', + '

foo

', + '

bar

', + '

baz

', + 'test', + ].join('\n') + + const clipboardData = new DataTransfer() + clipboardData.setData('text/html', data) + cy.get('@content').trigger('paste', { clipboardData }) + + cy.get('@content').should('have.text', 'testfoobarbaztest') + cy.get('.cm-line').should('have.length', 8) + }) + + it('handles pasted paragraphs in list items and table cells', function () { + mountEditor() + + const data = [ + 'test', + '

foo

bar

baz

', + '', + '
  1. foo

', + '

foo

', + 'test', + ].join('\n') + + const clipboardData = new DataTransfer() + clipboardData.setData('text/html', data) + cy.get('@content').trigger('paste', { clipboardData }) + + cy.get('@content').should( + 'have.text', + 'testfoobarbaz foo foo\\begin{tabular}{l}foo ↩\\end{tabular}test' + ) + cy.get('.cm-line').should('have.length', 17) + }) + it('handles pasted inline code', function () { mountEditor()