Skip to content

Commit

Permalink
Remove custom diff logic in favor of improved Delta#diff
Browse files Browse the repository at this point in the history
  • Loading branch information
dgreensp committed Oct 9, 2018
1 parent 303d73f commit c5c7ca6
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 91 deletions.
92 changes: 8 additions & 84 deletions core/editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,13 @@ class Editor {
const oldValue = mutations[0].oldValue.replace(CursorBlot.CONTENTS, '');
const oldText = new Delta().insert(oldValue);
const newText = new Delta().insert(textBlot.value());
const relativeSelectionInfo = selectionInfo && [
new Range(selectionInfo[0].index - index, selectionInfo[0].length),
new Range(selectionInfo[1].index - index, selectionInfo[1].length),
];
const relativeSelectionInfo = selectionInfo && {
oldRange: shiftRange(selectionInfo.oldRange, -index),
newRange: shiftRange(selectionInfo.newRange, -index),
};
const diffDelta = new Delta()
.retain(index)
.concat(diffDeltas(oldText, newText, relativeSelectionInfo));
.concat(oldText.diff(newText, relativeSelectionInfo));
change = diffDelta.reduce((delta, op) => {
if (op.insert) {
return delta.insert(op.insert, formats);
Expand All @@ -224,7 +224,7 @@ class Editor {
} else {
this.delta = this.getDelta();
if (!change || !equal(oldDelta.compose(change), this.delta)) {
change = diffDeltas(oldDelta, this.delta, selectionInfo);
change = oldDelta.diff(this.delta, selectionInfo);
}
}
return change;
Expand Down Expand Up @@ -339,84 +339,8 @@ function normalizeDelta(delta) {
}, new Delta());
}

function splitDelta(delta, index) {
return [delta.slice(0, index), delta.slice(index)];
}

function diffDeltas(oldDelta, newDelta, selectionInfo = undefined) {
if (selectionInfo == null) {
return oldDelta.diff(newDelta);
}

// generate better diffs than Delta#diff by taking into account the
// old and new selection. for example, a text change from "xxx" to "xx"
// could be a delete or forwards-delete of any one of the x's, or the
// result of selecting two of the x's and typing "x".
const [oldSelection, newSelection] = selectionInfo;
const oldDeltaLength = oldDelta.length();
const newDeltaLength = newDelta.length();
if (oldSelection.length === 0 && newSelection.length === 0) {
// see if we have an insert or delete before or after cursor
const oldCursor = oldSelection.index;
const newCursor = newSelection.index;
const [oldBefore, oldAfter] = splitDelta(oldDelta, oldCursor);
const [newBefore, newAfter] = splitDelta(newDelta, newCursor);
if (equal(oldAfter, newAfter)) {
const prefixLength = Math.min(oldCursor, newCursor);
const [oldPrefix, oldMiddle] = splitDelta(oldBefore, prefixLength);
const [newPrefix, newMiddle] = splitDelta(newBefore, prefixLength);
if (equal(oldPrefix, newPrefix)) {
// insert or delete right before cursor
return new Delta()
.retain(prefixLength)
.concat(oldMiddle.diff(newMiddle));
}
} else if (equal(oldBefore, newBefore)) {
const suffixLength = Math.min(
oldDeltaLength - oldCursor,
newDeltaLength - newCursor,
);
const [oldMiddle, oldSuffix] = splitDelta(
oldAfter,
oldDeltaLength - oldCursor - suffixLength,
);
const [newMiddle, newSuffix] = splitDelta(
newAfter,
newDeltaLength - newCursor - suffixLength,
);
if (equal(oldSuffix, newSuffix)) {
// insert or delete right after cursor
return new Delta().retain(oldCursor).concat(oldMiddle.diff(newMiddle));
}
}
}
if (oldSelection.length > 0 && newSelection.length === 0) {
// see if diff could be a splice of the old selection range
const oldPrefix = oldDelta.slice(0, oldSelection.index);
const oldSuffix = oldDelta.slice(oldSelection.index + oldSelection.length);
const prefixLength = oldPrefix.length();
const suffixLength = oldSuffix.length();
if (newDeltaLength >= prefixLength + suffixLength) {
const newPrefix = newDelta.slice(0, prefixLength);
const newSuffix = newDelta.slice(newDeltaLength - suffixLength);
if (equal(oldPrefix, newPrefix) && equal(oldSuffix, newSuffix)) {
const oldMiddle = oldDelta.slice(
prefixLength,
oldDeltaLength - suffixLength,
);
const newMiddle = newDelta.slice(
prefixLength,
newDeltaLength - suffixLength,
);
return new Delta()
.retain(prefixLength)
.concat(newMiddle)
.delete(oldMiddle.length());
}
}
}

return oldDelta.diff(newDelta);
function shiftRange({ index, length }, amount) {
return new Range(index + amount, length);
}

export default Editor;
2 changes: 1 addition & 1 deletion core/quill.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class Quill {
const oldRange = this.selection.lastRange;
const [newRange] = this.selection.getRange();
const selectionInfo =
oldRange && newRange ? [oldRange, newRange] : undefined;
oldRange && newRange ? { oldRange, newRange } : undefined;
modify.call(
this,
() => this.editor.update(null, mutations, selectionInfo),
Expand Down
16 changes: 11 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
"eventemitter3": "^3.1.0",
"extend": "^3.0.2",
"parchment": "quilljs/parchment#2674d396d363e3b4668111590426405e3754d1a0",
"quill-delta": "4.0.1"
"quill-delta": "4.1.0"
},
"devDependencies": {
"babel-core": "^6.26.3",
Expand Down

0 comments on commit c5c7ca6

Please sign in to comment.