@atlaskit/editor-plugin-show-diff 16.1.1 → 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 +17 -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/extractContributorTags.js +123 -43
- package/dist/cjs/pm-plugins/decorations/revealStyles.js +5 -1
- 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/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/extractContributorTags.js +60 -7
- package/dist/es2019/pm-plugins/decorations/revealStyles.js +5 -1
- 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/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/extractContributorTags.js +123 -43
- package/dist/esm/pm-plugins/decorations/revealStyles.js +5 -1
- 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/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/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 +5 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import _toArray from "@babel/runtime/helpers/toArray";
|
|
2
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import _toArray from "@babel/runtime/helpers/toArray";
|
|
3
3
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
4
4
|
import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
|
|
5
5
|
var _excluded = ["connectedToKey"];
|
|
@@ -51,6 +51,14 @@ var isSameBlockChange = function isSameBlockChange(inner, block) {
|
|
|
51
51
|
return inner.spec.attributionKey === block.spec.attributionKey && (block.from <= inner.from && inner.to <= block.to || inner.from <= block.from && block.to <= inner.to);
|
|
52
52
|
};
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Whether `outer` is the box `inner` sits in, for one contributor. Nested blocks they inserted read
|
|
56
|
+
* as one change, so only the outermost keeps a tag (EDITOR-8932).
|
|
57
|
+
*/
|
|
58
|
+
var containsBlock = function containsBlock(outer, inner) {
|
|
59
|
+
return outer.spec.attributionKey === inner.spec.attributionKey && outer.from <= inner.from && inner.to <= outer.to && outer.to - outer.from > inner.to - inner.from;
|
|
60
|
+
};
|
|
61
|
+
|
|
54
62
|
/**
|
|
55
63
|
* Which of two changes in the same range leads, and so is the one a tag captions. Position first,
|
|
56
64
|
* then `side`, since deleted content shares its `from` with the content that replaced it and paints
|
|
@@ -71,6 +79,19 @@ var containedBy = function containedBy(targets, _ref2) {
|
|
|
71
79
|
}).sort(byLeadingPosition);
|
|
72
80
|
};
|
|
73
81
|
|
|
82
|
+
/**
|
|
83
|
+
* The stop a target is stepped to by: the narrowest one that wholly covers it. A stop's range is
|
|
84
|
+
* the union of the decorations grouped into it, so one inserted run's inline highlight stretches
|
|
85
|
+
* its stop over every block the run spans — including blocks that are a stop of their own. Picking
|
|
86
|
+
* the narrowest keeps each of those blocks in the stop that actually reaches it, rather than
|
|
87
|
+
* letting the widest stop claim them all and fold away every tag but the first (EDITOR-8932).
|
|
88
|
+
*/
|
|
89
|
+
var owningStop = function owningStop(target, stops) {
|
|
90
|
+
return stops.reduce(function (narrowest, stop) {
|
|
91
|
+
return stop.from <= target.decoration.from && target.decoration.to <= stop.to && (narrowest === undefined || stop.to - stop.from < narrowest.to - narrowest.from) ? stop : narrowest;
|
|
92
|
+
}, undefined);
|
|
93
|
+
};
|
|
94
|
+
|
|
74
95
|
/**
|
|
75
96
|
* The one tag a navigation step reveals. `spec.isActive` is no use here: it covers everything the
|
|
76
97
|
* group's union range touches, so several tags revealed over each other (EDITOR-8971). Hence
|
|
@@ -139,6 +160,10 @@ export var extractContributorTags = function extractContributorTags(decorations,
|
|
|
139
160
|
});
|
|
140
161
|
var linkedDiffIds = new Map();
|
|
141
162
|
var folded = new Set();
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* A folded target keeps no tag of its own — it becomes a hover target of the host instead.
|
|
166
|
+
*/
|
|
142
167
|
var fold = function fold(host, target) {
|
|
143
168
|
var _linkedDiffIds$get, _linkedDiffIds$get2;
|
|
144
169
|
folded.add(target);
|
|
@@ -196,58 +221,113 @@ export var extractContributorTags = function extractContributorTags(decorations,
|
|
|
196
221
|
if (_ret === 0) continue;
|
|
197
222
|
}
|
|
198
223
|
|
|
224
|
+
// A nested block folds into the outermost one of the same contributor, so nesting adds no tags.
|
|
225
|
+
if (fg('confluence_ncs_step_diffing_version_history')) {
|
|
226
|
+
var blocksByContributor = new Map();
|
|
227
|
+
var _iterator2 = _createForOfIteratorHelper(blockTargets),
|
|
228
|
+
_step2;
|
|
229
|
+
try {
|
|
230
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
231
|
+
var _target$decoration$sp, _blocksByContributor$;
|
|
232
|
+
var target = _step2.value;
|
|
233
|
+
var key = (_target$decoration$sp = target.decoration.spec.attributionKey) !== null && _target$decoration$sp !== void 0 ? _target$decoration$sp : '';
|
|
234
|
+
blocksByContributor.set(key, [].concat(_toConsumableArray((_blocksByContributor$ = blocksByContributor.get(key)) !== null && _blocksByContributor$ !== void 0 ? _blocksByContributor$ : []), [target]));
|
|
235
|
+
}
|
|
236
|
+
} catch (err) {
|
|
237
|
+
_iterator2.e(err);
|
|
238
|
+
} finally {
|
|
239
|
+
_iterator2.f();
|
|
240
|
+
}
|
|
241
|
+
var _iterator3 = _createForOfIteratorHelper(blocksByContributor.values()),
|
|
242
|
+
_step3;
|
|
243
|
+
try {
|
|
244
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
245
|
+
var contributorBlocks = _step3.value;
|
|
246
|
+
// Block ranges nest rather than partially overlap, so ascending `from` then descending `to`
|
|
247
|
+
// reaches every block after the ones containing it. A stack of the blocks still open at
|
|
248
|
+
// this position then yields each block's container in one pass, rather than rescanning
|
|
249
|
+
// every block for the widest that contains it.
|
|
250
|
+
var nested = _toConsumableArray(contributorBlocks).sort(function (left, right) {
|
|
251
|
+
return left.decoration.from - right.decoration.from || right.decoration.to - left.decoration.to;
|
|
252
|
+
});
|
|
253
|
+
var open = [];
|
|
254
|
+
var _iterator4 = _createForOfIteratorHelper(nested),
|
|
255
|
+
_step4;
|
|
256
|
+
try {
|
|
257
|
+
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
258
|
+
var _target = _step4.value;
|
|
259
|
+
while (open.length > 0 && !containsBlock(open[open.length - 1].decoration, _target.decoration)) {
|
|
260
|
+
open.pop();
|
|
261
|
+
}
|
|
262
|
+
// Outermost first, so the bottom of the stack is the block the tag survives on.
|
|
263
|
+
if (open.length > 0) {
|
|
264
|
+
fold(open[0], _target);
|
|
265
|
+
}
|
|
266
|
+
open.push(_target);
|
|
267
|
+
}
|
|
268
|
+
} catch (err) {
|
|
269
|
+
_iterator4.e(err);
|
|
270
|
+
} finally {
|
|
271
|
+
_iterator4.f();
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} catch (err) {
|
|
275
|
+
_iterator3.e(err);
|
|
276
|
+
} finally {
|
|
277
|
+
_iterator3.f();
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
199
281
|
// One tag per contributor per navigation stop. The folds above only catch a replacement's two
|
|
200
282
|
// halves and a block's own highlights; two of one contributor's changes that merely touch are a
|
|
201
283
|
// single stop (`groupTouchingDecorations`) yet kept a tag each, so the stop's trailing tag was
|
|
202
284
|
// drawn but could never be stepped to (EDITOR-8971). It folds into the leading tag of its
|
|
203
285
|
// contributor, staying a hover target. Contributors are kept apart: a stop spanning two of them
|
|
204
286
|
// still captions each, rather than crediting one for the other's change.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
var key = (_target$decoration$sp = target.decoration.spec.attributionKey) !== null && _target$decoration$sp !== void 0 ? _target$decoration$sp : '';
|
|
220
|
-
byContributor.set(key, [].concat(_toConsumableArray((_byContributor$get = byContributor.get(key)) !== null && _byContributor$get !== void 0 ? _byContributor$get : []), [target]));
|
|
287
|
+
// Each target is counted against one stop only — see `owningStop`.
|
|
288
|
+
if (stops !== null && stops !== void 0 && stops.length) {
|
|
289
|
+
var byStopAndContributor = new Map();
|
|
290
|
+
var _iterator5 = _createForOfIteratorHelper(targets.filter(function (target) {
|
|
291
|
+
return !folded.has(target);
|
|
292
|
+
})),
|
|
293
|
+
_step5;
|
|
294
|
+
try {
|
|
295
|
+
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
|
|
296
|
+
var _target2$decoration$s, _byStopAndContributor;
|
|
297
|
+
var _target2 = _step5.value;
|
|
298
|
+
var stop = owningStop(_target2, stops);
|
|
299
|
+
if (stop === undefined) {
|
|
300
|
+
continue;
|
|
221
301
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
} finally {
|
|
225
|
-
_iterator3.f();
|
|
302
|
+
var _key = "".concat(stop.from, "-").concat(stop.to, "|").concat((_target2$decoration$s = _target2.decoration.spec.attributionKey) !== null && _target2$decoration$s !== void 0 ? _target2$decoration$s : '');
|
|
303
|
+
byStopAndContributor.set(_key, [].concat(_toConsumableArray((_byStopAndContributor = byStopAndContributor.get(_key)) !== null && _byStopAndContributor !== void 0 ? _byStopAndContributor : []), [_target2]));
|
|
226
304
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
305
|
+
} catch (err) {
|
|
306
|
+
_iterator5.e(err);
|
|
307
|
+
} finally {
|
|
308
|
+
_iterator5.f();
|
|
309
|
+
}
|
|
310
|
+
var _iterator6 = _createForOfIteratorHelper(byStopAndContributor.values()),
|
|
311
|
+
_step6;
|
|
312
|
+
try {
|
|
313
|
+
var _loop2 = function _loop2() {
|
|
314
|
+
var members = _step6.value;
|
|
315
|
+
var _sort = _toConsumableArray(members).sort(byLeadingPosition),
|
|
316
|
+
_sort2 = _toArray(_sort),
|
|
317
|
+
leader = _sort2[0],
|
|
318
|
+
trailing = _arrayLikeToArray(_sort2).slice(1);
|
|
319
|
+
trailing.forEach(function (target) {
|
|
320
|
+
return fold(leader, target);
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
|
|
324
|
+
_loop2();
|
|
245
325
|
}
|
|
326
|
+
} catch (err) {
|
|
327
|
+
_iterator6.e(err);
|
|
328
|
+
} finally {
|
|
329
|
+
_iterator6.f();
|
|
246
330
|
}
|
|
247
|
-
} catch (err) {
|
|
248
|
-
_iterator2.e(err);
|
|
249
|
-
} finally {
|
|
250
|
-
_iterator2.f();
|
|
251
331
|
}
|
|
252
332
|
var surviving = targets.filter(function (target) {
|
|
253
333
|
return !folded.has(target);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
import { agentBrandColorSchemes } from '@atlaskit/agent-color/agent-brand-color-schemes';
|
|
2
3
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
3
4
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
4
5
|
import { buildDeletedInlineStyleStandard, getDeletedInlineRevealColors, getInsertedInlineRevealColors } from './colorSchemes/factory';
|
|
@@ -108,6 +109,7 @@ export var resolveRevealStyle = function resolveRevealStyle(_ref4) {
|
|
|
108
109
|
return undefined;
|
|
109
110
|
}
|
|
110
111
|
var colors = getColorScheme(colorScheme);
|
|
112
|
+
var brand = isInserted && Object.prototype.hasOwnProperty.call(agentBrandColorSchemes, colors.insertColor) ? agentBrandColorSchemes[colors.insertColor] : undefined;
|
|
111
113
|
var _resolveRevealColors = resolveRevealColors(colors, {
|
|
112
114
|
hideAddedDiffsUnderline: hideAddedDiffsUnderline,
|
|
113
115
|
isActive: isActive,
|
|
@@ -117,7 +119,9 @@ export var resolveRevealStyle = function resolveRevealStyle(_ref4) {
|
|
|
117
119
|
border = _resolveRevealColors.border;
|
|
118
120
|
return {
|
|
119
121
|
role: isInserted ? 'added' : 'deleted',
|
|
120
|
-
style: (
|
|
122
|
+
style: (brand ? convertToInlineCss({
|
|
123
|
+
color: brand.text
|
|
124
|
+
}) : '') + (isInserted || !includeDeletedTextStyle ? '' : deletedTextOnlyStyle(colors, isActive)) + revealBaseStyle + buildWipeableBackground(background) + buildRevealVariables({
|
|
121
125
|
background: background,
|
|
122
126
|
border: border
|
|
123
127
|
})
|
|
@@ -54,6 +54,17 @@ function decorationSide(decoration) {
|
|
|
54
54
|
return isDiffDecoration(decoration) && decoration.spec.side || 0;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Whose change a decoration is part of, or `''` on an unattributed diff — where every decoration
|
|
59
|
+
* reads as one contributor and the grouping below is unchanged.
|
|
60
|
+
*
|
|
61
|
+
* Contributors are kept apart so one stop never covers two of them, since only the tag on the
|
|
62
|
+
* change stepped to reveals (EDITOR-8932).
|
|
63
|
+
*/
|
|
64
|
+
function contributorOf(decoration) {
|
|
65
|
+
return isDiffDecoration(decoration) && decoration.spec.attributionKey || '';
|
|
66
|
+
}
|
|
67
|
+
|
|
57
68
|
/**
|
|
58
69
|
* Collapses decorations that represent one continuous customer-facing edit.
|
|
59
70
|
*
|
|
@@ -62,34 +73,52 @@ function decorationSide(decoration) {
|
|
|
62
73
|
* deletion at the same location should be treated as one replacement. Zero-width decorations
|
|
63
74
|
* (normally deleted-content widgets) can join a group, but cannot extend its range and therefore
|
|
64
75
|
* cannot bridge two otherwise separate edits.
|
|
76
|
+
*
|
|
77
|
+
* One group per contributor within a run of touching ranges — see `contributorOf`.
|
|
65
78
|
*/
|
|
66
79
|
function groupTouchingDecorations(decorations, isInlineDecoration) {
|
|
67
80
|
if (decorations.length < 2) {
|
|
68
81
|
return decorations;
|
|
69
82
|
}
|
|
70
83
|
var groups = [];
|
|
71
|
-
|
|
72
|
-
var
|
|
73
|
-
var
|
|
84
|
+
// The groups a following decoration can still join — one per contributor, dropped at every gap.
|
|
85
|
+
var openGroups = [];
|
|
86
|
+
var clusterTo = 0;
|
|
74
87
|
var sortedDecorations = _toConsumableArray(decorations).sort(function (a, b) {
|
|
75
88
|
return a.from === b.from ? a.to - b.to : a.from - b.from;
|
|
76
89
|
});
|
|
77
90
|
sortedDecorations.forEach(function (decoration) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
groups.push({
|
|
83
|
-
decorations: currentGroup,
|
|
84
|
-
from: currentGroupFrom,
|
|
85
|
-
to: currentGroupTo
|
|
86
|
-
});
|
|
87
|
-
return;
|
|
91
|
+
var _openGroups$find;
|
|
92
|
+
// A gap ends the run: nothing before it can be joined.
|
|
93
|
+
if (decoration.from > clusterTo) {
|
|
94
|
+
openGroups = [];
|
|
88
95
|
}
|
|
89
|
-
|
|
90
|
-
//
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
var contributor = contributorOf(decoration);
|
|
97
|
+
// An unattributed decoration names nobody to keep apart, so it joins whatever is open — a
|
|
98
|
+
// decision item's own highlight must not split the stop from the tag on its list.
|
|
99
|
+
var openGroup = (_openGroups$find = openGroups.find(function (group) {
|
|
100
|
+
return group.contributor === contributor;
|
|
101
|
+
})) !== null && _openGroups$find !== void 0 ? _openGroups$find : contributor === '' ? openGroups[0] : openGroups.find(function (group) {
|
|
102
|
+
return group.contributor === '';
|
|
103
|
+
});
|
|
104
|
+
if (openGroup === undefined) {
|
|
105
|
+
var group = {
|
|
106
|
+
contributor: contributor,
|
|
107
|
+
decorations: [decoration],
|
|
108
|
+
from: decoration.from,
|
|
109
|
+
to: decoration.to
|
|
110
|
+
};
|
|
111
|
+
groups.push(group);
|
|
112
|
+
openGroups = [].concat(_toConsumableArray(openGroups), [group]);
|
|
113
|
+
} else {
|
|
114
|
+
// The first contributor to join claims the group, so the next one still starts its own.
|
|
115
|
+
openGroup.contributor = openGroup.contributor || contributor;
|
|
116
|
+
openGroup.decorations.push(decoration);
|
|
117
|
+
openGroup.to = Math.max(openGroup.to, decoration.to);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// A zero-width decoration must not extend the run and bridge a gap.
|
|
121
|
+
clusterTo = Math.max(clusterTo, decoration.to);
|
|
93
122
|
});
|
|
94
123
|
return groups.map(function (_ref) {
|
|
95
124
|
var _ref2, _group$find;
|
|
@@ -136,8 +165,8 @@ function groupTouchingDecorations(decorations, isInlineDecoration) {
|
|
|
136
165
|
* 4. When `doc` is passed: excludes diff-inline decorations whose range has no inline content
|
|
137
166
|
* (invalid positions, or block-only slices with no text/atoms — e.g. empty blocks)
|
|
138
167
|
* 5. When `confluence_ncs_step_diffing_version_history` is enabled, groups overlapping or
|
|
139
|
-
* directly touching ranges across decoration types into one result, using the
|
|
140
|
-
* grouped ranges
|
|
168
|
+
* directly touching ranges across decoration types into one result per contributor, using the
|
|
169
|
+
* union of all grouped ranges
|
|
141
170
|
* (zero-width widgets can join a group without extending it). Under
|
|
142
171
|
* `platform_editor_ai_show_diff_patch_1`, a group that starts with content painting above
|
|
143
172
|
* the content that replaced it — reports that widget as its `scrollTarget` spec,
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A node type's base name, with a schema variant's suffix stripped: `panel`, `panel_c1` and
|
|
5
|
+
* `panel_c1_root_only` all resolve to `panel`.
|
|
6
|
+
*
|
|
7
|
+
* Package-local rather than `getBaseNodeTypeName` from editor-common, which enumerates the variants
|
|
8
|
+
* it happens to know (`panel_c1` alone) and is shared with features outside this one. Derived
|
|
9
|
+
* instead of listed, so a variant added later needs no change here: the schema generator names a
|
|
10
|
+
* variant `<type>_<variant>`, and every other node name in the ADF schema is camelCase, so the
|
|
11
|
+
* first `_` is the boundary.
|
|
12
|
+
*
|
|
13
|
+
* Gated, so the diff behaves exactly as before for anyone outside the rollout.
|
|
14
|
+
*
|
|
15
|
+
* For taggability only — this gate is weaker than the ones attribution needs, so resolving a variant
|
|
16
|
+
* in the styling decisions would move the legacy diff for readers who see no tags.
|
|
17
|
+
*/
|
|
18
|
+
export var resolveBaseNodeName = function resolveBaseNodeName(name) {
|
|
19
|
+
return fg('confluence_ncs_step_diffing_version_history') ? name.split('_')[0] : name;
|
|
20
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { resolveBaseNodeName } from './baseNodeName';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Block nodes that host a contributor tag of their own — those whose whole box reads as one change.
|
|
5
|
+
* Everything that draws a box whatever it holds, plus the two lists that are inserted whole: without
|
|
6
|
+
* them the tag fell through to the text inside the first item (EDITOR-8932). Bullet and ordered lists
|
|
7
|
+
* are left out, since their items accrue one at a time. Tables and list items decorate per cell and
|
|
8
|
+
* per item, with no one-tag-per-block design yet. `blockCard` covers the datasource variant, which is
|
|
9
|
+
* the same node type.
|
|
10
|
+
*
|
|
11
|
+
* Base names only — match with the predicates below, never against `type.name` directly.
|
|
12
|
+
*/
|
|
13
|
+
var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'decisionList', 'embedCard', 'expand', 'extension', 'media', 'multiBodiedExtension', 'panel', 'rule', 'taskList']);
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Whether this node hosts a contributor tag of its own. Navigation grouping does not consult this:
|
|
17
|
+
* a run of these one contributor inserted is a single stop, tagged on the leading block.
|
|
18
|
+
*
|
|
19
|
+
* Resolved through `resolveBaseNodeName` so a schema variant counts as the type it is a variant of:
|
|
20
|
+
* `panel_c1` is the panel the table-in-panel schema inserts, and matching on `type.name` left it
|
|
21
|
+
* untagged (EDITOR-8932).
|
|
22
|
+
*
|
|
23
|
+
* By name, because the decoration spec carries `nodeName` rather than the type it came from.
|
|
24
|
+
*/
|
|
25
|
+
export var isTaggableBlockNodeName = function isTaggableBlockNodeName(name) {
|
|
26
|
+
return name !== undefined && TAGGABLE_BLOCK_NODES.has(resolveBaseNodeName(name));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/** As above, from the node type itself. */
|
|
30
|
+
export var isTaggableBlockNode = function isTaggableBlockNode(nodeType) {
|
|
31
|
+
return isTaggableBlockNodeName(nodeType.name);
|
|
32
|
+
};
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import { type Change } from 'prosemirror-changeset';
|
|
2
2
|
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
type Range = {
|
|
4
|
+
from: number;
|
|
5
|
+
to: number;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* A change, plus the block nodes it owns when it is one piece of a split — a piece's own range no
|
|
9
|
+
* longer covers the container it opened. Absent on an unsplit change, which decorates the blocks
|
|
10
|
+
* inside its own range as before.
|
|
11
|
+
*/
|
|
12
|
+
export type AttributedChange = Change & {
|
|
13
|
+
blockNodeRangesB?: Range[];
|
|
14
|
+
};
|
|
3
15
|
/**
|
|
4
16
|
* Collapses changes whose new-document ranges strictly overlap. Attribution runs are simplified
|
|
5
17
|
* independently, so runs either side of an unattributed step can come back covering the same
|
|
@@ -8,10 +20,17 @@ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
|
8
20
|
* Merging keeps every span from both sides, so the latest-writer rule still decides whose tag is
|
|
9
21
|
* shown. Ranges that merely touch are left alone, so an unattributed edit next to an attributed one
|
|
10
22
|
* is not credited to it.
|
|
23
|
+
*
|
|
24
|
+
* Contributors are separated first, by `splitMixedIdentityChanges` and `splitContainedChanges`.
|
|
25
|
+
* Both leave ranges that only touch, so they survive the collapse.
|
|
26
|
+
*
|
|
27
|
+
* Carries no gate of its own: the only caller reaches it through the attributed changeset, which
|
|
28
|
+
* already requires `confluence_ncs_step_diffing_version_history`.
|
|
11
29
|
*/
|
|
12
|
-
export declare const collapseOverlappingChanges: (changes: Change[]) =>
|
|
30
|
+
export declare const collapseOverlappingChanges: (changes: Change[], doc?: PMNode) => AttributedChange[];
|
|
13
31
|
/**
|
|
14
32
|
* Simplifies and optimizes consecutive changes without crossing an attribution boundary.
|
|
15
33
|
* A change which already contains more than one identity is deliberately kept isolated.
|
|
16
34
|
*/
|
|
17
35
|
export declare const simplifyChangesWithAttribution: (changes: readonly Change[], doc: PMNode) => Change[];
|
|
36
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AccentColor, DiffColorScheme } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* Hover highlight for deleted text under an 'onEmphasis' scheme. Inline styles cannot express
|
|
4
4
|
* `:hover`, so the resting style resolves its background from this property and
|
|
@@ -12,20 +12,13 @@ export declare const DELETED_HIGHLIGHT_BG_VAR = "--show-diff-deleted-highlight-b
|
|
|
12
12
|
* 'underline' scheme can darken the border without darkening the tint behind it.
|
|
13
13
|
*/
|
|
14
14
|
export declare const DELETED_HIGHLIGHT_BORDER_VAR = "--show-diff-deleted-highlight-border";
|
|
15
|
-
/**
|
|
16
|
-
|
|
17
|
-
*
|
|
18
|
-
* A `bolder` fill rather than the `subtlest` tint the highlight uses: the tag is a label on the
|
|
19
|
-
* change, and at tag size a tint reads as a second, weaker highlight sitting above the real one.
|
|
20
|
-
* `inverse` is the only text tone that reads on a bolder fill, and it needs no per-colour map —
|
|
21
|
-
* which is also why the tag carries no border: the fill alone bounds it.
|
|
22
|
-
*/
|
|
23
|
-
export declare function getAccentTokens(color: AdsAccentColor): {
|
|
15
|
+
/** Contributor tags use a bold fill with a contrasting foreground, including branded schemes. */
|
|
16
|
+
export declare function getAccentTokens(color: AccentColor): {
|
|
24
17
|
background: string;
|
|
25
18
|
text: string;
|
|
26
19
|
};
|
|
27
20
|
/** Border token for a contributor accent, used by the diff indicator. */
|
|
28
|
-
export declare function getAccentBorderColor(color:
|
|
21
|
+
export declare function getAccentBorderColor(color: AccentColor): string;
|
|
29
22
|
/** Inline inserted content — default state. */
|
|
30
23
|
export declare function buildInsertStyle(colors: DiffColorScheme): string;
|
|
31
24
|
/** Inline insert style for content within a block node (no background, underline only). */
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
+
import type { AgentBrandColorScheme } from '@atlaskit/agent-color/agent-presence-color-types';
|
|
1
2
|
/** Schemes consumers may explicitly request through the show-diff API. */
|
|
2
3
|
export type PublicColorScheme = 'standard' | 'traditional';
|
|
3
4
|
/** Attribution-only participant slots selected by the plugin, never by consumers. */
|
|
4
5
|
export declare const PARTICIPANT_COLOR_SCHEMES: readonly ['red', 'blue', 'green', 'yellow', 'purple', 'magenta', 'teal', 'orange', 'lime', 'gray'];
|
|
5
6
|
/** ADS accent hues used by the public and participant colour schemes. */
|
|
6
7
|
export type AdsAccentColor = (typeof PARTICIPANT_COLOR_SCHEMES)[number];
|
|
7
|
-
|
|
8
|
-
export type ColorScheme = PublicColorScheme |
|
|
8
|
+
export type AccentColor = AdsAccentColor | AgentBrandColorScheme;
|
|
9
|
+
export type ColorScheme = PublicColorScheme | AccentColor;
|
|
9
10
|
/**
|
|
10
11
|
* A show-diff colour scheme. Colour fields are ADS hues that `factory.ts` expands into token paths;
|
|
11
12
|
* the rest encode structural differences no colour can express. Ring widths, padding, radius and
|
|
@@ -15,15 +16,15 @@ export type DiffColorScheme = {
|
|
|
15
16
|
/** Stacking order of the square added-cell overlay. The rounded variant is always 2. */
|
|
16
17
|
addedCellOverlayZIndex: 1 | 2;
|
|
17
18
|
/** Deleted inline content, active/focused state. */
|
|
18
|
-
deleteActiveColor:
|
|
19
|
+
deleteActiveColor: AccentColor;
|
|
19
20
|
/** Deleted inline content. */
|
|
20
|
-
deleteColor:
|
|
21
|
+
deleteColor: AccentColor;
|
|
21
22
|
/** Active deleted-block ring: pale `background.accent.*.subtler.pressed` vs saturated `border.accent.*`. */
|
|
22
23
|
deletedBlockOutlineActiveEmphasis: 'background' | 'border';
|
|
23
24
|
/** Deleted cell outline: `color.border.disabled` hairline vs opaque accent border. */
|
|
24
25
|
deletedCellBorderProminence: 'subtle' | 'accent';
|
|
25
26
|
/** Deleted cell overlays. Gray in both current schemes. */
|
|
26
|
-
deletedCellColor:
|
|
27
|
+
deletedCellColor: AccentColor;
|
|
27
28
|
/** Opacity of the deleted cell overlay background. Counterpart to `insertedCellOpacity`. */
|
|
28
29
|
deletedCellOpacity: number;
|
|
29
30
|
/**
|
|
@@ -62,11 +63,11 @@ export type DiffColorScheme = {
|
|
|
62
63
|
/** Deleted row de-emphasis: tint the line-through, or tint the row text. Both read `deleteColor`. */
|
|
63
64
|
deletedRowTreatment: 'strikeColor' | 'textTint';
|
|
64
65
|
/** Optional text and strikethrough hue, independent of deletion borders. */
|
|
65
|
-
deleteTextColor?:
|
|
66
|
+
deleteTextColor?: AccentColor;
|
|
66
67
|
/** Inserted content, active/focused state. */
|
|
67
|
-
insertActiveColor:
|
|
68
|
+
insertActiveColor: AccentColor;
|
|
68
69
|
/** Inserted content, default state. */
|
|
69
|
-
insertColor:
|
|
70
|
+
insertColor: AccentColor;
|
|
70
71
|
/** Opacity of the inserted cell overlay background. */
|
|
71
72
|
insertedCellOpacity: number;
|
|
72
73
|
/** Bottom border tone for inserted text highlights. Defaults to accent. */
|
|
@@ -18,8 +18,8 @@ export declare function isInlineDiffDecorationRenderableInDoc(doc: PMNode, from:
|
|
|
18
18
|
* 4. When `doc` is passed: excludes diff-inline decorations whose range has no inline content
|
|
19
19
|
* (invalid positions, or block-only slices with no text/atoms — e.g. empty blocks)
|
|
20
20
|
* 5. When `confluence_ncs_step_diffing_version_history` is enabled, groups overlapping or
|
|
21
|
-
* directly touching ranges across decoration types into one result, using the
|
|
22
|
-
* grouped ranges
|
|
21
|
+
* directly touching ranges across decoration types into one result per contributor, using the
|
|
22
|
+
* union of all grouped ranges
|
|
23
23
|
* (zero-width widgets can join a group without extending it). Under
|
|
24
24
|
* `platform_editor_ai_show_diff_patch_1`, a group that starts with content painting above
|
|
25
25
|
* the content that replaced it — reports that widget as its `scrollTarget` spec,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A node type's base name, with a schema variant's suffix stripped: `panel`, `panel_c1` and
|
|
3
|
+
* `panel_c1_root_only` all resolve to `panel`.
|
|
4
|
+
*
|
|
5
|
+
* Package-local rather than `getBaseNodeTypeName` from editor-common, which enumerates the variants
|
|
6
|
+
* it happens to know (`panel_c1` alone) and is shared with features outside this one. Derived
|
|
7
|
+
* instead of listed, so a variant added later needs no change here: the schema generator names a
|
|
8
|
+
* variant `<type>_<variant>`, and every other node name in the ADF schema is camelCase, so the
|
|
9
|
+
* first `_` is the boundary.
|
|
10
|
+
*
|
|
11
|
+
* Gated, so the diff behaves exactly as before for anyone outside the rollout.
|
|
12
|
+
*
|
|
13
|
+
* For taggability only — this gate is weaker than the ones attribution needs, so resolving a variant
|
|
14
|
+
* in the styling decisions would move the legacy diff for readers who see no tags.
|
|
15
|
+
*/
|
|
16
|
+
export declare const resolveBaseNodeName: (name: string) => string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { NodeType } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
/**
|
|
3
|
+
* Whether this node hosts a contributor tag of its own. Navigation grouping does not consult this:
|
|
4
|
+
* a run of these one contributor inserted is a single stop, tagged on the leading block.
|
|
5
|
+
*
|
|
6
|
+
* Resolved through `resolveBaseNodeName` so a schema variant counts as the type it is a variant of:
|
|
7
|
+
* `panel_c1` is the panel the table-in-panel schema inserts, and matching on `type.name` left it
|
|
8
|
+
* untagged (EDITOR-8932).
|
|
9
|
+
*
|
|
10
|
+
* By name, because the decoration spec carries `nodeName` rather than the type it came from.
|
|
11
|
+
*/
|
|
12
|
+
export declare const isTaggableBlockNodeName: (name: string | undefined) => boolean;
|
|
13
|
+
/** As above, from the node type itself. */
|
|
14
|
+
export declare const isTaggableBlockNode: (nodeType: NodeType) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.2.0",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"atlaskit:src": "src/index.ts",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@atlaskit/adf-schema": "^57.5.0",
|
|
29
|
+
"@atlaskit/agent-color": "^0.2.0",
|
|
29
30
|
"@atlaskit/avatar": "^28.0.0",
|
|
30
31
|
"@atlaskit/custom-steps": "^1.1.0",
|
|
31
32
|
"@atlaskit/editor-plugin-accessibility-utils": "^18.0.0",
|
|
@@ -39,7 +40,7 @@
|
|
|
39
40
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
40
41
|
"@atlaskit/primitives": "^22.5.0",
|
|
41
42
|
"@atlaskit/tmp-editor-statsig": "^199.0.0",
|
|
42
|
-
"@atlaskit/tokens": "^18.
|
|
43
|
+
"@atlaskit/tokens": "^18.1.0",
|
|
43
44
|
"@babel/runtime": "^7.0.0",
|
|
44
45
|
"@compiled/react": "^1.0.2",
|
|
45
46
|
"bind-event-listener": "^3.0.0",
|
|
@@ -63,14 +64,14 @@
|
|
|
63
64
|
"@atlassian/confluence-presets": "workspace:^",
|
|
64
65
|
"@atlassian/content-reconciliation": "^0.1.3506",
|
|
65
66
|
"@atlassian/editor-ai-injected-editors": "^32.0.0",
|
|
66
|
-
"@atlassian/editor-plugin-ai": "^72.
|
|
67
|
+
"@atlassian/editor-plugin-ai": "^72.4.0",
|
|
67
68
|
"@atlassian/structured-docs-types": "workspace:^",
|
|
68
69
|
"react": "^19.2.0",
|
|
69
70
|
"react-dom": "^19.2.0",
|
|
70
71
|
"react-intl": "^7.0.0"
|
|
71
72
|
},
|
|
72
73
|
"peerDependencies": {
|
|
73
|
-
"@atlaskit/editor-common": "^122.
|
|
74
|
+
"@atlaskit/editor-common": "^122.12.0",
|
|
74
75
|
"react": "^18.2.0 || ^19.2.0",
|
|
75
76
|
"react-dom": "^18.2.0 || ^19.2.0",
|
|
76
77
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|