Skip to content

Commit

Permalink
Fix white spaces not being preserved when pasted into editor
Browse files Browse the repository at this point in the history
  • Loading branch information
luin committed Jul 18, 2024
1 parent 5d752e3 commit 2f59bea
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 10 deletions.
50 changes: 40 additions & 10 deletions packages/quill/src/modules/clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,18 +364,48 @@ function isBetweenInlineElements(node: HTMLElement, scroll: ScrollBlot) {
);
}

const preNodes = new WeakMap();
function isPre(node: Node | null) {
if (node == null) return false;
if (!preNodes.has(node)) {
// @ts-expect-error
enum WhiteSpaceStyle {
Collapsed,
Preserved,
Inherited,
}
const getWhiteSpaceStyle = (node: Node) => {
if (node instanceof HTMLElement) {
const { whiteSpace } = node.style;
if (
whiteSpace === 'pre' ||
whiteSpace === 'pre-wrap' ||
whiteSpace === 'break-spaces'
) {
return WhiteSpaceStyle.Preserved;
}
if (whiteSpace && whiteSpace !== 'inherit') {
return WhiteSpaceStyle.Collapsed;
}
if (node.tagName === 'PRE') {
preNodes.set(node, true);
} else {
preNodes.set(node, isPre(node.parentNode));
return WhiteSpaceStyle.Preserved;
}
}
return preNodes.get(node);
return WhiteSpaceStyle.Inherited;
};

const whiteSpacePreservationMap = new WeakMap();
function getShouldPreserveWhiteSpaces(node: Node | null) {
if (node == null) return false;

if (!whiteSpacePreservationMap.has(node)) {
let shouldPreserve = false;

const style = getWhiteSpaceStyle(node);
if (style === WhiteSpaceStyle.Preserved) {
shouldPreserve = true;
} else if (style === WhiteSpaceStyle.Inherited) {
shouldPreserve = getShouldPreserveWhiteSpaces(node.parentNode);
}

whiteSpacePreservationMap.set(node, shouldPreserve);
}
return whiteSpacePreservationMap.get(node);
}

function traverse(
Expand Down Expand Up @@ -631,7 +661,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot) {
if (node.parentElement?.tagName === 'O:P') {
return delta.insert(text.trim());
}
if (!isPre(node)) {
if (!getShouldPreserveWhiteSpaces(node)) {
if (
text.trim().length === 0 &&
text.includes('\n') &&
Expand Down
16 changes: 16 additions & 0 deletions packages/quill/test/unit/modules/clipboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,22 @@ describe('Clipboard', () => {
);
});

test('white-space', () => {
const html = '<span style="white-space:pre">0 1</span>';
expect(createClipboard().convert({ html })).toEqual(
new Delta().insert('0 1'),
);
});

test('white-space with nested levels', () => {
const html = `
<div style="white-space:pre"><span>0 1</span><span style="white-space:normal">0 1</span><span style="white-space:inherit">0 1</span></div>
`;
expect(createClipboard().convert({ html })).toEqual(
new Delta().insert('0 10 10 1'),
);
});

test('nested list', () => {
const delta = createClipboard().convert({
html: '<ol><li>One</li><li class="ql-indent-1">Alpha</li></ol>',
Expand Down

0 comments on commit 2f59bea

Please sign in to comment.