From 55fb1ab763d8b1ff977e210131f4044ce5a35e26 Mon Sep 17 00:00:00 2001 From: Gregor Weber Date: Tue, 20 Aug 2024 18:41:03 +0200 Subject: [PATCH] feat(extension-highlight): add paste rule --- packages/extension-highlight/src/highlight.ts | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/packages/extension-highlight/src/highlight.ts b/packages/extension-highlight/src/highlight.ts index 05b9f7635bf..b210136d37e 100644 --- a/packages/extension-highlight/src/highlight.ts +++ b/packages/extension-highlight/src/highlight.ts @@ -139,6 +139,49 @@ export const Highlight = Mark.create({ find: pasteRegex, type: this.type, }), + markPasteRule({ + find: (_, event) => { + const htmlStr = event?.clipboardData?.getData('text/html') + + if (!htmlStr) { + return + } + + const doc = new DOMParser().parseFromString(htmlStr, 'text/html') + + let indexAcc = 0 + + // skip if there are any paragraphs as it will make the character counting a lot harder + if (doc.querySelectorAll('p').length > 0) { + return + } + + return [...doc.querySelectorAll('span')].map(el => { + const color = el.style.backgroundColor + const text = el.textContent + const index = indexAcc + + if (!text) { + return + } + + // we only want to count text for elements which have the text node as a direct child + if (el.childNodes.length === 1 && el.childNodes[0].nodeType === Node.TEXT_NODE) { + indexAcc += text.length + } + if (!color || color === 'rgb(255, 255, 255)' || color === 'transparent') { + return + } + + return { text, data: { color }, index } + }).filter(m => !!m) + }, + type: this.type, + getAttributes: match => ({ + 'data-color': match.data?.color, + style: `background-color: ${match.data?.color}; color: inherit`, + }), + }), ] }, })