diff --git a/apps/editor/src/js/utils/wwPasteMsoList.js b/apps/editor/src/js/utils/wwPasteMsoList.js index bf9f9dad2d..10afc4e649 100644 --- a/apps/editor/src/js/utils/wwPasteMsoList.js +++ b/apps/editor/src/js/utils/wwPasteMsoList.js @@ -1,8 +1,8 @@ import domUtils from './dom'; +const MSO_CLASS_NAME_LIST_PARA = 'p.MsoListParagraph'; const MSO_CLASS_NAME_LIST_RX = /MsoListParagraph/; -const MSO_CLASS_NAME_NORMAL_RX = /MsoNormal/; -const MSO_STYLE_PREFIX_RX = /style=.*mso-/; +const MSO_STYLE_PREFIX_RX = /style=(.|\n)*mso-/; const MSO_STYLE_LIST_RX = /mso-list:(.*)/; const MSO_TAG_NAME_RX = /O:P/; const UNORDERED_LIST_BULLET_RX = /^(n|u|l)/; @@ -24,15 +24,26 @@ function getListItemContents(para) { while (walker.nextNode()) { const node = walker.currentNode; - if ( - domUtils.isElemNode(node) && - (isFromMso(node.outerHTML) || MSO_TAG_NAME_RX.test(node.nodeName)) - ) { - removedNodes.push(node); + if (domUtils.isElemNode(node)) { + const { outerHTML, textContent } = node; + const msoSpan = MSO_STYLE_PREFIX_RX.test(outerHTML); + const bulletSpan = MSO_STYLE_LIST_RX.test(outerHTML); + + if (msoSpan && !bulletSpan && textContent) { + removedNodes.push([node, true]); + } else if (MSO_TAG_NAME_RX.test(node.nodeName) || (msoSpan && !textContent) || bulletSpan) { + removedNodes.push([node, false]); + } } } - removedNodes.forEach(domUtils.remove); + removedNodes.forEach(([node, isUnwrap]) => { + if (isUnwrap) { + domUtils.unwrap(node); + } else { + domUtils.remove(node); + } + }); return para.innerHTML.trim(); } @@ -114,13 +125,30 @@ function makeList(listData) { return list; } -function makeListFromParagraphs(paras) { +export function makeListFromParagraphs(paras) { const listData = createListData(paras); const rootChildren = listData.filter(({ parent }) => !parent); return makeList(rootChildren); } +function isMsoParagraphEnd(node) { + let nextSibling = node; + + while (nextSibling) { + if (domUtils.isElemNode(nextSibling)) { + break; + } + nextSibling = nextSibling.nextSibling; + } + + if (nextSibling) { + return !MSO_CLASS_NAME_LIST_RX.test(nextSibling.className); + } + + return true; +} + /** * Convert pargraphs of ms office to standard list element * @param {HTMLElement} container - container element to convert to list @@ -128,25 +156,26 @@ function makeListFromParagraphs(paras) { export function convertMsoParagraphsToList(container) { let paras = []; - domUtils.findAll(container, 'p').forEach(para => { - const { className, nextSibling } = para; + domUtils.findAll(container, MSO_CLASS_NAME_LIST_PARA).forEach(para => { + const msoParaEnd = isMsoParagraphEnd(para.nextSibling); - if (MSO_CLASS_NAME_LIST_RX.test(className)) { - paras.push(para); + paras.push(para); - if (!nextSibling || (nextSibling && MSO_CLASS_NAME_NORMAL_RX.test(nextSibling.className))) { - const list = makeListFromParagraphs(paras); - const target = nextSibling || container; + if (msoParaEnd) { + const list = makeListFromParagraphs(paras); + const { nextSibling } = para; - if (nextSibling) { - domUtils.prepend(target, list); - } else { - domUtils.append(target, list); - } - - paras.forEach(domUtils.remove); - paras = []; + if (nextSibling) { + domUtils.insertBefore(list, nextSibling); + } else { + domUtils.append(container, list); } + + paras = []; } + + domUtils.remove(para); }); + + return container; } diff --git a/apps/editor/src/js/wwTablePasteHelper.js b/apps/editor/src/js/wwTablePasteHelper.js index 8bbf8d7a75..886c9aa2d4 100644 --- a/apps/editor/src/js/wwTablePasteHelper.js +++ b/apps/editor/src/js/wwTablePasteHelper.js @@ -129,15 +129,9 @@ class WwTablePasteHelper { container.innerHTML = html; - const pTagsContainer = document.createElement('div'); + convertMsoParagraphsToList(container); - domUtils.findAll(container, 'p').forEach(pTag => { - pTagsContainer.appendChild(pTag); - }); - - convertMsoParagraphsToList(pTagsContainer); - - return pTagsContainer.innerHTML; + return container.innerHTML; } /** @@ -156,10 +150,6 @@ class WwTablePasteHelper { html = html.slice(startFragmentIndex + startFramgmentStr.length, endFragmentIndex); } - if (isFromMso(html)) { - html = this._convertToMsoList(html); - } - // Wrap with if html contains dangling tags // Dangling tag is that tag does not have as parent node. if (/<\/td>((?!<\/tr>)[\s\S])*$/i.test(html)) { @@ -171,6 +161,10 @@ class WwTablePasteHelper { html = `${html}
`; } + if (isFromMso(html)) { + html = this._convertToMsoList(html); + } + container.appendChild(this._getSanitizedHtml(html)); this._pasteClipboardContainer(container); }