Skip to content

Commit

Permalink
fix: incorrect pasting if data copied from ms office has styling (#1258)
Browse files Browse the repository at this point in the history
  • Loading branch information
seonim-ryu committed Nov 18, 2020
1 parent 16203d1 commit 6ead334
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 36 deletions.
77 changes: 53 additions & 24 deletions apps/editor/src/js/utils/wwPasteMsoList.js
Original file line number Diff line number Diff line change
@@ -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)/;
Expand All @@ -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();
}
Expand Down Expand Up @@ -114,39 +125,57 @@ 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
*/
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;
}
18 changes: 6 additions & 12 deletions apps/editor/src/js/wwTablePasteHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

/**
Expand All @@ -156,10 +150,6 @@ class WwTablePasteHelper {
html = html.slice(startFragmentIndex + startFramgmentStr.length, endFragmentIndex);
}

if (isFromMso(html)) {
html = this._convertToMsoList(html);
}

// Wrap with <tr> if html contains dangling <td> tags
// Dangling <td> tag is that tag does not have <tr> as parent node.
if (/<\/td>((?!<\/tr>)[\s\S])*$/i.test(html)) {
Expand All @@ -171,6 +161,10 @@ class WwTablePasteHelper {
html = `<TABLE>${html}</TABLE>`;
}

if (isFromMso(html)) {
html = this._convertToMsoList(html);
}

container.appendChild(this._getSanitizedHtml(html));
this._pasteClipboardContainer(container);
}
Expand Down

0 comments on commit 6ead334

Please sign in to comment.