@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
76 lines • 2.72 kB
JavaScript
import { Fragment } from '@atlaskit/editor-prosemirror/model';
/**
* Narrows a full-list replacement to the minimal changed range.
*
* Compares the old root list node with the new replacement fragment
* from both ends to find the first and last positions where they differ,
* then returns only the changed subrange.
*
* This reduces the scope of `tr.replaceWith()` so that remote cursors
* on unchanged items are preserved during collaborative editing.
*/
export function narrowReplacementRange(doc, rootListStart, rootListEnd, fragment, contentStartOffsets) {
var oldNode = doc.nodeAt(rootListStart);
var newNode = fragment.childCount === 1 ? fragment.firstChild : null;
if (!oldNode || !newNode || newNode.type !== oldNode.type) {
return {
start: rootListStart,
end: rootListEnd,
fragment: fragment,
adjustedContentStartOffsets: contentStartOffsets
};
}
var minChildCount = Math.min(oldNode.childCount, newNode.childCount);
var commonPrefixChildren = 0;
var prefixSize = 0;
for (var i = 0; i < minChildCount; i++) {
var oldChild = oldNode.child(i);
var newChild = newNode.child(i);
if (oldChild.eq(newChild)) {
commonPrefixChildren++;
prefixSize += oldChild.nodeSize;
} else {
break;
}
}
var commonSuffixChildren = 0;
var suffixSize = 0;
for (var _i = 0; _i < minChildCount - commonPrefixChildren; _i++) {
var _oldChild = oldNode.child(oldNode.childCount - 1 - _i);
var _newChild = newNode.child(newNode.childCount - 1 - _i);
if (_oldChild.eq(_newChild)) {
commonSuffixChildren++;
suffixSize += _oldChild.nodeSize;
} else {
break;
}
}
var totalCommon = commonPrefixChildren + commonSuffixChildren;
if (totalCommon >= oldNode.childCount && totalCommon >= newNode.childCount) {
return {
start: rootListStart,
end: rootListStart,
fragment: Fragment.empty,
adjustedContentStartOffsets: contentStartOffsets
};
}
var narrowedStart = rootListStart + 1 + prefixSize;
var narrowedEnd = rootListEnd - 1 - suffixSize;
var changedChildStart = commonPrefixChildren;
var changedChildEnd = newNode.childCount - commonSuffixChildren;
var changedNodes = [];
for (var _i2 = changedChildStart; _i2 < changedChildEnd; _i2++) {
changedNodes.push(newNode.child(_i2));
}
var narrowedFragment = Fragment.from(changedNodes);
var prefixOffset = 1 + prefixSize;
var adjustedContentStartOffsets = contentStartOffsets.map(function (offset) {
return offset - prefixOffset;
});
return {
start: narrowedStart,
end: narrowedEnd,
fragment: narrowedFragment,
adjustedContentStartOffsets: adjustedContentStartOffsets
};
}