From 7296b25024c391c7877d66592f408cd64afad26f Mon Sep 17 00:00:00 2001 From: Zihua Li Date: Sat, 3 Feb 2024 12:55:53 +0800 Subject: [PATCH] Ignore whitespace between pasted empty paragraphs --- CHANGELOG.md | 1 + packages/quill/src/modules/clipboard.ts | 33 ++++++++++--------- .../quill/test/unit/modules/clipboard.spec.ts | 12 +++++++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 775506bd96..eb74c5b92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ - **Clipboard** Convert newlines between inline elements to a space. - **Clipboard** Avoid generating unsupported formats on paste. - **Clipboard** Improve support for pasting from Google Docs and Microsoft Word. +- **Clipboard** Ignore whitespace between pasted empty paragraphs. - **Syntax** Support highlight.js v10 and v11. # 2.0.0-beta.2 diff --git a/packages/quill/src/modules/clipboard.ts b/packages/quill/src/modules/clipboard.ts index e4a63cdf69..4f7243e298 100644 --- a/packages/quill/src/modules/clipboard.ts +++ b/packages/quill/src/modules/clipboard.ts @@ -294,8 +294,12 @@ function deltaEndsWith(delta: Delta, text: string) { return endText.slice(-1 * text.length) === text; } -function isLine(node: Element) { - if (node.childNodes.length === 0) return false; // Exclude embed blocks +function isLine(node: Node, scroll: ScrollBlot) { + if (!(node instanceof Element)) return false; + const match = scroll.query(node); + // @ts-expect-error + if (match && match.prototype instanceof EmbedBlot) return false; + return [ 'address', 'article', @@ -334,12 +338,12 @@ function isLine(node: Element) { ].includes(node.tagName.toLowerCase()); } -function isBetweenInlineElements(node: HTMLElement) { +function isBetweenInlineElements(node: HTMLElement, scroll: ScrollBlot) { return ( node.previousElementSibling && node.nextElementSibling && - !isLine(node.previousElementSibling) && - !isLine(node.nextElementSibling) + !isLine(node.previousElementSibling, scroll) && + !isLine(node.nextElementSibling, scroll) ); } @@ -525,15 +529,13 @@ function matchList(node: Node, delta: Delta, scroll: ScrollBlot) { function matchNewline(node: Node, delta: Delta, scroll: ScrollBlot) { if (!deltaEndsWith(delta, '\n')) { - // @ts-expect-error - if (isLine(node)) { + if (isLine(node, scroll)) { return delta.insert('\n'); } if (delta.length() > 0 && node.nextSibling) { let nextSibling: Node | null = node.nextSibling; while (nextSibling != null) { - // @ts-expect-error - if (isLine(nextSibling)) { + if (isLine(nextSibling, scroll)) { return delta.insert('\n'); } const match = scroll.query(nextSibling); @@ -596,7 +598,7 @@ function matchTable( return delta; } -function matchText(node: HTMLElement, delta: Delta) { +function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot) { // @ts-expect-error let text = node.data; // Word represents empty line with   @@ -607,7 +609,7 @@ function matchText(node: HTMLElement, delta: Delta) { if ( text.trim().length === 0 && text.includes('\n') && - !isBetweenInlineElements(node) + !isBetweenInlineElements(node, scroll) ) { return delta; } @@ -620,16 +622,17 @@ function matchText(node: HTMLElement, delta: Delta) { if ( (node.previousSibling == null && node.parentElement != null && - isLine(node.parentElement)) || - (node.previousSibling instanceof Element && isLine(node.previousSibling)) + isLine(node.parentElement, scroll)) || + (node.previousSibling instanceof Element && + isLine(node.previousSibling, scroll)) ) { text = text.replace(/^\s+/, replacer.bind(replacer, false)); } if ( (node.nextSibling == null && node.parentElement != null && - isLine(node.parentElement)) || - (node.nextSibling instanceof Element && isLine(node.nextSibling)) + isLine(node.parentElement, scroll)) || + (node.nextSibling instanceof Element && isLine(node.nextSibling, scroll)) ) { text = text.replace(/\s+$/, replacer.bind(replacer, false)); } diff --git a/packages/quill/test/unit/modules/clipboard.spec.ts b/packages/quill/test/unit/modules/clipboard.spec.ts index a39fac08dd..35c5ec8b67 100644 --- a/packages/quill/test/unit/modules/clipboard.spec.ts +++ b/packages/quill/test/unit/modules/clipboard.spec.ts @@ -262,6 +262,18 @@ describe('Clipboard', () => { expect(delta).toEqual(new Delta().insert('foo\nbar')); }); + test('space between empty paragraphs', () => { + const html = '

'; + const delta = createClipboard().convert({ html }); + expect(delta).toEqual(new Delta().insert('\n')); + }); + + test('newline between empty paragraphs', () => { + const html = '

\n

'; + const delta = createClipboard().convert({ html }); + expect(delta).toEqual(new Delta().insert('\n')); + }); + test('break', () => { const html = '
0
1
2
3

4

5
';