Skip to content

Commit

Permalink
Merge pull request #163 from daniel-eder/master
Browse files Browse the repository at this point in the history
Fix pasting bullet and ordered lists from Word into Memcode editor
  • Loading branch information
lakesare authored Aug 2, 2022
2 parents 58916b6 + 96f48d7 commit a7c360b
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
9 changes: 7 additions & 2 deletions frontend/components/Editor/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import standardToolbarContainer from '~/services/quill/standardToolbarContainer';
import dropOrPasteImageHandler from '~/services/quill/handlers/dropOrPasteImageHandler';
import msWordPasteMatchers from '~/services/quill/msWordPasteMatchers';
import uploadImageHandler from '~/services/quill/handlers/uploadImageHandler';
import markAsAnswerHandler from '~/services/quill/handlers/markAsAnswerHandler';
import codeBlockHandler from '~/services/quill/handlers/codeBlockHandler';
Expand Down Expand Up @@ -208,8 +209,12 @@ class Editor extends React.Component {
bindings
},

// https://github.com/zenoamaro/react-quill/issues/250
clipboard: { matchVisual: false },
clipboard: {
// https://github.com/zenoamaro/react-quill/issues/250
matchVisual: false,
// https://github.com/lakesare/memcode/pull/163
matchers: msWordPasteMatchers
},
imageResize: {
modules: ['Resize']
},
Expand Down
52 changes: 52 additions & 0 deletions frontend/services/quill/msWordPasteMatchers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// See https://github.com/quilljs/quill/issues/1225#issuecomment-1000785590

import Delta from 'quill-delta';

function matchMsWordList(node, delta) {
// Clone the operations
let ops = delta.ops.map((op) => Object.assign({}, op));

// Trim the front of the first op to remove the bullet/number
let bulletOp = ops.find((op) => op.insert && op.insert.trim().length);
if (!bulletOp) { return delta }

bulletOp.insert = bulletOp.insert.trimLeft();
let listPrefix = bulletOp.insert.match(/^.*?(^·|\.)/) || bulletOp.insert[0];
bulletOp.insert = bulletOp.insert.substring(listPrefix[0].length, bulletOp.insert.length);

// Trim the newline off the last op
let last = ops[ops.length-1];
last.insert = last.insert.substring(0, last.insert.length - 1);

// Determine the list type
let listType = listPrefix[0].length === 1 ? 'bullet' : 'ordered';

// Determine the list indent
let style = node.getAttribute('style').replace(/\n+/g, '');
let levelMatch = style.match(/level(\d+)/);
let indent = levelMatch ? levelMatch[1] - 1 : 0;

// Add the list attribute
ops.push({insert: '\n', attributes: {list: listType, indent}})

return new Delta(ops);
}

function maybeMatchMsWordList(node, delta) {
if (delta.ops[0].insert.trimLeft()[0] === '·') {
return matchMsWordList(node, delta);
}

return delta;
}

const msWordPasteMatchers = [
['p.MsoListParagraphCxSpFirst', matchMsWordList],
['p.MsoListParagraphCxSpMiddle', matchMsWordList],
['p.MsoListParagraphCxSpLast', matchMsWordList],
['p.MsoListParagraph', matchMsWordList],
['p.msolistparagraph', matchMsWordList],
['p.MsoNormal', maybeMatchMsWordList]
];

export default msWordPasteMatchers;

0 comments on commit a7c360b

Please sign in to comment.