@atlaskit/editor-plugin-show-diff 16.1.0 → 16.2.0
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 +33 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +67 -22
- package/dist/cjs/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +242 -26
- package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +71 -37
- package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +5 -1
- package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +0 -2
- package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +21 -14
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
- package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +123 -43
- package/dist/cjs/pm-plugins/decorations/revealStyles.js +5 -1
- package/dist/cjs/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +33 -0
- package/dist/cjs/pm-plugins/decorations/utils/createMarginAbsorber.js +43 -0
- package/dist/cjs/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +76 -0
- package/dist/cjs/pm-plugins/decorations/utils/safeResolve.js +24 -0
- package/dist/cjs/pm-plugins/getScrollableDecorations.js +48 -19
- package/dist/cjs/pm-plugins/utils/baseNodeName.js +25 -0
- package/dist/cjs/pm-plugins/utils/taggableBlockNodes.js +37 -0
- package/dist/cjs/ui/ContributorTag/contributorTagController.js +4 -4
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +39 -2
- package/dist/es2019/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +196 -10
- package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +51 -19
- package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +3 -0
- package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +0 -2
- package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +23 -14
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
- package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +60 -7
- package/dist/es2019/pm-plugins/decorations/revealStyles.js +5 -1
- package/dist/es2019/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +29 -0
- package/dist/es2019/pm-plugins/decorations/utils/createMarginAbsorber.js +39 -0
- package/dist/es2019/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +69 -0
- package/dist/es2019/pm-plugins/decorations/utils/safeResolve.js +18 -0
- package/dist/es2019/pm-plugins/getScrollableDecorations.js +44 -19
- package/dist/es2019/pm-plugins/utils/baseNodeName.js +18 -0
- package/dist/es2019/pm-plugins/utils/taggableBlockNodes.js +28 -0
- package/dist/es2019/ui/ContributorTag/contributorTagController.js +4 -4
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +67 -22
- package/dist/esm/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +243 -26
- package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +71 -37
- package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +5 -1
- package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +0 -2
- package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +21 -14
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
- package/dist/esm/pm-plugins/decorations/extractContributorTags.js +123 -43
- package/dist/esm/pm-plugins/decorations/revealStyles.js +5 -1
- package/dist/esm/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +28 -0
- package/dist/esm/pm-plugins/decorations/utils/createMarginAbsorber.js +37 -0
- package/dist/esm/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +70 -0
- package/dist/esm/pm-plugins/decorations/utils/safeResolve.js +18 -0
- package/dist/esm/pm-plugins/getScrollableDecorations.js +48 -19
- package/dist/esm/pm-plugins/utils/baseNodeName.js +20 -0
- package/dist/esm/pm-plugins/utils/taggableBlockNodes.js +32 -0
- package/dist/esm/ui/ContributorTag/contributorTagController.js +4 -4
- package/dist/types/pm-plugins/calculateDiff/simplifyChangesWithAttribution.d.ts +20 -1
- package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +4 -11
- package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +9 -8
- package/dist/types/pm-plugins/decorations/utils/absorbFirstChildMarginReset.d.ts +23 -0
- package/dist/types/pm-plugins/decorations/utils/createMarginAbsorber.d.ts +23 -0
- package/dist/types/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.d.ts +26 -0
- package/dist/types/pm-plugins/decorations/utils/safeResolve.d.ts +13 -0
- package/dist/types/pm-plugins/getScrollableDecorations.d.ts +2 -2
- package/dist/types/pm-plugins/utils/baseNodeName.d.ts +16 -0
- package/dist/types/pm-plugins/utils/taggableBlockNodes.d.ts +14 -0
- package/package.json +14 -5
|
@@ -190,8 +190,51 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
|
|
|
190
190
|
diffType = _ref5.diffType,
|
|
191
191
|
_ref5$coarseTableCell = _ref5.coarseTableCellsOnly,
|
|
192
192
|
coarseTableCellsOnly = _ref5$coarseTableCell === void 0 ? false : _ref5$coarseTableCell,
|
|
193
|
-
tagMountContext = _ref5.tagMountContext
|
|
193
|
+
tagMountContext = _ref5.tagMountContext,
|
|
194
|
+
nodeRanges = _ref5.nodeRanges;
|
|
194
195
|
var decorations = [];
|
|
196
|
+
|
|
197
|
+
// Exact-nodes path: only reached for a split change (EDITOR-8932), which names the nodes it
|
|
198
|
+
// owns. Deliberately kept separate from the walk below rather than sharing it.
|
|
199
|
+
if (nodeRanges) {
|
|
200
|
+
var _iterator = _createForOfIteratorHelper(nodeRanges),
|
|
201
|
+
_step;
|
|
202
|
+
try {
|
|
203
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
204
|
+
var _step$value = _step.value,
|
|
205
|
+
pos = _step$value.from,
|
|
206
|
+
nodeEnd = _step$value.to;
|
|
207
|
+
var node = doc.nodeAt(pos);
|
|
208
|
+
if (!(node !== null && node !== void 0 && node.isBlock)) {
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
var isActive = isRangeActive(activeIndexPos, pos, nodeEnd);
|
|
212
|
+
decorations.push.apply(decorations, _toConsumableArray(createBlockChangedDecoration({
|
|
213
|
+
attributionKey: attributionKey,
|
|
214
|
+
change: {
|
|
215
|
+
from: pos,
|
|
216
|
+
to: nodeEnd,
|
|
217
|
+
name: node.type.name
|
|
218
|
+
},
|
|
219
|
+
colorScheme: colorScheme,
|
|
220
|
+
isInserted: isInserted,
|
|
221
|
+
isActive: isActive,
|
|
222
|
+
shouldHideDeleted: shouldHideDeleted,
|
|
223
|
+
showContributorTags: showContributorTags,
|
|
224
|
+
showIndicators: showIndicators,
|
|
225
|
+
doc: doc,
|
|
226
|
+
diffType: diffType,
|
|
227
|
+
tagMountContext: tagMountContext
|
|
228
|
+
})));
|
|
229
|
+
}
|
|
230
|
+
} catch (err) {
|
|
231
|
+
_iterator.e(err);
|
|
232
|
+
} finally {
|
|
233
|
+
_iterator.f();
|
|
234
|
+
}
|
|
235
|
+
return decorations;
|
|
236
|
+
}
|
|
237
|
+
|
|
195
238
|
// Coarse path: inside the large table, only cell/header overlays are kept — the
|
|
196
239
|
// table/row/paragraph decorations there are redundant and cause expensive per-cell
|
|
197
240
|
// re-render. Blocks outside the table keep their normal decorations.
|
|
@@ -205,18 +248,18 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
|
|
|
205
248
|
}
|
|
206
249
|
}
|
|
207
250
|
if (node.isBlock && (!isExtendedEnabled(diffType) || pos + node.nodeSize <= to)) {
|
|
208
|
-
var
|
|
209
|
-
var
|
|
251
|
+
var _nodeEnd = pos + node.nodeSize;
|
|
252
|
+
var _isActive = isRangeActive(activeIndexPos, pos, _nodeEnd);
|
|
210
253
|
decorations.push.apply(decorations, _toConsumableArray(createBlockChangedDecoration({
|
|
211
254
|
attributionKey: attributionKey,
|
|
212
255
|
change: {
|
|
213
256
|
from: pos,
|
|
214
|
-
to:
|
|
257
|
+
to: _nodeEnd,
|
|
215
258
|
name: node.type.name
|
|
216
259
|
},
|
|
217
260
|
colorScheme: colorScheme,
|
|
218
261
|
isInserted: isInserted,
|
|
219
|
-
isActive:
|
|
262
|
+
isActive: _isActive,
|
|
220
263
|
shouldHideDeleted: shouldHideDeleted,
|
|
221
264
|
showContributorTags: showContributorTags,
|
|
222
265
|
showIndicators: showIndicators,
|
|
@@ -339,13 +382,13 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
339
382
|
}
|
|
340
383
|
var pendingAttrSteps = [];
|
|
341
384
|
var stepMaps = [];
|
|
342
|
-
var
|
|
343
|
-
|
|
385
|
+
var _iterator2 = _createForOfIteratorHelper(simplifiedSteps.entries()),
|
|
386
|
+
_step2;
|
|
344
387
|
try {
|
|
345
|
-
for (
|
|
346
|
-
var
|
|
347
|
-
stepIndex =
|
|
348
|
-
step =
|
|
388
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
389
|
+
var _step2$value = _slicedToArray(_step2.value, 2),
|
|
390
|
+
stepIndex = _step2$value[0],
|
|
391
|
+
step = _step2$value[1];
|
|
349
392
|
var result = step.apply(steppedDoc);
|
|
350
393
|
if (result.failed === null && result.doc) {
|
|
351
394
|
if (stepIsValidAttrChange(step, steppedDoc, result.doc)) {
|
|
@@ -364,9 +407,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
364
407
|
// Gate the complete attribution fix: mapped positions and step-time nodes are used together.
|
|
365
408
|
// The fallback deliberately preserves the legacy raw-position lookups for rollout safety.
|
|
366
409
|
} catch (err) {
|
|
367
|
-
|
|
410
|
+
_iterator2.e(err);
|
|
368
411
|
} finally {
|
|
369
|
-
|
|
412
|
+
_iterator2.f();
|
|
370
413
|
}
|
|
371
414
|
var attrStepContexts = fg('platform_editor_reduce_diff_attr_sensitivity') ? pendingAttrSteps.flatMap(function (_ref1) {
|
|
372
415
|
var afterNode = _ref1.afterNode,
|
|
@@ -454,7 +497,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
454
497
|
tr: tr,
|
|
455
498
|
attributedChanges: attributedChanges
|
|
456
499
|
});
|
|
457
|
-
changes = collapseOverlappingChanges(uncollapsedChanges);
|
|
500
|
+
changes = collapseOverlappingChanges(uncollapsedChanges, tr.doc);
|
|
458
501
|
|
|
459
502
|
// Still colours-only: a tags-only diff keeps the plain colour scheme.
|
|
460
503
|
if (attributionColoringEnabled) {
|
|
@@ -551,13 +594,13 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
551
594
|
// table (the cell overlays added below provide the highlight without the
|
|
552
595
|
// expensive content re-render); leaf blocks outside the table still get theirs.
|
|
553
596
|
var coarseTables = useCoarseTableDecoration ? tableRanges(tr.doc, change.fromB, change.toB) : [];
|
|
554
|
-
var
|
|
555
|
-
|
|
597
|
+
var _iterator3 = _createForOfIteratorHelper(leafTextblockRanges(tr.doc, change.fromB, change.toB)),
|
|
598
|
+
_step3;
|
|
556
599
|
try {
|
|
557
|
-
for (
|
|
558
|
-
var
|
|
559
|
-
from =
|
|
560
|
-
to =
|
|
600
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
601
|
+
var _step3$value = _slicedToArray(_step3.value, 2),
|
|
602
|
+
from = _step3$value[0],
|
|
603
|
+
to = _step3$value[1];
|
|
561
604
|
if (useCoarseTableDecoration && isInsideTable(coarseTables, from)) {
|
|
562
605
|
continue;
|
|
563
606
|
}
|
|
@@ -584,9 +627,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
584
627
|
}))));
|
|
585
628
|
}
|
|
586
629
|
} catch (err) {
|
|
587
|
-
|
|
630
|
+
_iterator3.e(err);
|
|
588
631
|
} finally {
|
|
589
|
-
|
|
632
|
+
_iterator3.f();
|
|
590
633
|
}
|
|
591
634
|
} else {
|
|
592
635
|
decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration(_objectSpread({
|
|
@@ -613,6 +656,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
613
656
|
doc: tr.doc,
|
|
614
657
|
from: change.fromB,
|
|
615
658
|
to: change.toB,
|
|
659
|
+
// A split piece's own range no longer covers the container it opened (EDITOR-8932).
|
|
660
|
+
nodeRanges: change.blockNodeRangesB,
|
|
616
661
|
colorScheme: changeColorScheme
|
|
617
662
|
}, isExtendedEnabled(diffType) && {
|
|
618
663
|
isInserted: isInserted,
|
|
@@ -1,13 +1,20 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
|
-
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
4
|
-
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
5
3
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
6
4
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
7
5
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
6
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
7
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
8
8
|
import { simplifyChanges } from 'prosemirror-changeset';
|
|
9
9
|
import { getAttributionKey } from '../decorations/colorSchemes/attributions';
|
|
10
10
|
import { optimizeChanges } from './optimizeChanges';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A change, plus the block nodes it owns when it is one piece of a split — a piece's own range no
|
|
14
|
+
* longer covers the container it opened. Absent on an unsplit change, which decorates the blocks
|
|
15
|
+
* inside its own range as before.
|
|
16
|
+
*/
|
|
17
|
+
|
|
11
18
|
var getAttributionIdentity = function getAttributionIdentity(change) {
|
|
12
19
|
var identities = new Set();
|
|
13
20
|
for (var _i = 0, _arr = [].concat(_toConsumableArray(change.deleted), _toConsumableArray(change.inserted)); _i < _arr.length; _i++) {
|
|
@@ -29,55 +36,265 @@ var byNewDocRange = function byNewDocRange(left, right) {
|
|
|
29
36
|
return left.fromB - right.fromB || left.toB - right.toB;
|
|
30
37
|
};
|
|
31
38
|
|
|
39
|
+
/** Union of the given ranges, with overlapping and touching ones merged. */
|
|
40
|
+
var mergeRanges = function mergeRanges(ranges) {
|
|
41
|
+
return _toConsumableArray(ranges).sort(function (left, right) {
|
|
42
|
+
return left.from - right.from;
|
|
43
|
+
}).reduce(function (merged, range) {
|
|
44
|
+
var last = merged[merged.length - 1];
|
|
45
|
+
if (last && range.from <= last.to) {
|
|
46
|
+
last.to = Math.max(last.to, range.to);
|
|
47
|
+
return merged;
|
|
48
|
+
}
|
|
49
|
+
return [].concat(_toConsumableArray(merged), [_objectSpread({}, range)]);
|
|
50
|
+
}, []);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/** Whether `inner` sits wholly inside `outer` and covers less of the document. */
|
|
54
|
+
var isContained = function isContained(outer, inner) {
|
|
55
|
+
return inner.toB > inner.fromB && outer.fromB <= inner.fromB && inner.toB <= outer.toB && inner.toB - inner.fromB < outer.toB - outer.fromB;
|
|
56
|
+
};
|
|
57
|
+
|
|
32
58
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* Merging keeps every span from both sides, so the latest-writer rule still decides whose tag is
|
|
38
|
-
* shown. Ranges that merely touch are left alone, so an unattributed edit next to an attributed one
|
|
39
|
-
* is not credited to it.
|
|
59
|
+
* The block nodes in `change` whose opening position `ownsPosition` claims. Ownership is by opening
|
|
60
|
+
* position so a block another contributor added inside a container is not claimed by whoever opened
|
|
61
|
+
* the container. `undefined` for a range this document cannot resolve, which falls the piece back
|
|
62
|
+
* to decorating its own range.
|
|
40
63
|
*/
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
return
|
|
64
|
+
var blockNodeRanges = function blockNodeRanges(doc, change, ownsPosition) {
|
|
65
|
+
if (!doc || change.from >= change.to || change.to > doc.content.size) {
|
|
66
|
+
return undefined;
|
|
44
67
|
}
|
|
68
|
+
var ranges = [];
|
|
69
|
+
doc.nodesBetween(change.from, change.to, function (node, pos) {
|
|
70
|
+
if (node.isBlock && ownsPosition(pos) && pos + node.nodeSize <= change.to) {
|
|
71
|
+
ranges.push({
|
|
72
|
+
from: pos,
|
|
73
|
+
to: pos + node.nodeSize
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return true;
|
|
77
|
+
});
|
|
78
|
+
return ranges;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Splits a change whose spans name more than one contributor into one change per run of consecutive
|
|
83
|
+
* spans sharing a key.
|
|
84
|
+
*
|
|
85
|
+
* `prosemirror-changeset` merges contiguous inserted content into one change while keeping per-span
|
|
86
|
+
* data, so a panel inserted by one contributor and edited inside by another arrives as a single
|
|
87
|
+
* change holding every span — and the latest-writer rule credited all of it, panel included, to
|
|
88
|
+
* whoever wrote last (EDITOR-8932).
|
|
89
|
+
*/
|
|
90
|
+
var splitMixedIdentityChanges = function splitMixedIdentityChanges(changes, doc) {
|
|
91
|
+
return changes.flatMap(function (change) {
|
|
92
|
+
if (getAttributionIdentity(change).mergeable) {
|
|
93
|
+
return [change];
|
|
94
|
+
}
|
|
95
|
+
var runs = [];
|
|
96
|
+
var offset = change.fromB;
|
|
97
|
+
var _iterator = _createForOfIteratorHelper(change.inserted),
|
|
98
|
+
_step;
|
|
99
|
+
try {
|
|
100
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
101
|
+
var span = _step.value;
|
|
102
|
+
var key = getAttributionKey(span.data);
|
|
103
|
+
var last = runs[runs.length - 1];
|
|
104
|
+
if (last && last.key === key) {
|
|
105
|
+
last.to = offset + span.length;
|
|
106
|
+
last.spans.push(span);
|
|
107
|
+
} else {
|
|
108
|
+
runs.push({
|
|
109
|
+
key: key,
|
|
110
|
+
from: offset,
|
|
111
|
+
to: offset + span.length,
|
|
112
|
+
spans: [span]
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
offset += span.length;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// The offsets above are only positions if the spans partition the inserted range.
|
|
119
|
+
} catch (err) {
|
|
120
|
+
_iterator.e(err);
|
|
121
|
+
} finally {
|
|
122
|
+
_iterator.f();
|
|
123
|
+
}
|
|
124
|
+
if (runs.length < 2 || offset !== change.toB) {
|
|
125
|
+
return [change];
|
|
126
|
+
}
|
|
127
|
+
return runs.map(function (run, index) {
|
|
128
|
+
var owned = blockNodeRanges(doc, {
|
|
129
|
+
from: change.fromB,
|
|
130
|
+
to: change.toB
|
|
131
|
+
}, function (pos) {
|
|
132
|
+
return pos >= run.from && pos < run.to;
|
|
133
|
+
});
|
|
134
|
+
return _objectSpread(_objectSpread({}, change), {}, {
|
|
135
|
+
fromA: index === 0 ? change.fromA : change.toA,
|
|
136
|
+
fromB: run.from,
|
|
137
|
+
toB: run.to,
|
|
138
|
+
deleted: index === 0 ? change.deleted : [],
|
|
139
|
+
inserted: run.spans
|
|
140
|
+
}, owned ? {
|
|
141
|
+
blockNodeRangesB: owned
|
|
142
|
+
} : {});
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
};
|
|
45
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Subtracts every other author's contained change from a change's range, so both contributions
|
|
149
|
+
* survive. Applies when the contributors arrive as separate changes rather than as spans of one —
|
|
150
|
+
* the `step` diff type. A contained change by the same author, and one that only partially
|
|
151
|
+
* overlaps, are left for the collapse below.
|
|
152
|
+
*
|
|
153
|
+
* The leading fragment keeps the deleted side, so one deletion is not drawn once per fragment.
|
|
154
|
+
*/
|
|
155
|
+
var splitContainedChanges = function splitContainedChanges(changes, doc) {
|
|
156
|
+
return changes.flatMap(function (change) {
|
|
157
|
+
var _getAttributionIdenti = getAttributionIdentity(change),
|
|
158
|
+
key = _getAttributionIdenti.key;
|
|
159
|
+
var inner = mergeRanges(changes.filter(function (other) {
|
|
160
|
+
var otherKey = getAttributionIdentity(other).key;
|
|
161
|
+
return other !== change && key !== undefined && otherKey !== undefined && otherKey !== key && isContained(change, other);
|
|
162
|
+
}).map(function (_ref) {
|
|
163
|
+
var fromB = _ref.fromB,
|
|
164
|
+
toB = _ref.toB;
|
|
165
|
+
return {
|
|
166
|
+
from: fromB,
|
|
167
|
+
to: toB
|
|
168
|
+
};
|
|
169
|
+
}));
|
|
170
|
+
if (inner.length === 0) {
|
|
171
|
+
return [change];
|
|
172
|
+
}
|
|
173
|
+
var gaps = [];
|
|
174
|
+
var cursor = change.fromB;
|
|
175
|
+
var _iterator2 = _createForOfIteratorHelper(inner),
|
|
176
|
+
_step2;
|
|
177
|
+
try {
|
|
178
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
179
|
+
var _step2$value = _step2.value,
|
|
180
|
+
from = _step2$value.from,
|
|
181
|
+
to = _step2$value.to;
|
|
182
|
+
if (from > cursor) {
|
|
183
|
+
gaps.push({
|
|
184
|
+
from: cursor,
|
|
185
|
+
to: from
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
cursor = Math.max(cursor, to);
|
|
189
|
+
}
|
|
190
|
+
} catch (err) {
|
|
191
|
+
_iterator2.e(err);
|
|
192
|
+
} finally {
|
|
193
|
+
_iterator2.f();
|
|
194
|
+
}
|
|
195
|
+
if (change.toB > cursor) {
|
|
196
|
+
gaps.push({
|
|
197
|
+
from: cursor,
|
|
198
|
+
to: change.toB
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Subtracted end to end, so nothing is left to highlight — but the blocks are still owned.
|
|
203
|
+
var fragments = gaps.length > 0 ? gaps : [{
|
|
204
|
+
from: change.toB,
|
|
205
|
+
to: change.toB
|
|
206
|
+
}];
|
|
207
|
+
// The outer author's: every block in their range that no inner change opened.
|
|
208
|
+
var owned = blockNodeRanges(doc, {
|
|
209
|
+
from: change.fromB,
|
|
210
|
+
to: change.toB
|
|
211
|
+
}, function (pos) {
|
|
212
|
+
return !inner.some(function (_ref2) {
|
|
213
|
+
var from = _ref2.from,
|
|
214
|
+
to = _ref2.to;
|
|
215
|
+
return pos >= from && pos < to;
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
return fragments.map(function (fragment, index) {
|
|
219
|
+
return _objectSpread(_objectSpread({}, change), {}, {
|
|
220
|
+
fromA: index === 0 ? change.fromA : change.toA,
|
|
221
|
+
fromB: fragment.from,
|
|
222
|
+
toB: fragment.to,
|
|
223
|
+
deleted: index === 0 ? change.deleted : []
|
|
224
|
+
}, owned ? {
|
|
225
|
+
blockNodeRangesB: index === 0 ? owned : []
|
|
226
|
+
} : {});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The blocks a merged change owns. Both sides must name theirs, or the merge falls back to its own
|
|
233
|
+
* range — narrowing it could drop a block altogether.
|
|
234
|
+
*/
|
|
235
|
+
var mergeBlockNodeRanges = function mergeBlockNodeRanges(left, right) {
|
|
236
|
+
return left.blockNodeRangesB && right.blockNodeRangesB ? [].concat(_toConsumableArray(left.blockNodeRangesB), _toConsumableArray(right.blockNodeRangesB)) : undefined;
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/** Unions the changes whose new-document ranges strictly overlap, leaving touching ones alone. */
|
|
240
|
+
var collapse = function collapse(changes) {
|
|
46
241
|
// A zero-length new-document range paints no inline decoration, so it is kept aside rather than
|
|
47
242
|
// folded into a neighbouring insertion.
|
|
48
243
|
var emptyRanges = changes.filter(function (change) {
|
|
49
244
|
return change.toB <= change.fromB;
|
|
50
245
|
});
|
|
51
246
|
var collapsed = [];
|
|
52
|
-
var
|
|
247
|
+
var _iterator3 = _createForOfIteratorHelper(changes.filter(function (change) {
|
|
53
248
|
return change.toB > change.fromB;
|
|
54
249
|
}).sort(byNewDocRange)),
|
|
55
|
-
|
|
250
|
+
_step3;
|
|
56
251
|
try {
|
|
57
|
-
for (
|
|
58
|
-
var change =
|
|
252
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
253
|
+
var change = _step3.value;
|
|
59
254
|
var current = collapsed[collapsed.length - 1];
|
|
60
255
|
if (current && change.fromB < current.toB) {
|
|
61
|
-
|
|
256
|
+
var blockNodeRangesB = mergeBlockNodeRanges(current, change);
|
|
257
|
+
collapsed[collapsed.length - 1] = _objectSpread({
|
|
62
258
|
fromA: Math.min(current.fromA, change.fromA),
|
|
63
259
|
toA: Math.max(current.toA, change.toA),
|
|
64
260
|
fromB: Math.min(current.fromB, change.fromB),
|
|
65
261
|
toB: Math.max(current.toB, change.toB),
|
|
66
262
|
deleted: [].concat(_toConsumableArray(current.deleted), _toConsumableArray(change.deleted)),
|
|
67
263
|
inserted: [].concat(_toConsumableArray(current.inserted), _toConsumableArray(change.inserted))
|
|
68
|
-
}
|
|
264
|
+
}, blockNodeRangesB ? {
|
|
265
|
+
blockNodeRangesB: blockNodeRangesB
|
|
266
|
+
} : {});
|
|
69
267
|
} else {
|
|
70
268
|
collapsed.push(_objectSpread({}, change));
|
|
71
269
|
}
|
|
72
270
|
}
|
|
73
271
|
} catch (err) {
|
|
74
|
-
|
|
272
|
+
_iterator3.e(err);
|
|
75
273
|
} finally {
|
|
76
|
-
|
|
274
|
+
_iterator3.f();
|
|
77
275
|
}
|
|
78
276
|
return [].concat(collapsed, _toConsumableArray(emptyRanges)).sort(byNewDocRange);
|
|
79
277
|
};
|
|
80
278
|
|
|
279
|
+
/**
|
|
280
|
+
* Collapses changes whose new-document ranges strictly overlap. Attribution runs are simplified
|
|
281
|
+
* independently, so runs either side of an unattributed step can come back covering the same
|
|
282
|
+
* characters — which stacks two inline decorations and renders one contributor tag per copy.
|
|
283
|
+
*
|
|
284
|
+
* Merging keeps every span from both sides, so the latest-writer rule still decides whose tag is
|
|
285
|
+
* shown. Ranges that merely touch are left alone, so an unattributed edit next to an attributed one
|
|
286
|
+
* is not credited to it.
|
|
287
|
+
*
|
|
288
|
+
* Contributors are separated first, by `splitMixedIdentityChanges` and `splitContainedChanges`.
|
|
289
|
+
* Both leave ranges that only touch, so they survive the collapse.
|
|
290
|
+
*
|
|
291
|
+
* Carries no gate of its own: the only caller reaches it through the attributed changeset, which
|
|
292
|
+
* already requires `confluence_ncs_step_diffing_version_history`.
|
|
293
|
+
*/
|
|
294
|
+
export var collapseOverlappingChanges = function collapseOverlappingChanges(changes, doc) {
|
|
295
|
+
return collapse(splitContainedChanges(splitMixedIdentityChanges(changes, doc), doc));
|
|
296
|
+
};
|
|
297
|
+
|
|
81
298
|
/**
|
|
82
299
|
* Simplifies and optimizes consecutive changes without crossing an attribution boundary.
|
|
83
300
|
* A change which already contains more than one identity is deliberately kept isolated.
|
|
@@ -107,12 +324,12 @@ export var simplifyChangesWithAttribution = function simplifyChangesWithAttribut
|
|
|
107
324
|
run = [];
|
|
108
325
|
runIdentity = undefined;
|
|
109
326
|
};
|
|
110
|
-
var
|
|
111
|
-
|
|
327
|
+
var _iterator4 = _createForOfIteratorHelper(changes),
|
|
328
|
+
_step4;
|
|
112
329
|
try {
|
|
113
|
-
for (
|
|
330
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
114
331
|
var _runIdentity;
|
|
115
|
-
var change =
|
|
332
|
+
var change = _step4.value;
|
|
116
333
|
var identity = getAttributionIdentity(change);
|
|
117
334
|
var canJoinRun = ((_runIdentity = runIdentity) === null || _runIdentity === void 0 ? void 0 : _runIdentity.mergeable) === true && identity.mergeable && runIdentity.key === identity.key;
|
|
118
335
|
if (run.length > 0 && !canJoinRun) {
|
|
@@ -125,9 +342,9 @@ export var simplifyChangesWithAttribution = function simplifyChangesWithAttribut
|
|
|
125
342
|
}
|
|
126
343
|
}
|
|
127
344
|
} catch (err) {
|
|
128
|
-
|
|
345
|
+
_iterator4.e(err);
|
|
129
346
|
} finally {
|
|
130
|
-
|
|
347
|
+
_iterator4.f();
|
|
131
348
|
}
|
|
132
349
|
flush();
|
|
133
350
|
return result;
|