@atlaskit/editor-plugin-show-diff 20.0.1 → 20.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/CHANGELOG.md +23 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +9 -10
- package/dist/cjs/pm-plugins/calculateDiff/groupDeletedColumnChanges.js +92 -26
- package/dist/cjs/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +46 -22
- package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +4 -5
- package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +1 -1
- package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +3 -1
- package/dist/cjs/pm-plugins/getScrollableDecorations.js +1 -8
- package/dist/cjs/pm-plugins/main.js +5 -2
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +9 -10
- package/dist/es2019/pm-plugins/calculateDiff/groupDeletedColumnChanges.js +85 -14
- package/dist/es2019/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +42 -22
- package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +4 -5
- package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +1 -1
- package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +1 -1
- package/dist/es2019/pm-plugins/getScrollableDecorations.js +1 -6
- package/dist/es2019/pm-plugins/main.js +5 -1
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +9 -10
- package/dist/esm/pm-plugins/calculateDiff/groupDeletedColumnChanges.js +92 -26
- package/dist/esm/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +46 -22
- package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +4 -5
- package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +1 -1
- package/dist/esm/pm-plugins/decorations/extractContributorTags.js +3 -1
- package/dist/esm/pm-plugins/getScrollableDecorations.js +1 -8
- package/dist/esm/pm-plugins/main.js +5 -2
- package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +6 -4
- package/dist/types/pm-plugins/calculateDiff/simplifyChangesWithAttribution.d.ts +2 -2
- package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +2 -3
- package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +1 -0
- package/dist/types/pm-plugins/decorations/extractContributorTags.d.ts +1 -0
- package/dist/types/pm-plugins/main.d.ts +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 20.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 20.0.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`4d3e3d0afb998`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4d3e3d0afb998) -
|
|
14
|
+
Fix "Removed" labels on table diffs:
|
|
15
|
+
- Keep the label on deleted table rows attached to its row when the page scrolls.
|
|
16
|
+
- Identify deleted table columns by cell `localId` when a diff replaces the whole table, so
|
|
17
|
+
columns with matching content, such as empty columns, are labelled correctly. Tables without
|
|
18
|
+
usable cell ids fall back to comparing whole columns, and only label columns when that
|
|
19
|
+
comparison has one answer.
|
|
20
|
+
|
|
21
|
+
- [`b8c8e84ed75bd`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/b8c8e84ed75bd) -
|
|
22
|
+
Keep unattributed diff decorations separate from attributed changes in navigation and active
|
|
23
|
+
highlighting under `confluence_ncs_step_diffing_version_history`.
|
|
24
|
+
- Updated dependencies
|
|
25
|
+
|
|
3
26
|
## 20.0.1
|
|
4
27
|
|
|
5
28
|
### Patch Changes
|
|
@@ -127,19 +127,18 @@ var leafTextblockRanges = function leafTextblockRanges(doc, from, to) {
|
|
|
127
127
|
// once it has more leaf textblocks (~cells) than this threshold. Small tables
|
|
128
128
|
// keep the precise per-cell path.
|
|
129
129
|
var LARGE_TABLE_LEAF_THRESHOLD = 40;
|
|
130
|
-
|
|
131
130
|
/**
|
|
132
|
-
* An active scrollable change may contain several underlying diff changes.
|
|
133
|
-
*
|
|
131
|
+
* An active scrollable change may contain several underlying diff changes. With attribution, only
|
|
132
|
+
* ranges belonging to the selected contributor (including the anonymous contributor) are active.
|
|
134
133
|
*/
|
|
135
|
-
var isRangeActive = function isRangeActive(activeIndexPos, from, to) {
|
|
134
|
+
var isRangeActive = function isRangeActive(activeIndexPos, from, to, attributionKey) {
|
|
136
135
|
if (activeIndexPos === undefined) {
|
|
137
136
|
return undefined;
|
|
138
137
|
}
|
|
139
138
|
if (!(0, _fg.fg)('confluence_ncs_step_diffing_version_history')) {
|
|
140
139
|
return from === activeIndexPos.from && to === activeIndexPos.to;
|
|
141
140
|
}
|
|
142
|
-
return from <= activeIndexPos.to && activeIndexPos.from <= to;
|
|
141
|
+
return from <= activeIndexPos.to && activeIndexPos.from <= to && (!('attributionKey' in activeIndexPos) || activeIndexPos.attributionKey === attributionKey);
|
|
143
142
|
};
|
|
144
143
|
var isLargeInsertedTableRange = function isLargeInsertedTableRange(doc, from, to) {
|
|
145
144
|
var containsTable = false;
|
|
@@ -214,7 +213,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
|
|
|
214
213
|
if (!(node !== null && node !== void 0 && node.isBlock)) {
|
|
215
214
|
continue;
|
|
216
215
|
}
|
|
217
|
-
var isActive = isRangeActive(activeIndexPos, pos, nodeEnd);
|
|
216
|
+
var isActive = isRangeActive(activeIndexPos, pos, nodeEnd, attributionKey);
|
|
218
217
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createBlockChangedDecoration.createBlockChangedDecoration)({
|
|
219
218
|
attributionKey: attributionKey,
|
|
220
219
|
change: {
|
|
@@ -258,7 +257,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
|
|
|
258
257
|
}
|
|
259
258
|
if (node.isBlock && (!requireContainedBlocks || pos >= from) && pos + node.nodeSize <= to) {
|
|
260
259
|
var _nodeEnd = pos + node.nodeSize;
|
|
261
|
-
var _isActive = isRangeActive(activeIndexPos, pos, _nodeEnd);
|
|
260
|
+
var _isActive = isRangeActive(activeIndexPos, pos, _nodeEnd, attributionKey);
|
|
262
261
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createBlockChangedDecoration.createBlockChangedDecoration)({
|
|
263
262
|
attributionKey: attributionKey,
|
|
264
263
|
change: {
|
|
@@ -542,7 +541,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
542
541
|
var leftAnchorId = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? "replacement-".concat(change.fromA, "-").concat(change.toA, "-").concat(change.fromB, "-").concat(change.toB) : undefined;
|
|
543
542
|
var changeColorScheme = attributionColors ? (0, _attributions.getColorSchemeForChange)(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
|
|
544
543
|
var attributionKey = showContributorTags ? (0, _attributions.getAttributionKeyForChange)(change, attributedChanges) : undefined;
|
|
545
|
-
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
544
|
+
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
546
545
|
var deletedColumns = change.deletedColumns;
|
|
547
546
|
// On an inverted diff the table that lost columns is the one in `tr.doc`, so the column
|
|
548
547
|
// indices address it directly and each label anchors inside its own cell.
|
|
@@ -779,7 +778,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
779
778
|
var _attributionColors$ge, _attributionColors;
|
|
780
779
|
var changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
|
|
781
780
|
var attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
782
|
-
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
781
|
+
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
783
782
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
|
|
784
783
|
attributionKey: attributionKey,
|
|
785
784
|
change: change,
|
|
@@ -808,7 +807,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
808
807
|
var attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
809
808
|
if (change.isInline) {
|
|
810
809
|
// Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
|
|
811
|
-
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
810
|
+
var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
812
811
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
|
|
813
812
|
attributionKey: attributionKey,
|
|
814
813
|
change: change,
|
|
@@ -13,7 +13,6 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
|
|
|
13
13
|
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; } }
|
|
14
14
|
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; }
|
|
15
15
|
var CELL_CONTENT_OFFSET = exports.CELL_CONTENT_OFFSET = 2;
|
|
16
|
-
var IGNORED_CELL_ATTRS = ['localId', 'colwidth'];
|
|
17
16
|
var tablesIn = function tablesIn(doc) {
|
|
18
17
|
var tables = [];
|
|
19
18
|
doc.descendants(function (node, pos) {
|
|
@@ -63,41 +62,107 @@ var positionMatchedColumns = function positionMatchedColumns(_ref) {
|
|
|
63
62
|
}
|
|
64
63
|
return surviving;
|
|
65
64
|
};
|
|
66
|
-
var
|
|
67
|
-
var
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
var headerLocalIds = function headerLocalIds(table) {
|
|
66
|
+
var _table$node$firstChil, _table$node$firstChil2;
|
|
67
|
+
return ((_table$node$firstChil = (_table$node$firstChil2 = table.node.firstChild) === null || _table$node$firstChil2 === void 0 ? void 0 : _table$node$firstChil2.children) !== null && _table$node$firstChil !== void 0 ? _table$node$firstChil : []).map(function (cell) {
|
|
68
|
+
var _cell$attrs$localId;
|
|
69
|
+
return (_cell$attrs$localId = cell.attrs.localId) !== null && _cell$attrs$localId !== void 0 ? _cell$attrs$localId : undefined;
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Cells keep their `localId` when a column is deleted, so the first row's ids name each remaining
|
|
75
|
+
* column even when the steps replaced the whole table. Missing or repeated ids, such as in content
|
|
76
|
+
* pasted from elsewhere, cannot name a column.
|
|
77
|
+
*/
|
|
78
|
+
var localIdMatchedColumns = function localIdMatchedColumns(before, after) {
|
|
79
|
+
var beforeIds = headerLocalIds(before);
|
|
80
|
+
if (beforeIds.some(function (id) {
|
|
81
|
+
return !id;
|
|
82
|
+
}) || new Set(beforeIds).size !== beforeIds.length) {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
var surviving = new Set();
|
|
86
|
+
var previousColumn = -1;
|
|
87
|
+
var _iterator = _createForOfIteratorHelper(headerLocalIds(after)),
|
|
71
88
|
_step;
|
|
72
89
|
try {
|
|
73
|
-
var _loop = function _loop() {
|
|
74
|
-
var afterCell = _step.value;
|
|
75
|
-
var matches = beforeCells.flatMap(function (beforeCell, column) {
|
|
76
|
-
return (0, _document.areNodesEqualIgnoreAttrs)(beforeCell, afterCell, IGNORED_CELL_ATTRS) ? [column] : [];
|
|
77
|
-
});
|
|
78
|
-
if (matches.length !== 1) {
|
|
79
|
-
return {
|
|
80
|
-
v: false
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
surviving.add(matches[0]);
|
|
84
|
-
},
|
|
85
|
-
_ret;
|
|
86
90
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
87
|
-
|
|
88
|
-
|
|
91
|
+
var id = _step.value;
|
|
92
|
+
var column = id ? beforeIds.indexOf(id) : -1;
|
|
93
|
+
if (column <= previousColumn) {
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
surviving.add(column);
|
|
97
|
+
previousColumn = column;
|
|
89
98
|
}
|
|
90
99
|
} catch (err) {
|
|
91
100
|
_iterator.e(err);
|
|
92
101
|
} finally {
|
|
93
102
|
_iterator.f();
|
|
94
103
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
104
|
+
return surviving;
|
|
105
|
+
};
|
|
106
|
+
var IGNORED_CELL_ATTRS = ['localId', 'colwidth'];
|
|
107
|
+
|
|
108
|
+
/** Rows may also have been deleted, so the remaining cells only need to appear in order. */
|
|
109
|
+
var isColumnKept = function isColumnKept(before, beforeColumn, after, afterColumn) {
|
|
110
|
+
var beforeRow = 0;
|
|
111
|
+
return after.node.children.every(function (afterRow) {
|
|
112
|
+
var afterCell = afterRow.maybeChild(afterColumn);
|
|
113
|
+
while (beforeRow < before.node.childCount) {
|
|
114
|
+
var beforeCell = before.node.child(beforeRow++).maybeChild(beforeColumn);
|
|
115
|
+
if (afterCell && beforeCell && (0, _document.areNodesEqualIgnoreAttrs)(beforeCell, afterCell, IGNORED_CELL_ATTRS)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
98
120
|
});
|
|
99
121
|
};
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Pairs each remaining column with an equal original column, keeping their order, and takes each
|
|
125
|
+
* pair from the `direction` end first. Returns the original column of each remaining column.
|
|
126
|
+
*/
|
|
127
|
+
var pairColumnsInOrder = function pairColumnsInOrder(beforeWidth, afterWidth, isMatch, direction) {
|
|
128
|
+
var step = direction === 'left' ? 1 : -1;
|
|
129
|
+
var pairing = [];
|
|
130
|
+
var beforeColumn = direction === 'left' ? 0 : beforeWidth - 1;
|
|
131
|
+
var afterColumn = direction === 'left' ? 0 : afterWidth - 1;
|
|
132
|
+
for (; afterColumn >= 0 && afterColumn < afterWidth; afterColumn += step) {
|
|
133
|
+
while (beforeColumn >= 0 && beforeColumn < beforeWidth && !isMatch(beforeColumn, afterColumn)) {
|
|
134
|
+
beforeColumn += step;
|
|
135
|
+
}
|
|
136
|
+
if (beforeColumn < 0 || beforeColumn >= beforeWidth) {
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
pairing.push(beforeColumn);
|
|
140
|
+
beforeColumn += step;
|
|
141
|
+
}
|
|
142
|
+
return direction === 'left' ? pairing : pairing.reverse();
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* For tables whose cells have no usable ids, such as content created before cells had ids. Every
|
|
147
|
+
* valid pairing of remaining columns to original ones lies between the leftmost and the rightmost
|
|
148
|
+
* pairing, so the columns are only reported when those two agree. Otherwise, such as when several
|
|
149
|
+
* original columns are identical, which of them were removed cannot be known.
|
|
150
|
+
*/
|
|
151
|
+
var uniquelyContentMatchedColumns = function uniquelyContentMatchedColumns(before, after, beforeWidth, afterWidth) {
|
|
152
|
+
var isMatch = function isMatch(beforeColumn, afterColumn) {
|
|
153
|
+
return isColumnKept(before, beforeColumn, after, afterColumn);
|
|
154
|
+
};
|
|
155
|
+
var leftmost = pairColumnsInOrder(beforeWidth, afterWidth, isMatch, 'left');
|
|
156
|
+
var rightmost = pairColumnsInOrder(beforeWidth, afterWidth, isMatch, 'right');
|
|
157
|
+
if (!leftmost || !rightmost || leftmost.some(function (column, index) {
|
|
158
|
+
return column !== rightmost[index];
|
|
159
|
+
})) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
return new Set(leftmost);
|
|
163
|
+
};
|
|
100
164
|
var findDeletedColumns = function findDeletedColumns(before, after, afterToBefore) {
|
|
165
|
+
var _localIdMatchedColumn;
|
|
101
166
|
var beforeMap = _tableMap.TableMap.get(before.node);
|
|
102
167
|
var afterMap = _tableMap.TableMap.get(after.node);
|
|
103
168
|
// Merged or malformed tables do not have reliable column indices.
|
|
@@ -105,13 +170,14 @@ var findDeletedColumns = function findDeletedColumns(before, after, afterToBefor
|
|
|
105
170
|
return [];
|
|
106
171
|
}
|
|
107
172
|
var beforeOffsets = columnOffsets(beforeMap, before.node);
|
|
108
|
-
var
|
|
173
|
+
var positionMatched = positionMatchedColumns({
|
|
109
174
|
before: before,
|
|
110
175
|
after: after,
|
|
111
176
|
afterToBefore: afterToBefore,
|
|
112
177
|
beforeOffsets: beforeOffsets
|
|
113
178
|
});
|
|
114
|
-
|
|
179
|
+
var surviving = positionMatched.size === afterMap.width ? positionMatched : (_localIdMatchedColumn = localIdMatchedColumns(before, after)) !== null && _localIdMatchedColumn !== void 0 ? _localIdMatchedColumn : uniquelyContentMatchedColumns(before, after, beforeMap.width, afterMap.width);
|
|
180
|
+
if (!surviving) {
|
|
115
181
|
return [];
|
|
116
182
|
}
|
|
117
183
|
return beforeOffsets.flatMap(function (_, column) {
|
|
@@ -38,6 +38,11 @@ var getAttributionIdentity = function getAttributionIdentity(change) {
|
|
|
38
38
|
mergeable: true
|
|
39
39
|
};
|
|
40
40
|
};
|
|
41
|
+
var hasContributor = function hasContributor(change) {
|
|
42
|
+
return [].concat((0, _toConsumableArray2.default)(change.deleted), (0, _toConsumableArray2.default)(change.inserted)).some(function (span) {
|
|
43
|
+
return (0, _attributions.getAttributionKey)(span.data) !== undefined;
|
|
44
|
+
});
|
|
45
|
+
};
|
|
41
46
|
var byNewDocRange = function byNewDocRange(left, right) {
|
|
42
47
|
return left.fromB - right.fromB || left.toB - right.toB;
|
|
43
48
|
};
|
|
@@ -95,12 +100,28 @@ var blockNodeRanges = function blockNodeRanges(doc, change, ownsPosition) {
|
|
|
95
100
|
*/
|
|
96
101
|
var splitMixedIdentityChanges = function splitMixedIdentityChanges(changes, doc) {
|
|
97
102
|
return changes.flatMap(function (change) {
|
|
98
|
-
|
|
99
|
-
|
|
103
|
+
var _change$inserted$;
|
|
104
|
+
// A replacement can carry an anonymous deletion and an authored insertion. The deleted side
|
|
105
|
+
// needs its own zero-width change or the insertion's actor claims the deletion too.
|
|
106
|
+
var deletedKeys = new Set(change.deleted.map(function (span) {
|
|
107
|
+
return (0, _attributions.getAttributionKey)(span.data);
|
|
108
|
+
}));
|
|
109
|
+
var firstInsertedKey = (0, _attributions.getAttributionKey)((_change$inserted$ = change.inserted[0]) === null || _change$inserted$ === void 0 ? void 0 : _change$inserted$.data);
|
|
110
|
+
var detachDeleted = change.deleted.length > 0 && change.inserted.length > 0 && deletedKeys.size === 1 && !deletedKeys.has(firstInsertedKey) && (deletedKeys.has(undefined) || firstInsertedKey === undefined);
|
|
111
|
+
var deletedChange = detachDeleted ? [_objectSpread(_objectSpread({}, change), {}, {
|
|
112
|
+
toB: change.fromB,
|
|
113
|
+
inserted: []
|
|
114
|
+
})] : [];
|
|
115
|
+
var contentChange = detachDeleted ? _objectSpread(_objectSpread({}, change), {}, {
|
|
116
|
+
fromA: change.toA,
|
|
117
|
+
deleted: []
|
|
118
|
+
}) : change;
|
|
119
|
+
if (getAttributionIdentity(contentChange).mergeable) {
|
|
120
|
+
return [].concat(deletedChange, [contentChange]);
|
|
100
121
|
}
|
|
101
122
|
var runs = [];
|
|
102
|
-
var offset =
|
|
103
|
-
var _iterator = _createForOfIteratorHelper(
|
|
123
|
+
var offset = contentChange.fromB;
|
|
124
|
+
var _iterator = _createForOfIteratorHelper(contentChange.inserted),
|
|
104
125
|
_step;
|
|
105
126
|
try {
|
|
106
127
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -127,32 +148,32 @@ var splitMixedIdentityChanges = function splitMixedIdentityChanges(changes, doc)
|
|
|
127
148
|
} finally {
|
|
128
149
|
_iterator.f();
|
|
129
150
|
}
|
|
130
|
-
if (runs.length < 2 || offset !==
|
|
131
|
-
return [
|
|
151
|
+
if (runs.length < 2 || offset !== contentChange.toB) {
|
|
152
|
+
return [].concat(deletedChange, [contentChange]);
|
|
132
153
|
}
|
|
133
|
-
return runs.map(function (run, index) {
|
|
154
|
+
return [].concat(deletedChange, (0, _toConsumableArray2.default)(runs.map(function (run, index) {
|
|
134
155
|
var owned = blockNodeRanges(doc, {
|
|
135
|
-
from:
|
|
136
|
-
to:
|
|
156
|
+
from: contentChange.fromB,
|
|
157
|
+
to: contentChange.toB
|
|
137
158
|
}, function (pos) {
|
|
138
159
|
return pos >= run.from && pos < run.to;
|
|
139
160
|
});
|
|
140
|
-
return _objectSpread(_objectSpread({},
|
|
141
|
-
fromA: index === 0 ?
|
|
161
|
+
return _objectSpread(_objectSpread({}, contentChange), {}, {
|
|
162
|
+
fromA: index === 0 ? contentChange.fromA : contentChange.toA,
|
|
142
163
|
fromB: run.from,
|
|
143
164
|
toB: run.to,
|
|
144
|
-
deleted: index === 0 ?
|
|
165
|
+
deleted: index === 0 ? contentChange.deleted : [],
|
|
145
166
|
inserted: run.spans
|
|
146
167
|
}, owned ? {
|
|
147
168
|
blockNodeRangesB: owned
|
|
148
169
|
} : {});
|
|
149
|
-
});
|
|
170
|
+
})));
|
|
150
171
|
});
|
|
151
172
|
};
|
|
152
173
|
|
|
153
174
|
/**
|
|
154
|
-
* Subtracts every
|
|
155
|
-
*
|
|
175
|
+
* Subtracts every differently attributed contained change from a change's range, including when
|
|
176
|
+
* one has no contributor. Applies when the changes arrive separately rather than as spans of one —
|
|
156
177
|
* the `step` diff type. A contained change by the same author, and one that only partially
|
|
157
178
|
* overlaps, are left for the collapse below.
|
|
158
179
|
*
|
|
@@ -161,10 +182,11 @@ var splitMixedIdentityChanges = function splitMixedIdentityChanges(changes, doc)
|
|
|
161
182
|
var splitContainedChanges = function splitContainedChanges(changes, doc) {
|
|
162
183
|
return changes.flatMap(function (change) {
|
|
163
184
|
var _getAttributionIdenti = getAttributionIdentity(change),
|
|
164
|
-
key = _getAttributionIdenti.key
|
|
185
|
+
key = _getAttributionIdenti.key,
|
|
186
|
+
mergeable = _getAttributionIdenti.mergeable;
|
|
165
187
|
var inner = mergeRanges(changes.filter(function (other) {
|
|
166
|
-
var
|
|
167
|
-
return other !== change &&
|
|
188
|
+
var otherIdentity = getAttributionIdentity(other);
|
|
189
|
+
return other !== change && mergeable && otherIdentity.mergeable && otherIdentity.key !== key && isContained(change, other);
|
|
168
190
|
}).map(function (_ref) {
|
|
169
191
|
var fromB = _ref.fromB,
|
|
170
192
|
toB = _ref.toB;
|
|
@@ -242,7 +264,7 @@ var mergeBlockNodeRanges = function mergeBlockNodeRanges(left, right) {
|
|
|
242
264
|
return left.blockNodeRangesB && right.blockNodeRangesB ? [].concat((0, _toConsumableArray2.default)(left.blockNodeRangesB), (0, _toConsumableArray2.default)(right.blockNodeRangesB)) : undefined;
|
|
243
265
|
};
|
|
244
266
|
|
|
245
|
-
/** Unions
|
|
267
|
+
/** Unions overlapping changes, except when only one side names a contributor. */
|
|
246
268
|
var collapse = function collapse(changes) {
|
|
247
269
|
// A zero-length new-document range paints no inline decoration, so it is kept aside rather than
|
|
248
270
|
// folded into a neighbouring insertion.
|
|
@@ -258,7 +280,9 @@ var collapse = function collapse(changes) {
|
|
|
258
280
|
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
259
281
|
var change = _step3.value;
|
|
260
282
|
var current = collapsed[collapsed.length - 1];
|
|
261
|
-
|
|
283
|
+
var currentHasContributor = current && hasContributor(current);
|
|
284
|
+
var changeHasContributor = hasContributor(change);
|
|
285
|
+
if (current && change.fromB < current.toB && currentHasContributor === changeHasContributor) {
|
|
262
286
|
var blockNodeRangesB = mergeBlockNodeRanges(current, change);
|
|
263
287
|
collapsed[collapsed.length - 1] = _objectSpread({
|
|
264
288
|
fromA: Math.min(current.fromA, change.fromA),
|
|
@@ -288,8 +312,8 @@ var collapse = function collapse(changes) {
|
|
|
288
312
|
* characters — which stacks two inline decorations and renders one contributor tag per copy.
|
|
289
313
|
*
|
|
290
314
|
* Merging keeps every span from both sides, so the latest-writer rule still decides whose tag is
|
|
291
|
-
* shown
|
|
292
|
-
*
|
|
315
|
+
* shown among attributed edits. An unattributed change never merges with an attributed one.
|
|
316
|
+
* Ranges that merely touch are left alone.
|
|
293
317
|
*
|
|
294
318
|
* Contributors are separated first, by `splitMixedIdentityChanges` and `splitContainedChanges`.
|
|
295
319
|
* Both leave ranges that only touch, so they survive the collapse.
|
|
@@ -244,13 +244,12 @@ var getAttributionKeyForChanges = function getAttributionKeyForChanges(changes)
|
|
|
244
244
|
};
|
|
245
245
|
|
|
246
246
|
/**
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* back to the latest overlapping attributed step.
|
|
247
|
+
* Preserve overlap attribution outside Confluence version history. Within version history, a
|
|
248
|
+
* recovery step's keyless spans must not inherit an overlapping NCS step's actor.
|
|
250
249
|
*/
|
|
251
250
|
var getAttributionKeyForChange = exports.getAttributionKeyForChange = function getAttributionKeyForChange(change, attributedChanges) {
|
|
252
|
-
var
|
|
253
|
-
return
|
|
251
|
+
var directKey = getAttributionKeyForChanges([change]);
|
|
252
|
+
return directKey !== null && directKey !== void 0 ? directKey : (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? undefined : getAttributionKeyForChanges(attributedChanges.filter(function (attributedChange) {
|
|
254
253
|
return changesOverlap(change, attributedChange);
|
|
255
254
|
}));
|
|
256
255
|
};
|
|
@@ -222,7 +222,7 @@ var createChangedRowDOM = function createChangedRowDOM(_ref3) {
|
|
|
222
222
|
return tr;
|
|
223
223
|
};
|
|
224
224
|
var supportsAnchorPositioning = function supportsAnchorPositioning() {
|
|
225
|
-
return typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('top', 'anchor(--a top)');
|
|
225
|
+
return typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('top', 'anchor(--a top)') && CSS.supports('position-anchor', '--a');
|
|
226
226
|
};
|
|
227
227
|
var createAnchoredRemovedLozengeWidget = function createAnchoredRemovedLozengeWidget(_ref4) {
|
|
228
228
|
var anchorName = _ref4.anchorName,
|
|
@@ -233,6 +233,9 @@ var createAnchoredRemovedLozengeWidget = function createAnchoredRemovedLozengeWi
|
|
|
233
233
|
var lozenge = (0, _wrapBlockNodeView.createRemovedLozenge)(intl, isActive, colorScheme, true);
|
|
234
234
|
var inset = lozenge.style.top;
|
|
235
235
|
lozenge.style.setProperty('position', 'fixed');
|
|
236
|
+
// Fixed labels only follow their default anchor on scroll, and escape scroll-container clipping.
|
|
237
|
+
lozenge.style.setProperty('position-anchor', "--".concat(anchorName));
|
|
238
|
+
lozenge.style.setProperty('position-visibility', 'anchors-visible');
|
|
236
239
|
lozenge.style.setProperty('top', "calc(anchor(--".concat(anchorName, " top) + ").concat(inset, ")"));
|
|
237
240
|
lozenge.style.setProperty('left', "calc(anchor(--".concat(anchorName, " right) - ").concat(inset, ")"));
|
|
238
241
|
lozenge.style.setProperty('right', 'auto');
|
|
@@ -148,7 +148,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
148
148
|
// node renders beneath its replacement; otherwise anchor at the start (change.fromB).
|
|
149
149
|
var anchorPos = placeBelow ? change.toB : change.fromB;
|
|
150
150
|
var safeInsertPos = (0, _findSafeInsertPos.findSafeInsertPos)(newDoc, anchorPos, slice);
|
|
151
|
-
var isActive = activeIndexPos && ((0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? safeInsertPos >= activeIndexPos.from && safeInsertPos <= activeIndexPos.to : safeInsertPos === activeIndexPos.from && safeInsertPos === activeIndexPos.to);
|
|
151
|
+
var isActive = activeIndexPos && ((0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? safeInsertPos >= activeIndexPos.from && safeInsertPos <= activeIndexPos.to && (!('attributionKey' in activeIndexPos) || activeIndexPos.attributionKey === attributionKey) : safeInsertPos === activeIndexPos.from && safeInsertPos === activeIndexPos.to);
|
|
152
152
|
if (deletedBlankLineCount > 0) {
|
|
153
153
|
// The blocks have no content to serialize, so the deletion is shown as one struck-through
|
|
154
154
|
// return glyph per line the author removed. A single widget, not one per line: the lines are
|
|
@@ -104,7 +104,9 @@ var owningStop = function owningStop(target, stops) {
|
|
|
104
104
|
* containment, and the leading change of what it covers.
|
|
105
105
|
*/
|
|
106
106
|
var resolveActiveTarget = function resolveActiveTarget(surviving, activeIndexPos) {
|
|
107
|
-
return containedBy(surviving, activeIndexPos)
|
|
107
|
+
return containedBy(surviving, activeIndexPos).find(function (target) {
|
|
108
|
+
return !(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !('attributionKey' in activeIndexPos) || target.decoration.spec.attributionKey === activeIndexPos.attributionKey;
|
|
109
|
+
});
|
|
108
110
|
};
|
|
109
111
|
|
|
110
112
|
/**
|
|
@@ -90,18 +90,13 @@ function groupTouchingDecorations(decorations, isInlineDecoration) {
|
|
|
90
90
|
return a.from === b.from ? a.to - b.to : a.from - b.from;
|
|
91
91
|
});
|
|
92
92
|
sortedDecorations.forEach(function (decoration) {
|
|
93
|
-
var _openGroups$find;
|
|
94
93
|
// A gap ends the run: nothing before it can be joined.
|
|
95
94
|
if (decoration.from > clusterTo) {
|
|
96
95
|
openGroups = [];
|
|
97
96
|
}
|
|
98
97
|
var contributor = contributorOf(decoration);
|
|
99
|
-
|
|
100
|
-
// decision item's own highlight must not split the stop from the tag on its list.
|
|
101
|
-
var openGroup = (_openGroups$find = openGroups.find(function (group) {
|
|
98
|
+
var openGroup = openGroups.find(function (group) {
|
|
102
99
|
return group.contributor === contributor;
|
|
103
|
-
})) !== null && _openGroups$find !== void 0 ? _openGroups$find : contributor === '' ? openGroups[0] : openGroups.find(function (group) {
|
|
104
|
-
return group.contributor === '';
|
|
105
100
|
});
|
|
106
101
|
if (openGroup === undefined) {
|
|
107
102
|
var group = {
|
|
@@ -113,8 +108,6 @@ function groupTouchingDecorations(decorations, isInlineDecoration) {
|
|
|
113
108
|
groups.push(group);
|
|
114
109
|
openGroups = [].concat((0, _toConsumableArray2.default)(openGroups), [group]);
|
|
115
110
|
} else {
|
|
116
|
-
// The first contributor to join claims the group, so the next one still starts its own.
|
|
117
|
-
openGroup.contributor = openGroup.contributor || contributor;
|
|
118
111
|
openGroup.decorations.push(decoration);
|
|
119
112
|
openGroup.to = Math.max(openGroup.to, decoration.to);
|
|
120
113
|
}
|
|
@@ -12,6 +12,7 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
|
12
12
|
var _state2 = require("@atlaskit/editor-prosemirror/state");
|
|
13
13
|
var _transformOverride = require("@atlaskit/editor-prosemirror/transform-override");
|
|
14
14
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
15
|
+
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
15
16
|
var _announceActiveDiff = require("../ui/DiffNavigation/announceActiveDiff");
|
|
16
17
|
var _calculateDiffDecorations = require("./calculateDiff/calculateDiffDecorations");
|
|
17
18
|
var _decorationKeys = require("./decorations/decorationKeys");
|
|
@@ -177,10 +178,12 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
|
|
|
177
178
|
var activeDecoration = _decorations[nextIndex];
|
|
178
179
|
newPluginState = _objectSpread(_objectSpread({}, currentPluginState), {}, {
|
|
179
180
|
activeIndex: nextIndex,
|
|
180
|
-
activeIndexPos: activeDecoration ? {
|
|
181
|
+
activeIndexPos: activeDecoration ? _objectSpread({
|
|
181
182
|
from: activeDecoration.from,
|
|
182
183
|
to: activeDecoration.to
|
|
183
|
-
}
|
|
184
|
+
}, (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? {
|
|
185
|
+
attributionKey: (0, _decorationKeys.isDiffDecoration)(activeDecoration) ? activeDecoration.spec.attributionKey : undefined
|
|
186
|
+
} : {}) : undefined
|
|
184
187
|
});
|
|
185
188
|
// Recalculate decorations with the new active index
|
|
186
189
|
var _calculateDiffDecorat2 = (0, _calculateDiffDecorations.calculateDiffDecorations)({
|
|
@@ -114,19 +114,18 @@ const leafTextblockRanges = (doc, from, to) => {
|
|
|
114
114
|
// once it has more leaf textblocks (~cells) than this threshold. Small tables
|
|
115
115
|
// keep the precise per-cell path.
|
|
116
116
|
const LARGE_TABLE_LEAF_THRESHOLD = 40;
|
|
117
|
-
|
|
118
117
|
/**
|
|
119
|
-
* An active scrollable change may contain several underlying diff changes.
|
|
120
|
-
*
|
|
118
|
+
* An active scrollable change may contain several underlying diff changes. With attribution, only
|
|
119
|
+
* ranges belonging to the selected contributor (including the anonymous contributor) are active.
|
|
121
120
|
*/
|
|
122
|
-
const isRangeActive = (activeIndexPos, from, to) => {
|
|
121
|
+
const isRangeActive = (activeIndexPos, from, to, attributionKey) => {
|
|
123
122
|
if (activeIndexPos === undefined) {
|
|
124
123
|
return undefined;
|
|
125
124
|
}
|
|
126
125
|
if (!fg('confluence_ncs_step_diffing_version_history')) {
|
|
127
126
|
return from === activeIndexPos.from && to === activeIndexPos.to;
|
|
128
127
|
}
|
|
129
|
-
return from <= activeIndexPos.to && activeIndexPos.from <= to;
|
|
128
|
+
return from <= activeIndexPos.to && activeIndexPos.from <= to && (!('attributionKey' in activeIndexPos) || activeIndexPos.attributionKey === attributionKey);
|
|
130
129
|
};
|
|
131
130
|
const isLargeInsertedTableRange = (doc, from, to) => {
|
|
132
131
|
let containsTable = false;
|
|
@@ -187,7 +186,7 @@ const calculateNodesForBlockDecoration = ({
|
|
|
187
186
|
if (!(node !== null && node !== void 0 && node.isBlock)) {
|
|
188
187
|
continue;
|
|
189
188
|
}
|
|
190
|
-
const isActive = isRangeActive(activeIndexPos, pos, nodeEnd);
|
|
189
|
+
const isActive = isRangeActive(activeIndexPos, pos, nodeEnd, attributionKey);
|
|
191
190
|
decorations.push(...createBlockChangedDecoration({
|
|
192
191
|
attributionKey,
|
|
193
192
|
change: {
|
|
@@ -226,7 +225,7 @@ const calculateNodesForBlockDecoration = ({
|
|
|
226
225
|
}
|
|
227
226
|
if (node.isBlock && (!requireContainedBlocks || pos >= from) && pos + node.nodeSize <= to) {
|
|
228
227
|
const nodeEnd = pos + node.nodeSize;
|
|
229
|
-
const isActive = isRangeActive(activeIndexPos, pos, nodeEnd);
|
|
228
|
+
const isActive = isRangeActive(activeIndexPos, pos, nodeEnd, attributionKey);
|
|
230
229
|
decorations.push(...createBlockChangedDecoration({
|
|
231
230
|
attributionKey,
|
|
232
231
|
change: {
|
|
@@ -488,7 +487,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
488
487
|
const leftAnchorId = fg('platform_editor_ai_show_diff_patch_2') ? `replacement-${change.fromA}-${change.toA}-${change.fromB}-${change.toB}` : undefined;
|
|
489
488
|
const changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
|
|
490
489
|
const attributionKey = showContributorTags ? getAttributionKeyForChange(change, attributedChanges) : undefined;
|
|
491
|
-
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
490
|
+
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
492
491
|
const {
|
|
493
492
|
deletedColumns
|
|
494
493
|
} = change;
|
|
@@ -701,7 +700,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
701
700
|
var _attributionColors$ge, _attributionColors;
|
|
702
701
|
const changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
|
|
703
702
|
const attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
704
|
-
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
703
|
+
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
705
704
|
decorations.push(...createInlineChangedDecoration({
|
|
706
705
|
attributionKey,
|
|
707
706
|
change,
|
|
@@ -726,7 +725,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
726
725
|
const attributionKey = showContributorTags ? change.attributionKey : undefined;
|
|
727
726
|
if (change.isInline) {
|
|
728
727
|
// Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
|
|
729
|
-
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
728
|
+
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB, attributionKey);
|
|
730
729
|
decorations.push(...createInlineChangedDecoration({
|
|
731
730
|
attributionKey,
|
|
732
731
|
change,
|