Skip to content

Commit

Permalink
Ignore whitespace between pasted empty paragraphs
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Feb 3, 2024
1 parent 6904758 commit df3549c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 15 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 18 additions & 15 deletions packages/quill/src/modules/clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down Expand Up @@ -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)
);
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 <o:p>&nbsp;</o:p>
Expand All @@ -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;
}
Expand All @@ -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));
}
Expand Down
12 changes: 12 additions & 0 deletions packages/quill/test/unit/modules/clipboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,18 @@ describe('Clipboard', () => {
expect(delta).toEqual(new Delta().insert('foo\nbar'));
});

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

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

test('break', () => {
const html =
'<div>0<br>1</div><div>2<br></div><div>3</div><div><br>4</div><div><br></div><div>5</div>';
Expand Down

0 comments on commit df3549c

Please sign in to comment.