@portabletext/editor 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -2
- package/lib/index.d.mts +22 -97
- package/lib/index.d.ts +22 -97
- package/lib/index.esm.js +1065 -1377
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +1128 -1430
- package/lib/index.js.map +1 -1
- package/lib/index.mjs +1065 -1377
- package/lib/index.mjs.map +1 -1
- package/package.json +40 -22
- package/src/editor/Editable.tsx +32 -38
- package/src/editor/components/Synchronizer.tsx +1 -1
- package/src/editor/plugins/__tests__/createWithInsertData.test.tsx +166 -0
- package/src/editor/plugins/createWithInsertData.ts +34 -1
- package/src/editor/plugins/createWithPatches.ts +2 -2
- package/src/editor/plugins/createWithUndoRedo.ts +1 -1
- package/src/index.ts +1 -2
- package/src/types/editor.ts +4 -3
- package/src/utils/__tests__/dmpToOperations.test.ts +1 -1
- package/src/utils/applyPatch.ts +8 -8
- package/src/utils/operationToPatches.ts +2 -2
- package/src/utils/validateValue.ts +1 -1
- package/src/patch/PatchEvent.ts +0 -33
- package/src/patch/applyPatch.ts +0 -29
- package/src/patch/array.ts +0 -89
- package/src/patch/arrayInsert.ts +0 -27
- package/src/patch/object.ts +0 -39
- package/src/patch/patches.ts +0 -53
- package/src/patch/primitive.ts +0 -43
- package/src/patch/string.ts +0 -51
- package/src/types/patch.ts +0 -65
- package/src/utils/patches.ts +0 -36
package/lib/index.mjs
CHANGED
|
@@ -10,21 +10,19 @@ import { styled } from "styled-components";
|
|
|
10
10
|
import uniq from "lodash/uniq.js";
|
|
11
11
|
import { Subject } from "rxjs";
|
|
12
12
|
import { Schema } from "@sanity/schema";
|
|
13
|
+
import { diffMatchPatch as diffMatchPatch$1, set, insert, setIfMissing, unset } from "@portabletext/patches/patch-event";
|
|
13
14
|
import get from "lodash/get.js";
|
|
14
15
|
import isUndefined from "lodash/isUndefined.js";
|
|
15
16
|
import omitBy from "lodash/omitBy.js";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import findIndex from "lodash/findIndex.js";
|
|
19
|
-
import clone from "lodash/clone.js";
|
|
20
|
-
import omit from "lodash/omit.js";
|
|
21
|
-
import flatten$1 from "lodash/flatten.js";
|
|
17
|
+
import { applyAll } from "@portabletext/patches/apply";
|
|
18
|
+
import flatten from "lodash/flatten.js";
|
|
22
19
|
import { isHotkey } from "is-hotkey-esm";
|
|
23
20
|
import { htmlToBlocks, normalizeBlock } from "@sanity/block-tools";
|
|
24
21
|
import isPlainObject from "lodash/isPlainObject.js";
|
|
25
22
|
import throttle from "lodash/throttle.js";
|
|
26
23
|
import { randomKey } from "@sanity/util/content";
|
|
27
24
|
import debounce from "lodash/debounce.js";
|
|
25
|
+
export * from "@portabletext/patches/types";
|
|
28
26
|
const rootName = "sanity-pte:";
|
|
29
27
|
debug$l(rootName);
|
|
30
28
|
function debugWithName(name) {
|
|
@@ -721,1062 +719,240 @@ function compileType(rawType) {
|
|
|
721
719
|
types: [rawType]
|
|
722
720
|
}).get(rawType.name);
|
|
723
721
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
function
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
const text1Length = text1.length, text2Length = text2.length;
|
|
739
|
-
if (text1Length === 0 || text2Length === 0)
|
|
740
|
-
return 0;
|
|
741
|
-
text1Length > text2Length ? text1 = text1.substring(text1Length - text2Length) : text1Length < text2Length && (text2 = text2.substring(0, text1Length));
|
|
742
|
-
const textLength = Math.min(text1Length, text2Length);
|
|
743
|
-
if (text1 === text2)
|
|
744
|
-
return textLength;
|
|
745
|
-
let best = 0, length = 1;
|
|
746
|
-
for (let found = 0; found !== -1; ) {
|
|
747
|
-
const pattern = text1.substring(textLength - length);
|
|
748
|
-
if (found = text2.indexOf(pattern), found === -1)
|
|
749
|
-
return best;
|
|
750
|
-
length += found, (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) && (best = length, length++);
|
|
722
|
+
const debug$j = debugWithName("operationToPatches");
|
|
723
|
+
debug$j.enabled = !1;
|
|
724
|
+
function createOperationToPatches(types) {
|
|
725
|
+
const textBlockName = types.block.name;
|
|
726
|
+
function insertTextPatch(editor, operation, beforeValue) {
|
|
727
|
+
debug$j.enabled && debug$j("Operation", JSON.stringify(operation, null, 2));
|
|
728
|
+
const block = editor.isTextBlock(editor.children[operation.path[0]]) && editor.children[operation.path[0]];
|
|
729
|
+
if (!block)
|
|
730
|
+
throw new Error("Could not find block");
|
|
731
|
+
const textChild = editor.isTextBlock(block) && editor.isTextSpan(block.children[operation.path[1]]) && block.children[operation.path[1]];
|
|
732
|
+
if (!textChild)
|
|
733
|
+
throw new Error("Could not find child");
|
|
734
|
+
const path = [{ _key: block._key }, "children", { _key: textChild._key }, "text"], prevBlock = beforeValue[operation.path[0]], prevChild = editor.isTextBlock(prevBlock) && prevBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevChild) ? prevChild.text : "", patch = diffMatchPatch$1(prevText, textChild.text, path);
|
|
735
|
+
return patch.value.length ? [patch] : [];
|
|
751
736
|
}
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
if (!text1 || !text2 || text1[text1.length - 1] !== text2[text2.length - 1])
|
|
764
|
-
return 0;
|
|
765
|
-
let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerEnd = 0;
|
|
766
|
-
for (; pointerMin < pointerMid; )
|
|
767
|
-
text1.substring(text1.length - pointerMid, text1.length - pointerEnd) === text2.substring(text2.length - pointerMid, text2.length - pointerEnd) ? (pointerMin = pointerMid, pointerEnd = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
|
|
768
|
-
return pointerMid;
|
|
769
|
-
}
|
|
770
|
-
function cleanupSemantic(rawDiffs) {
|
|
771
|
-
let diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
|
|
772
|
-
const equalities = [];
|
|
773
|
-
let equalitiesLength = 0, lastEquality = null, pointer = 0, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0;
|
|
774
|
-
for (; pointer < diffs.length; )
|
|
775
|
-
diffs[pointer][0] === DIFF_EQUAL ? (equalities[equalitiesLength++] = pointer, lengthInsertions1 = lengthInsertions2, lengthDeletions1 = lengthDeletions2, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = diffs[pointer][1]) : (diffs[pointer][0] === DIFF_INSERT ? lengthInsertions2 += diffs[pointer][1].length : lengthDeletions2 += diffs[pointer][1].length, lastEquality && lastEquality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastEquality.length <= Math.max(lengthInsertions2, lengthDeletions2) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = null, hasChanges = !0)), pointer++;
|
|
776
|
-
for (hasChanges && (diffs = cleanupMerge(diffs)), diffs = cleanupSemanticLossless(diffs), pointer = 1; pointer < diffs.length; ) {
|
|
777
|
-
if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
|
|
778
|
-
const deletion = diffs[pointer - 1][1], insertion = diffs[pointer][1], overlapLength1 = getCommonOverlap(deletion, insertion), overlapLength2 = getCommonOverlap(insertion, deletion);
|
|
779
|
-
overlapLength1 >= overlapLength2 ? (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]), diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1), diffs[pointer + 1][1] = insertion.substring(overlapLength1), pointer++) : (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]), diffs[pointer - 1][0] = DIFF_INSERT, diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2), diffs[pointer + 1][0] = DIFF_DELETE, diffs[pointer + 1][1] = deletion.substring(overlapLength2), pointer++), pointer++;
|
|
780
|
-
}
|
|
781
|
-
pointer++;
|
|
737
|
+
function removeTextPatch(editor, operation, beforeValue) {
|
|
738
|
+
const block = editor && editor.children[operation.path[0]];
|
|
739
|
+
if (!block)
|
|
740
|
+
throw new Error("Could not find block");
|
|
741
|
+
const child = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, textChild = editor.isTextSpan(child) ? child : void 0;
|
|
742
|
+
if (child && !textChild)
|
|
743
|
+
throw new Error("Expected span");
|
|
744
|
+
if (!textChild)
|
|
745
|
+
throw new Error("Could not find child");
|
|
746
|
+
const path = [{ _key: block._key }, "children", { _key: textChild._key }, "text"], beforeBlock = beforeValue[operation.path[0]], prevTextChild = editor.isTextBlock(beforeBlock) && beforeBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevTextChild) && prevTextChild.text, patch = diffMatchPatch$1(prevText || "", textChild.text, path);
|
|
747
|
+
return patch.value ? [patch] : [];
|
|
782
748
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
749
|
+
function setNodePatch(editor, operation) {
|
|
750
|
+
if (operation.path.length === 1) {
|
|
751
|
+
const block = editor.children[operation.path[0]];
|
|
752
|
+
if (typeof block._key != "string")
|
|
753
|
+
throw new Error("Expected block to have a _key");
|
|
754
|
+
const setNode = omitBy(
|
|
755
|
+
{ ...editor.children[operation.path[0]], ...operation.newProperties },
|
|
756
|
+
isUndefined
|
|
757
|
+
);
|
|
758
|
+
return [set(fromSlateValue([setNode], textBlockName)[0], [{ _key: block._key }])];
|
|
759
|
+
} else if (operation.path.length === 2) {
|
|
760
|
+
const block = editor.children[operation.path[0]];
|
|
761
|
+
if (editor.isTextBlock(block)) {
|
|
762
|
+
const child = block.children[operation.path[1]];
|
|
763
|
+
if (child) {
|
|
764
|
+
const blockKey = block._key, childKey = child._key, patches = [], keys = Object.keys(operation.newProperties);
|
|
765
|
+
return keys.forEach((keyName) => {
|
|
766
|
+
if (keys.length === 1 && keyName === "_key") {
|
|
767
|
+
const val = get(operation.newProperties, keyName);
|
|
768
|
+
patches.push(
|
|
769
|
+
set(val, [{ _key: blockKey }, "children", block.children.indexOf(child), keyName])
|
|
770
|
+
);
|
|
771
|
+
} else {
|
|
772
|
+
const val = get(operation.newProperties, keyName);
|
|
773
|
+
patches.push(set(val, [{ _key: blockKey }, "children", { _key: childKey }, keyName]));
|
|
774
|
+
}
|
|
775
|
+
}), patches;
|
|
776
|
+
}
|
|
777
|
+
throw new Error("Could not find a valid child");
|
|
778
|
+
}
|
|
779
|
+
throw new Error("Could not find a valid block");
|
|
780
|
+
} else
|
|
781
|
+
throw new Error(`Unexpected path encountered: ${JSON.stringify(operation.path)}`);
|
|
793
782
|
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
if (
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
783
|
+
function insertNodePatch(editor, operation, beforeValue) {
|
|
784
|
+
const block = beforeValue[operation.path[0]], isTextBlock = editor.isTextBlock(block);
|
|
785
|
+
if (operation.path.length === 1) {
|
|
786
|
+
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block == null ? void 0 : block._key : beforeBlock == null ? void 0 : beforeBlock._key;
|
|
787
|
+
return targetKey ? [
|
|
788
|
+
insert([fromSlateValue([operation.node], textBlockName)[0]], position, [
|
|
789
|
+
{ _key: targetKey }
|
|
790
|
+
])
|
|
791
|
+
] : [
|
|
792
|
+
setIfMissing(beforeValue, []),
|
|
793
|
+
insert([fromSlateValue([operation.node], textBlockName)[0]], "before", [
|
|
794
|
+
operation.path[0]
|
|
795
|
+
])
|
|
796
|
+
];
|
|
797
|
+
} else if (isTextBlock && operation.path.length === 2 && editor.children[operation.path[0]]) {
|
|
798
|
+
const position = block.children.length === 0 || !block.children[operation.path[1] - 1] ? "before" : "after", node = { ...operation.node };
|
|
799
|
+
!node._type && Text.isText(node) && (node._type = "span", node.marks = []);
|
|
800
|
+
const child = fromSlateValue(
|
|
801
|
+
[
|
|
802
|
+
{
|
|
803
|
+
_key: "bogus",
|
|
804
|
+
_type: textBlockName,
|
|
805
|
+
children: [node]
|
|
806
|
+
}
|
|
807
|
+
],
|
|
808
|
+
textBlockName
|
|
809
|
+
)[0].children[0];
|
|
810
|
+
return [
|
|
811
|
+
insert([child], position, [
|
|
812
|
+
{ _key: block._key },
|
|
813
|
+
"children",
|
|
814
|
+
block.children.length <= 1 || !block.children[operation.path[1] - 1] ? 0 : { _key: block.children[operation.path[1] - 1]._key }
|
|
815
|
+
])
|
|
816
|
+
];
|
|
817
|
+
}
|
|
818
|
+
return debug$j("Something was inserted into a void block. Not producing editor patches."), [];
|
|
819
|
+
}
|
|
820
|
+
function splitNodePatch(editor, operation, beforeValue) {
|
|
821
|
+
const patches = [], splitBlock = editor.children[operation.path[0]];
|
|
822
|
+
if (!editor.isTextBlock(splitBlock))
|
|
823
|
+
throw new Error(
|
|
824
|
+
`Block with path ${JSON.stringify(
|
|
825
|
+
operation.path[0]
|
|
826
|
+
)} is not a text block and can't be split`
|
|
827
|
+
);
|
|
828
|
+
if (operation.path.length === 1) {
|
|
829
|
+
const oldBlock = beforeValue[operation.path[0]];
|
|
830
|
+
if (editor.isTextBlock(oldBlock)) {
|
|
831
|
+
const targetValue = fromSlateValue(
|
|
832
|
+
[editor.children[operation.path[0] + 1]],
|
|
833
|
+
textBlockName
|
|
834
|
+
)[0];
|
|
835
|
+
targetValue && (patches.push(insert([targetValue], "after", [{ _key: splitBlock._key }])), oldBlock.children.slice(operation.position).forEach((span) => {
|
|
836
|
+
const path = [{ _key: oldBlock._key }, "children", { _key: span._key }];
|
|
837
|
+
patches.push(unset(path));
|
|
838
|
+
}));
|
|
802
839
|
}
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
840
|
+
return patches;
|
|
841
|
+
}
|
|
842
|
+
if (operation.path.length === 2) {
|
|
843
|
+
const splitSpan = splitBlock.children[operation.path[1]];
|
|
844
|
+
if (editor.isTextSpan(splitSpan)) {
|
|
845
|
+
const targetSpans = fromSlateValue(
|
|
846
|
+
[
|
|
847
|
+
{
|
|
848
|
+
...splitBlock,
|
|
849
|
+
children: splitBlock.children.slice(operation.path[1] + 1, operation.path[1] + 2)
|
|
850
|
+
}
|
|
851
|
+
],
|
|
852
|
+
textBlockName
|
|
853
|
+
)[0].children;
|
|
854
|
+
patches.push(
|
|
855
|
+
insert(targetSpans, "after", [
|
|
856
|
+
{ _key: splitBlock._key },
|
|
857
|
+
"children",
|
|
858
|
+
{ _key: splitSpan._key }
|
|
859
|
+
])
|
|
860
|
+
), patches.push(
|
|
861
|
+
set(splitSpan.text, [
|
|
862
|
+
{ _key: splitBlock._key },
|
|
863
|
+
"children",
|
|
864
|
+
{ _key: splitSpan._key },
|
|
865
|
+
"text"
|
|
866
|
+
])
|
|
867
|
+
);
|
|
808
868
|
}
|
|
809
|
-
|
|
869
|
+
return patches;
|
|
810
870
|
}
|
|
811
|
-
|
|
871
|
+
return patches;
|
|
812
872
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
case DIFF_DELETE:
|
|
825
|
-
countDelete++, textDelete += diffs[pointer][1], pointer++;
|
|
826
|
-
break;
|
|
827
|
-
case DIFF_EQUAL:
|
|
828
|
-
countDelete + countInsert > 1 ? (countDelete !== 0 && countInsert !== 0 && (commonlength = getCommonPrefix(textInsert, textDelete), commonlength !== 0 && (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL ? diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength) : (diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]), pointer++), textInsert = textInsert.substring(commonlength), textDelete = textDelete.substring(commonlength)), commonlength = getCommonSuffix(textInsert, textDelete), commonlength !== 0 && (diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1], textInsert = textInsert.substring(0, textInsert.length - commonlength), textDelete = textDelete.substring(0, textDelete.length - commonlength))), pointer -= countDelete + countInsert, diffs.splice(pointer, countDelete + countInsert), textDelete.length && (diffs.splice(pointer, 0, [DIFF_DELETE, textDelete]), pointer++), textInsert.length && (diffs.splice(pointer, 0, [DIFF_INSERT, textInsert]), pointer++), pointer++) : pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL ? (diffs[pointer - 1][1] += diffs[pointer][1], diffs.splice(pointer, 1)) : pointer++, countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
|
|
829
|
-
break;
|
|
830
|
-
default:
|
|
831
|
-
throw new Error("Unknown diff operation");
|
|
832
|
-
}
|
|
833
|
-
diffs[diffs.length - 1][1] === "" && diffs.pop();
|
|
834
|
-
let hasChanges = !1;
|
|
835
|
-
for (pointer = 1; pointer < diffs.length - 1; )
|
|
836
|
-
diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL && (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1] ? (diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length), diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1], diffs.splice(pointer - 1, 1), hasChanges = !0) : diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1] && (diffs[pointer - 1][1] += diffs[pointer + 1][1], diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1], diffs.splice(pointer + 1, 1), hasChanges = !0)), pointer++;
|
|
837
|
-
return hasChanges && (diffs = cleanupMerge(diffs)), diffs;
|
|
838
|
-
}
|
|
839
|
-
function trueCount() {
|
|
840
|
-
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++)
|
|
841
|
-
args[_key] = arguments[_key];
|
|
842
|
-
return args.reduce((n, bool) => n + (bool ? 1 : 0), 0);
|
|
843
|
-
}
|
|
844
|
-
function cleanupEfficiency(rawDiffs) {
|
|
845
|
-
let editCost = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 4, diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
|
|
846
|
-
const equalities = [];
|
|
847
|
-
let equalitiesLength = 0, lastEquality = null, pointer = 0, preIns = !1, preDel = !1, postIns = !1, postDel = !1;
|
|
848
|
-
for (; pointer < diffs.length; )
|
|
849
|
-
diffs[pointer][0] === DIFF_EQUAL ? (diffs[pointer][1].length < editCost && (postIns || postDel) ? (equalities[equalitiesLength++] = pointer, preIns = postIns, preDel = postDel, lastEquality = diffs[pointer][1]) : (equalitiesLength = 0, lastEquality = null), postIns = !1, postDel = !1) : (diffs[pointer][0] === DIFF_DELETE ? postDel = !0 : postIns = !0, lastEquality && (preIns && preDel && postIns && postDel || lastEquality.length < editCost / 2 && trueCount(preIns, preDel, postIns, postDel) === 3) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, lastEquality = null, preIns && preDel ? (postIns = !0, postDel = !0, equalitiesLength = 0) : (equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, postIns = !1, postDel = !1), hasChanges = !0)), pointer++;
|
|
850
|
-
return hasChanges && (diffs = cleanupMerge(diffs)), diffs;
|
|
851
|
-
}
|
|
852
|
-
function bisect(text1, text2, deadline) {
|
|
853
|
-
const text1Length = text1.length, text2Length = text2.length, maxD = Math.ceil((text1Length + text2Length) / 2), vOffset = maxD, vLength = 2 * maxD, v1 = new Array(vLength), v2 = new Array(vLength);
|
|
854
|
-
for (let x = 0; x < vLength; x++)
|
|
855
|
-
v1[x] = -1, v2[x] = -1;
|
|
856
|
-
v1[vOffset + 1] = 0, v2[vOffset + 1] = 0;
|
|
857
|
-
const delta = text1Length - text2Length, front = delta % 2 !== 0;
|
|
858
|
-
let k1start = 0, k1end = 0, k2start = 0, k2end = 0;
|
|
859
|
-
for (let d = 0; d < maxD && !(Date.now() > deadline); d++) {
|
|
860
|
-
for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
|
|
861
|
-
const k1Offset = vOffset + k1;
|
|
862
|
-
let x1;
|
|
863
|
-
k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1] ? x1 = v1[k1Offset + 1] : x1 = v1[k1Offset - 1] + 1;
|
|
864
|
-
let y1 = x1 - k1;
|
|
865
|
-
for (; x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1); )
|
|
866
|
-
x1++, y1++;
|
|
867
|
-
if (v1[k1Offset] = x1, x1 > text1Length)
|
|
868
|
-
k1end += 2;
|
|
869
|
-
else if (y1 > text2Length)
|
|
870
|
-
k1start += 2;
|
|
871
|
-
else if (front) {
|
|
872
|
-
const k2Offset = vOffset + delta - k1;
|
|
873
|
-
if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
|
|
874
|
-
const x2 = text1Length - v2[k2Offset];
|
|
875
|
-
if (x1 >= x2)
|
|
876
|
-
return bisectSplit(text1, text2, x1, y1, deadline);
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
|
|
881
|
-
const k2Offset = vOffset + k2;
|
|
882
|
-
let x2;
|
|
883
|
-
k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1] ? x2 = v2[k2Offset + 1] : x2 = v2[k2Offset - 1] + 1;
|
|
884
|
-
let y2 = x2 - k2;
|
|
885
|
-
for (; x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1); )
|
|
886
|
-
x2++, y2++;
|
|
887
|
-
if (v2[k2Offset] = x2, x2 > text1Length)
|
|
888
|
-
k2end += 2;
|
|
889
|
-
else if (y2 > text2Length)
|
|
890
|
-
k2start += 2;
|
|
891
|
-
else if (!front) {
|
|
892
|
-
const k1Offset = vOffset + delta - k2;
|
|
893
|
-
if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
|
|
894
|
-
const x1 = v1[k1Offset], y1 = vOffset + x1 - k1Offset;
|
|
895
|
-
if (x2 = text1Length - x2, x1 >= x2)
|
|
896
|
-
return bisectSplit(text1, text2, x1, y1, deadline);
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
}
|
|
901
|
-
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
902
|
-
}
|
|
903
|
-
function bisectSplit(text1, text2, x, y, deadline) {
|
|
904
|
-
const text1a = text1.substring(0, x), text2a = text2.substring(0, y), text1b = text1.substring(x), text2b = text2.substring(y), diffs = doDiff(text1a, text2a, {
|
|
905
|
-
checkLines: !1,
|
|
906
|
-
deadline
|
|
907
|
-
}), diffsb = doDiff(text1b, text2b, {
|
|
908
|
-
checkLines: !1,
|
|
909
|
-
deadline
|
|
910
|
-
});
|
|
911
|
-
return diffs.concat(diffsb);
|
|
912
|
-
}
|
|
913
|
-
function findHalfMatch(text1, text2) {
|
|
914
|
-
if ((arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 1) <= 0)
|
|
915
|
-
return null;
|
|
916
|
-
const longText = text1.length > text2.length ? text1 : text2, shortText = text1.length > text2.length ? text2 : text1;
|
|
917
|
-
if (longText.length < 4 || shortText.length * 2 < longText.length)
|
|
918
|
-
return null;
|
|
919
|
-
const halfMatch1 = halfMatchI(longText, shortText, Math.ceil(longText.length / 4)), halfMatch2 = halfMatchI(longText, shortText, Math.ceil(longText.length / 2));
|
|
920
|
-
let halfMatch;
|
|
921
|
-
if (halfMatch1 && halfMatch2)
|
|
922
|
-
halfMatch = halfMatch1[4].length > halfMatch2[4].length ? halfMatch1 : halfMatch2;
|
|
923
|
-
else {
|
|
924
|
-
if (!halfMatch1 && !halfMatch2)
|
|
925
|
-
return null;
|
|
926
|
-
halfMatch2 ? halfMatch1 || (halfMatch = halfMatch2) : halfMatch = halfMatch1;
|
|
927
|
-
}
|
|
928
|
-
if (!halfMatch)
|
|
929
|
-
throw new Error("Unable to find a half match.");
|
|
930
|
-
let text1A, text1B, text2A, text2B;
|
|
931
|
-
text1.length > text2.length ? (text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3]) : (text2A = halfMatch[0], text2B = halfMatch[1], text1A = halfMatch[2], text1B = halfMatch[3]);
|
|
932
|
-
const midCommon = halfMatch[4];
|
|
933
|
-
return [text1A, text1B, text2A, text2B, midCommon];
|
|
934
|
-
}
|
|
935
|
-
function halfMatchI(longText, shortText, i) {
|
|
936
|
-
const seed = longText.slice(i, i + Math.floor(longText.length / 4));
|
|
937
|
-
let j = -1, bestCommon = "", bestLongTextA, bestLongTextB, bestShortTextA, bestShortTextB;
|
|
938
|
-
for (; (j = shortText.indexOf(seed, j + 1)) !== -1; ) {
|
|
939
|
-
const prefixLength = getCommonPrefix(longText.slice(i), shortText.slice(j)), suffixLength = getCommonSuffix(longText.slice(0, i), shortText.slice(0, j));
|
|
940
|
-
bestCommon.length < suffixLength + prefixLength && (bestCommon = shortText.slice(j - suffixLength, j) + shortText.slice(j, j + prefixLength), bestLongTextA = longText.slice(0, i - suffixLength), bestLongTextB = longText.slice(i + prefixLength), bestShortTextA = shortText.slice(0, j - suffixLength), bestShortTextB = shortText.slice(j + prefixLength));
|
|
873
|
+
function removeNodePatch(editor, operation, beforeValue) {
|
|
874
|
+
const block = beforeValue[operation.path[0]];
|
|
875
|
+
if (operation.path.length === 1) {
|
|
876
|
+
if (block && block._key)
|
|
877
|
+
return [unset([{ _key: block._key }])];
|
|
878
|
+
throw new Error("Block not found");
|
|
879
|
+
} else if (editor.isTextBlock(block) && operation.path.length === 2) {
|
|
880
|
+
const spanToRemove = editor.isTextBlock(block) && block.children && block.children[operation.path[1]];
|
|
881
|
+
return spanToRemove ? [unset([{ _key: block._key }, "children", { _key: spanToRemove._key }])] : (debug$j("Span not found in editor trying to remove node"), []);
|
|
882
|
+
} else
|
|
883
|
+
return debug$j("Not creating patch inside object block"), [];
|
|
941
884
|
}
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
885
|
+
function mergeNodePatch(editor, operation, beforeValue) {
|
|
886
|
+
const patches = [], block = beforeValue[operation.path[0]], targetBlock = editor.children[operation.path[0]];
|
|
887
|
+
if (operation.path.length === 1)
|
|
888
|
+
if (block != null && block._key) {
|
|
889
|
+
const newBlock = fromSlateValue([editor.children[operation.path[0] - 1]], textBlockName)[0];
|
|
890
|
+
patches.push(set(newBlock, [{ _key: newBlock._key }])), patches.push(unset([{ _key: block._key }]));
|
|
891
|
+
} else
|
|
892
|
+
throw new Error("Target key not found!");
|
|
893
|
+
else if (operation.path.length === 2 && editor.isTextBlock(targetBlock)) {
|
|
894
|
+
const mergedSpan = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, targetSpan = targetBlock.children[operation.path[1] - 1];
|
|
895
|
+
editor.isTextSpan(targetSpan) && (patches.push(
|
|
896
|
+
set(targetSpan.text, [{ _key: block._key }, "children", { _key: targetSpan._key }, "text"])
|
|
897
|
+
), mergedSpan && patches.push(unset([{ _key: block._key }, "children", { _key: mergedSpan._key }])));
|
|
898
|
+
} else
|
|
899
|
+
debug$j("Void nodes can't be merged, not creating any patches");
|
|
900
|
+
return patches;
|
|
950
901
|
}
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
902
|
+
function moveNodePatch(editor, operation, beforeValue) {
|
|
903
|
+
const patches = [], block = beforeValue[operation.path[0]], targetBlock = beforeValue[operation.newPath[0]];
|
|
904
|
+
if (operation.path.length === 1) {
|
|
905
|
+
const position = operation.path[0] > operation.newPath[0] ? "before" : "after";
|
|
906
|
+
patches.push(unset([{ _key: block._key }])), patches.push(
|
|
907
|
+
insert([fromSlateValue([block], textBlockName)[0]], position, [{ _key: targetBlock._key }])
|
|
908
|
+
);
|
|
909
|
+
} else if (operation.path.length === 2 && editor.isTextBlock(block) && editor.isTextBlock(targetBlock)) {
|
|
910
|
+
const child = block.children[operation.path[1]], targetChild = targetBlock.children[operation.newPath[1]], position = operation.newPath[1] === targetBlock.children.length ? "after" : "before", childToInsert = fromSlateValue([block], textBlockName)[0].children[operation.path[1]];
|
|
911
|
+
patches.push(unset([{ _key: block._key }, "children", { _key: child._key }])), patches.push(
|
|
912
|
+
insert([childToInsert], position, [
|
|
913
|
+
{ _key: targetBlock._key },
|
|
914
|
+
"children",
|
|
915
|
+
{ _key: targetChild._key }
|
|
916
|
+
])
|
|
917
|
+
);
|
|
962
918
|
}
|
|
963
|
-
return
|
|
919
|
+
return patches;
|
|
964
920
|
}
|
|
965
|
-
let maxLines = 4e4;
|
|
966
|
-
const chars1 = diffLinesToMunge(textA);
|
|
967
|
-
maxLines = 65535;
|
|
968
|
-
const chars2 = diffLinesToMunge(textB);
|
|
969
921
|
return {
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
922
|
+
insertNodePatch,
|
|
923
|
+
insertTextPatch,
|
|
924
|
+
mergeNodePatch,
|
|
925
|
+
moveNodePatch,
|
|
926
|
+
removeNodePatch,
|
|
927
|
+
removeTextPatch,
|
|
928
|
+
setNodePatch,
|
|
929
|
+
splitNodePatch
|
|
973
930
|
};
|
|
974
931
|
}
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
deadline: opts.deadline
|
|
1000
|
-
});
|
|
1001
|
-
for (let j = aa.length - 1; j >= 0; j--)
|
|
1002
|
-
diffs.splice(pointer, 0, aa[j]);
|
|
1003
|
-
pointer += aa.length;
|
|
1004
|
-
}
|
|
1005
|
-
countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
|
|
1006
|
-
break;
|
|
1007
|
-
default:
|
|
1008
|
-
throw new Error("Unknown diff operation.");
|
|
1009
|
-
}
|
|
1010
|
-
pointer++;
|
|
1011
|
-
}
|
|
1012
|
-
return diffs.pop(), diffs;
|
|
1013
|
-
}
|
|
1014
|
-
function computeDiff(text1, text2, opts) {
|
|
1015
|
-
let diffs;
|
|
1016
|
-
if (!text1)
|
|
1017
|
-
return [[DIFF_INSERT, text2]];
|
|
1018
|
-
if (!text2)
|
|
1019
|
-
return [[DIFF_DELETE, text1]];
|
|
1020
|
-
const longtext = text1.length > text2.length ? text1 : text2, shorttext = text1.length > text2.length ? text2 : text1, i = longtext.indexOf(shorttext);
|
|
1021
|
-
if (i !== -1)
|
|
1022
|
-
return diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]], text1.length > text2.length && (diffs[0][0] = DIFF_DELETE, diffs[2][0] = DIFF_DELETE), diffs;
|
|
1023
|
-
if (shorttext.length === 1)
|
|
1024
|
-
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
1025
|
-
const halfMatch = findHalfMatch(text1, text2);
|
|
1026
|
-
if (halfMatch) {
|
|
1027
|
-
const text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3], midCommon = halfMatch[4], diffsA = doDiff(text1A, text2A, opts), diffsB = doDiff(text1B, text2B, opts);
|
|
1028
|
-
return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
|
|
1029
|
-
}
|
|
1030
|
-
return opts.checkLines && text1.length > 100 && text2.length > 100 ? doLineModeDiff(text1, text2, opts) : bisect(text1, text2, opts.deadline);
|
|
1031
|
-
}
|
|
1032
|
-
const DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0;
|
|
1033
|
-
function diff(textA, textB, opts) {
|
|
1034
|
-
if (textA === null || textB === null)
|
|
1035
|
-
throw new Error("Null input. (diff)");
|
|
1036
|
-
const diffs = doDiff(textA, textB, createInternalOpts(opts || {}));
|
|
1037
|
-
return adjustDiffForSurrogatePairs(diffs), diffs;
|
|
1038
|
-
}
|
|
1039
|
-
function doDiff(textA, textB, options) {
|
|
1040
|
-
let text1 = textA, text2 = textB;
|
|
1041
|
-
if (text1 === text2)
|
|
1042
|
-
return text1 ? [[DIFF_EQUAL, text1]] : [];
|
|
1043
|
-
let commonlength = getCommonPrefix(text1, text2);
|
|
1044
|
-
const commonprefix = text1.substring(0, commonlength);
|
|
1045
|
-
text1 = text1.substring(commonlength), text2 = text2.substring(commonlength), commonlength = getCommonSuffix(text1, text2);
|
|
1046
|
-
const commonsuffix = text1.substring(text1.length - commonlength);
|
|
1047
|
-
text1 = text1.substring(0, text1.length - commonlength), text2 = text2.substring(0, text2.length - commonlength);
|
|
1048
|
-
let diffs = computeDiff(text1, text2, options);
|
|
1049
|
-
return commonprefix && diffs.unshift([DIFF_EQUAL, commonprefix]), commonsuffix && diffs.push([DIFF_EQUAL, commonsuffix]), diffs = cleanupMerge(diffs), diffs;
|
|
1050
|
-
}
|
|
1051
|
-
function createDeadLine(timeout) {
|
|
1052
|
-
let t = 1;
|
|
1053
|
-
return typeof timeout < "u" && (t = timeout <= 0 ? Number.MAX_VALUE : timeout), Date.now() + t * 1e3;
|
|
1054
|
-
}
|
|
1055
|
-
function createInternalOpts(opts) {
|
|
1056
|
-
return {
|
|
1057
|
-
checkLines: !0,
|
|
1058
|
-
deadline: createDeadLine(opts.timeout || 1),
|
|
1059
|
-
...opts
|
|
1060
|
-
};
|
|
1061
|
-
}
|
|
1062
|
-
function combineChar(data, char, dir) {
|
|
1063
|
-
return dir === 1 ? data + char : char + data;
|
|
1064
|
-
}
|
|
1065
|
-
function splitChar(data, dir) {
|
|
1066
|
-
return dir === 1 ? [data.substring(0, data.length - 1), data[data.length - 1]] : [data.substring(1), data[0]];
|
|
1067
|
-
}
|
|
1068
|
-
function hasSharedChar(diffs, i, j, dir) {
|
|
1069
|
-
return dir === 1 ? diffs[i][1][diffs[i][1].length - 1] === diffs[j][1][diffs[j][1].length - 1] : diffs[i][1][0] === diffs[j][1][0];
|
|
1070
|
-
}
|
|
1071
|
-
function deisolateChar(diffs, i, dir) {
|
|
1072
|
-
const inv = dir === 1 ? -1 : 1;
|
|
1073
|
-
let insertIdx = null, deleteIdx = null, j = i + dir;
|
|
1074
|
-
for (; j >= 0 && j < diffs.length && (insertIdx === null || deleteIdx === null); j += dir) {
|
|
1075
|
-
const [op, text2] = diffs[j];
|
|
1076
|
-
if (text2.length !== 0) {
|
|
1077
|
-
if (op === DIFF_INSERT) {
|
|
1078
|
-
insertIdx === null && (insertIdx = j);
|
|
1079
|
-
continue;
|
|
1080
|
-
} else if (op === DIFF_DELETE) {
|
|
1081
|
-
deleteIdx === null && (deleteIdx = j);
|
|
1082
|
-
continue;
|
|
1083
|
-
} else if (op === DIFF_EQUAL) {
|
|
1084
|
-
if (insertIdx === null && deleteIdx === null) {
|
|
1085
|
-
const [rest, char2] = splitChar(diffs[i][1], dir);
|
|
1086
|
-
diffs[i][1] = rest, diffs[j][1] = combineChar(diffs[j][1], char2, inv);
|
|
1087
|
-
return;
|
|
1088
|
-
}
|
|
1089
|
-
break;
|
|
1090
|
-
}
|
|
1091
|
-
}
|
|
1092
|
-
}
|
|
1093
|
-
if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
|
|
1094
|
-
const [insertText, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText] = splitChar(diffs[deleteIdx][1], inv);
|
|
1095
|
-
diffs[insertIdx][1] = insertText, diffs[deleteIdx][1] = deleteText, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
|
|
1096
|
-
return;
|
|
1097
|
-
}
|
|
1098
|
-
const [text, char] = splitChar(diffs[i][1], dir);
|
|
1099
|
-
diffs[i][1] = text, insertIdx === null ? (diffs.splice(j, 0, [DIFF_INSERT, char]), deleteIdx !== null && deleteIdx >= j && deleteIdx++) : diffs[insertIdx][1] = combineChar(diffs[insertIdx][1], char, inv), deleteIdx === null ? diffs.splice(j, 0, [DIFF_DELETE, char]) : diffs[deleteIdx][1] = combineChar(diffs[deleteIdx][1], char, inv);
|
|
1100
|
-
}
|
|
1101
|
-
function adjustDiffForSurrogatePairs(diffs) {
|
|
1102
|
-
for (let i = 0; i < diffs.length; i++) {
|
|
1103
|
-
const [diffType, diffText] = diffs[i];
|
|
1104
|
-
if (diffText.length === 0) continue;
|
|
1105
|
-
const firstChar = diffText[0], lastChar = diffText[diffText.length - 1];
|
|
1106
|
-
isHighSurrogate(lastChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, 1), isLowSurrogate(firstChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, -1);
|
|
1107
|
-
}
|
|
1108
|
-
for (let i = 0; i < diffs.length; i++)
|
|
1109
|
-
diffs[i][1].length === 0 && diffs.splice(i, 1);
|
|
1110
|
-
}
|
|
1111
|
-
const DEFAULT_OPTIONS = {
|
|
1112
|
-
/**
|
|
1113
|
-
* At what point is no match declared (0.0 = perfection, 1.0 = very loose).
|
|
1114
|
-
*/
|
|
1115
|
-
threshold: 0.5,
|
|
1116
|
-
/**
|
|
1117
|
-
* How far to search for a match (0 = exact location, 1000+ = broad match).
|
|
1118
|
-
* A match this many characters away from the expected location will add
|
|
1119
|
-
* 1.0 to the score (0.0 is a perfect match).
|
|
1120
|
-
*/
|
|
1121
|
-
distance: 1e3
|
|
1122
|
-
};
|
|
1123
|
-
function applyDefaults(options) {
|
|
1124
|
-
return {
|
|
1125
|
-
...DEFAULT_OPTIONS,
|
|
1126
|
-
...options
|
|
1127
|
-
};
|
|
1128
|
-
}
|
|
1129
|
-
const MAX_BITS$1 = 32;
|
|
1130
|
-
function bitap(text, pattern, loc) {
|
|
1131
|
-
let opts = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
|
|
1132
|
-
if (pattern.length > MAX_BITS$1)
|
|
1133
|
-
throw new Error("Pattern too long for this browser.");
|
|
1134
|
-
const options = applyDefaults(opts), s = getAlphabetFromPattern(pattern);
|
|
1135
|
-
function getBitapScore(e, x) {
|
|
1136
|
-
const accuracy = e / pattern.length, proximity = Math.abs(loc - x);
|
|
1137
|
-
return options.distance ? accuracy + proximity / options.distance : proximity ? 1 : accuracy;
|
|
1138
|
-
}
|
|
1139
|
-
let scoreThreshold = options.threshold, bestLoc = text.indexOf(pattern, loc);
|
|
1140
|
-
bestLoc !== -1 && (scoreThreshold = Math.min(getBitapScore(0, bestLoc), scoreThreshold), bestLoc = text.lastIndexOf(pattern, loc + pattern.length), bestLoc !== -1 && (scoreThreshold = Math.min(getBitapScore(0, bestLoc), scoreThreshold)));
|
|
1141
|
-
const matchmask = 1 << pattern.length - 1;
|
|
1142
|
-
bestLoc = -1;
|
|
1143
|
-
let binMin, binMid, binMax = pattern.length + text.length, lastRd = [];
|
|
1144
|
-
for (let d = 0; d < pattern.length; d++) {
|
|
1145
|
-
for (binMin = 0, binMid = binMax; binMin < binMid; )
|
|
1146
|
-
getBitapScore(d, loc + binMid) <= scoreThreshold ? binMin = binMid : binMax = binMid, binMid = Math.floor((binMax - binMin) / 2 + binMin);
|
|
1147
|
-
binMax = binMid;
|
|
1148
|
-
let start = Math.max(1, loc - binMid + 1);
|
|
1149
|
-
const finish = Math.min(loc + binMid, text.length) + pattern.length, rd = new Array(finish + 2);
|
|
1150
|
-
rd[finish + 1] = (1 << d) - 1;
|
|
1151
|
-
for (let j = finish; j >= start; j--) {
|
|
1152
|
-
const charMatch = s[text.charAt(j - 1)];
|
|
1153
|
-
if (d === 0 ? rd[j] = (rd[j + 1] << 1 | 1) & charMatch : rd[j] = (rd[j + 1] << 1 | 1) & charMatch | ((lastRd[j + 1] | lastRd[j]) << 1 | 1) | lastRd[j + 1], rd[j] & matchmask) {
|
|
1154
|
-
const score = getBitapScore(d, j - 1);
|
|
1155
|
-
if (score <= scoreThreshold)
|
|
1156
|
-
if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc)
|
|
1157
|
-
start = Math.max(1, 2 * loc - bestLoc);
|
|
1158
|
-
else
|
|
1159
|
-
break;
|
|
1160
|
-
}
|
|
1161
|
-
}
|
|
1162
|
-
if (getBitapScore(d + 1, loc) > scoreThreshold)
|
|
1163
|
-
break;
|
|
1164
|
-
lastRd = rd;
|
|
1165
|
-
}
|
|
1166
|
-
return bestLoc;
|
|
1167
|
-
}
|
|
1168
|
-
function getAlphabetFromPattern(pattern) {
|
|
1169
|
-
const s = {};
|
|
1170
|
-
for (let i = 0; i < pattern.length; i++)
|
|
1171
|
-
s[pattern.charAt(i)] = 0;
|
|
1172
|
-
for (let i = 0; i < pattern.length; i++)
|
|
1173
|
-
s[pattern.charAt(i)] |= 1 << pattern.length - i - 1;
|
|
1174
|
-
return s;
|
|
1175
|
-
}
|
|
1176
|
-
function match(text, pattern, searchLocation) {
|
|
1177
|
-
if (text === null || pattern === null || searchLocation === null)
|
|
1178
|
-
throw new Error("Null input. (match())");
|
|
1179
|
-
const loc = Math.max(0, Math.min(searchLocation, text.length));
|
|
1180
|
-
if (text === pattern)
|
|
1181
|
-
return 0;
|
|
1182
|
-
if (text.length) {
|
|
1183
|
-
if (text.substring(loc, loc + pattern.length) === pattern)
|
|
1184
|
-
return loc;
|
|
1185
|
-
} else return -1;
|
|
1186
|
-
return bitap(text, pattern, loc);
|
|
1187
|
-
}
|
|
1188
|
-
function createPatchObject(start1, start2) {
|
|
1189
|
-
return {
|
|
1190
|
-
diffs: [],
|
|
1191
|
-
start1,
|
|
1192
|
-
start2,
|
|
1193
|
-
utf8Start1: start1,
|
|
1194
|
-
utf8Start2: start2,
|
|
1195
|
-
length1: 0,
|
|
1196
|
-
length2: 0,
|
|
1197
|
-
utf8Length1: 0,
|
|
1198
|
-
utf8Length2: 0
|
|
1199
|
-
};
|
|
1200
|
-
}
|
|
1201
|
-
function diffText1(diffs) {
|
|
1202
|
-
const text = [];
|
|
1203
|
-
for (let x = 0; x < diffs.length; x++)
|
|
1204
|
-
diffs[x][0] !== DIFF_INSERT && (text[x] = diffs[x][1]);
|
|
1205
|
-
return text.join("");
|
|
1206
|
-
}
|
|
1207
|
-
function diffText2(diffs) {
|
|
1208
|
-
const text = [];
|
|
1209
|
-
for (let x = 0; x < diffs.length; x++)
|
|
1210
|
-
diffs[x][0] !== DIFF_DELETE && (text[x] = diffs[x][1]);
|
|
1211
|
-
return text.join("");
|
|
1212
|
-
}
|
|
1213
|
-
function countUtf8Bytes(str) {
|
|
1214
|
-
let bytes = 0;
|
|
1215
|
-
for (let i = 0; i < str.length; i++) {
|
|
1216
|
-
const codePoint = str.codePointAt(i);
|
|
1217
|
-
if (typeof codePoint > "u")
|
|
1218
|
-
throw new Error("Failed to get codepoint");
|
|
1219
|
-
bytes += utf8len(codePoint);
|
|
1220
|
-
}
|
|
1221
|
-
return bytes;
|
|
1222
|
-
}
|
|
1223
|
-
function adjustIndiciesToUcs2(patches, base) {
|
|
1224
|
-
let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, byteOffset = 0, idx = 0;
|
|
1225
|
-
function advanceTo(target) {
|
|
1226
|
-
for (; byteOffset < target; ) {
|
|
1227
|
-
const codePoint = base.codePointAt(idx);
|
|
1228
|
-
if (typeof codePoint > "u")
|
|
1229
|
-
return idx;
|
|
1230
|
-
byteOffset += utf8len(codePoint), codePoint > 65535 ? idx += 2 : idx += 1;
|
|
1231
|
-
}
|
|
1232
|
-
if (!options.allowExceedingIndices && byteOffset !== target)
|
|
1233
|
-
throw new Error("Failed to determine byte offset");
|
|
1234
|
-
return idx;
|
|
1235
|
-
}
|
|
1236
|
-
const adjusted = [];
|
|
1237
|
-
for (const patch of patches)
|
|
1238
|
-
adjusted.push({
|
|
1239
|
-
diffs: patch.diffs.map((diff2) => cloneDiff(diff2)),
|
|
1240
|
-
start1: advanceTo(patch.start1),
|
|
1241
|
-
start2: advanceTo(patch.start2),
|
|
1242
|
-
utf8Start1: patch.utf8Start1,
|
|
1243
|
-
utf8Start2: patch.utf8Start2,
|
|
1244
|
-
length1: patch.length1,
|
|
1245
|
-
length2: patch.length2,
|
|
1246
|
-
utf8Length1: patch.utf8Length1,
|
|
1247
|
-
utf8Length2: patch.utf8Length2
|
|
1248
|
-
});
|
|
1249
|
-
return adjusted;
|
|
1250
|
-
}
|
|
1251
|
-
function utf8len(codePoint) {
|
|
1252
|
-
return codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
1253
|
-
}
|
|
1254
|
-
const MAX_BITS = 32, DEFAULT_MARGIN = 4, DEFAULT_OPTS = {
|
|
1255
|
-
margin: 4
|
|
1256
|
-
};
|
|
1257
|
-
function getDefaultOpts() {
|
|
1258
|
-
let opts = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : {};
|
|
1259
|
-
return {
|
|
1260
|
-
...DEFAULT_OPTS,
|
|
1261
|
-
...opts
|
|
1262
|
-
};
|
|
1263
|
-
}
|
|
1264
|
-
function make(a, b, options) {
|
|
1265
|
-
if (typeof a == "string" && typeof b == "string") {
|
|
1266
|
-
let diffs = diff(a, b, {
|
|
1267
|
-
checkLines: !0
|
|
1268
|
-
});
|
|
1269
|
-
return diffs.length > 2 && (diffs = cleanupSemantic(diffs), diffs = cleanupEfficiency(diffs)), _make(a, diffs, getDefaultOpts(options));
|
|
1270
|
-
}
|
|
1271
|
-
if (a && Array.isArray(a) && typeof b > "u")
|
|
1272
|
-
return _make(diffText1(a), a, getDefaultOpts(options));
|
|
1273
|
-
if (typeof a == "string" && b && Array.isArray(b))
|
|
1274
|
-
return _make(a, b, getDefaultOpts(options));
|
|
1275
|
-
throw new Error("Unknown call format to make()");
|
|
1276
|
-
}
|
|
1277
|
-
function _make(textA, diffs, options) {
|
|
1278
|
-
if (diffs.length === 0)
|
|
1279
|
-
return [];
|
|
1280
|
-
const patches = [];
|
|
1281
|
-
let patch = createPatchObject(0, 0), patchDiffLength = 0, charCount1 = 0, charCount2 = 0, utf8Count1 = 0, utf8Count2 = 0, prepatchText = textA, postpatchText = textA;
|
|
1282
|
-
for (let x = 0; x < diffs.length; x++) {
|
|
1283
|
-
const currentDiff = diffs[x], [diffType, diffText] = currentDiff, diffTextLength = diffText.length, diffByteLength = countUtf8Bytes(diffText);
|
|
1284
|
-
switch (!patchDiffLength && diffType !== DIFF_EQUAL && (patch.start1 = charCount1, patch.start2 = charCount2, patch.utf8Start1 = utf8Count1, patch.utf8Start2 = utf8Count2), diffType) {
|
|
1285
|
-
case DIFF_INSERT:
|
|
1286
|
-
patch.diffs[patchDiffLength++] = currentDiff, patch.length2 += diffTextLength, patch.utf8Length2 += diffByteLength, postpatchText = postpatchText.substring(0, charCount2) + diffText + postpatchText.substring(charCount2);
|
|
1287
|
-
break;
|
|
1288
|
-
case DIFF_DELETE:
|
|
1289
|
-
patch.length1 += diffTextLength, patch.utf8Length1 += diffByteLength, patch.diffs[patchDiffLength++] = currentDiff, postpatchText = postpatchText.substring(0, charCount2) + postpatchText.substring(charCount2 + diffTextLength);
|
|
1290
|
-
break;
|
|
1291
|
-
case DIFF_EQUAL:
|
|
1292
|
-
diffTextLength <= 2 * options.margin && patchDiffLength && diffs.length !== x + 1 ? (patch.diffs[patchDiffLength++] = currentDiff, patch.length1 += diffTextLength, patch.length2 += diffTextLength, patch.utf8Length1 += diffByteLength, patch.utf8Length2 += diffByteLength) : diffTextLength >= 2 * options.margin && patchDiffLength && (addContext(patch, prepatchText, options), patches.push(patch), patch = createPatchObject(-1, -1), patchDiffLength = 0, prepatchText = postpatchText, charCount1 = charCount2, utf8Count1 = utf8Count2);
|
|
1293
|
-
break;
|
|
1294
|
-
default:
|
|
1295
|
-
throw new Error("Unknown diff type");
|
|
1296
|
-
}
|
|
1297
|
-
diffType !== DIFF_INSERT && (charCount1 += diffTextLength, utf8Count1 += diffByteLength), diffType !== DIFF_DELETE && (charCount2 += diffTextLength, utf8Count2 += diffByteLength);
|
|
1298
|
-
}
|
|
1299
|
-
return patchDiffLength && (addContext(patch, prepatchText, options), patches.push(patch)), patches;
|
|
1300
|
-
}
|
|
1301
|
-
function addContext(patch, text, opts) {
|
|
1302
|
-
if (text.length === 0)
|
|
1303
|
-
return;
|
|
1304
|
-
let pattern = text.substring(patch.start2, patch.start2 + patch.length1), padding = 0;
|
|
1305
|
-
for (; text.indexOf(pattern) !== text.lastIndexOf(pattern) && pattern.length < MAX_BITS - opts.margin - opts.margin; )
|
|
1306
|
-
padding += opts.margin, pattern = text.substring(patch.start2 - padding, patch.start2 + patch.length1 + padding);
|
|
1307
|
-
padding += opts.margin;
|
|
1308
|
-
let prefixStart = patch.start2 - padding;
|
|
1309
|
-
prefixStart >= 1 && isLowSurrogate(text[prefixStart]) && prefixStart--;
|
|
1310
|
-
const prefix = text.substring(prefixStart, patch.start2);
|
|
1311
|
-
prefix && patch.diffs.unshift([DIFF_EQUAL, prefix]);
|
|
1312
|
-
const prefixLength = prefix.length, prefixUtf8Length = countUtf8Bytes(prefix);
|
|
1313
|
-
let suffixEnd = patch.start2 + patch.length1 + padding;
|
|
1314
|
-
suffixEnd < text.length && isLowSurrogate(text[suffixEnd]) && suffixEnd++;
|
|
1315
|
-
const suffix = text.substring(patch.start2 + patch.length1, suffixEnd);
|
|
1316
|
-
suffix && patch.diffs.push([DIFF_EQUAL, suffix]);
|
|
1317
|
-
const suffixLength = suffix.length, suffixUtf8Length = countUtf8Bytes(suffix);
|
|
1318
|
-
patch.start1 -= prefixLength, patch.start2 -= prefixLength, patch.utf8Start1 -= prefixUtf8Length, patch.utf8Start2 -= prefixUtf8Length, patch.length1 += prefixLength + suffixLength, patch.length2 += prefixLength + suffixLength, patch.utf8Length1 += prefixUtf8Length + suffixUtf8Length, patch.utf8Length2 += prefixUtf8Length + suffixUtf8Length;
|
|
1319
|
-
}
|
|
1320
|
-
function levenshtein(diffs) {
|
|
1321
|
-
let leven = 0, insertions = 0, deletions = 0;
|
|
1322
|
-
for (let x = 0; x < diffs.length; x++) {
|
|
1323
|
-
const op = diffs[x][0], data = diffs[x][1];
|
|
1324
|
-
switch (op) {
|
|
1325
|
-
case DIFF_INSERT:
|
|
1326
|
-
insertions += data.length;
|
|
1327
|
-
break;
|
|
1328
|
-
case DIFF_DELETE:
|
|
1329
|
-
deletions += data.length;
|
|
1330
|
-
break;
|
|
1331
|
-
case DIFF_EQUAL:
|
|
1332
|
-
leven += Math.max(insertions, deletions), insertions = 0, deletions = 0;
|
|
1333
|
-
break;
|
|
1334
|
-
default:
|
|
1335
|
-
throw new Error("Unknown diff operation.");
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
return leven += Math.max(insertions, deletions), leven;
|
|
1339
|
-
}
|
|
1340
|
-
function xIndex(diffs, loc) {
|
|
1341
|
-
let chars1 = 0, chars2 = 0, lastChars1 = 0, lastChars2 = 0, x;
|
|
1342
|
-
for (x = 0; x < diffs.length && (diffs[x][0] !== DIFF_INSERT && (chars1 += diffs[x][1].length), diffs[x][0] !== DIFF_DELETE && (chars2 += diffs[x][1].length), !(chars1 > loc)); x++)
|
|
1343
|
-
lastChars1 = chars1, lastChars2 = chars2;
|
|
1344
|
-
return diffs.length !== x && diffs[x][0] === DIFF_DELETE ? lastChars2 : lastChars2 + (loc - lastChars1);
|
|
1345
|
-
}
|
|
1346
|
-
function addPadding(patches) {
|
|
1347
|
-
const paddingLength = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MARGIN;
|
|
1348
|
-
let nullPadding = "";
|
|
1349
|
-
for (let x = 1; x <= paddingLength; x++)
|
|
1350
|
-
nullPadding += String.fromCharCode(x);
|
|
1351
|
-
for (const p of patches)
|
|
1352
|
-
p.start1 += paddingLength, p.start2 += paddingLength, p.utf8Start1 += paddingLength, p.utf8Start2 += paddingLength;
|
|
1353
|
-
let patch = patches[0], diffs = patch.diffs;
|
|
1354
|
-
if (diffs.length === 0 || diffs[0][0] !== DIFF_EQUAL)
|
|
1355
|
-
diffs.unshift([DIFF_EQUAL, nullPadding]), patch.start1 -= paddingLength, patch.start2 -= paddingLength, patch.utf8Start1 -= paddingLength, patch.utf8Start2 -= paddingLength, patch.length1 += paddingLength, patch.length2 += paddingLength, patch.utf8Length1 += paddingLength, patch.utf8Length2 += paddingLength;
|
|
1356
|
-
else if (paddingLength > diffs[0][1].length) {
|
|
1357
|
-
const firstDiffLength = diffs[0][1].length, extraLength = paddingLength - firstDiffLength;
|
|
1358
|
-
diffs[0][1] = nullPadding.substring(firstDiffLength) + diffs[0][1], patch.start1 -= extraLength, patch.start2 -= extraLength, patch.utf8Start1 -= extraLength, patch.utf8Start2 -= extraLength, patch.length1 += extraLength, patch.length2 += extraLength, patch.utf8Length1 += extraLength, patch.utf8Length2 += extraLength;
|
|
1359
|
-
}
|
|
1360
|
-
if (patch = patches[patches.length - 1], diffs = patch.diffs, diffs.length === 0 || diffs[diffs.length - 1][0] !== DIFF_EQUAL)
|
|
1361
|
-
diffs.push([DIFF_EQUAL, nullPadding]), patch.length1 += paddingLength, patch.length2 += paddingLength, patch.utf8Length1 += paddingLength, patch.utf8Length2 += paddingLength;
|
|
1362
|
-
else if (paddingLength > diffs[diffs.length - 1][1].length) {
|
|
1363
|
-
const extraLength = paddingLength - diffs[diffs.length - 1][1].length;
|
|
1364
|
-
diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength), patch.length1 += extraLength, patch.length2 += extraLength, patch.utf8Length1 += extraLength, patch.utf8Length2 += extraLength;
|
|
1365
|
-
}
|
|
1366
|
-
return nullPadding;
|
|
1367
|
-
}
|
|
1368
|
-
function splitMax(patches) {
|
|
1369
|
-
let margin = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MARGIN;
|
|
1370
|
-
const patchSize = MAX_BITS;
|
|
1371
|
-
for (let x = 0; x < patches.length; x++) {
|
|
1372
|
-
if (patches[x].length1 <= patchSize)
|
|
1373
|
-
continue;
|
|
1374
|
-
const bigpatch = patches[x];
|
|
1375
|
-
patches.splice(x--, 1);
|
|
1376
|
-
let start1 = bigpatch.start1, start2 = bigpatch.start2, preContext = "";
|
|
1377
|
-
for (; bigpatch.diffs.length !== 0; ) {
|
|
1378
|
-
const patch = createPatchObject(start1 - preContext.length, start2 - preContext.length);
|
|
1379
|
-
let empty = !0;
|
|
1380
|
-
if (preContext !== "") {
|
|
1381
|
-
const precontextByteCount = countUtf8Bytes(preContext);
|
|
1382
|
-
patch.length1 = preContext.length, patch.utf8Length1 = precontextByteCount, patch.length2 = preContext.length, patch.utf8Length2 = precontextByteCount, patch.diffs.push([DIFF_EQUAL, preContext]);
|
|
1383
|
-
}
|
|
1384
|
-
for (; bigpatch.diffs.length !== 0 && patch.length1 < patchSize - margin; ) {
|
|
1385
|
-
const diffType = bigpatch.diffs[0][0];
|
|
1386
|
-
let diffText = bigpatch.diffs[0][1], diffTextByteCount = countUtf8Bytes(diffText);
|
|
1387
|
-
if (diffType === DIFF_INSERT) {
|
|
1388
|
-
patch.length2 += diffText.length, patch.utf8Length2 += diffTextByteCount, start2 += diffText.length;
|
|
1389
|
-
const diff2 = bigpatch.diffs.shift();
|
|
1390
|
-
diff2 && patch.diffs.push(diff2), empty = !1;
|
|
1391
|
-
} else diffType === DIFF_DELETE && patch.diffs.length === 1 && patch.diffs[0][0] === DIFF_EQUAL && diffText.length > 2 * patchSize ? (patch.length1 += diffText.length, patch.utf8Length1 += diffTextByteCount, start1 += diffText.length, empty = !1, patch.diffs.push([diffType, diffText]), bigpatch.diffs.shift()) : (diffText = diffText.substring(0, patchSize - patch.length1 - margin), diffTextByteCount = countUtf8Bytes(diffText), patch.length1 += diffText.length, patch.utf8Length1 += diffTextByteCount, start1 += diffText.length, diffType === DIFF_EQUAL ? (patch.length2 += diffText.length, patch.utf8Length2 += diffTextByteCount, start2 += diffText.length) : empty = !1, patch.diffs.push([diffType, diffText]), diffText === bigpatch.diffs[0][1] ? bigpatch.diffs.shift() : bigpatch.diffs[0][1] = bigpatch.diffs[0][1].substring(diffText.length));
|
|
1392
|
-
}
|
|
1393
|
-
preContext = diffText2(patch.diffs), preContext = preContext.substring(preContext.length - margin);
|
|
1394
|
-
const postContext = diffText1(bigpatch.diffs).substring(0, margin), postContextByteCount = countUtf8Bytes(postContext);
|
|
1395
|
-
postContext !== "" && (patch.length1 += postContext.length, patch.length2 += postContext.length, patch.utf8Length1 += postContextByteCount, patch.utf8Length2 += postContextByteCount, patch.diffs.length !== 0 && patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL ? patch.diffs[patch.diffs.length - 1][1] += postContext : patch.diffs.push([DIFF_EQUAL, postContext])), empty || patches.splice(++x, 0, patch);
|
|
1396
|
-
}
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
function apply$4(patches, originalText) {
|
|
1400
|
-
let opts = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
1401
|
-
if (typeof patches == "string")
|
|
1402
|
-
throw new Error("Patches must be an array - pass the patch to `parsePatch()` first");
|
|
1403
|
-
let text = originalText;
|
|
1404
|
-
if (patches.length === 0)
|
|
1405
|
-
return [text, []];
|
|
1406
|
-
const parsed = adjustIndiciesToUcs2(patches, text, {
|
|
1407
|
-
allowExceedingIndices: opts.allowExceedingIndices
|
|
1408
|
-
}), margin = opts.margin || DEFAULT_MARGIN, deleteThreshold = opts.deleteThreshold || 0.4, nullPadding = addPadding(parsed, margin);
|
|
1409
|
-
text = nullPadding + text + nullPadding, splitMax(parsed, margin);
|
|
1410
|
-
let delta = 0;
|
|
1411
|
-
const results = [];
|
|
1412
|
-
for (let x = 0; x < parsed.length; x++) {
|
|
1413
|
-
const expectedLoc = parsed[x].start2 + delta, text1 = diffText1(parsed[x].diffs);
|
|
1414
|
-
let startLoc, endLoc = -1;
|
|
1415
|
-
if (text1.length > MAX_BITS ? (startLoc = match(text, text1.substring(0, MAX_BITS), expectedLoc), startLoc !== -1 && (endLoc = match(text, text1.substring(text1.length - MAX_BITS), expectedLoc + text1.length - MAX_BITS), (endLoc === -1 || startLoc >= endLoc) && (startLoc = -1))) : startLoc = match(text, text1, expectedLoc), startLoc === -1)
|
|
1416
|
-
results[x] = !1, delta -= parsed[x].length2 - parsed[x].length1;
|
|
1417
|
-
else {
|
|
1418
|
-
results[x] = !0, delta = startLoc - expectedLoc;
|
|
1419
|
-
let text2;
|
|
1420
|
-
if (endLoc === -1 ? text2 = text.substring(startLoc, startLoc + text1.length) : text2 = text.substring(startLoc, endLoc + MAX_BITS), text1 === text2)
|
|
1421
|
-
text = text.substring(0, startLoc) + diffText2(parsed[x].diffs) + text.substring(startLoc + text1.length);
|
|
1422
|
-
else {
|
|
1423
|
-
let diffs = diff(text1, text2, {
|
|
1424
|
-
checkLines: !1
|
|
1425
|
-
});
|
|
1426
|
-
if (text1.length > MAX_BITS && levenshtein(diffs) / text1.length > deleteThreshold)
|
|
1427
|
-
results[x] = !1;
|
|
1428
|
-
else {
|
|
1429
|
-
diffs = cleanupSemanticLossless(diffs);
|
|
1430
|
-
let index1 = 0, index2 = 0;
|
|
1431
|
-
for (let y = 0; y < parsed[x].diffs.length; y++) {
|
|
1432
|
-
const mod = parsed[x].diffs[y];
|
|
1433
|
-
mod[0] !== DIFF_EQUAL && (index2 = xIndex(diffs, index1)), mod[0] === DIFF_INSERT ? text = text.substring(0, startLoc + index2) + mod[1] + text.substring(startLoc + index2) : mod[0] === DIFF_DELETE && (text = text.substring(0, startLoc + index2) + text.substring(startLoc + xIndex(diffs, index1 + mod[1].length))), mod[0] !== DIFF_DELETE && (index1 += mod[1].length);
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
}
|
|
1439
|
-
return text = text.substring(nullPadding.length, text.length - nullPadding.length), [text, results];
|
|
1440
|
-
}
|
|
1441
|
-
function stringify(patches) {
|
|
1442
|
-
return patches.map(stringifyPatch).join("");
|
|
1443
|
-
}
|
|
1444
|
-
function stringifyPatch(patch) {
|
|
1445
|
-
const {
|
|
1446
|
-
utf8Length1,
|
|
1447
|
-
utf8Length2,
|
|
1448
|
-
utf8Start1,
|
|
1449
|
-
utf8Start2,
|
|
1450
|
-
diffs
|
|
1451
|
-
} = patch;
|
|
1452
|
-
let coords1;
|
|
1453
|
-
utf8Length1 === 0 ? coords1 = "".concat(utf8Start1, ",0") : utf8Length1 === 1 ? coords1 = "".concat(utf8Start1 + 1) : coords1 = "".concat(utf8Start1 + 1, ",").concat(utf8Length1);
|
|
1454
|
-
let coords2;
|
|
1455
|
-
utf8Length2 === 0 ? coords2 = "".concat(utf8Start2, ",0") : utf8Length2 === 1 ? coords2 = "".concat(utf8Start2 + 1) : coords2 = "".concat(utf8Start2 + 1, ",").concat(utf8Length2);
|
|
1456
|
-
const text = ["@@ -".concat(coords1, " +").concat(coords2, ` @@
|
|
1457
|
-
`)];
|
|
1458
|
-
let op;
|
|
1459
|
-
for (let x = 0; x < diffs.length; x++) {
|
|
1460
|
-
switch (diffs[x][0]) {
|
|
1461
|
-
case DIFF_INSERT:
|
|
1462
|
-
op = "+";
|
|
1463
|
-
break;
|
|
1464
|
-
case DIFF_DELETE:
|
|
1465
|
-
op = "-";
|
|
1466
|
-
break;
|
|
1467
|
-
case DIFF_EQUAL:
|
|
1468
|
-
op = " ";
|
|
1469
|
-
break;
|
|
1470
|
-
default:
|
|
1471
|
-
throw new Error("Unknown patch operation.");
|
|
1472
|
-
}
|
|
1473
|
-
text[x + 1] = "".concat(op + encodeURI(diffs[x][1]), `
|
|
1474
|
-
`);
|
|
1475
|
-
}
|
|
1476
|
-
return text.join("").replace(/%20/g, " ");
|
|
1477
|
-
}
|
|
1478
|
-
const patchHeader = /^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;
|
|
1479
|
-
function parse(textline) {
|
|
1480
|
-
if (!textline)
|
|
1481
|
-
return [];
|
|
1482
|
-
const patches = [], lines = textline.split(`
|
|
1483
|
-
`);
|
|
1484
|
-
let textPointer = 0;
|
|
1485
|
-
for (; textPointer < lines.length; ) {
|
|
1486
|
-
const m = lines[textPointer].match(patchHeader);
|
|
1487
|
-
if (!m)
|
|
1488
|
-
throw new Error("Invalid patch string: ".concat(lines[textPointer]));
|
|
1489
|
-
const patch = createPatchObject(toInt(m[1]), toInt(m[3]));
|
|
1490
|
-
for (patches.push(patch), m[2] === "" ? (patch.start1--, patch.utf8Start1--, patch.length1 = 1, patch.utf8Length1 = 1) : m[2] === "0" ? (patch.length1 = 0, patch.utf8Length1 = 0) : (patch.start1--, patch.utf8Start1--, patch.utf8Length1 = toInt(m[2]), patch.length1 = patch.utf8Length1), m[4] === "" ? (patch.start2--, patch.utf8Start2--, patch.length2 = 1, patch.utf8Length2 = 1) : m[4] === "0" ? (patch.length2 = 0, patch.utf8Length2 = 0) : (patch.start2--, patch.utf8Start2--, patch.utf8Length2 = toInt(m[4]), patch.length2 = patch.utf8Length2), textPointer++; textPointer < lines.length; ) {
|
|
1491
|
-
const currentLine = lines[textPointer], sign = currentLine.charAt(0);
|
|
1492
|
-
if (sign === "@")
|
|
1493
|
-
break;
|
|
1494
|
-
if (sign === "") {
|
|
1495
|
-
textPointer++;
|
|
1496
|
-
continue;
|
|
1497
|
-
}
|
|
1498
|
-
let line;
|
|
1499
|
-
try {
|
|
1500
|
-
line = decodeURI(currentLine.slice(1));
|
|
1501
|
-
} catch {
|
|
1502
|
-
throw new Error("Illegal escape in parse: ".concat(currentLine));
|
|
1503
|
-
}
|
|
1504
|
-
const utf8Diff = countUtf8Bytes(line) - line.length;
|
|
1505
|
-
if (sign === "-")
|
|
1506
|
-
patch.diffs.push([DIFF_DELETE, line]), patch.length1 -= utf8Diff;
|
|
1507
|
-
else if (sign === "+")
|
|
1508
|
-
patch.diffs.push([DIFF_INSERT, line]), patch.length2 -= utf8Diff;
|
|
1509
|
-
else if (sign === " ")
|
|
1510
|
-
patch.diffs.push([DIFF_EQUAL, line]), patch.length1 -= utf8Diff, patch.length2 -= utf8Diff;
|
|
1511
|
-
else
|
|
1512
|
-
throw new Error('Invalid patch mode "'.concat(sign, '" in: ').concat(line));
|
|
1513
|
-
textPointer++;
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
return patches;
|
|
1517
|
-
}
|
|
1518
|
-
function toInt(num) {
|
|
1519
|
-
return parseInt(num, 10);
|
|
1520
|
-
}
|
|
1521
|
-
function setIfMissing(value, path = []) {
|
|
1522
|
-
return {
|
|
1523
|
-
type: "setIfMissing",
|
|
1524
|
-
path,
|
|
1525
|
-
value
|
|
1526
|
-
};
|
|
1527
|
-
}
|
|
1528
|
-
function diffMatchPatch$1(currentValue, nextValue, path = []) {
|
|
1529
|
-
const patches = make(currentValue, nextValue), patch = stringify(patches);
|
|
1530
|
-
return { type: "diffMatchPatch", path, value: patch };
|
|
1531
|
-
}
|
|
1532
|
-
function insert$1(items, position, path = []) {
|
|
1533
|
-
return {
|
|
1534
|
-
type: "insert",
|
|
1535
|
-
path,
|
|
1536
|
-
position,
|
|
1537
|
-
items
|
|
1538
|
-
};
|
|
1539
|
-
}
|
|
1540
|
-
function set(value, path = []) {
|
|
1541
|
-
return { type: "set", path, value };
|
|
1542
|
-
}
|
|
1543
|
-
function unset(path = []) {
|
|
1544
|
-
return { type: "unset", path };
|
|
1545
|
-
}
|
|
1546
|
-
const debug$j = debugWithName("operationToPatches");
|
|
1547
|
-
debug$j.enabled = !1;
|
|
1548
|
-
function createOperationToPatches(types) {
|
|
1549
|
-
const textBlockName = types.block.name;
|
|
1550
|
-
function insertTextPatch(editor, operation, beforeValue) {
|
|
1551
|
-
debug$j.enabled && debug$j("Operation", JSON.stringify(operation, null, 2));
|
|
1552
|
-
const block = editor.isTextBlock(editor.children[operation.path[0]]) && editor.children[operation.path[0]];
|
|
1553
|
-
if (!block)
|
|
1554
|
-
throw new Error("Could not find block");
|
|
1555
|
-
const textChild = editor.isTextBlock(block) && editor.isTextSpan(block.children[operation.path[1]]) && block.children[operation.path[1]];
|
|
1556
|
-
if (!textChild)
|
|
1557
|
-
throw new Error("Could not find child");
|
|
1558
|
-
const path = [{ _key: block._key }, "children", { _key: textChild._key }, "text"], prevBlock = beforeValue[operation.path[0]], prevChild = editor.isTextBlock(prevBlock) && prevBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevChild) ? prevChild.text : "", patch = diffMatchPatch$1(prevText, textChild.text, path);
|
|
1559
|
-
return patch.value.length ? [patch] : [];
|
|
1560
|
-
}
|
|
1561
|
-
function removeTextPatch(editor, operation, beforeValue) {
|
|
1562
|
-
const block = editor && editor.children[operation.path[0]];
|
|
1563
|
-
if (!block)
|
|
1564
|
-
throw new Error("Could not find block");
|
|
1565
|
-
const child = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, textChild = editor.isTextSpan(child) ? child : void 0;
|
|
1566
|
-
if (child && !textChild)
|
|
1567
|
-
throw new Error("Expected span");
|
|
1568
|
-
if (!textChild)
|
|
1569
|
-
throw new Error("Could not find child");
|
|
1570
|
-
const path = [{ _key: block._key }, "children", { _key: textChild._key }, "text"], beforeBlock = beforeValue[operation.path[0]], prevTextChild = editor.isTextBlock(beforeBlock) && beforeBlock.children[operation.path[1]], prevText = editor.isTextSpan(prevTextChild) && prevTextChild.text, patch = diffMatchPatch$1(prevText || "", textChild.text, path);
|
|
1571
|
-
return patch.value ? [patch] : [];
|
|
1572
|
-
}
|
|
1573
|
-
function setNodePatch(editor, operation) {
|
|
1574
|
-
if (operation.path.length === 1) {
|
|
1575
|
-
const block = editor.children[operation.path[0]];
|
|
1576
|
-
if (typeof block._key != "string")
|
|
1577
|
-
throw new Error("Expected block to have a _key");
|
|
1578
|
-
const setNode = omitBy(
|
|
1579
|
-
{ ...editor.children[operation.path[0]], ...operation.newProperties },
|
|
1580
|
-
isUndefined
|
|
1581
|
-
);
|
|
1582
|
-
return [set(fromSlateValue([setNode], textBlockName)[0], [{ _key: block._key }])];
|
|
1583
|
-
} else if (operation.path.length === 2) {
|
|
1584
|
-
const block = editor.children[operation.path[0]];
|
|
1585
|
-
if (editor.isTextBlock(block)) {
|
|
1586
|
-
const child = block.children[operation.path[1]];
|
|
1587
|
-
if (child) {
|
|
1588
|
-
const blockKey = block._key, childKey = child._key, patches = [], keys = Object.keys(operation.newProperties);
|
|
1589
|
-
return keys.forEach((keyName) => {
|
|
1590
|
-
if (keys.length === 1 && keyName === "_key") {
|
|
1591
|
-
const val = get(operation.newProperties, keyName);
|
|
1592
|
-
patches.push(
|
|
1593
|
-
set(val, [{ _key: blockKey }, "children", block.children.indexOf(child), keyName])
|
|
1594
|
-
);
|
|
1595
|
-
} else {
|
|
1596
|
-
const val = get(operation.newProperties, keyName);
|
|
1597
|
-
patches.push(set(val, [{ _key: blockKey }, "children", { _key: childKey }, keyName]));
|
|
1598
|
-
}
|
|
1599
|
-
}), patches;
|
|
1600
|
-
}
|
|
1601
|
-
throw new Error("Could not find a valid child");
|
|
1602
|
-
}
|
|
1603
|
-
throw new Error("Could not find a valid block");
|
|
1604
|
-
} else
|
|
1605
|
-
throw new Error(`Unexpected path encountered: ${JSON.stringify(operation.path)}`);
|
|
1606
|
-
}
|
|
1607
|
-
function insertNodePatch(editor, operation, beforeValue) {
|
|
1608
|
-
const block = beforeValue[operation.path[0]], isTextBlock = editor.isTextBlock(block);
|
|
1609
|
-
if (operation.path.length === 1) {
|
|
1610
|
-
const position = operation.path[0] === 0 ? "before" : "after", beforeBlock = beforeValue[operation.path[0] - 1], targetKey = operation.path[0] === 0 ? block == null ? void 0 : block._key : beforeBlock == null ? void 0 : beforeBlock._key;
|
|
1611
|
-
return targetKey ? [
|
|
1612
|
-
insert$1([fromSlateValue([operation.node], textBlockName)[0]], position, [
|
|
1613
|
-
{ _key: targetKey }
|
|
1614
|
-
])
|
|
1615
|
-
] : [
|
|
1616
|
-
setIfMissing(beforeValue, []),
|
|
1617
|
-
insert$1([fromSlateValue([operation.node], textBlockName)[0]], "before", [
|
|
1618
|
-
operation.path[0]
|
|
1619
|
-
])
|
|
1620
|
-
];
|
|
1621
|
-
} else if (isTextBlock && operation.path.length === 2 && editor.children[operation.path[0]]) {
|
|
1622
|
-
const position = block.children.length === 0 || !block.children[operation.path[1] - 1] ? "before" : "after", node = { ...operation.node };
|
|
1623
|
-
!node._type && Text.isText(node) && (node._type = "span", node.marks = []);
|
|
1624
|
-
const child = fromSlateValue(
|
|
1625
|
-
[
|
|
1626
|
-
{
|
|
1627
|
-
_key: "bogus",
|
|
1628
|
-
_type: textBlockName,
|
|
1629
|
-
children: [node]
|
|
1630
|
-
}
|
|
1631
|
-
],
|
|
1632
|
-
textBlockName
|
|
1633
|
-
)[0].children[0];
|
|
1634
|
-
return [
|
|
1635
|
-
insert$1([child], position, [
|
|
1636
|
-
{ _key: block._key },
|
|
1637
|
-
"children",
|
|
1638
|
-
block.children.length <= 1 || !block.children[operation.path[1] - 1] ? 0 : { _key: block.children[operation.path[1] - 1]._key }
|
|
1639
|
-
])
|
|
1640
|
-
];
|
|
1641
|
-
}
|
|
1642
|
-
return debug$j("Something was inserted into a void block. Not producing editor patches."), [];
|
|
1643
|
-
}
|
|
1644
|
-
function splitNodePatch(editor, operation, beforeValue) {
|
|
1645
|
-
const patches = [], splitBlock = editor.children[operation.path[0]];
|
|
1646
|
-
if (!editor.isTextBlock(splitBlock))
|
|
1647
|
-
throw new Error(
|
|
1648
|
-
`Block with path ${JSON.stringify(
|
|
1649
|
-
operation.path[0]
|
|
1650
|
-
)} is not a text block and can't be split`
|
|
1651
|
-
);
|
|
1652
|
-
if (operation.path.length === 1) {
|
|
1653
|
-
const oldBlock = beforeValue[operation.path[0]];
|
|
1654
|
-
if (editor.isTextBlock(oldBlock)) {
|
|
1655
|
-
const targetValue = fromSlateValue(
|
|
1656
|
-
[editor.children[operation.path[0] + 1]],
|
|
1657
|
-
textBlockName
|
|
1658
|
-
)[0];
|
|
1659
|
-
targetValue && (patches.push(insert$1([targetValue], "after", [{ _key: splitBlock._key }])), oldBlock.children.slice(operation.position).forEach((span) => {
|
|
1660
|
-
const path = [{ _key: oldBlock._key }, "children", { _key: span._key }];
|
|
1661
|
-
patches.push(unset(path));
|
|
1662
|
-
}));
|
|
1663
|
-
}
|
|
1664
|
-
return patches;
|
|
1665
|
-
}
|
|
1666
|
-
if (operation.path.length === 2) {
|
|
1667
|
-
const splitSpan = splitBlock.children[operation.path[1]];
|
|
1668
|
-
if (editor.isTextSpan(splitSpan)) {
|
|
1669
|
-
const targetSpans = fromSlateValue(
|
|
1670
|
-
[
|
|
1671
|
-
{
|
|
1672
|
-
...splitBlock,
|
|
1673
|
-
children: splitBlock.children.slice(operation.path[1] + 1, operation.path[1] + 2)
|
|
1674
|
-
}
|
|
1675
|
-
],
|
|
1676
|
-
textBlockName
|
|
1677
|
-
)[0].children;
|
|
1678
|
-
patches.push(
|
|
1679
|
-
insert$1(targetSpans, "after", [
|
|
1680
|
-
{ _key: splitBlock._key },
|
|
1681
|
-
"children",
|
|
1682
|
-
{ _key: splitSpan._key }
|
|
1683
|
-
])
|
|
1684
|
-
), patches.push(
|
|
1685
|
-
set(splitSpan.text, [
|
|
1686
|
-
{ _key: splitBlock._key },
|
|
1687
|
-
"children",
|
|
1688
|
-
{ _key: splitSpan._key },
|
|
1689
|
-
"text"
|
|
1690
|
-
])
|
|
1691
|
-
);
|
|
1692
|
-
}
|
|
1693
|
-
return patches;
|
|
1694
|
-
}
|
|
1695
|
-
return patches;
|
|
1696
|
-
}
|
|
1697
|
-
function removeNodePatch(editor, operation, beforeValue) {
|
|
1698
|
-
const block = beforeValue[operation.path[0]];
|
|
1699
|
-
if (operation.path.length === 1) {
|
|
1700
|
-
if (block && block._key)
|
|
1701
|
-
return [unset([{ _key: block._key }])];
|
|
1702
|
-
throw new Error("Block not found");
|
|
1703
|
-
} else if (editor.isTextBlock(block) && operation.path.length === 2) {
|
|
1704
|
-
const spanToRemove = editor.isTextBlock(block) && block.children && block.children[operation.path[1]];
|
|
1705
|
-
return spanToRemove ? [unset([{ _key: block._key }, "children", { _key: spanToRemove._key }])] : (debug$j("Span not found in editor trying to remove node"), []);
|
|
1706
|
-
} else
|
|
1707
|
-
return debug$j("Not creating patch inside object block"), [];
|
|
1708
|
-
}
|
|
1709
|
-
function mergeNodePatch(editor, operation, beforeValue) {
|
|
1710
|
-
const patches = [], block = beforeValue[operation.path[0]], targetBlock = editor.children[operation.path[0]];
|
|
1711
|
-
if (operation.path.length === 1)
|
|
1712
|
-
if (block != null && block._key) {
|
|
1713
|
-
const newBlock = fromSlateValue([editor.children[operation.path[0] - 1]], textBlockName)[0];
|
|
1714
|
-
patches.push(set(newBlock, [{ _key: newBlock._key }])), patches.push(unset([{ _key: block._key }]));
|
|
1715
|
-
} else
|
|
1716
|
-
throw new Error("Target key not found!");
|
|
1717
|
-
else if (operation.path.length === 2 && editor.isTextBlock(targetBlock)) {
|
|
1718
|
-
const mergedSpan = editor.isTextBlock(block) && block.children[operation.path[1]] || void 0, targetSpan = targetBlock.children[operation.path[1] - 1];
|
|
1719
|
-
editor.isTextSpan(targetSpan) && (patches.push(
|
|
1720
|
-
set(targetSpan.text, [{ _key: block._key }, "children", { _key: targetSpan._key }, "text"])
|
|
1721
|
-
), mergedSpan && patches.push(unset([{ _key: block._key }, "children", { _key: mergedSpan._key }])));
|
|
1722
|
-
} else
|
|
1723
|
-
debug$j("Void nodes can't be merged, not creating any patches");
|
|
1724
|
-
return patches;
|
|
1725
|
-
}
|
|
1726
|
-
function moveNodePatch(editor, operation, beforeValue) {
|
|
1727
|
-
const patches = [], block = beforeValue[operation.path[0]], targetBlock = beforeValue[operation.newPath[0]];
|
|
1728
|
-
if (operation.path.length === 1) {
|
|
1729
|
-
const position = operation.path[0] > operation.newPath[0] ? "before" : "after";
|
|
1730
|
-
patches.push(unset([{ _key: block._key }])), patches.push(
|
|
1731
|
-
insert$1([fromSlateValue([block], textBlockName)[0]], position, [{ _key: targetBlock._key }])
|
|
1732
|
-
);
|
|
1733
|
-
} else if (operation.path.length === 2 && editor.isTextBlock(block) && editor.isTextBlock(targetBlock)) {
|
|
1734
|
-
const child = block.children[operation.path[1]], targetChild = targetBlock.children[operation.newPath[1]], position = operation.newPath[1] === targetBlock.children.length ? "after" : "before", childToInsert = fromSlateValue([block], textBlockName)[0].children[operation.path[1]];
|
|
1735
|
-
patches.push(unset([{ _key: block._key }, "children", { _key: child._key }])), patches.push(
|
|
1736
|
-
insert$1([childToInsert], position, [
|
|
1737
|
-
{ _key: targetBlock._key },
|
|
1738
|
-
"children",
|
|
1739
|
-
{ _key: targetChild._key }
|
|
1740
|
-
])
|
|
1741
|
-
);
|
|
1742
|
-
}
|
|
1743
|
-
return patches;
|
|
1744
|
-
}
|
|
1745
|
-
return {
|
|
1746
|
-
insertNodePatch,
|
|
1747
|
-
insertTextPatch,
|
|
1748
|
-
mergeNodePatch,
|
|
1749
|
-
moveNodePatch,
|
|
1750
|
-
removeNodePatch,
|
|
1751
|
-
removeTextPatch,
|
|
1752
|
-
setNodePatch,
|
|
1753
|
-
splitNodePatch
|
|
1754
|
-
};
|
|
1755
|
-
}
|
|
1756
|
-
const debug$i = debugWithName("API:editable");
|
|
1757
|
-
function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
1758
|
-
return function(editor) {
|
|
1759
|
-
return portableTextEditor.setEditable({
|
|
1760
|
-
focus: () => {
|
|
1761
|
-
ReactEditor.focus(editor);
|
|
1762
|
-
},
|
|
1763
|
-
blur: () => {
|
|
1764
|
-
ReactEditor.blur(editor);
|
|
1765
|
-
},
|
|
1766
|
-
toggleMark: (mark) => {
|
|
1767
|
-
editor.pteToggleMark(mark);
|
|
1768
|
-
},
|
|
1769
|
-
toggleList: (listStyle) => {
|
|
1770
|
-
editor.pteToggleListItem(listStyle);
|
|
1771
|
-
},
|
|
1772
|
-
toggleBlockStyle: (blockStyle) => {
|
|
1773
|
-
editor.pteToggleBlockStyle(blockStyle);
|
|
1774
|
-
},
|
|
1775
|
-
isMarkActive: (mark) => {
|
|
1776
|
-
try {
|
|
1777
|
-
return editor.pteIsMarkActive(mark);
|
|
1778
|
-
} catch (err) {
|
|
1779
|
-
return console.warn(err), !1;
|
|
932
|
+
const debug$i = debugWithName("API:editable");
|
|
933
|
+
function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
934
|
+
return function(editor) {
|
|
935
|
+
return portableTextEditor.setEditable({
|
|
936
|
+
focus: () => {
|
|
937
|
+
ReactEditor.focus(editor);
|
|
938
|
+
},
|
|
939
|
+
blur: () => {
|
|
940
|
+
ReactEditor.blur(editor);
|
|
941
|
+
},
|
|
942
|
+
toggleMark: (mark) => {
|
|
943
|
+
editor.pteToggleMark(mark);
|
|
944
|
+
},
|
|
945
|
+
toggleList: (listStyle) => {
|
|
946
|
+
editor.pteToggleListItem(listStyle);
|
|
947
|
+
},
|
|
948
|
+
toggleBlockStyle: (blockStyle) => {
|
|
949
|
+
editor.pteToggleBlockStyle(blockStyle);
|
|
950
|
+
},
|
|
951
|
+
isMarkActive: (mark) => {
|
|
952
|
+
try {
|
|
953
|
+
return editor.pteIsMarkActive(mark);
|
|
954
|
+
} catch (err) {
|
|
955
|
+
return console.warn(err), !1;
|
|
1780
956
|
}
|
|
1781
957
|
},
|
|
1782
958
|
marks: () => ({
|
|
@@ -2054,300 +1230,828 @@ function createWithEditableAPI(portableTextEditor, types, keyGenerator) {
|
|
|
2054
1230
|
})), editor.children.length === 0 && (editor.children = [editor.pteCreateEmptyBlock()]), editor.onChange();
|
|
2055
1231
|
}
|
|
2056
1232
|
}
|
|
2057
|
-
},
|
|
2058
|
-
removeAnnotation: (type) => {
|
|
2059
|
-
let { selection } = editor;
|
|
2060
|
-
if (debug$i("Removing annotation", type), selection) {
|
|
2061
|
-
if (Range.isCollapsed(selection)) {
|
|
2062
|
-
const [node, nodePath] = Editor.node(editor, selection, { depth: 2 });
|
|
2063
|
-
Text.isText(node) && node.marks && typeof node.text == "string" && (Transforms.select(editor, nodePath), selection = editor.selection);
|
|
2064
|
-
}
|
|
2065
|
-
Editor.withoutNormalizing(editor, () => {
|
|
2066
|
-
if (selection && Range.isExpanded(selection)) {
|
|
2067
|
-
if (selection = editor.selection, !selection)
|
|
2068
|
-
return;
|
|
2069
|
-
[
|
|
2070
|
-
...Editor.nodes(editor, {
|
|
2071
|
-
at: selection,
|
|
2072
|
-
match: (node) => editor.isTextBlock(node) && Array.isArray(node.markDefs) && node.markDefs.some((def) => def._type === type.name)
|
|
2073
|
-
})
|
|
2074
|
-
].forEach(([block]) => {
|
|
2075
|
-
editor.isTextBlock(block) && Array.isArray(block.markDefs) && block.markDefs.filter((def) => def._type === type.name).forEach((def) => {
|
|
2076
|
-
Editor.removeMark(editor, def._key);
|
|
2077
|
-
});
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
}), Editor.normalize(editor), editor.onChange();
|
|
1233
|
+
},
|
|
1234
|
+
removeAnnotation: (type) => {
|
|
1235
|
+
let { selection } = editor;
|
|
1236
|
+
if (debug$i("Removing annotation", type), selection) {
|
|
1237
|
+
if (Range.isCollapsed(selection)) {
|
|
1238
|
+
const [node, nodePath] = Editor.node(editor, selection, { depth: 2 });
|
|
1239
|
+
Text.isText(node) && node.marks && typeof node.text == "string" && (Transforms.select(editor, nodePath), selection = editor.selection);
|
|
1240
|
+
}
|
|
1241
|
+
Editor.withoutNormalizing(editor, () => {
|
|
1242
|
+
if (selection && Range.isExpanded(selection)) {
|
|
1243
|
+
if (selection = editor.selection, !selection)
|
|
1244
|
+
return;
|
|
1245
|
+
[
|
|
1246
|
+
...Editor.nodes(editor, {
|
|
1247
|
+
at: selection,
|
|
1248
|
+
match: (node) => editor.isTextBlock(node) && Array.isArray(node.markDefs) && node.markDefs.some((def) => def._type === type.name)
|
|
1249
|
+
})
|
|
1250
|
+
].forEach(([block]) => {
|
|
1251
|
+
editor.isTextBlock(block) && Array.isArray(block.markDefs) && block.markDefs.filter((def) => def._type === type.name).forEach((def) => {
|
|
1252
|
+
Editor.removeMark(editor, def._key);
|
|
1253
|
+
});
|
|
1254
|
+
});
|
|
1255
|
+
}
|
|
1256
|
+
}), Editor.normalize(editor), editor.onChange();
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
getSelection: () => {
|
|
1260
|
+
let ptRange = null;
|
|
1261
|
+
if (editor.selection) {
|
|
1262
|
+
const existing = SLATE_TO_PORTABLE_TEXT_RANGE.get(editor.selection);
|
|
1263
|
+
if (existing)
|
|
1264
|
+
return existing;
|
|
1265
|
+
ptRange = toPortableTextRange(
|
|
1266
|
+
fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)),
|
|
1267
|
+
editor.selection,
|
|
1268
|
+
types
|
|
1269
|
+
), SLATE_TO_PORTABLE_TEXT_RANGE.set(editor.selection, ptRange);
|
|
1270
|
+
}
|
|
1271
|
+
return ptRange;
|
|
1272
|
+
},
|
|
1273
|
+
getValue: () => fromSlateValue(editor.children, types.block.name, KEY_TO_VALUE_ELEMENT.get(editor)),
|
|
1274
|
+
isCollapsedSelection: () => !!editor.selection && Range.isCollapsed(editor.selection),
|
|
1275
|
+
isExpandedSelection: () => !!editor.selection && Range.isExpanded(editor.selection),
|
|
1276
|
+
insertBreak: () => {
|
|
1277
|
+
editor.insertBreak(), editor.onChange();
|
|
1278
|
+
},
|
|
1279
|
+
getFragment: () => fromSlateValue(editor.getFragment(), types.block.name),
|
|
1280
|
+
isSelectionsOverlapping: (selectionA, selectionB) => {
|
|
1281
|
+
const rangeA = toSlateRange(selectionA, editor), rangeB = toSlateRange(selectionB, editor);
|
|
1282
|
+
return Range.isRange(rangeA) && Range.isRange(rangeB) && Range.includes(rangeA, rangeB);
|
|
1283
|
+
}
|
|
1284
|
+
}), editor;
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
function createWithInsertBreak(types) {
|
|
1288
|
+
return function(editor) {
|
|
1289
|
+
const { insertBreak } = editor;
|
|
1290
|
+
return editor.insertBreak = () => {
|
|
1291
|
+
if (editor.selection) {
|
|
1292
|
+
const focusBlockPath = editor.selection.focus.path.slice(0, 1), focusBlock = Node.descendant(editor, focusBlockPath);
|
|
1293
|
+
if (editor.isTextBlock(focusBlock)) {
|
|
1294
|
+
const [, end] = Range.edges(editor.selection), isEndAtStartOfNode = Editor.isStart(editor, end, end.path), isEmptyTextBlock = focusBlock && isEqualToEmptyEditor([focusBlock], types);
|
|
1295
|
+
if (isEndAtStartOfNode && !isEmptyTextBlock) {
|
|
1296
|
+
Editor.insertNode(editor, editor.pteCreateEmptyBlock());
|
|
1297
|
+
const [nextBlockPath] = Path.next(focusBlockPath);
|
|
1298
|
+
Transforms.select(editor, {
|
|
1299
|
+
anchor: { path: [nextBlockPath, 0], offset: 0 },
|
|
1300
|
+
focus: { path: [nextBlockPath, 0], offset: 0 }
|
|
1301
|
+
}), editor.onChange();
|
|
1302
|
+
return;
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
insertBreak();
|
|
1307
|
+
}, editor;
|
|
1308
|
+
};
|
|
1309
|
+
}
|
|
1310
|
+
function createWithMaxBlocks(maxBlocks) {
|
|
1311
|
+
return function(editor) {
|
|
1312
|
+
const { apply: apply2 } = editor;
|
|
1313
|
+
return editor.apply = (operation) => {
|
|
1314
|
+
const rows = maxBlocks;
|
|
1315
|
+
rows > 0 && editor.children.length >= rows && (operation.type === "insert_node" || operation.type === "split_node") && operation.path.length === 1 || apply2(operation);
|
|
1316
|
+
}, editor;
|
|
1317
|
+
};
|
|
1318
|
+
}
|
|
1319
|
+
const PRESERVE_KEYS = /* @__PURE__ */ new WeakMap();
|
|
1320
|
+
function withPreserveKeys(editor, fn) {
|
|
1321
|
+
const prev = isPreservingKeys(editor);
|
|
1322
|
+
PRESERVE_KEYS.set(editor, !0), fn(), PRESERVE_KEYS.set(editor, prev);
|
|
1323
|
+
}
|
|
1324
|
+
function isPreservingKeys(editor) {
|
|
1325
|
+
return PRESERVE_KEYS.get(editor);
|
|
1326
|
+
}
|
|
1327
|
+
function createWithObjectKeys(schemaTypes, keyGenerator) {
|
|
1328
|
+
return function(editor) {
|
|
1329
|
+
PRESERVE_KEYS.set(editor, !1);
|
|
1330
|
+
const { apply: apply2, normalizeNode } = editor;
|
|
1331
|
+
return editor.apply = (operation) => {
|
|
1332
|
+
if (operation.type === "split_node") {
|
|
1333
|
+
const withNewKey = !isPreservingKeys(editor) || !("_key" in operation.properties);
|
|
1334
|
+
operation.properties = {
|
|
1335
|
+
...operation.properties,
|
|
1336
|
+
...withNewKey ? { _key: keyGenerator() } : {}
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
if (operation.type === "insert_node") {
|
|
1340
|
+
const withNewKey = !isPreservingKeys(editor) || !("_key" in operation.node);
|
|
1341
|
+
Editor.isEditor(operation.node) || (operation.node = {
|
|
1342
|
+
...operation.node,
|
|
1343
|
+
...withNewKey ? { _key: keyGenerator() } : {}
|
|
1344
|
+
});
|
|
1345
|
+
}
|
|
1346
|
+
apply2(operation);
|
|
1347
|
+
}, editor.normalizeNode = (entry) => {
|
|
1348
|
+
const [node, path] = entry;
|
|
1349
|
+
if (Element$1.isElement(node) && node._type === schemaTypes.block.name) {
|
|
1350
|
+
node._key || Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path });
|
|
1351
|
+
for (const [child, childPath] of Node.children(editor, path))
|
|
1352
|
+
if (!child._key) {
|
|
1353
|
+
Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
|
|
1354
|
+
return;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
normalizeNode(entry);
|
|
1358
|
+
}, editor;
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
function isHighSurrogate(char) {
|
|
1362
|
+
const charCode = char.charCodeAt(0);
|
|
1363
|
+
return charCode >= 55296 && charCode <= 56319;
|
|
1364
|
+
}
|
|
1365
|
+
function isLowSurrogate(char) {
|
|
1366
|
+
const charCode = char.charCodeAt(0);
|
|
1367
|
+
return charCode >= 56320 && charCode <= 57343;
|
|
1368
|
+
}
|
|
1369
|
+
function cloneDiff(diff2) {
|
|
1370
|
+
const [type, patch] = diff2;
|
|
1371
|
+
return [type, patch];
|
|
1372
|
+
}
|
|
1373
|
+
function getCommonOverlap(textA, textB) {
|
|
1374
|
+
let text1 = textA, text2 = textB;
|
|
1375
|
+
const text1Length = text1.length, text2Length = text2.length;
|
|
1376
|
+
if (text1Length === 0 || text2Length === 0)
|
|
1377
|
+
return 0;
|
|
1378
|
+
text1Length > text2Length ? text1 = text1.substring(text1Length - text2Length) : text1Length < text2Length && (text2 = text2.substring(0, text1Length));
|
|
1379
|
+
const textLength = Math.min(text1Length, text2Length);
|
|
1380
|
+
if (text1 === text2)
|
|
1381
|
+
return textLength;
|
|
1382
|
+
let best = 0, length = 1;
|
|
1383
|
+
for (let found = 0; found !== -1; ) {
|
|
1384
|
+
const pattern = text1.substring(textLength - length);
|
|
1385
|
+
if (found = text2.indexOf(pattern), found === -1)
|
|
1386
|
+
return best;
|
|
1387
|
+
length += found, (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) && (best = length, length++);
|
|
1388
|
+
}
|
|
1389
|
+
return best;
|
|
1390
|
+
}
|
|
1391
|
+
function getCommonPrefix(text1, text2) {
|
|
1392
|
+
if (!text1 || !text2 || text1[0] !== text2[0])
|
|
1393
|
+
return 0;
|
|
1394
|
+
let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerStart = 0;
|
|
1395
|
+
for (; pointerMin < pointerMid; )
|
|
1396
|
+
text1.substring(pointerStart, pointerMid) === text2.substring(pointerStart, pointerMid) ? (pointerMin = pointerMid, pointerStart = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
|
|
1397
|
+
return pointerMid;
|
|
1398
|
+
}
|
|
1399
|
+
function getCommonSuffix(text1, text2) {
|
|
1400
|
+
if (!text1 || !text2 || text1[text1.length - 1] !== text2[text2.length - 1])
|
|
1401
|
+
return 0;
|
|
1402
|
+
let pointerMin = 0, pointerMax = Math.min(text1.length, text2.length), pointerMid = pointerMax, pointerEnd = 0;
|
|
1403
|
+
for (; pointerMin < pointerMid; )
|
|
1404
|
+
text1.substring(text1.length - pointerMid, text1.length - pointerEnd) === text2.substring(text2.length - pointerMid, text2.length - pointerEnd) ? (pointerMin = pointerMid, pointerEnd = pointerMin) : pointerMax = pointerMid, pointerMid = Math.floor((pointerMax - pointerMin) / 2 + pointerMin);
|
|
1405
|
+
return pointerMid;
|
|
1406
|
+
}
|
|
1407
|
+
function cleanupSemantic(rawDiffs) {
|
|
1408
|
+
let diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
|
|
1409
|
+
const equalities = [];
|
|
1410
|
+
let equalitiesLength = 0, lastEquality = null, pointer = 0, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0;
|
|
1411
|
+
for (; pointer < diffs.length; )
|
|
1412
|
+
diffs[pointer][0] === DIFF_EQUAL ? (equalities[equalitiesLength++] = pointer, lengthInsertions1 = lengthInsertions2, lengthDeletions1 = lengthDeletions2, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = diffs[pointer][1]) : (diffs[pointer][0] === DIFF_INSERT ? lengthInsertions2 += diffs[pointer][1].length : lengthDeletions2 += diffs[pointer][1].length, lastEquality && lastEquality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastEquality.length <= Math.max(lengthInsertions2, lengthDeletions2) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, lengthInsertions1 = 0, lengthDeletions1 = 0, lengthInsertions2 = 0, lengthDeletions2 = 0, lastEquality = null, hasChanges = !0)), pointer++;
|
|
1413
|
+
for (hasChanges && (diffs = cleanupMerge(diffs)), diffs = cleanupSemanticLossless(diffs), pointer = 1; pointer < diffs.length; ) {
|
|
1414
|
+
if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
|
|
1415
|
+
const deletion = diffs[pointer - 1][1], insertion = diffs[pointer][1], overlapLength1 = getCommonOverlap(deletion, insertion), overlapLength2 = getCommonOverlap(insertion, deletion);
|
|
1416
|
+
overlapLength1 >= overlapLength2 ? (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]), diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1), diffs[pointer + 1][1] = insertion.substring(overlapLength1), pointer++) : (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) && (diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]), diffs[pointer - 1][0] = DIFF_INSERT, diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2), diffs[pointer + 1][0] = DIFF_DELETE, diffs[pointer + 1][1] = deletion.substring(overlapLength2), pointer++), pointer++;
|
|
1417
|
+
}
|
|
1418
|
+
pointer++;
|
|
1419
|
+
}
|
|
1420
|
+
return diffs;
|
|
1421
|
+
}
|
|
1422
|
+
const nonAlphaNumericRegex = /[^a-zA-Z0-9]/, whitespaceRegex = /\s/, linebreakRegex = /[\r\n]/, blanklineEndRegex = /\n\r?\n$/, blanklineStartRegex = /^\r?\n\r?\n/;
|
|
1423
|
+
function cleanupSemanticLossless(rawDiffs) {
|
|
1424
|
+
const diffs = rawDiffs.map((diff2) => cloneDiff(diff2));
|
|
1425
|
+
function diffCleanupSemanticScore(one, two) {
|
|
1426
|
+
if (!one || !two)
|
|
1427
|
+
return 6;
|
|
1428
|
+
const char1 = one.charAt(one.length - 1), char2 = two.charAt(0), nonAlphaNumeric1 = char1.match(nonAlphaNumericRegex), nonAlphaNumeric2 = char2.match(nonAlphaNumericRegex), whitespace1 = nonAlphaNumeric1 && char1.match(whitespaceRegex), whitespace2 = nonAlphaNumeric2 && char2.match(whitespaceRegex), lineBreak1 = whitespace1 && char1.match(linebreakRegex), lineBreak2 = whitespace2 && char2.match(linebreakRegex), blankLine1 = lineBreak1 && one.match(blanklineEndRegex), blankLine2 = lineBreak2 && two.match(blanklineStartRegex);
|
|
1429
|
+
return blankLine1 || blankLine2 ? 5 : lineBreak1 || lineBreak2 ? 4 : nonAlphaNumeric1 && !whitespace1 && whitespace2 ? 3 : whitespace1 || whitespace2 ? 2 : nonAlphaNumeric1 || nonAlphaNumeric2 ? 1 : 0;
|
|
1430
|
+
}
|
|
1431
|
+
let pointer = 1;
|
|
1432
|
+
for (; pointer < diffs.length - 1; ) {
|
|
1433
|
+
if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
|
|
1434
|
+
let equality1 = diffs[pointer - 1][1], edit = diffs[pointer][1], equality2 = diffs[pointer + 1][1];
|
|
1435
|
+
const commonOffset = getCommonSuffix(equality1, edit);
|
|
1436
|
+
if (commonOffset) {
|
|
1437
|
+
const commonString = edit.substring(edit.length - commonOffset);
|
|
1438
|
+
equality1 = equality1.substring(0, equality1.length - commonOffset), edit = commonString + edit.substring(0, edit.length - commonOffset), equality2 = commonString + equality2;
|
|
1439
|
+
}
|
|
1440
|
+
let bestEquality1 = equality1, bestEdit = edit, bestEquality2 = equality2, bestScore = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
|
|
1441
|
+
for (; edit.charAt(0) === equality2.charAt(0); ) {
|
|
1442
|
+
equality1 += edit.charAt(0), edit = edit.substring(1) + equality2.charAt(0), equality2 = equality2.substring(1);
|
|
1443
|
+
const score = diffCleanupSemanticScore(equality1, edit) + diffCleanupSemanticScore(edit, equality2);
|
|
1444
|
+
score >= bestScore && (bestScore = score, bestEquality1 = equality1, bestEdit = edit, bestEquality2 = equality2);
|
|
1445
|
+
}
|
|
1446
|
+
diffs[pointer - 1][1] !== bestEquality1 && (bestEquality1 ? diffs[pointer - 1][1] = bestEquality1 : (diffs.splice(pointer - 1, 1), pointer--), diffs[pointer][1] = bestEdit, bestEquality2 ? diffs[pointer + 1][1] = bestEquality2 : (diffs.splice(pointer + 1, 1), pointer--));
|
|
1447
|
+
}
|
|
1448
|
+
pointer++;
|
|
1449
|
+
}
|
|
1450
|
+
return diffs;
|
|
1451
|
+
}
|
|
1452
|
+
function cleanupMerge(rawDiffs) {
|
|
1453
|
+
let diffs = rawDiffs.map((diff2) => cloneDiff(diff2));
|
|
1454
|
+
diffs.push([DIFF_EQUAL, ""]);
|
|
1455
|
+
let pointer = 0, countDelete = 0, countInsert = 0, textDelete = "", textInsert = "", commonlength;
|
|
1456
|
+
for (; pointer < diffs.length; )
|
|
1457
|
+
switch (diffs[pointer][0]) {
|
|
1458
|
+
case DIFF_INSERT:
|
|
1459
|
+
countInsert++, textInsert += diffs[pointer][1], pointer++;
|
|
1460
|
+
break;
|
|
1461
|
+
case DIFF_DELETE:
|
|
1462
|
+
countDelete++, textDelete += diffs[pointer][1], pointer++;
|
|
1463
|
+
break;
|
|
1464
|
+
case DIFF_EQUAL:
|
|
1465
|
+
countDelete + countInsert > 1 ? (countDelete !== 0 && countInsert !== 0 && (commonlength = getCommonPrefix(textInsert, textDelete), commonlength !== 0 && (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL ? diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength) : (diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]), pointer++), textInsert = textInsert.substring(commonlength), textDelete = textDelete.substring(commonlength)), commonlength = getCommonSuffix(textInsert, textDelete), commonlength !== 0 && (diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1], textInsert = textInsert.substring(0, textInsert.length - commonlength), textDelete = textDelete.substring(0, textDelete.length - commonlength))), pointer -= countDelete + countInsert, diffs.splice(pointer, countDelete + countInsert), textDelete.length && (diffs.splice(pointer, 0, [DIFF_DELETE, textDelete]), pointer++), textInsert.length && (diffs.splice(pointer, 0, [DIFF_INSERT, textInsert]), pointer++), pointer++) : pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL ? (diffs[pointer - 1][1] += diffs[pointer][1], diffs.splice(pointer, 1)) : pointer++, countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
|
|
1466
|
+
break;
|
|
1467
|
+
default:
|
|
1468
|
+
throw new Error("Unknown diff operation");
|
|
1469
|
+
}
|
|
1470
|
+
diffs[diffs.length - 1][1] === "" && diffs.pop();
|
|
1471
|
+
let hasChanges = !1;
|
|
1472
|
+
for (pointer = 1; pointer < diffs.length - 1; )
|
|
1473
|
+
diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL && (diffs[pointer][1].substring(diffs[pointer][1].length - diffs[pointer - 1][1].length) === diffs[pointer - 1][1] ? (diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length), diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1], diffs.splice(pointer - 1, 1), hasChanges = !0) : diffs[pointer][1].substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1] && (diffs[pointer - 1][1] += diffs[pointer + 1][1], diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1], diffs.splice(pointer + 1, 1), hasChanges = !0)), pointer++;
|
|
1474
|
+
return hasChanges && (diffs = cleanupMerge(diffs)), diffs;
|
|
1475
|
+
}
|
|
1476
|
+
function trueCount() {
|
|
1477
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++)
|
|
1478
|
+
args[_key] = arguments[_key];
|
|
1479
|
+
return args.reduce((n, bool) => n + (bool ? 1 : 0), 0);
|
|
1480
|
+
}
|
|
1481
|
+
function cleanupEfficiency(rawDiffs) {
|
|
1482
|
+
let editCost = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 4, diffs = rawDiffs.map((diff2) => cloneDiff(diff2)), hasChanges = !1;
|
|
1483
|
+
const equalities = [];
|
|
1484
|
+
let equalitiesLength = 0, lastEquality = null, pointer = 0, preIns = !1, preDel = !1, postIns = !1, postDel = !1;
|
|
1485
|
+
for (; pointer < diffs.length; )
|
|
1486
|
+
diffs[pointer][0] === DIFF_EQUAL ? (diffs[pointer][1].length < editCost && (postIns || postDel) ? (equalities[equalitiesLength++] = pointer, preIns = postIns, preDel = postDel, lastEquality = diffs[pointer][1]) : (equalitiesLength = 0, lastEquality = null), postIns = !1, postDel = !1) : (diffs[pointer][0] === DIFF_DELETE ? postDel = !0 : postIns = !0, lastEquality && (preIns && preDel && postIns && postDel || lastEquality.length < editCost / 2 && trueCount(preIns, preDel, postIns, postDel) === 3) && (diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastEquality]), diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT, equalitiesLength--, lastEquality = null, preIns && preDel ? (postIns = !0, postDel = !0, equalitiesLength = 0) : (equalitiesLength--, pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1, postIns = !1, postDel = !1), hasChanges = !0)), pointer++;
|
|
1487
|
+
return hasChanges && (diffs = cleanupMerge(diffs)), diffs;
|
|
1488
|
+
}
|
|
1489
|
+
function bisect(text1, text2, deadline) {
|
|
1490
|
+
const text1Length = text1.length, text2Length = text2.length, maxD = Math.ceil((text1Length + text2Length) / 2), vOffset = maxD, vLength = 2 * maxD, v1 = new Array(vLength), v2 = new Array(vLength);
|
|
1491
|
+
for (let x = 0; x < vLength; x++)
|
|
1492
|
+
v1[x] = -1, v2[x] = -1;
|
|
1493
|
+
v1[vOffset + 1] = 0, v2[vOffset + 1] = 0;
|
|
1494
|
+
const delta = text1Length - text2Length, front = delta % 2 !== 0;
|
|
1495
|
+
let k1start = 0, k1end = 0, k2start = 0, k2end = 0;
|
|
1496
|
+
for (let d = 0; d < maxD && !(Date.now() > deadline); d++) {
|
|
1497
|
+
for (let k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
|
|
1498
|
+
const k1Offset = vOffset + k1;
|
|
1499
|
+
let x1;
|
|
1500
|
+
k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1] ? x1 = v1[k1Offset + 1] : x1 = v1[k1Offset - 1] + 1;
|
|
1501
|
+
let y1 = x1 - k1;
|
|
1502
|
+
for (; x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1); )
|
|
1503
|
+
x1++, y1++;
|
|
1504
|
+
if (v1[k1Offset] = x1, x1 > text1Length)
|
|
1505
|
+
k1end += 2;
|
|
1506
|
+
else if (y1 > text2Length)
|
|
1507
|
+
k1start += 2;
|
|
1508
|
+
else if (front) {
|
|
1509
|
+
const k2Offset = vOffset + delta - k1;
|
|
1510
|
+
if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
|
|
1511
|
+
const x2 = text1Length - v2[k2Offset];
|
|
1512
|
+
if (x1 >= x2)
|
|
1513
|
+
return bisectSplit(text1, text2, x1, y1, deadline);
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
for (let k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
|
|
1518
|
+
const k2Offset = vOffset + k2;
|
|
1519
|
+
let x2;
|
|
1520
|
+
k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1] ? x2 = v2[k2Offset + 1] : x2 = v2[k2Offset - 1] + 1;
|
|
1521
|
+
let y2 = x2 - k2;
|
|
1522
|
+
for (; x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1); )
|
|
1523
|
+
x2++, y2++;
|
|
1524
|
+
if (v2[k2Offset] = x2, x2 > text1Length)
|
|
1525
|
+
k2end += 2;
|
|
1526
|
+
else if (y2 > text2Length)
|
|
1527
|
+
k2start += 2;
|
|
1528
|
+
else if (!front) {
|
|
1529
|
+
const k1Offset = vOffset + delta - k2;
|
|
1530
|
+
if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
|
|
1531
|
+
const x1 = v1[k1Offset], y1 = vOffset + x1 - k1Offset;
|
|
1532
|
+
if (x2 = text1Length - x2, x1 >= x2)
|
|
1533
|
+
return bisectSplit(text1, text2, x1, y1, deadline);
|
|
2081
1534
|
}
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
1539
|
+
}
|
|
1540
|
+
function bisectSplit(text1, text2, x, y, deadline) {
|
|
1541
|
+
const text1a = text1.substring(0, x), text2a = text2.substring(0, y), text1b = text1.substring(x), text2b = text2.substring(y), diffs = doDiff(text1a, text2a, {
|
|
1542
|
+
checkLines: !1,
|
|
1543
|
+
deadline
|
|
1544
|
+
}), diffsb = doDiff(text1b, text2b, {
|
|
1545
|
+
checkLines: !1,
|
|
1546
|
+
deadline
|
|
1547
|
+
});
|
|
1548
|
+
return diffs.concat(diffsb);
|
|
1549
|
+
}
|
|
1550
|
+
function findHalfMatch(text1, text2) {
|
|
1551
|
+
if ((arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 1) <= 0)
|
|
1552
|
+
return null;
|
|
1553
|
+
const longText = text1.length > text2.length ? text1 : text2, shortText = text1.length > text2.length ? text2 : text1;
|
|
1554
|
+
if (longText.length < 4 || shortText.length * 2 < longText.length)
|
|
1555
|
+
return null;
|
|
1556
|
+
const halfMatch1 = halfMatchI(longText, shortText, Math.ceil(longText.length / 4)), halfMatch2 = halfMatchI(longText, shortText, Math.ceil(longText.length / 2));
|
|
1557
|
+
let halfMatch;
|
|
1558
|
+
if (halfMatch1 && halfMatch2)
|
|
1559
|
+
halfMatch = halfMatch1[4].length > halfMatch2[4].length ? halfMatch1 : halfMatch2;
|
|
1560
|
+
else {
|
|
1561
|
+
if (!halfMatch1 && !halfMatch2)
|
|
1562
|
+
return null;
|
|
1563
|
+
halfMatch2 ? halfMatch1 || (halfMatch = halfMatch2) : halfMatch = halfMatch1;
|
|
1564
|
+
}
|
|
1565
|
+
if (!halfMatch)
|
|
1566
|
+
throw new Error("Unable to find a half match.");
|
|
1567
|
+
let text1A, text1B, text2A, text2B;
|
|
1568
|
+
text1.length > text2.length ? (text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3]) : (text2A = halfMatch[0], text2B = halfMatch[1], text1A = halfMatch[2], text1B = halfMatch[3]);
|
|
1569
|
+
const midCommon = halfMatch[4];
|
|
1570
|
+
return [text1A, text1B, text2A, text2B, midCommon];
|
|
1571
|
+
}
|
|
1572
|
+
function halfMatchI(longText, shortText, i) {
|
|
1573
|
+
const seed = longText.slice(i, i + Math.floor(longText.length / 4));
|
|
1574
|
+
let j = -1, bestCommon = "", bestLongTextA, bestLongTextB, bestShortTextA, bestShortTextB;
|
|
1575
|
+
for (; (j = shortText.indexOf(seed, j + 1)) !== -1; ) {
|
|
1576
|
+
const prefixLength = getCommonPrefix(longText.slice(i), shortText.slice(j)), suffixLength = getCommonSuffix(longText.slice(0, i), shortText.slice(0, j));
|
|
1577
|
+
bestCommon.length < suffixLength + prefixLength && (bestCommon = shortText.slice(j - suffixLength, j) + shortText.slice(j, j + prefixLength), bestLongTextA = longText.slice(0, i - suffixLength), bestLongTextB = longText.slice(i + prefixLength), bestShortTextA = shortText.slice(0, j - suffixLength), bestShortTextB = shortText.slice(j + prefixLength));
|
|
1578
|
+
}
|
|
1579
|
+
return bestCommon.length * 2 >= longText.length ? [bestLongTextA || "", bestLongTextB || "", bestShortTextA || "", bestShortTextB || "", bestCommon || ""] : null;
|
|
1580
|
+
}
|
|
1581
|
+
function charsToLines(diffs, lineArray) {
|
|
1582
|
+
for (let x = 0; x < diffs.length; x++) {
|
|
1583
|
+
const chars = diffs[x][1], text = [];
|
|
1584
|
+
for (let y = 0; y < chars.length; y++)
|
|
1585
|
+
text[y] = lineArray[chars.charCodeAt(y)];
|
|
1586
|
+
diffs[x][1] = text.join("");
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
function linesToChars(textA, textB) {
|
|
1590
|
+
const lineArray = [], lineHash = {};
|
|
1591
|
+
lineArray[0] = "";
|
|
1592
|
+
function diffLinesToMunge(text) {
|
|
1593
|
+
let chars = "", lineStart = 0, lineEnd = -1, lineArrayLength = lineArray.length;
|
|
1594
|
+
for (; lineEnd < text.length - 1; ) {
|
|
1595
|
+
lineEnd = text.indexOf(`
|
|
1596
|
+
`, lineStart), lineEnd === -1 && (lineEnd = text.length - 1);
|
|
1597
|
+
let line = text.slice(lineStart, lineEnd + 1);
|
|
1598
|
+
(lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== void 0) ? chars += String.fromCharCode(lineHash[line]) : (lineArrayLength === maxLines && (line = text.slice(lineStart), lineEnd = text.length), chars += String.fromCharCode(lineArrayLength), lineHash[line] = lineArrayLength, lineArray[lineArrayLength++] = line), lineStart = lineEnd + 1;
|
|
1599
|
+
}
|
|
1600
|
+
return chars;
|
|
1601
|
+
}
|
|
1602
|
+
let maxLines = 4e4;
|
|
1603
|
+
const chars1 = diffLinesToMunge(textA);
|
|
1604
|
+
maxLines = 65535;
|
|
1605
|
+
const chars2 = diffLinesToMunge(textB);
|
|
1606
|
+
return {
|
|
1607
|
+
chars1,
|
|
1608
|
+
chars2,
|
|
1609
|
+
lineArray
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
function doLineModeDiff(textA, textB, opts) {
|
|
1613
|
+
let text1 = textA, text2 = textB;
|
|
1614
|
+
const a = linesToChars(text1, text2);
|
|
1615
|
+
text1 = a.chars1, text2 = a.chars2;
|
|
1616
|
+
const linearray = a.lineArray;
|
|
1617
|
+
let diffs = doDiff(text1, text2, {
|
|
1618
|
+
checkLines: !1,
|
|
1619
|
+
deadline: opts.deadline
|
|
1620
|
+
});
|
|
1621
|
+
charsToLines(diffs, linearray), diffs = cleanupSemantic(diffs), diffs.push([DIFF_EQUAL, ""]);
|
|
1622
|
+
let pointer = 0, countDelete = 0, countInsert = 0, textDelete = "", textInsert = "";
|
|
1623
|
+
for (; pointer < diffs.length; ) {
|
|
1624
|
+
switch (diffs[pointer][0]) {
|
|
1625
|
+
case DIFF_INSERT:
|
|
1626
|
+
countInsert++, textInsert += diffs[pointer][1];
|
|
1627
|
+
break;
|
|
1628
|
+
case DIFF_DELETE:
|
|
1629
|
+
countDelete++, textDelete += diffs[pointer][1];
|
|
1630
|
+
break;
|
|
1631
|
+
case DIFF_EQUAL:
|
|
1632
|
+
if (countDelete >= 1 && countInsert >= 1) {
|
|
1633
|
+
diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert), pointer = pointer - countDelete - countInsert;
|
|
1634
|
+
const aa = doDiff(textDelete, textInsert, {
|
|
1635
|
+
checkLines: !1,
|
|
1636
|
+
deadline: opts.deadline
|
|
1637
|
+
});
|
|
1638
|
+
for (let j = aa.length - 1; j >= 0; j--)
|
|
1639
|
+
diffs.splice(pointer, 0, aa[j]);
|
|
1640
|
+
pointer += aa.length;
|
|
2094
1641
|
}
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
1642
|
+
countInsert = 0, countDelete = 0, textDelete = "", textInsert = "";
|
|
1643
|
+
break;
|
|
1644
|
+
default:
|
|
1645
|
+
throw new Error("Unknown diff operation.");
|
|
1646
|
+
}
|
|
1647
|
+
pointer++;
|
|
1648
|
+
}
|
|
1649
|
+
return diffs.pop(), diffs;
|
|
1650
|
+
}
|
|
1651
|
+
function computeDiff(text1, text2, opts) {
|
|
1652
|
+
let diffs;
|
|
1653
|
+
if (!text1)
|
|
1654
|
+
return [[DIFF_INSERT, text2]];
|
|
1655
|
+
if (!text2)
|
|
1656
|
+
return [[DIFF_DELETE, text1]];
|
|
1657
|
+
const longtext = text1.length > text2.length ? text1 : text2, shorttext = text1.length > text2.length ? text2 : text1, i = longtext.indexOf(shorttext);
|
|
1658
|
+
if (i !== -1)
|
|
1659
|
+
return diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]], text1.length > text2.length && (diffs[0][0] = DIFF_DELETE, diffs[2][0] = DIFF_DELETE), diffs;
|
|
1660
|
+
if (shorttext.length === 1)
|
|
1661
|
+
return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
|
|
1662
|
+
const halfMatch = findHalfMatch(text1, text2);
|
|
1663
|
+
if (halfMatch) {
|
|
1664
|
+
const text1A = halfMatch[0], text1B = halfMatch[1], text2A = halfMatch[2], text2B = halfMatch[3], midCommon = halfMatch[4], diffsA = doDiff(text1A, text2A, opts), diffsB = doDiff(text1B, text2B, opts);
|
|
1665
|
+
return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
|
|
1666
|
+
}
|
|
1667
|
+
return opts.checkLines && text1.length > 100 && text2.length > 100 ? doLineModeDiff(text1, text2, opts) : bisect(text1, text2, opts.deadline);
|
|
1668
|
+
}
|
|
1669
|
+
const DIFF_DELETE = -1, DIFF_INSERT = 1, DIFF_EQUAL = 0;
|
|
1670
|
+
function diff(textA, textB, opts) {
|
|
1671
|
+
if (textA === null || textB === null)
|
|
1672
|
+
throw new Error("Null input. (diff)");
|
|
1673
|
+
const diffs = doDiff(textA, textB, createInternalOpts(opts || {}));
|
|
1674
|
+
return adjustDiffForSurrogatePairs(diffs), diffs;
|
|
1675
|
+
}
|
|
1676
|
+
function doDiff(textA, textB, options) {
|
|
1677
|
+
let text1 = textA, text2 = textB;
|
|
1678
|
+
if (text1 === text2)
|
|
1679
|
+
return text1 ? [[DIFF_EQUAL, text1]] : [];
|
|
1680
|
+
let commonlength = getCommonPrefix(text1, text2);
|
|
1681
|
+
const commonprefix = text1.substring(0, commonlength);
|
|
1682
|
+
text1 = text1.substring(commonlength), text2 = text2.substring(commonlength), commonlength = getCommonSuffix(text1, text2);
|
|
1683
|
+
const commonsuffix = text1.substring(text1.length - commonlength);
|
|
1684
|
+
text1 = text1.substring(0, text1.length - commonlength), text2 = text2.substring(0, text2.length - commonlength);
|
|
1685
|
+
let diffs = computeDiff(text1, text2, options);
|
|
1686
|
+
return commonprefix && diffs.unshift([DIFF_EQUAL, commonprefix]), commonsuffix && diffs.push([DIFF_EQUAL, commonsuffix]), diffs = cleanupMerge(diffs), diffs;
|
|
1687
|
+
}
|
|
1688
|
+
function createDeadLine(timeout) {
|
|
1689
|
+
let t = 1;
|
|
1690
|
+
return typeof timeout < "u" && (t = timeout <= 0 ? Number.MAX_VALUE : timeout), Date.now() + t * 1e3;
|
|
1691
|
+
}
|
|
1692
|
+
function createInternalOpts(opts) {
|
|
1693
|
+
return {
|
|
1694
|
+
checkLines: !0,
|
|
1695
|
+
deadline: createDeadLine(opts.timeout || 1),
|
|
1696
|
+
...opts
|
|
2109
1697
|
};
|
|
2110
1698
|
}
|
|
2111
|
-
function
|
|
2112
|
-
return
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
1699
|
+
function combineChar(data, char, dir) {
|
|
1700
|
+
return dir === 1 ? data + char : char + data;
|
|
1701
|
+
}
|
|
1702
|
+
function splitChar(data, dir) {
|
|
1703
|
+
return dir === 1 ? [data.substring(0, data.length - 1), data[data.length - 1]] : [data.substring(1), data[0]];
|
|
1704
|
+
}
|
|
1705
|
+
function hasSharedChar(diffs, i, j, dir) {
|
|
1706
|
+
return dir === 1 ? diffs[i][1][diffs[i][1].length - 1] === diffs[j][1][diffs[j][1].length - 1] : diffs[i][1][0] === diffs[j][1][0];
|
|
1707
|
+
}
|
|
1708
|
+
function deisolateChar(diffs, i, dir) {
|
|
1709
|
+
const inv = dir === 1 ? -1 : 1;
|
|
1710
|
+
let insertIdx = null, deleteIdx = null, j = i + dir;
|
|
1711
|
+
for (; j >= 0 && j < diffs.length && (insertIdx === null || deleteIdx === null); j += dir) {
|
|
1712
|
+
const [op, text2] = diffs[j];
|
|
1713
|
+
if (text2.length !== 0) {
|
|
1714
|
+
if (op === DIFF_INSERT) {
|
|
1715
|
+
insertIdx === null && (insertIdx = j);
|
|
1716
|
+
continue;
|
|
1717
|
+
} else if (op === DIFF_DELETE) {
|
|
1718
|
+
deleteIdx === null && (deleteIdx = j);
|
|
1719
|
+
continue;
|
|
1720
|
+
} else if (op === DIFF_EQUAL) {
|
|
1721
|
+
if (insertIdx === null && deleteIdx === null) {
|
|
1722
|
+
const [rest, char2] = splitChar(diffs[i][1], dir);
|
|
1723
|
+
diffs[i][1] = rest, diffs[j][1] = combineChar(diffs[j][1], char2, inv);
|
|
1724
|
+
return;
|
|
2128
1725
|
}
|
|
1726
|
+
break;
|
|
2129
1727
|
}
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
if (insertIdx !== null && deleteIdx !== null && hasSharedChar(diffs, insertIdx, deleteIdx, dir)) {
|
|
1731
|
+
const [insertText, insertChar] = splitChar(diffs[insertIdx][1], inv), [deleteText] = splitChar(diffs[deleteIdx][1], inv);
|
|
1732
|
+
diffs[insertIdx][1] = insertText, diffs[deleteIdx][1] = deleteText, diffs[i][1] = combineChar(diffs[i][1], insertChar, dir);
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
const [text, char] = splitChar(diffs[i][1], dir);
|
|
1736
|
+
diffs[i][1] = text, insertIdx === null ? (diffs.splice(j, 0, [DIFF_INSERT, char]), deleteIdx !== null && deleteIdx >= j && deleteIdx++) : diffs[insertIdx][1] = combineChar(diffs[insertIdx][1], char, inv), deleteIdx === null ? diffs.splice(j, 0, [DIFF_DELETE, char]) : diffs[deleteIdx][1] = combineChar(diffs[deleteIdx][1], char, inv);
|
|
2133
1737
|
}
|
|
2134
|
-
function
|
|
2135
|
-
|
|
2136
|
-
const
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
1738
|
+
function adjustDiffForSurrogatePairs(diffs) {
|
|
1739
|
+
for (let i = 0; i < diffs.length; i++) {
|
|
1740
|
+
const [diffType, diffText] = diffs[i];
|
|
1741
|
+
if (diffText.length === 0) continue;
|
|
1742
|
+
const firstChar = diffText[0], lastChar = diffText[diffText.length - 1];
|
|
1743
|
+
isHighSurrogate(lastChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, 1), isLowSurrogate(firstChar) && diffType === DIFF_EQUAL && deisolateChar(diffs, i, -1);
|
|
1744
|
+
}
|
|
1745
|
+
for (let i = 0; i < diffs.length; i++)
|
|
1746
|
+
diffs[i][1].length === 0 && diffs.splice(i, 1);
|
|
1747
|
+
}
|
|
1748
|
+
const DEFAULT_OPTIONS = {
|
|
1749
|
+
/**
|
|
1750
|
+
* At what point is no match declared (0.0 = perfection, 1.0 = very loose).
|
|
1751
|
+
*/
|
|
1752
|
+
threshold: 0.5,
|
|
1753
|
+
/**
|
|
1754
|
+
* How far to search for a match (0 = exact location, 1000+ = broad match).
|
|
1755
|
+
* A match this many characters away from the expected location will add
|
|
1756
|
+
* 1.0 to the score (0.0 is a perfect match).
|
|
1757
|
+
*/
|
|
1758
|
+
distance: 1e3
|
|
1759
|
+
};
|
|
1760
|
+
function applyDefaults(options) {
|
|
1761
|
+
return {
|
|
1762
|
+
...DEFAULT_OPTIONS,
|
|
1763
|
+
...options
|
|
2141
1764
|
};
|
|
2142
1765
|
}
|
|
2143
|
-
const
|
|
2144
|
-
function
|
|
2145
|
-
|
|
2146
|
-
|
|
1766
|
+
const MAX_BITS$1 = 32;
|
|
1767
|
+
function bitap(text, pattern, loc) {
|
|
1768
|
+
let opts = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : {};
|
|
1769
|
+
if (pattern.length > MAX_BITS$1)
|
|
1770
|
+
throw new Error("Pattern too long for this browser.");
|
|
1771
|
+
const options = applyDefaults(opts), s = getAlphabetFromPattern(pattern);
|
|
1772
|
+
function getBitapScore(e, x) {
|
|
1773
|
+
const accuracy = e / pattern.length, proximity = Math.abs(loc - x);
|
|
1774
|
+
return options.distance ? accuracy + proximity / options.distance : proximity ? 1 : accuracy;
|
|
1775
|
+
}
|
|
1776
|
+
let scoreThreshold = options.threshold, bestLoc = text.indexOf(pattern, loc);
|
|
1777
|
+
bestLoc !== -1 && (scoreThreshold = Math.min(getBitapScore(0, bestLoc), scoreThreshold), bestLoc = text.lastIndexOf(pattern, loc + pattern.length), bestLoc !== -1 && (scoreThreshold = Math.min(getBitapScore(0, bestLoc), scoreThreshold)));
|
|
1778
|
+
const matchmask = 1 << pattern.length - 1;
|
|
1779
|
+
bestLoc = -1;
|
|
1780
|
+
let binMin, binMid, binMax = pattern.length + text.length, lastRd = [];
|
|
1781
|
+
for (let d = 0; d < pattern.length; d++) {
|
|
1782
|
+
for (binMin = 0, binMid = binMax; binMin < binMid; )
|
|
1783
|
+
getBitapScore(d, loc + binMid) <= scoreThreshold ? binMin = binMid : binMax = binMid, binMid = Math.floor((binMax - binMin) / 2 + binMin);
|
|
1784
|
+
binMax = binMid;
|
|
1785
|
+
let start = Math.max(1, loc - binMid + 1);
|
|
1786
|
+
const finish = Math.min(loc + binMid, text.length) + pattern.length, rd = new Array(finish + 2);
|
|
1787
|
+
rd[finish + 1] = (1 << d) - 1;
|
|
1788
|
+
for (let j = finish; j >= start; j--) {
|
|
1789
|
+
const charMatch = s[text.charAt(j - 1)];
|
|
1790
|
+
if (d === 0 ? rd[j] = (rd[j + 1] << 1 | 1) & charMatch : rd[j] = (rd[j + 1] << 1 | 1) & charMatch | ((lastRd[j + 1] | lastRd[j]) << 1 | 1) | lastRd[j + 1], rd[j] & matchmask) {
|
|
1791
|
+
const score = getBitapScore(d, j - 1);
|
|
1792
|
+
if (score <= scoreThreshold)
|
|
1793
|
+
if (scoreThreshold = score, bestLoc = j - 1, bestLoc > loc)
|
|
1794
|
+
start = Math.max(1, 2 * loc - bestLoc);
|
|
1795
|
+
else
|
|
1796
|
+
break;
|
|
1797
|
+
}
|
|
1798
|
+
}
|
|
1799
|
+
if (getBitapScore(d + 1, loc) > scoreThreshold)
|
|
1800
|
+
break;
|
|
1801
|
+
lastRd = rd;
|
|
1802
|
+
}
|
|
1803
|
+
return bestLoc;
|
|
2147
1804
|
}
|
|
2148
|
-
function
|
|
2149
|
-
|
|
1805
|
+
function getAlphabetFromPattern(pattern) {
|
|
1806
|
+
const s = {};
|
|
1807
|
+
for (let i = 0; i < pattern.length; i++)
|
|
1808
|
+
s[pattern.charAt(i)] = 0;
|
|
1809
|
+
for (let i = 0; i < pattern.length; i++)
|
|
1810
|
+
s[pattern.charAt(i)] |= 1 << pattern.length - i - 1;
|
|
1811
|
+
return s;
|
|
2150
1812
|
}
|
|
2151
|
-
function
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
node._key || Transforms.setNodes(editor, { _key: keyGenerator() }, { at: path });
|
|
2175
|
-
for (const [child, childPath] of Node.children(editor, path))
|
|
2176
|
-
if (!child._key) {
|
|
2177
|
-
Transforms.setNodes(editor, { _key: keyGenerator() }, { at: childPath });
|
|
2178
|
-
return;
|
|
2179
|
-
}
|
|
2180
|
-
}
|
|
2181
|
-
normalizeNode(entry);
|
|
2182
|
-
}, editor;
|
|
1813
|
+
function match(text, pattern, searchLocation) {
|
|
1814
|
+
if (text === null || pattern === null || searchLocation === null)
|
|
1815
|
+
throw new Error("Null input. (match())");
|
|
1816
|
+
const loc = Math.max(0, Math.min(searchLocation, text.length));
|
|
1817
|
+
if (text === pattern)
|
|
1818
|
+
return 0;
|
|
1819
|
+
if (text.length) {
|
|
1820
|
+
if (text.substring(loc, loc + pattern.length) === pattern)
|
|
1821
|
+
return loc;
|
|
1822
|
+
} else return -1;
|
|
1823
|
+
return bitap(text, pattern, loc);
|
|
1824
|
+
}
|
|
1825
|
+
function createPatchObject(start1, start2) {
|
|
1826
|
+
return {
|
|
1827
|
+
diffs: [],
|
|
1828
|
+
start1,
|
|
1829
|
+
start2,
|
|
1830
|
+
utf8Start1: start1,
|
|
1831
|
+
utf8Start2: start2,
|
|
1832
|
+
length1: 0,
|
|
1833
|
+
length2: 0,
|
|
1834
|
+
utf8Length1: 0,
|
|
1835
|
+
utf8Length2: 0
|
|
2183
1836
|
};
|
|
2184
1837
|
}
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
if (array.length === 0)
|
|
2191
|
-
return items;
|
|
2192
|
-
const len = array.length, idx = Math.abs((len + index) % len) % len, normalizedIdx = position === "after" ? idx + 1 : idx, copy = array.slice();
|
|
2193
|
-
return copy.splice(normalizedIdx, 0, ...flatten(items)), copy;
|
|
2194
|
-
}
|
|
2195
|
-
function flatten(...values) {
|
|
2196
|
-
return values.reduce((prev, item) => prev.concat(item), []);
|
|
2197
|
-
}
|
|
2198
|
-
const hasOwn = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
|
|
2199
|
-
function move(arr, from, to) {
|
|
2200
|
-
const nextValue = arr.slice(), val = nextValue[from];
|
|
2201
|
-
return nextValue.splice(from, 1), nextValue.splice(to, 0, val), nextValue;
|
|
1838
|
+
function diffText1(diffs) {
|
|
1839
|
+
const text = [];
|
|
1840
|
+
for (let x = 0; x < diffs.length; x++)
|
|
1841
|
+
diffs[x][0] !== DIFF_INSERT && (text[x] = diffs[x][1]);
|
|
1842
|
+
return text.join("");
|
|
2202
1843
|
}
|
|
2203
|
-
function
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
return
|
|
1844
|
+
function diffText2(diffs) {
|
|
1845
|
+
const text = [];
|
|
1846
|
+
for (let x = 0; x < diffs.length; x++)
|
|
1847
|
+
diffs[x][0] !== DIFF_DELETE && (text[x] = diffs[x][1]);
|
|
1848
|
+
return text.join("");
|
|
2208
1849
|
}
|
|
2209
|
-
function
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
} else if (patch.type === "set") {
|
|
2217
|
-
if (!Array.isArray(patch.value))
|
|
2218
|
-
throw new Error("Cannot set value of an array to a non-array");
|
|
2219
|
-
return patch.value;
|
|
2220
|
-
} else {
|
|
2221
|
-
if (patch.type === "unset")
|
|
2222
|
-
return;
|
|
2223
|
-
if (patch.type === "move") {
|
|
2224
|
-
if (!patch.value || !hasOwn(patch.value, "from") || !hasOwn(patch.value, "to"))
|
|
2225
|
-
throw new Error(
|
|
2226
|
-
`Invalid value of 'move' patch. Expected a value with "from" and "to" indexes, instead got: ${JSON.stringify(
|
|
2227
|
-
patch.value
|
|
2228
|
-
)}`
|
|
2229
|
-
);
|
|
2230
|
-
return move(nextValue, patch.value.from, patch.value.to);
|
|
2231
|
-
}
|
|
2232
|
-
}
|
|
2233
|
-
throw new Error(`Invalid array operation: ${patch.type}`);
|
|
1850
|
+
function countUtf8Bytes(str) {
|
|
1851
|
+
let bytes = 0;
|
|
1852
|
+
for (let i = 0; i < str.length; i++) {
|
|
1853
|
+
const codePoint = str.codePointAt(i);
|
|
1854
|
+
if (typeof codePoint > "u")
|
|
1855
|
+
throw new Error("Failed to get codepoint");
|
|
1856
|
+
bytes += utf8len(codePoint);
|
|
2234
1857
|
}
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
return nextValue.splice(index, 1), nextValue;
|
|
1858
|
+
return bytes;
|
|
1859
|
+
}
|
|
1860
|
+
function adjustIndiciesToUcs2(patches, base) {
|
|
1861
|
+
let options = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {}, byteOffset = 0, idx = 0;
|
|
1862
|
+
function advanceTo(target) {
|
|
1863
|
+
for (; byteOffset < target; ) {
|
|
1864
|
+
const codePoint = base.codePointAt(idx);
|
|
1865
|
+
if (typeof codePoint > "u")
|
|
1866
|
+
return idx;
|
|
1867
|
+
byteOffset += utf8len(codePoint), codePoint > 65535 ? idx += 2 : idx += 1;
|
|
2246
1868
|
}
|
|
1869
|
+
if (!options.allowExceedingIndices && byteOffset !== target)
|
|
1870
|
+
throw new Error("Failed to determine byte offset");
|
|
1871
|
+
return idx;
|
|
2247
1872
|
}
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
1873
|
+
const adjusted = [];
|
|
1874
|
+
for (const patch of patches)
|
|
1875
|
+
adjusted.push({
|
|
1876
|
+
diffs: patch.diffs.map((diff2) => cloneDiff(diff2)),
|
|
1877
|
+
start1: advanceTo(patch.start1),
|
|
1878
|
+
start2: advanceTo(patch.start2),
|
|
1879
|
+
utf8Start1: patch.utf8Start1,
|
|
1880
|
+
utf8Start2: patch.utf8Start2,
|
|
1881
|
+
length1: patch.length1,
|
|
1882
|
+
length2: patch.length2,
|
|
1883
|
+
utf8Length1: patch.utf8Length1,
|
|
1884
|
+
utf8Length2: patch.utf8Length2
|
|
1885
|
+
});
|
|
1886
|
+
return adjusted;
|
|
2252
1887
|
}
|
|
2253
|
-
function
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
1888
|
+
function utf8len(codePoint) {
|
|
1889
|
+
return codePoint <= 127 ? 1 : codePoint <= 2047 ? 2 : codePoint <= 65535 ? 3 : 4;
|
|
1890
|
+
}
|
|
1891
|
+
const MAX_BITS = 32, DEFAULT_MARGIN = 4;
|
|
1892
|
+
function levenshtein(diffs) {
|
|
1893
|
+
let leven = 0, insertions = 0, deletions = 0;
|
|
1894
|
+
for (let x = 0; x < diffs.length; x++) {
|
|
1895
|
+
const op = diffs[x][0], data = diffs[x][1];
|
|
1896
|
+
switch (op) {
|
|
1897
|
+
case DIFF_INSERT:
|
|
1898
|
+
insertions += data.length;
|
|
1899
|
+
break;
|
|
1900
|
+
case DIFF_DELETE:
|
|
1901
|
+
deletions += data.length;
|
|
1902
|
+
break;
|
|
1903
|
+
case DIFF_EQUAL:
|
|
1904
|
+
leven += Math.max(insertions, deletions), insertions = 0, deletions = 0;
|
|
1905
|
+
break;
|
|
1906
|
+
default:
|
|
1907
|
+
throw new Error("Unknown diff operation.");
|
|
2265
1908
|
}
|
|
2266
|
-
throw new Error(`Invalid object operation: ${patch.type}`);
|
|
2267
1909
|
}
|
|
2268
|
-
|
|
2269
|
-
if (typeof head != "string")
|
|
2270
|
-
throw new Error(`Expected field name to be a string, instad got: ${head}`);
|
|
2271
|
-
return tail.length === 0 && patch.type === "unset" ? omit(nextValue, head) : (nextValue[head] = _apply(nextValue[head], {
|
|
2272
|
-
...patch,
|
|
2273
|
-
path: tail
|
|
2274
|
-
}), nextValue);
|
|
1910
|
+
return leven += Math.max(insertions, deletions), leven;
|
|
2275
1911
|
}
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
1912
|
+
function xIndex(diffs, loc) {
|
|
1913
|
+
let chars1 = 0, chars2 = 0, lastChars1 = 0, lastChars2 = 0, x;
|
|
1914
|
+
for (x = 0; x < diffs.length && (diffs[x][0] !== DIFF_INSERT && (chars1 += diffs[x][1].length), diffs[x][0] !== DIFF_DELETE && (chars2 += diffs[x][1].length), !(chars1 > loc)); x++)
|
|
1915
|
+
lastChars1 = chars1, lastChars2 = chars2;
|
|
1916
|
+
return diffs.length !== x && diffs[x][0] === DIFF_DELETE ? lastChars2 : lastChars2 + (loc - lastChars1);
|
|
1917
|
+
}
|
|
1918
|
+
function addPadding(patches) {
|
|
1919
|
+
const paddingLength = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MARGIN;
|
|
1920
|
+
let nullPadding = "";
|
|
1921
|
+
for (let x = 1; x <= paddingLength; x++)
|
|
1922
|
+
nullPadding += String.fromCharCode(x);
|
|
1923
|
+
for (const p of patches)
|
|
1924
|
+
p.start1 += paddingLength, p.start2 += paddingLength, p.utf8Start1 += paddingLength, p.utf8Start2 += paddingLength;
|
|
1925
|
+
let patch = patches[0], diffs = patch.diffs;
|
|
1926
|
+
if (diffs.length === 0 || diffs[0][0] !== DIFF_EQUAL)
|
|
1927
|
+
diffs.unshift([DIFF_EQUAL, nullPadding]), patch.start1 -= paddingLength, patch.start2 -= paddingLength, patch.utf8Start1 -= paddingLength, patch.utf8Start2 -= paddingLength, patch.length1 += paddingLength, patch.length2 += paddingLength, patch.utf8Length1 += paddingLength, patch.utf8Length2 += paddingLength;
|
|
1928
|
+
else if (paddingLength > diffs[0][1].length) {
|
|
1929
|
+
const firstDiffLength = diffs[0][1].length, extraLength = paddingLength - firstDiffLength;
|
|
1930
|
+
diffs[0][1] = nullPadding.substring(firstDiffLength) + diffs[0][1], patch.start1 -= extraLength, patch.start2 -= extraLength, patch.utf8Start1 -= extraLength, patch.utf8Start2 -= extraLength, patch.length1 += extraLength, patch.length2 += extraLength, patch.utf8Length1 += extraLength, patch.utf8Length2 += extraLength;
|
|
2293
1931
|
}
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
if (
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
);
|
|
2302
|
-
if (patch.path.length > 0)
|
|
2303
|
-
throw new Error(
|
|
2304
|
-
`Cannot apply deep operations on primitive values. Received patch with type "${patch.type}" and path "${patch.path.map((path) => JSON.stringify(path)).join(".")} that targeted the value "${JSON.stringify(value)}"`
|
|
2305
|
-
);
|
|
2306
|
-
return OPERATIONS$1[patch.type](value, patch.value);
|
|
1932
|
+
if (patch = patches[patches.length - 1], diffs = patch.diffs, diffs.length === 0 || diffs[diffs.length - 1][0] !== DIFF_EQUAL)
|
|
1933
|
+
diffs.push([DIFF_EQUAL, nullPadding]), patch.length1 += paddingLength, patch.length2 += paddingLength, patch.utf8Length1 += paddingLength, patch.utf8Length2 += paddingLength;
|
|
1934
|
+
else if (paddingLength > diffs[diffs.length - 1][1].length) {
|
|
1935
|
+
const extraLength = paddingLength - diffs[diffs.length - 1][1].length;
|
|
1936
|
+
diffs[diffs.length - 1][1] += nullPadding.substring(0, extraLength), patch.length1 += extraLength, patch.length2 += extraLength, patch.utf8Length1 += extraLength, patch.utf8Length2 += extraLength;
|
|
1937
|
+
}
|
|
1938
|
+
return nullPadding;
|
|
2307
1939
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
1940
|
+
function splitMax(patches) {
|
|
1941
|
+
let margin = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : DEFAULT_MARGIN;
|
|
1942
|
+
const patchSize = MAX_BITS;
|
|
1943
|
+
for (let x = 0; x < patches.length; x++) {
|
|
1944
|
+
if (patches[x].length1 <= patchSize)
|
|
1945
|
+
continue;
|
|
1946
|
+
const bigpatch = patches[x];
|
|
1947
|
+
patches.splice(x--, 1);
|
|
1948
|
+
let start1 = bigpatch.start1, start2 = bigpatch.start2, preContext = "";
|
|
1949
|
+
for (; bigpatch.diffs.length !== 0; ) {
|
|
1950
|
+
const patch = createPatchObject(start1 - preContext.length, start2 - preContext.length);
|
|
1951
|
+
let empty = !0;
|
|
1952
|
+
if (preContext !== "") {
|
|
1953
|
+
const precontextByteCount = countUtf8Bytes(preContext);
|
|
1954
|
+
patch.length1 = preContext.length, patch.utf8Length1 = precontextByteCount, patch.length2 = preContext.length, patch.utf8Length2 = precontextByteCount, patch.diffs.push([DIFF_EQUAL, preContext]);
|
|
1955
|
+
}
|
|
1956
|
+
for (; bigpatch.diffs.length !== 0 && patch.length1 < patchSize - margin; ) {
|
|
1957
|
+
const diffType = bigpatch.diffs[0][0];
|
|
1958
|
+
let diffText = bigpatch.diffs[0][1], diffTextByteCount = countUtf8Bytes(diffText);
|
|
1959
|
+
if (diffType === DIFF_INSERT) {
|
|
1960
|
+
patch.length2 += diffText.length, patch.utf8Length2 += diffTextByteCount, start2 += diffText.length;
|
|
1961
|
+
const diff2 = bigpatch.diffs.shift();
|
|
1962
|
+
diff2 && patch.diffs.push(diff2), empty = !1;
|
|
1963
|
+
} else diffType === DIFF_DELETE && patch.diffs.length === 1 && patch.diffs[0][0] === DIFF_EQUAL && diffText.length > 2 * patchSize ? (patch.length1 += diffText.length, patch.utf8Length1 += diffTextByteCount, start1 += diffText.length, empty = !1, patch.diffs.push([diffType, diffText]), bigpatch.diffs.shift()) : (diffText = diffText.substring(0, patchSize - patch.length1 - margin), diffTextByteCount = countUtf8Bytes(diffText), patch.length1 += diffText.length, patch.utf8Length1 += diffTextByteCount, start1 += diffText.length, diffType === DIFF_EQUAL ? (patch.length2 += diffText.length, patch.utf8Length2 += diffTextByteCount, start2 += diffText.length) : empty = !1, patch.diffs.push([diffType, diffText]), diffText === bigpatch.diffs[0][1] ? bigpatch.diffs.shift() : bigpatch.diffs[0][1] = bigpatch.diffs[0][1].substring(diffText.length));
|
|
1964
|
+
}
|
|
1965
|
+
preContext = diffText2(patch.diffs), preContext = preContext.substring(preContext.length - margin);
|
|
1966
|
+
const postContext = diffText1(bigpatch.diffs).substring(0, margin), postContextByteCount = countUtf8Bytes(postContext);
|
|
1967
|
+
postContext !== "" && (patch.length1 += postContext.length, patch.length2 += postContext.length, patch.utf8Length1 += postContextByteCount, patch.utf8Length2 += postContextByteCount, patch.diffs.length !== 0 && patch.diffs[patch.diffs.length - 1][0] === DIFF_EQUAL ? patch.diffs[patch.diffs.length - 1][1] += postContext : patch.diffs.push([DIFF_EQUAL, postContext])), empty || patches.splice(++x, 0, patch);
|
|
1968
|
+
}
|
|
2325
1969
|
}
|
|
2326
|
-
}, SUPPORTED_PATCH_TYPES = Object.keys(OPERATIONS);
|
|
2327
|
-
function apply(value, patch) {
|
|
2328
|
-
if (!SUPPORTED_PATCH_TYPES.includes(patch.type))
|
|
2329
|
-
throw new Error(
|
|
2330
|
-
`Received patch of unsupported type: "${JSON.stringify(
|
|
2331
|
-
patch.type
|
|
2332
|
-
)}" for string. This is most likely a bug.`
|
|
2333
|
-
);
|
|
2334
|
-
if (patch.path.length > 0)
|
|
2335
|
-
throw new Error(
|
|
2336
|
-
`Cannot apply deep operations on string values. Received patch with type "${patch.type}" and path "${patch.path.join(".")} that targeted the value "${JSON.stringify(value)}"`
|
|
2337
|
-
);
|
|
2338
|
-
const func = OPERATIONS[patch.type];
|
|
2339
|
-
if (func)
|
|
2340
|
-
return func(value, patch.value);
|
|
2341
|
-
throw new Error("Unknown patch type");
|
|
2342
1970
|
}
|
|
2343
|
-
function
|
|
2344
|
-
|
|
1971
|
+
function apply(patches, originalText) {
|
|
1972
|
+
let opts = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : {};
|
|
1973
|
+
if (typeof patches == "string")
|
|
1974
|
+
throw new Error("Patches must be an array - pass the patch to `parsePatch()` first");
|
|
1975
|
+
let text = originalText;
|
|
1976
|
+
if (patches.length === 0)
|
|
1977
|
+
return [text, []];
|
|
1978
|
+
const parsed = adjustIndiciesToUcs2(patches, text, {
|
|
1979
|
+
allowExceedingIndices: opts.allowExceedingIndices
|
|
1980
|
+
}), margin = opts.margin || DEFAULT_MARGIN, deleteThreshold = opts.deleteThreshold || 0.4, nullPadding = addPadding(parsed, margin);
|
|
1981
|
+
text = nullPadding + text + nullPadding, splitMax(parsed, margin);
|
|
1982
|
+
let delta = 0;
|
|
1983
|
+
const results = [];
|
|
1984
|
+
for (let x = 0; x < parsed.length; x++) {
|
|
1985
|
+
const expectedLoc = parsed[x].start2 + delta, text1 = diffText1(parsed[x].diffs);
|
|
1986
|
+
let startLoc, endLoc = -1;
|
|
1987
|
+
if (text1.length > MAX_BITS ? (startLoc = match(text, text1.substring(0, MAX_BITS), expectedLoc), startLoc !== -1 && (endLoc = match(text, text1.substring(text1.length - MAX_BITS), expectedLoc + text1.length - MAX_BITS), (endLoc === -1 || startLoc >= endLoc) && (startLoc = -1))) : startLoc = match(text, text1, expectedLoc), startLoc === -1)
|
|
1988
|
+
results[x] = !1, delta -= parsed[x].length2 - parsed[x].length1;
|
|
1989
|
+
else {
|
|
1990
|
+
results[x] = !0, delta = startLoc - expectedLoc;
|
|
1991
|
+
let text2;
|
|
1992
|
+
if (endLoc === -1 ? text2 = text.substring(startLoc, startLoc + text1.length) : text2 = text.substring(startLoc, endLoc + MAX_BITS), text1 === text2)
|
|
1993
|
+
text = text.substring(0, startLoc) + diffText2(parsed[x].diffs) + text.substring(startLoc + text1.length);
|
|
1994
|
+
else {
|
|
1995
|
+
let diffs = diff(text1, text2, {
|
|
1996
|
+
checkLines: !1
|
|
1997
|
+
});
|
|
1998
|
+
if (text1.length > MAX_BITS && levenshtein(diffs) / text1.length > deleteThreshold)
|
|
1999
|
+
results[x] = !1;
|
|
2000
|
+
else {
|
|
2001
|
+
diffs = cleanupSemanticLossless(diffs);
|
|
2002
|
+
let index1 = 0, index2 = 0;
|
|
2003
|
+
for (let y = 0; y < parsed[x].diffs.length; y++) {
|
|
2004
|
+
const mod = parsed[x].diffs[y];
|
|
2005
|
+
mod[0] !== DIFF_EQUAL && (index2 = xIndex(diffs, index1)), mod[0] === DIFF_INSERT ? text = text.substring(0, startLoc + index2) + mod[1] + text.substring(startLoc + index2) : mod[0] === DIFF_DELETE && (text = text.substring(0, startLoc + index2) + text.substring(startLoc + xIndex(diffs, index1 + mod[1].length))), mod[0] !== DIFF_DELETE && (index1 += mod[1].length);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
}
|
|
2009
|
+
}
|
|
2010
|
+
}
|
|
2011
|
+
return text = text.substring(nullPadding.length, text.length - nullPadding.length), [text, results];
|
|
2345
2012
|
}
|
|
2346
|
-
|
|
2347
|
-
|
|
2013
|
+
const patchHeader = /^@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@$/;
|
|
2014
|
+
function parse(textline) {
|
|
2015
|
+
if (!textline)
|
|
2016
|
+
return [];
|
|
2017
|
+
const patches = [], lines = textline.split(`
|
|
2018
|
+
`);
|
|
2019
|
+
let textPointer = 0;
|
|
2020
|
+
for (; textPointer < lines.length; ) {
|
|
2021
|
+
const m = lines[textPointer].match(patchHeader);
|
|
2022
|
+
if (!m)
|
|
2023
|
+
throw new Error("Invalid patch string: ".concat(lines[textPointer]));
|
|
2024
|
+
const patch = createPatchObject(toInt(m[1]), toInt(m[3]));
|
|
2025
|
+
for (patches.push(patch), m[2] === "" ? (patch.start1--, patch.utf8Start1--, patch.length1 = 1, patch.utf8Length1 = 1) : m[2] === "0" ? (patch.length1 = 0, patch.utf8Length1 = 0) : (patch.start1--, patch.utf8Start1--, patch.utf8Length1 = toInt(m[2]), patch.length1 = patch.utf8Length1), m[4] === "" ? (patch.start2--, patch.utf8Start2--, patch.length2 = 1, patch.utf8Length2 = 1) : m[4] === "0" ? (patch.length2 = 0, patch.utf8Length2 = 0) : (patch.start2--, patch.utf8Start2--, patch.utf8Length2 = toInt(m[4]), patch.length2 = patch.utf8Length2), textPointer++; textPointer < lines.length; ) {
|
|
2026
|
+
const currentLine = lines[textPointer], sign = currentLine.charAt(0);
|
|
2027
|
+
if (sign === "@")
|
|
2028
|
+
break;
|
|
2029
|
+
if (sign === "") {
|
|
2030
|
+
textPointer++;
|
|
2031
|
+
continue;
|
|
2032
|
+
}
|
|
2033
|
+
let line;
|
|
2034
|
+
try {
|
|
2035
|
+
line = decodeURI(currentLine.slice(1));
|
|
2036
|
+
} catch {
|
|
2037
|
+
throw new Error("Illegal escape in parse: ".concat(currentLine));
|
|
2038
|
+
}
|
|
2039
|
+
const utf8Diff = countUtf8Bytes(line) - line.length;
|
|
2040
|
+
if (sign === "-")
|
|
2041
|
+
patch.diffs.push([DIFF_DELETE, line]), patch.length1 -= utf8Diff;
|
|
2042
|
+
else if (sign === "+")
|
|
2043
|
+
patch.diffs.push([DIFF_INSERT, line]), patch.length2 -= utf8Diff;
|
|
2044
|
+
else if (sign === " ")
|
|
2045
|
+
patch.diffs.push([DIFF_EQUAL, line]), patch.length1 -= utf8Diff, patch.length2 -= utf8Diff;
|
|
2046
|
+
else
|
|
2047
|
+
throw new Error('Invalid patch mode "'.concat(sign, '" in: ').concat(line));
|
|
2048
|
+
textPointer++;
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
return patches;
|
|
2348
2052
|
}
|
|
2349
|
-
function
|
|
2350
|
-
return
|
|
2053
|
+
function toInt(num) {
|
|
2054
|
+
return parseInt(num, 10);
|
|
2351
2055
|
}
|
|
2352
2056
|
const debug$h = debugWithName("applyPatches"), debugVerbose$3 = debug$h.enabled && !0;
|
|
2353
2057
|
function createApplyPatch(schemaTypes) {
|
|
@@ -2388,7 +2092,7 @@ function diffMatchPatch(editor, patch) {
|
|
|
2388
2092
|
return debug$h("Child not found"), !1;
|
|
2389
2093
|
if (!(block && editor.isTextBlock(block) && patch.path.length === 4 && patch.path[1] === "children" && patch.path[3] === "text") || !Text.isText(child))
|
|
2390
2094
|
return !1;
|
|
2391
|
-
const patches = parse(patch.value), [newValue] = apply
|
|
2095
|
+
const patches = parse(patch.value), [newValue] = apply(patches, child.text, { allowExceedingIndices: !0 }), diff$1 = cleanupEfficiency(diff(child.text, newValue), 5);
|
|
2392
2096
|
debugState(editor, "before");
|
|
2393
2097
|
let offset = 0;
|
|
2394
2098
|
for (const [op, text] of diff$1)
|
|
@@ -2608,7 +2312,7 @@ function createWithUndoRedo(options) {
|
|
|
2608
2312
|
const otherPatches = remotePatches.filter((item) => item.time >= step.timestamp);
|
|
2609
2313
|
let transformedOperations = step.operations;
|
|
2610
2314
|
otherPatches.forEach((item) => {
|
|
2611
|
-
transformedOperations = flatten
|
|
2315
|
+
transformedOperations = flatten(
|
|
2612
2316
|
transformedOperations.map(
|
|
2613
2317
|
(op) => transformOperation(editor, item.patch, op, item.snapshot, item.previousSnapshot)
|
|
2614
2318
|
)
|
|
@@ -2641,7 +2345,7 @@ function createWithUndoRedo(options) {
|
|
|
2641
2345
|
const otherPatches = remotePatches.filter((item) => item.time >= step.timestamp);
|
|
2642
2346
|
let transformedOperations = step.operations;
|
|
2643
2347
|
otherPatches.forEach((item) => {
|
|
2644
|
-
transformedOperations = flatten
|
|
2348
|
+
transformedOperations = flatten(
|
|
2645
2349
|
transformedOperations.map(
|
|
2646
2350
|
(op) => transformOperation(editor, item.patch, op, item.snapshot, item.previousSnapshot)
|
|
2647
2351
|
)
|
|
@@ -2759,7 +2463,7 @@ function createWithPatches({
|
|
|
2759
2463
|
schemaTypes
|
|
2760
2464
|
}) {
|
|
2761
2465
|
let previousChildren;
|
|
2762
|
-
const
|
|
2466
|
+
const applyPatch = createApplyPatch(schemaTypes);
|
|
2763
2467
|
return function(editor) {
|
|
2764
2468
|
IS_PROCESSING_REMOTE_CHANGES.set(editor, !1), PATCHING.set(editor, !0), previousChildren = [...editor.children];
|
|
2765
2469
|
const { apply: apply2 } = editor;
|
|
@@ -2776,7 +2480,7 @@ function createWithPatches({
|
|
|
2776
2480
|
withoutSaving(editor, () => {
|
|
2777
2481
|
withPreserveKeys(editor, () => {
|
|
2778
2482
|
patches.forEach((patch) => {
|
|
2779
|
-
debug$f.enabled && debug$f(`Handling remote patch ${JSON.stringify(patch)}`), changed =
|
|
2483
|
+
debug$f.enabled && debug$f(`Handling remote patch ${JSON.stringify(patch)}`), changed = applyPatch(editor, patch);
|
|
2780
2484
|
});
|
|
2781
2485
|
});
|
|
2782
2486
|
});
|
|
@@ -2803,7 +2507,7 @@ function createWithPatches({
|
|
|
2803
2507
|
const editorIsEmpty = isEqualToEmptyEditor(editor.children, schemaTypes);
|
|
2804
2508
|
if (!isPatching(editor))
|
|
2805
2509
|
return editor;
|
|
2806
|
-
switch (editorWasEmpty && !editorIsEmpty && operation.type !== "set_selection" && patches.push(insert
|
|
2510
|
+
switch (editorWasEmpty && !editorIsEmpty && operation.type !== "set_selection" && patches.push(insert(previousChildren, "before", [0])), operation.type) {
|
|
2807
2511
|
case "insert_text":
|
|
2808
2512
|
patches = [
|
|
2809
2513
|
...patches,
|
|
@@ -3575,7 +3279,7 @@ function validateValue(value, types, keyGenerator) {
|
|
|
3575
3279
|
autoResolve: !0,
|
|
3576
3280
|
patches: [
|
|
3577
3281
|
setIfMissing([], [{ _key: blk._key }, "children"]),
|
|
3578
|
-
insert
|
|
3282
|
+
insert([newSpan], "after", [{ _key: blk._key }, "children", 0])
|
|
3579
3283
|
],
|
|
3580
3284
|
description: `Children for text block with _key '${blk._key}' is empty.`,
|
|
3581
3285
|
action: "Insert an empty text",
|
|
@@ -3600,7 +3304,7 @@ function validateValue(value, types, keyGenerator) {
|
|
|
3600
3304
|
}
|
|
3601
3305
|
}, !0;
|
|
3602
3306
|
const allUsedMarks = uniq(
|
|
3603
|
-
flatten
|
|
3307
|
+
flatten(
|
|
3604
3308
|
textBlock.children.filter((cld) => cld._type === types.span.name).map((cld) => cld.marks || [])
|
|
3605
3309
|
)
|
|
3606
3310
|
);
|
|
@@ -3772,7 +3476,8 @@ function createWithInsertData(change$, schemaTypes, keyGenerator) {
|
|
|
3772
3476
|
editor,
|
|
3773
3477
|
toSlateValue(parsed, { schemaTypes }),
|
|
3774
3478
|
keyGenerator,
|
|
3775
|
-
spanTypeName
|
|
3479
|
+
spanTypeName,
|
|
3480
|
+
schemaTypes
|
|
3776
3481
|
), validation = validateValue(parsed, schemaTypes, keyGenerator);
|
|
3777
3482
|
if (!validation.valid && !((_a = validation.resolution) != null && _a.autoResolve)) {
|
|
3778
3483
|
const errorDescription = `${(_b = validation.resolution) == null ? void 0 : _b.description}`;
|
|
@@ -3853,21 +3558,32 @@ const entityMap = {
|
|
|
3853
3558
|
function escapeHtml(str) {
|
|
3854
3559
|
return String(str).replace(/[&<>"'`=/]/g, (s) => entityMap[s]);
|
|
3855
3560
|
}
|
|
3856
|
-
function _regenerateKeys(editor, fragment, keyGenerator, spanTypeName) {
|
|
3561
|
+
function _regenerateKeys(editor, fragment, keyGenerator, spanTypeName, editorTypes) {
|
|
3857
3562
|
return fragment.map((node) => {
|
|
3858
3563
|
const newNode = { ...node };
|
|
3859
|
-
editor.isTextBlock(newNode)
|
|
3860
|
-
const
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3564
|
+
if (editor.isTextBlock(newNode)) {
|
|
3565
|
+
const annotations = editorTypes.annotations.map((t) => t.name);
|
|
3566
|
+
if (annotations.length === 0) {
|
|
3567
|
+
const { markDefs, ...NewNodeNoDefs } = newNode;
|
|
3568
|
+
return { ...NewNodeNoDefs, _key: keyGenerator() };
|
|
3569
|
+
}
|
|
3570
|
+
if ((newNode.markDefs || []).some((def) => !annotations.includes(def._type))) {
|
|
3571
|
+
const allowedAnnotations = (newNode.markDefs || []).filter((def) => annotations.includes(def._type));
|
|
3572
|
+
return { ...newNode, markDefs: allowedAnnotations, _key: keyGenerator() };
|
|
3573
|
+
}
|
|
3574
|
+
newNode.markDefs = (newNode.markDefs || []).map((def) => {
|
|
3575
|
+
const oldKey = def._key, newKey = keyGenerator();
|
|
3576
|
+
return newNode.children = newNode.children.map(
|
|
3577
|
+
(child) => child._type === spanTypeName && editor.isTextSpan(child) ? {
|
|
3578
|
+
...child,
|
|
3579
|
+
marks: child.marks && child.marks.includes(oldKey) ? (
|
|
3580
|
+
// eslint-disable-next-line max-nested-callbacks
|
|
3581
|
+
[...child.marks].filter((mark) => mark !== oldKey).concat(newKey)
|
|
3582
|
+
) : child.marks
|
|
3583
|
+
} : child
|
|
3584
|
+
), { ...def, _key: newKey };
|
|
3585
|
+
});
|
|
3586
|
+
}
|
|
3871
3587
|
const nodeWithNewKeys = { ...newNode, _key: keyGenerator() };
|
|
3872
3588
|
return editor.isTextBlock(nodeWithNewKeys) && (nodeWithNewKeys.children = nodeWithNewKeys.children.map((child) => ({
|
|
3873
3589
|
...child,
|
|
@@ -4720,35 +4436,20 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
|
|
|
4720
4436
|
[onCopy]
|
|
4721
4437
|
), handlePaste = useCallback(
|
|
4722
4438
|
(event) => {
|
|
4723
|
-
if (event.preventDefault(),
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
new Promise((resolve) => {
|
|
4729
|
-
const value = PortableTextEditor.getValue(portableTextEditor), ptRange = toPortableTextRange(value, slateEditor.selection, schemaTypes), path = (ptRange == null ? void 0 : ptRange.focus.path) || [];
|
|
4730
|
-
resolve(
|
|
4731
|
-
onPaste({
|
|
4732
|
-
event,
|
|
4733
|
-
value,
|
|
4734
|
-
path,
|
|
4735
|
-
schemaTypes
|
|
4736
|
-
})
|
|
4737
|
-
);
|
|
4738
|
-
}).then((result) => {
|
|
4739
|
-
if (debug("Custom paste function from client resolved", result), change$.next({ type: "loading", isLoading: !0 }), !result || !result.insert) {
|
|
4740
|
-
debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData);
|
|
4741
|
-
return;
|
|
4742
|
-
}
|
|
4743
|
-
if (result && result.insert) {
|
|
4744
|
-
slateEditor.insertFragment(
|
|
4745
|
-
toSlateValue(result.insert, { schemaTypes })
|
|
4746
|
-
), change$.next({ type: "loading", isLoading: !1 });
|
|
4747
|
-
return;
|
|
4748
|
-
}
|
|
4749
|
-
console.warn("Your onPaste function returned something unexpected:", result);
|
|
4750
|
-
}).catch((error) => (change$.next({ type: "loading", isLoading: !1 }), console.error(error), error));
|
|
4439
|
+
if (event.preventDefault(), !slateEditor.selection)
|
|
4440
|
+
return;
|
|
4441
|
+
if (!onPaste) {
|
|
4442
|
+
debug("Pasting normally"), slateEditor.insertData(event.clipboardData);
|
|
4443
|
+
return;
|
|
4751
4444
|
}
|
|
4445
|
+
const value = PortableTextEditor.getValue(portableTextEditor), ptRange = toPortableTextRange(value, slateEditor.selection, schemaTypes), path = (ptRange == null ? void 0 : ptRange.focus.path) || [], onPasteResult = onPaste({ event, value, path, schemaTypes });
|
|
4446
|
+
onPasteResult === void 0 ? (debug("No result from custom paste handler, pasting normally"), slateEditor.insertData(event.clipboardData)) : (change$.next({ type: "loading", isLoading: !0 }), Promise.resolve(onPasteResult).then((result) => {
|
|
4447
|
+
debug("Custom paste function from client resolved", result), result && result.insert ? slateEditor.insertFragment(
|
|
4448
|
+
toSlateValue(result.insert, { schemaTypes })
|
|
4449
|
+
) : console.warn("Your onPaste function returned something unexpected:", result);
|
|
4450
|
+
}).catch((error) => (console.error(error), error)).finally(() => {
|
|
4451
|
+
change$.next({ type: "loading", isLoading: !1 });
|
|
4452
|
+
}));
|
|
4752
4453
|
},
|
|
4753
4454
|
[change$, onPaste, portableTextEditor, schemaTypes, slateEditor]
|
|
4754
4455
|
), handleOnFocus = useCallback(
|
|
@@ -4873,22 +4574,9 @@ const debug$1 = debugWithName("components:Leaf"), EMPTY_MARKS = [], Leaf = (prop
|
|
|
4873
4574
|
}
|
|
4874
4575
|
) : null;
|
|
4875
4576
|
});
|
|
4876
|
-
function compactPatches(patches) {
|
|
4877
|
-
const lastPatch = patches.slice(-1)[0];
|
|
4878
|
-
if (lastPatch && lastPatch.type === "unset" && lastPatch.path.length === 0)
|
|
4879
|
-
return [lastPatch];
|
|
4880
|
-
let finalPatches = patches;
|
|
4881
|
-
return finalPatches = finalPatches.filter((patch, index) => {
|
|
4882
|
-
if (!patch)
|
|
4883
|
-
return !1;
|
|
4884
|
-
const nextPatch = finalPatches[index + 1];
|
|
4885
|
-
return !(nextPatch && nextPatch.type === "set" && patch.type === "set" && isEqual(patch.path, nextPatch.path));
|
|
4886
|
-
}), finalPatches.length !== patches.length ? finalPatches : patches;
|
|
4887
|
-
}
|
|
4888
4577
|
export {
|
|
4889
4578
|
PortableTextEditable,
|
|
4890
4579
|
PortableTextEditor,
|
|
4891
|
-
compactPatches,
|
|
4892
4580
|
defaultKeyGenerator as keyGenerator,
|
|
4893
4581
|
usePortableTextEditor,
|
|
4894
4582
|
usePortableTextEditorSelection
|