Skip to content

Commit

Permalink
Convert non-breaking spaces to regular spaces
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Aug 27, 2024
1 parent b213e10 commit 08522f8
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 14 deletions.
14 changes: 7 additions & 7 deletions packages/quill/src/modules/clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,9 @@ function matchTable(
return delta;
}

const NBSP = '\u00a0';
const SPACE_EXCLUDE_NBSP = `[^\\S${NBSP}]`;

function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot) {
// @ts-expect-error
let text = node.data;
Expand All @@ -639,29 +642,26 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot) {
) {
return delta;
}
const replacer = (collapse: unknown, match: string) => {
const replaced = match.replace(/[^\u00a0]/g, ''); // \u00a0 is nbsp;
return replaced.length < 1 && collapse ? ' ' : replaced;
};
text = text.replace(/\r\n/g, ' ').replace(/\n/g, ' ');
text = text.replace(/\s\s+/g, replacer.bind(replacer, true)); // collapse whitespace
text = text.replace(new RegExp(`${SPACE_EXCLUDE_NBSP}{2,}`, 'g'), ' '); // collapse whitespace
if (
(node.previousSibling == null &&
node.parentElement != null &&
isLine(node.parentElement, scroll)) ||
(node.previousSibling instanceof Element &&
isLine(node.previousSibling, scroll))
) {
text = text.replace(/^\s+/, replacer.bind(replacer, false));
text = text.replace(new RegExp(`^${SPACE_EXCLUDE_NBSP}+`), '');
}
if (
(node.nextSibling == null &&
node.parentElement != null &&
isLine(node.parentElement, scroll)) ||
(node.nextSibling instanceof Element && isLine(node.nextSibling, scroll))
) {
text = text.replace(/\s+$/, replacer.bind(replacer, false));
text = text.replace(new RegExp(`${SPACE_EXCLUDE_NBSP}+$`), '');
}
text = text.replaceAll(NBSP, ' ');
}
return delta.insert(text);
}
Expand Down
24 changes: 17 additions & 7 deletions packages/quill/test/unit/modules/clipboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,12 @@ describe('Clipboard', () => {
expect(delta).toEqual(new Delta().insert('0\n1 2 3 4\n5 6 7 8'));
});

test('multiple whitespaces', () => {
const html = '<div>1 2 3</div>';
const delta = createClipboard().convert({ html });
expect(delta).toEqual(new Delta().insert('1 2 3'));
});

test('inline whitespace', () => {
const html = '<p>0 <strong>1</strong> 2</p>';
const delta = createClipboard().convert({ html });
Expand All @@ -256,19 +262,23 @@ describe('Clipboard', () => {
const html = '<span>0&nbsp;<strong>1</strong>&nbsp;2</span>';
const delta = createClipboard().convert({ html });
expect(delta).toEqual(
new Delta()
.insert('0\u00a0')
.insert('1', { bold: true })
.insert('\u00a02'),
new Delta().insert('0 ').insert('1', { bold: true }).insert(' 2'),
);
});

test('consecutive intentional whitespace', () => {
const html = '<strong>&nbsp;&nbsp;1&nbsp;&nbsp;</strong>';
const delta = createClipboard().convert({ html });
expect(delta).toEqual(
new Delta().insert('\u00a0\u00a01\u00a0\u00a0', { bold: true }),
);
expect(delta).toEqual(new Delta().insert(' 1 ', { bold: true }));
});

test('intentional whitespace at line start/end', () => {
expect(
createClipboard().convert({ html: '<p>0 &nbsp;</p><p>&nbsp; 2</p>' }),
).toEqual(new Delta().insert('0 \n 2'));
expect(
createClipboard().convert({ html: '<p>0&nbsp; </p><p> &nbsp;2</p>' }),
).toEqual(new Delta().insert('0 \n 2'));
});

test('newlines between inline elements', () => {
Expand Down

0 comments on commit 08522f8

Please sign in to comment.