prosemirror-changeset 2.4.3 → 2.4.4
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/CHANGELOG.md +6 -0
- package/dist/index.cjs +6 -4
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +7 -4
- package/package.json +1 -1
- package/src/diff.ts +6 -4
- package/test/test-diff.ts +8 -0
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -53,13 +53,14 @@ function tokens(frag, encoder, start, end, target) {
|
|
|
53
53
|
}
|
|
54
54
|
return target;
|
|
55
55
|
}
|
|
56
|
-
var MAX_DIFF_SIZE = 2500
|
|
56
|
+
var MAX_DIFF_SIZE = 2500,
|
|
57
|
+
MAX_TOKEN_SIZE = 10000;
|
|
57
58
|
function minUnchanged(sizeA, sizeB) {
|
|
58
59
|
return Math.min(15, Math.max(2, Math.floor(Math.max(sizeA, sizeB) / 10)));
|
|
59
60
|
}
|
|
60
61
|
function computeDiff(fragA, fragB, range) {
|
|
61
62
|
var encoder = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : DefaultEncoder;
|
|
62
|
-
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) >
|
|
63
|
+
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) > MAX_TOKEN_SIZE) return [range];
|
|
63
64
|
var tokA = tokens(fragA, encoder, range.fromA, range.toA, []);
|
|
64
65
|
var tokB = tokens(fragB, encoder, range.fromB, range.toB, []);
|
|
65
66
|
return diff(tokA, tokB, range, encoder.compareTokens);
|
|
@@ -71,7 +72,8 @@ function diff(tokA, tokB, range, cmp) {
|
|
|
71
72
|
while (start < tokA.length && start < tokB.length && cmp(tokA[start], tokB[start])) start++;
|
|
72
73
|
if (start == tokA.length && start == tokB.length) return [];
|
|
73
74
|
while (endA > start && endB > start && cmp(tokA[endA - 1], tokB[endB - 1])) endA--, endB--;
|
|
74
|
-
if (endA == start
|
|
75
|
+
if (endA == start && endB == start) return [];
|
|
76
|
+
if (endA == start || endB == start || endA == endB && endA == start + 1 || Math.max(endA, endB) - start > MAX_DIFF_SIZE) return [range.slice(start, endA, start, endB)];
|
|
75
77
|
var lenA = endA - start,
|
|
76
78
|
lenB = endB - start;
|
|
77
79
|
var max = Math.min(MAX_DIFF_SIZE, lenA + lenB);
|
|
@@ -134,7 +136,7 @@ function diff(tokA, tokB, range, cmp) {
|
|
|
134
136
|
}
|
|
135
137
|
if (size % 2 == 0) history.push(frontier.slice());
|
|
136
138
|
}
|
|
137
|
-
return [range];
|
|
139
|
+
return [range.slice(start, endA, start, endB)];
|
|
138
140
|
}
|
|
139
141
|
var Span = function () {
|
|
140
142
|
function Span(length, data) {
|
package/dist/index.d.cts
CHANGED
|
@@ -183,4 +183,5 @@ declare class ChangeSet<Data = any> {
|
|
|
183
183
|
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>, changes?: readonly Change<Data>[]): ChangeSet<Data>;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
export { Change,
|
|
186
|
+
export { Change, ChangeSet, Span, simplifyChanges };
|
|
187
|
+
export type { ChangeJSON, TokenEncoder };
|
package/dist/index.d.ts
CHANGED
|
@@ -183,4 +183,5 @@ declare class ChangeSet<Data = any> {
|
|
|
183
183
|
static create<Data = any>(doc: Node, combine?: (dataA: Data, dataB: Data) => Data, tokenEncoder?: TokenEncoder<any>, changes?: readonly Change<Data>[]): ChangeSet<Data>;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
export { Change,
|
|
186
|
+
export { Change, ChangeSet, Span, simplifyChanges };
|
|
187
|
+
export type { ChangeJSON, TokenEncoder };
|
package/dist/index.js
CHANGED
|
@@ -42,7 +42,7 @@ function tokens(frag, encoder, start, end, target) {
|
|
|
42
42
|
// The code below will refuse to compute a diff with more than 5000
|
|
43
43
|
// insertions or deletions, which takes about 300ms to reach on my
|
|
44
44
|
// machine. This is a safeguard against runaway computations.
|
|
45
|
-
const MAX_DIFF_SIZE = 2500;
|
|
45
|
+
const MAX_DIFF_SIZE = 2500, MAX_TOKEN_SIZE = 10000;
|
|
46
46
|
// This obscure mess of constants computes the minimum length of an
|
|
47
47
|
// unchanged range (not at the start/end of the compared content). The
|
|
48
48
|
// idea is to make it higher in bigger replacements, so that you don't
|
|
@@ -54,7 +54,7 @@ function minUnchanged(sizeA, sizeB) {
|
|
|
54
54
|
function computeDiff(fragA, fragB, range, encoder = DefaultEncoder) {
|
|
55
55
|
// When one side is longer than our max scan distance, the algorithm
|
|
56
56
|
// will never find a diff.
|
|
57
|
-
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) >
|
|
57
|
+
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) > MAX_TOKEN_SIZE)
|
|
58
58
|
return [range];
|
|
59
59
|
let tokA = tokens(fragA, encoder, range.fromA, range.toA, []);
|
|
60
60
|
let tokB = tokens(fragB, encoder, range.fromB, range.toB, []);
|
|
@@ -69,9 +69,12 @@ function diff(tokA, tokB, range, cmp) {
|
|
|
69
69
|
return [];
|
|
70
70
|
while (endA > start && endB > start && cmp(tokA[endA - 1], tokB[endB - 1]))
|
|
71
71
|
endA--, endB--;
|
|
72
|
+
// No difference
|
|
73
|
+
if (endA == start && endB == start)
|
|
74
|
+
return [];
|
|
72
75
|
// If the result is simple _or_ too big to cheaply compute, return
|
|
73
76
|
// the remaining region as the diff
|
|
74
|
-
if (endA == start || endB == start || (endA == endB && endA == start + 1))
|
|
77
|
+
if (endA == start || endB == start || (endA == endB && endA == start + 1) || Math.max(endA, endB) - start > MAX_DIFF_SIZE)
|
|
75
78
|
return [range.slice(start, endA, start, endB)];
|
|
76
79
|
// This is an implementation of Myers' diff algorithm
|
|
77
80
|
// See https://neil.fraser.name/writing/diff/myers.pdf and
|
|
@@ -136,7 +139,7 @@ function diff(tokA, tokB, range, cmp) {
|
|
|
136
139
|
}
|
|
137
140
|
// The loop exited, meaning the maximum amount of work was done.
|
|
138
141
|
// Just return a change spanning the entire range.
|
|
139
|
-
return [range];
|
|
142
|
+
return [range.slice(start, endA, start, endB)];
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
/**
|
package/package.json
CHANGED
package/src/diff.ts
CHANGED
|
@@ -64,7 +64,7 @@ function tokens<T>(frag: Fragment, encoder: TokenEncoder<T>, start: number, end:
|
|
|
64
64
|
// The code below will refuse to compute a diff with more than 5000
|
|
65
65
|
// insertions or deletions, which takes about 300ms to reach on my
|
|
66
66
|
// machine. This is a safeguard against runaway computations.
|
|
67
|
-
const MAX_DIFF_SIZE = 2500
|
|
67
|
+
const MAX_DIFF_SIZE = 2500, MAX_TOKEN_SIZE = 10000
|
|
68
68
|
|
|
69
69
|
// This obscure mess of constants computes the minimum length of an
|
|
70
70
|
// unchanged range (not at the start/end of the compared content). The
|
|
@@ -78,7 +78,7 @@ function minUnchanged(sizeA: number, sizeB: number) {
|
|
|
78
78
|
export function computeDiff(fragA: Fragment, fragB: Fragment, range: Change, encoder: TokenEncoder<any> = DefaultEncoder) {
|
|
79
79
|
// When one side is longer than our max scan distance, the algorithm
|
|
80
80
|
// will never find a diff.
|
|
81
|
-
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) >
|
|
81
|
+
if (Math.max(range.toA - range.fromA, range.toB - range.fromB) > MAX_TOKEN_SIZE)
|
|
82
82
|
return [range]
|
|
83
83
|
let tokA = tokens(fragA, encoder, range.fromA, range.toA, [])
|
|
84
84
|
let tokB = tokens(fragB, encoder, range.fromB, range.toB, [])
|
|
@@ -91,9 +91,11 @@ function diff<T>(tokA: T[], tokB: T[], range: Change, cmp: (a: T, b: T) => boole
|
|
|
91
91
|
while (start < tokA.length && start < tokB.length && cmp(tokA[start], tokB[start])) start++
|
|
92
92
|
if (start == tokA.length && start == tokB.length) return []
|
|
93
93
|
while (endA > start && endB > start && cmp(tokA[endA - 1], tokB[endB - 1])) endA--, endB--
|
|
94
|
+
// No difference
|
|
95
|
+
if (endA == start && endB == start) return []
|
|
94
96
|
// If the result is simple _or_ too big to cheaply compute, return
|
|
95
97
|
// the remaining region as the diff
|
|
96
|
-
if (endA == start || endB == start || (endA == endB && endA == start + 1))
|
|
98
|
+
if (endA == start || endB == start || (endA == endB && endA == start + 1) || Math.max(endA, endB) - start > MAX_DIFF_SIZE)
|
|
97
99
|
return [range.slice(start, endA, start, endB)]
|
|
98
100
|
|
|
99
101
|
// This is an implementation of Myers' diff algorithm
|
|
@@ -152,5 +154,5 @@ function diff<T>(tokA: T[], tokB: T[], range: Change, cmp: (a: T, b: T) => boole
|
|
|
152
154
|
}
|
|
153
155
|
// The loop exited, meaning the maximum amount of work was done.
|
|
154
156
|
// Just return a change spanning the entire range.
|
|
155
|
-
return [range]
|
|
157
|
+
return [range.slice(start, endA, start, endB)]
|
|
156
158
|
}
|
package/test/test-diff.ts
CHANGED
|
@@ -66,4 +66,12 @@ describe("computeDiff", () => {
|
|
|
66
66
|
|
|
67
67
|
it("sees the difference between different closing tokens", () =>
|
|
68
68
|
test(doc(p("a")), doc(h1("oo")), [0, 3, 0, 4]))
|
|
69
|
+
|
|
70
|
+
it("finds no changes on unchanged content", () =>
|
|
71
|
+
test(doc(p("abc")), doc(p("abc"))))
|
|
72
|
+
|
|
73
|
+
it("can compute a diff for a big change with unchanged prefix/suffix", () =>
|
|
74
|
+
test(doc(p("x".repeat(2000) + "a" + "y".repeat(2000))),
|
|
75
|
+
doc(p("x".repeat(2000) + "b" + "y".repeat(2000))),
|
|
76
|
+
[2001, 2002, 2001, 2002]))
|
|
69
77
|
})
|