From 9d7feb9796e4b76e01f4ac2d0cb117bb091aa3d5 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 21 Oct 2021 18:38:34 -0400 Subject: [PATCH] fix: rich text copy and paste now saves formatting properly --- .../field-types/RichText/plugins/withHTML.tsx | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/admin/components/forms/field-types/RichText/plugins/withHTML.tsx b/src/admin/components/forms/field-types/RichText/plugins/withHTML.tsx index 9659577211..dbaa1a75a4 100644 --- a/src/admin/components/forms/field-types/RichText/plugins/withHTML.tsx +++ b/src/admin/components/forms/field-types/RichText/plugins/withHTML.tsx @@ -13,7 +13,7 @@ const ELEMENT_TAGS = { IMG: (el) => ({ type: 'image', url: el.getAttribute('src') }), LI: () => ({ type: 'li' }), OL: () => ({ type: 'ol' }), - P: () => ({ type: 'paragraph' }), + P: () => ({ type: 'p' }), PRE: () => ({ type: 'code' }), UL: () => ({ type: 'ul' }), }; @@ -28,7 +28,7 @@ const TEXT_TAGS = { U: () => ({ underline: true }), }; -const deserialize = (el) => { +export const deserialize = (el) => { if (el.nodeType === 3) { return el.textContent; } if (el.nodeType !== 1) { @@ -37,6 +37,7 @@ const deserialize = (el) => { return '\n'; } + const { nodeName } = el; let parent = el; @@ -47,10 +48,15 @@ const deserialize = (el) => { ) { [parent] = el.childNodes; } - const children = Array.from(parent.childNodes) + + let children = Array.from(parent.childNodes) .map(deserialize) .flat(); + if (children.length === 0) { + children = [{ text: '' }]; + } + if (el.nodeName === 'BODY') { return jsx('fragment', {}, children); } @@ -65,21 +71,20 @@ const deserialize = (el) => { return children.map((child) => jsx('text', attrs, child)); } - return children; + return children.map((child) => (typeof child === 'string' + ? jsx('element', ELEMENT_TAGS.P(), [{ text: child }]) + : child)); }; const withHTML = (incomingEditor) => { - const { insertData, isInline, isVoid } = incomingEditor; + const { insertData } = incomingEditor; const editor = incomingEditor; - editor.isInline = (element) => (element.type === 'link' ? true : isInline(element)); - - editor.isVoid = (element) => (element.type === 'image' ? true : isVoid(element)); - editor.insertData = (data) => { const html = data.getData('text/html'); + if (html) { const parsed = new DOMParser().parseFromString(html, 'text/html'); const fragment = deserialize(parsed.body);