From 5e612f4e0c0040ea38ddfd35446d032e0048d190 Mon Sep 17 00:00:00 2001 From: Zihua Li <635902+luin@users.noreply.github.com> Date: Wed, 17 Jul 2024 23:24:07 +0800 Subject: [PATCH] Fix white spaces not being preserved when pasted into editor --- packages/quill/src/modules/clipboard.ts | 47 +++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/packages/quill/src/modules/clipboard.ts b/packages/quill/src/modules/clipboard.ts index e4c3f755b5..6884686310 100644 --- a/packages/quill/src/modules/clipboard.ts +++ b/packages/quill/src/modules/clipboard.ts @@ -365,14 +365,47 @@ function isBetweenInlineElements(node: HTMLElement, scroll: ScrollBlot) { } const preNodes = new WeakMap(); -function isPre(node: Node | null) { + +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') { + return WhiteSpaceStyle.Preserved; + } + } + return WhiteSpaceStyle.Inherited; +}; + +function shouldPreserveWhiteSpaces(node: Node | null) { if (node == null) return false; + if (!preNodes.has(node)) { - // @ts-expect-error - if (node.tagName === 'PRE') { - preNodes.set(node, true); - } else { - preNodes.set(node, isPre(node.parentNode)); + const type = getWhiteSpaceStyle(node); + switch (type) { + case WhiteSpaceStyle.Preserved: + preNodes.set(node, true); + break; + case WhiteSpaceStyle.Collapsed: + preNodes.set(node, false); + break; + case WhiteSpaceStyle.Inherited: + preNodes.set(node, shouldPreserveWhiteSpaces(node.parentNode)); + break; } } return preNodes.get(node); @@ -631,7 +664,7 @@ function matchText(node: HTMLElement, delta: Delta, scroll: ScrollBlot) { if (node.parentElement?.tagName === 'O:P') { return delta.insert(text.trim()); } - if (!isPre(node)) { + if (!shouldPreserveWhiteSpaces(node)) { if ( text.trim().length === 0 && text.includes('\n') &&