@atlaskit/editor-plugin-show-diff 14.2.10 → 14.3.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 +21 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +2 -22
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +18 -7
- package/dist/cjs/pm-plugins/calculateDiff/computeDiffChanges.js +5 -6
- package/dist/cjs/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +44 -0
- package/dist/cjs/pm-plugins/calculateDiff/isMarkOnlyChange.js +50 -0
- package/dist/cjs/pm-plugins/calculateDiff/markAwareTokenEncoder.js +38 -0
- package/dist/cjs/pm-plugins/calculateDiff/selectTokenEncoder.js +36 -0
- package/dist/cjs/pm-plugins/calculateDiff/simplifySteps.js +3 -3
- package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +68 -17
- package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +68 -12
- package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
- package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +16 -1
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +3 -3
- package/dist/es2019/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +1 -21
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +19 -7
- package/dist/es2019/pm-plugins/calculateDiff/computeDiffChanges.js +6 -6
- package/dist/es2019/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +36 -0
- package/dist/es2019/pm-plugins/calculateDiff/isMarkOnlyChange.js +47 -0
- package/dist/es2019/pm-plugins/calculateDiff/markAwareTokenEncoder.js +25 -0
- package/dist/es2019/pm-plugins/calculateDiff/selectTokenEncoder.js +30 -0
- package/dist/es2019/pm-plugins/calculateDiff/simplifySteps.js +1 -1
- package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +55 -11
- package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +67 -12
- package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
- package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +14 -1
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +7 -0
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +1 -1
- package/dist/esm/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +1 -21
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +18 -7
- package/dist/esm/pm-plugins/calculateDiff/computeDiffChanges.js +5 -6
- package/dist/esm/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +38 -0
- package/dist/esm/pm-plugins/calculateDiff/isMarkOnlyChange.js +44 -0
- package/dist/esm/pm-plugins/calculateDiff/markAwareTokenEncoder.js +33 -0
- package/dist/esm/pm-plugins/calculateDiff/selectTokenEncoder.js +30 -0
- package/dist/esm/pm-plugins/calculateDiff/simplifySteps.js +1 -1
- package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +68 -17
- package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +69 -12
- package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
- package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +14 -1
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +1 -1
- package/dist/types/pm-plugins/calculateDiff/encodeCharacterWithMarks.d.ts +9 -0
- package/dist/types/pm-plugins/calculateDiff/isMarkOnlyChange.d.ts +15 -0
- package/dist/types/pm-plugins/calculateDiff/markAwareTokenEncoder.d.ts +9 -0
- package/dist/types/pm-plugins/calculateDiff/selectTokenEncoder.d.ts +17 -0
- package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +3 -3
- package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +1 -1
- package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +1 -1
- package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +19 -19
- package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +1 -1
- package/package.json +7 -39
|
@@ -72,14 +72,26 @@ var createAttributionScheme = function createAttributionScheme(color) {
|
|
|
72
72
|
});
|
|
73
73
|
};
|
|
74
74
|
|
|
75
|
-
/** Maps public schemes and attribution-only
|
|
75
|
+
/** Maps public schemes and attribution-only participant slots to their data objects. */
|
|
76
76
|
var colorSchemeRegistry = exports.colorSchemeRegistry = {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
purple: createAttributionScheme('purple'),
|
|
82
|
-
|
|
77
|
+
'red-bolder': createAttributionScheme('red-bolder'),
|
|
78
|
+
'blue-bolder': createAttributionScheme('blue-bolder'),
|
|
79
|
+
'green-bolder': createAttributionScheme('green-bolder'),
|
|
80
|
+
'yellow-bolder': createAttributionScheme('yellow-bolder'),
|
|
81
|
+
'purple-bolder': createAttributionScheme('purple-bolder'),
|
|
82
|
+
'magenta-bolder': createAttributionScheme('magenta-bolder'),
|
|
83
|
+
'teal-bolder': createAttributionScheme('teal-bolder'),
|
|
84
|
+
'orange-bolder': createAttributionScheme('orange-bolder'),
|
|
85
|
+
'lime-bolder': createAttributionScheme('lime-bolder'),
|
|
86
|
+
'gray-bolder': createAttributionScheme('gray-bolder'),
|
|
87
|
+
'blue-subtle': createAttributionScheme('blue-subtle'),
|
|
88
|
+
'red-subtle': createAttributionScheme('red-subtle'),
|
|
89
|
+
'orange-subtle': createAttributionScheme('orange-subtle'),
|
|
90
|
+
'yellow-subtle': createAttributionScheme('yellow-subtle'),
|
|
91
|
+
'green-subtle': createAttributionScheme('green-subtle'),
|
|
92
|
+
'teal-subtle': createAttributionScheme('teal-subtle'),
|
|
93
|
+
'purple-subtle': createAttributionScheme('purple-subtle'),
|
|
94
|
+
'magenta-subtle': createAttributionScheme('magenta-subtle'),
|
|
83
95
|
traditional: traditionalScheme,
|
|
84
96
|
standard: standardScheme
|
|
85
97
|
};
|
|
@@ -2,4 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
|
-
});
|
|
5
|
+
});
|
|
6
|
+
exports.PARTICIPANT_COLOR_SCHEMES = void 0;
|
|
7
|
+
/** Attribution-only participant slots selected by the plugin, never by consumers. */
|
|
8
|
+
var PARTICIPANT_COLOR_SCHEMES = exports.PARTICIPANT_COLOR_SCHEMES = ['red-bolder', 'blue-bolder', 'green-bolder', 'yellow-bolder', 'purple-bolder', 'magenta-bolder', 'teal-bolder', 'orange-bolder', 'lime-bolder', 'gray-bolder', 'blue-subtle', 'red-subtle', 'orange-subtle', 'yellow-subtle', 'green-subtle', 'teal-subtle', 'purple-subtle', 'magenta-subtle'];
|
|
9
|
+
|
|
10
|
+
/** ADS accent hues used by the public and participant colour schemes. */
|
|
11
|
+
|
|
12
|
+
/** A public scheme or an attribution participant slot resolved internally for one change. */
|
|
13
|
+
|
|
14
|
+
/** A colour value that the factory expands into a complete set of diff-safe ADS tokens. */
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* A show-diff colour scheme. Colour fields are ADS hues or shared participant slots that
|
|
18
|
+
* `factory.ts` expands into token paths; the rest encode structural differences no colour can
|
|
19
|
+
* express. Ring widths, padding, radius and pointer-events are fixed in the factory, not per scheme.
|
|
20
|
+
*/
|
|
@@ -347,7 +347,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
347
347
|
decorations.push(leftAnchor);
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
-
decorations.push(_view.Decoration.widget(safeInsertPos, dom, _objectSpread(_objectSpread({}, (0, _decorationKeys.buildDiffDecorationSpec)(_objectSpread({
|
|
350
|
+
decorations.push(_view.Decoration.widget(safeInsertPos, dom, _objectSpread(_objectSpread(_objectSpread({}, (0, _decorationKeys.buildDiffDecorationSpec)(_objectSpread({
|
|
351
351
|
decorationType: 'widget',
|
|
352
352
|
diffId: diffId,
|
|
353
353
|
isActive: isActive,
|
|
@@ -356,7 +356,9 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
356
356
|
// placeBelow anchors at the end of the new content, so render on the
|
|
357
357
|
// trailing side (1); otherwise render before the new content (-1).
|
|
358
358
|
side: placeBelow ? 1 : -1
|
|
359
|
-
}))),
|
|
359
|
+
}))), (0, _fg.fg)('platform_editor_diff_inline_mark_changes') && {
|
|
360
|
+
marks: []
|
|
361
|
+
}), {}, {
|
|
360
362
|
destroy: function destroy() {
|
|
361
363
|
var _constrainMediaObserv2;
|
|
362
364
|
return (_constrainMediaObserv2 = constrainMediaObserver) === null || _constrainMediaObserv2 === void 0 ? void 0 : _constrainMediaObserv2.disconnect();
|
|
@@ -8,7 +8,7 @@ exports.stepIsValidAttrChange = exports.isInlineAttrChangeNodeName = exports.get
|
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
9
|
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
10
10
|
var _omit = _interopRequireDefault(require("lodash/omit"));
|
|
11
|
-
var
|
|
11
|
+
var _setAttrs = require("@atlaskit/adf-schema/steps/set-attrs");
|
|
12
12
|
var _deprecatedPlatformFeatureExperiments = require("@atlaskit/editor-common/deprecated-platform-feature-experiments");
|
|
13
13
|
var _nodeTypeUtils = require("@atlaskit/editor-common/utils/node-type-utils");
|
|
14
14
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
@@ -72,7 +72,7 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
72
72
|
finalPos = attrStepContext.finalPos,
|
|
73
73
|
originalPos = attrStepContext.originalPos,
|
|
74
74
|
step = attrStepContext.step;
|
|
75
|
-
if (!(step instanceof _transform.AttrStep) && !(step instanceof
|
|
75
|
+
if (!(step instanceof _transform.AttrStep) && !(step instanceof _setAttrs.SetAttrsStep)) {
|
|
76
76
|
return undefined;
|
|
77
77
|
}
|
|
78
78
|
var stepAttrs = getStepAttrs(step);
|
|
@@ -203,7 +203,7 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
|
|
|
203
203
|
*/
|
|
204
204
|
var stepIsValidAttrChange = exports.stepIsValidAttrChange = function stepIsValidAttrChange(step, beforeDoc, afterDoc) {
|
|
205
205
|
try {
|
|
206
|
-
if (step instanceof _transform.AttrStep || step instanceof
|
|
206
|
+
if (step instanceof _transform.AttrStep || step instanceof _setAttrs.SetAttrsStep) {
|
|
207
207
|
var attrStepAfter = afterDoc.nodeAt(step.pos);
|
|
208
208
|
var attrStepBefore = beforeDoc.nodeAt(step.pos);
|
|
209
209
|
// The change affected the document
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
|
|
2
2
|
import { getDiffableAttrNames } from '../decorations/utils/diffableAttrs';
|
|
3
|
+
import { encodeCharacterWithMarks } from './encodeCharacterWithMarks';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Attribute-aware token encoder for `prosemirror-changeset`. The default encoder
|
|
@@ -20,27 +21,6 @@ const encodeNodeWithAttrs = (node, attrNames) => {
|
|
|
20
21
|
return `${node.type.name}|${parts.join('|')}`;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
|
-
// Fold a character's marks (type + attrs) into its token so a formatting-only change
|
|
24
|
-
// (bold/italic/link/colour, or a link whose `href` changes) registers as a real diff.
|
|
25
|
-
// The default encoder returns just the char code, so marked and unmarked text tokenise
|
|
26
|
-
// identically. Marks and their attrs are sorted so the token is order-independent.
|
|
27
|
-
const encodeCharacterWithMarks = (char, marks) => {
|
|
28
|
-
if (marks.length === 0) {
|
|
29
|
-
// Fast path: unmarked text keeps the numeric char code (unchanged behaviour).
|
|
30
|
-
return char;
|
|
31
|
-
}
|
|
32
|
-
const markKey = marks.map(mark => {
|
|
33
|
-
var _mark$attrs;
|
|
34
|
-
const attrs = (_mark$attrs = mark.attrs) !== null && _mark$attrs !== void 0 ? _mark$attrs : {};
|
|
35
|
-
const attrParts = Object.keys(attrs).sort().map(key => {
|
|
36
|
-
var _attrs$key;
|
|
37
|
-
return `${key}=${JSON.stringify((_attrs$key = attrs[key]) !== null && _attrs$key !== void 0 ? _attrs$key : null)}`;
|
|
38
|
-
});
|
|
39
|
-
return attrParts.length > 0 ? `${mark.type.name}(${attrParts.join(',')})` : mark.type.name;
|
|
40
|
-
}).sort().join('&');
|
|
41
|
-
return `${char}\u0000${markKey}`;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
24
|
// Like the library default, but node types with a `diffableAttrs` rule fold their
|
|
45
25
|
// attrs into the open token, and text characters fold in their marks. Node-end is
|
|
46
26
|
// unchanged, hence `string | number`.
|
|
@@ -17,10 +17,11 @@ import { extractDiffDescriptors } from '../decorations/decorationKeys';
|
|
|
17
17
|
import { getAttrChangeRanges, stepIsValidAttrChange } from '../decorations/utils/getAttrChangeRanges';
|
|
18
18
|
import { getMarkChangeRanges } from '../decorations/utils/getMarkChangeRanges';
|
|
19
19
|
import { getDefaultDiffType, isExtendedEnabled } from '../isExtendedEnabled';
|
|
20
|
-
import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
|
|
21
20
|
import { diffBySteps } from './diffBySteps';
|
|
22
21
|
import { groupChangesByBlock } from './groupChangesByBlock';
|
|
22
|
+
import { isMarkOnlyChange } from './isMarkOnlyChange';
|
|
23
23
|
import { optimizeChanges } from './optimizeChanges';
|
|
24
|
+
import { selectTokenEncoder } from './selectTokenEncoder';
|
|
24
25
|
import { simplifyChangesWithAttribution } from './simplifyChangesWithAttribution';
|
|
25
26
|
import { simplifySteps, simplifyStepsWithAttribution } from './simplifySteps';
|
|
26
27
|
import { classifySmartChanges } from './smart/classifySmartChanges';
|
|
@@ -354,10 +355,11 @@ const calculateDiffDecorationsInner = ({
|
|
|
354
355
|
};
|
|
355
356
|
}
|
|
356
357
|
}
|
|
357
|
-
// The attribute-aware encoder is only needed by the smart classifier and is
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
358
|
+
// The attribute-aware encoder is only needed by the smart classifier and is gated with it.
|
|
359
|
+
const {
|
|
360
|
+
tokenEncoder,
|
|
361
|
+
shouldHideMarkOnlyDeletions
|
|
362
|
+
} = selectTokenEncoder(diffType === 'smart' && fg('platform_editor_ai_smart_diff'));
|
|
361
363
|
let changes;
|
|
362
364
|
let attributedChanges = [];
|
|
363
365
|
let attributionColors;
|
|
@@ -409,6 +411,16 @@ const calculateDiffDecorationsInner = ({
|
|
|
409
411
|
const changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
|
|
410
412
|
const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
|
|
411
413
|
|
|
414
|
+
// The deleted side of a mark-only change is a byte-identical copy of the new text, so it is
|
|
415
|
+
// suppressed in the clean view. `hideDeletedDiffs` is load-bearing: when false the reviewer
|
|
416
|
+
// asked to compare against the original, and the deleted side is the only place the
|
|
417
|
+
// previous formatting is visible.
|
|
418
|
+
const isMarkOnly = shouldHideMarkOnlyDeletions && hideDeletedDiffs && change.deleted.length > 0 && isMarkOnlyChange({
|
|
419
|
+
change,
|
|
420
|
+
originalDoc,
|
|
421
|
+
newDoc: tr.doc
|
|
422
|
+
});
|
|
423
|
+
|
|
412
424
|
// Hoisted because it decides BOTH where the deleted widget is anchored and — since the
|
|
413
425
|
// widget pins whichever end of the range it sits at — how the indicator anchors below are
|
|
414
426
|
// allowed to move.
|
|
@@ -439,7 +451,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
439
451
|
// change. Used to decide if indicator anchor positions should be adjusted
|
|
440
452
|
// inward — when the widget is present the anchor must stay at the block
|
|
441
453
|
// boundary to keep the indicator bar continuous with the deleted content.
|
|
442
|
-
const willRenderDeletedWidget = change.deleted.length > 0 && !(isExtendedEnabled(diffType) && !isInverted && hideDeletedDiffs && change.inserted.length > 0);
|
|
454
|
+
const willRenderDeletedWidget = change.deleted.length > 0 && !isMarkOnly && !(isExtendedEnabled(diffType) && !isInverted && hideDeletedDiffs && change.inserted.length > 0);
|
|
443
455
|
if (isSmartNodeLevel) {
|
|
444
456
|
// For a large inserted table, skip the O(cells) inline decorations inside the
|
|
445
457
|
// table (the cell overlays added below provide the highlight without the
|
|
@@ -501,7 +513,7 @@ const calculateDiffDecorationsInner = ({
|
|
|
501
513
|
coarseTableCellsOnly: useCoarseTableDecoration
|
|
502
514
|
}));
|
|
503
515
|
}
|
|
504
|
-
if (change.deleted.length > 0) {
|
|
516
|
+
if (change.deleted.length > 0 && !isMarkOnly) {
|
|
505
517
|
const shouldHideDeleted = isExtendedEnabled(diffType) ? !isInverted && hideDeletedDiffs && change.inserted.length > 0 : false;
|
|
506
518
|
if (!shouldHideDeleted) {
|
|
507
519
|
decorations.push(...createNodeChangedDecorationWidget({
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
* reconstructed by applying the (simplified) steps to `originalDoc`.
|
|
15
15
|
*/
|
|
16
16
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
17
|
-
import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
|
|
18
17
|
import { diffBySteps } from './diffBySteps';
|
|
19
18
|
import { groupChangesByBlock } from './groupChangesByBlock';
|
|
20
19
|
import { optimizeChanges } from './optimizeChanges';
|
|
20
|
+
import { selectTokenEncoder } from './selectTokenEncoder';
|
|
21
21
|
import { simplifySteps } from './simplifySteps';
|
|
22
22
|
import { classifySmartChanges } from './smart/classifySmartChanges';
|
|
23
23
|
/**
|
|
@@ -64,11 +64,11 @@ export const computeDiffChanges = ({
|
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
//
|
|
68
|
-
//
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
// This utility does not apply the smart-diff gate (see the file docstring); a caller
|
|
68
|
+
// requesting `smart` is already behind it.
|
|
69
|
+
const {
|
|
70
|
+
tokenEncoder
|
|
71
|
+
} = selectTokenEncoder(diffType === 'smart');
|
|
72
72
|
const changeset = ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, steppedDoc);
|
|
73
73
|
if (diffType === 'smart') {
|
|
74
74
|
return {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** U+0000 cannot occur in ProseMirror text content, so a token can never be ambiguous. */
|
|
2
|
+
const MARK_KEY_SEPARATOR = '\u0000';
|
|
3
|
+
const buildMarkKey = marks => marks.map(mark => {
|
|
4
|
+
var _mark$attrs;
|
|
5
|
+
const attrs = (_mark$attrs = mark.attrs) !== null && _mark$attrs !== void 0 ? _mark$attrs : {};
|
|
6
|
+
const attrParts = Object.keys(attrs).sort().map(key => {
|
|
7
|
+
var _attrs$key;
|
|
8
|
+
return `${key}=${JSON.stringify((_attrs$key = attrs[key]) !== null && _attrs$key !== void 0 ? _attrs$key : null)}`;
|
|
9
|
+
});
|
|
10
|
+
return attrParts.length > 0 ? `${mark.type.name}(${attrParts.join(',')})` : mark.type.name;
|
|
11
|
+
}).sort().join('&');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Keyed on array identity: `prosemirror-changeset` passes the same `child.marks` reference for
|
|
15
|
+
* every character in a text node, so this collapses the key building to once per node.
|
|
16
|
+
*/
|
|
17
|
+
const markKeyCache = new WeakMap();
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Folds a character's marks into its `prosemirror-changeset` token. The library default returns
|
|
21
|
+
* only the char code, so marked and unmarked text tokenise identically and a formatting-only edit
|
|
22
|
+
* is invisible to the changeset.
|
|
23
|
+
*
|
|
24
|
+
* Marks and attrs are sorted so the token is order-independent.
|
|
25
|
+
*/
|
|
26
|
+
export const encodeCharacterWithMarks = (char, marks) => {
|
|
27
|
+
if (marks.length === 0) {
|
|
28
|
+
return char;
|
|
29
|
+
}
|
|
30
|
+
let markKey = markKeyCache.get(marks);
|
|
31
|
+
if (markKey === undefined) {
|
|
32
|
+
markKey = buildMarkKey(marks);
|
|
33
|
+
markKeyCache.set(marks, markKey);
|
|
34
|
+
}
|
|
35
|
+
return `${char}${MARK_KEY_SEPARATOR}${markKey}`;
|
|
36
|
+
};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** U+0000 cannot occur in ProseMirror text content, so this cannot collide with document text. */
|
|
2
|
+
const NODE_MARKER = '\u0000';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Node types and text only; marks and attrs excluded.
|
|
6
|
+
*
|
|
7
|
+
* Text is unprefixed so adjacent runs concatenate — a run only splits because its marks differ, so
|
|
8
|
+
* `strong("hello")` and `strong("hel") + em("lo")` must match. Attrs are excluded because a
|
|
9
|
+
* reconstructed agent edit regenerates `localId`s; `getAttrChangeRanges` reports attrs separately.
|
|
10
|
+
*/
|
|
11
|
+
const markFreeSignature = (doc, from, to) => {
|
|
12
|
+
const parts = [];
|
|
13
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
|
14
|
+
if (node.isText) {
|
|
15
|
+
var _node$text;
|
|
16
|
+
const start = Math.max(pos, from) - pos;
|
|
17
|
+
const end = Math.min(pos + node.nodeSize, to) - pos;
|
|
18
|
+
parts.push(((_node$text = node.text) !== null && _node$text !== void 0 ? _node$text : '').slice(start, end));
|
|
19
|
+
} else {
|
|
20
|
+
parts.push(`${NODE_MARKER}${node.type.name}`);
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
});
|
|
24
|
+
return parts.join('');
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether a change differs only in marks, with identical structure and text on both sides. Only
|
|
29
|
+
* produced when a mark-aware token encoder is in use.
|
|
30
|
+
*/
|
|
31
|
+
export const isMarkOnlyChange = ({
|
|
32
|
+
change,
|
|
33
|
+
newDoc,
|
|
34
|
+
originalDoc
|
|
35
|
+
}) => {
|
|
36
|
+
const {
|
|
37
|
+
fromA,
|
|
38
|
+
toA,
|
|
39
|
+
fromB,
|
|
40
|
+
toB
|
|
41
|
+
} = change;
|
|
42
|
+
const isPureInsertionOrDeletion = toA === fromA || toB === fromB;
|
|
43
|
+
if (isPureInsertionOrDeletion || toA - fromA !== toB - fromB) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return markFreeSignature(originalDoc, fromA, toA) === markFreeSignature(newDoc, fromB, toB);
|
|
47
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { encodeCharacterWithMarks } from './encodeCharacterWithMarks';
|
|
2
|
+
|
|
3
|
+
/** Mirrors the library's private (unexported) `typeID` so node-end tokens match. */
|
|
4
|
+
const typeID = type => {
|
|
5
|
+
const cache = type.schema.cached.changeSetIDs || (type.schema.cached.changeSetIDs = Object.create(null));
|
|
6
|
+
let id = cache[type.name];
|
|
7
|
+
if (id == null) {
|
|
8
|
+
cache[type.name] = id = Object.keys(type.schema.nodes).indexOf(type.name) + 1;
|
|
9
|
+
}
|
|
10
|
+
return id;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The library default encoder plus mark folding on text characters.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately narrower than `attrAwareTokenEncoder`: node-start tokens keep the library default
|
|
17
|
+
* and do not fold in diffable attributes, which `getAttrChangeRanges` already reports for every
|
|
18
|
+
* diff type.
|
|
19
|
+
*/
|
|
20
|
+
export const markAwareTokenEncoder = {
|
|
21
|
+
encodeCharacter: (char, marks) => encodeCharacterWithMarks(char, marks),
|
|
22
|
+
encodeNodeStart: node => node.type.name,
|
|
23
|
+
encodeNodeEnd: node => -typeID(node.type),
|
|
24
|
+
compareTokens: (a, b) => a === b
|
|
25
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
2
|
+
import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
|
|
3
|
+
import { markAwareTokenEncoder } from './markAwareTokenEncoder';
|
|
4
|
+
/**
|
|
5
|
+
* Single place `platform_editor_diff_inline_mark_changes` is read, shared by
|
|
6
|
+
* `calculateDiffDecorations` and `computeDiffChanges` so the two cannot drift.
|
|
7
|
+
*
|
|
8
|
+
* With the gate off this returns what both callers computed before it existed.
|
|
9
|
+
*
|
|
10
|
+
* @param useAttrAwareEncoder Caller is running the smart classifier, which needs node attrs folded
|
|
11
|
+
* into the token.
|
|
12
|
+
*/
|
|
13
|
+
export const selectTokenEncoder = useAttrAwareEncoder => {
|
|
14
|
+
if (useAttrAwareEncoder) {
|
|
15
|
+
return {
|
|
16
|
+
tokenEncoder: attrAwareTokenEncoder,
|
|
17
|
+
shouldHideMarkOnlyDeletions: false
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (fg('platform_editor_diff_inline_mark_changes')) {
|
|
21
|
+
return {
|
|
22
|
+
tokenEncoder: markAwareTokenEncoder,
|
|
23
|
+
shouldHideMarkOnlyDeletions: true
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
tokenEncoder: undefined,
|
|
28
|
+
shouldHideMarkOnlyDeletions: false
|
|
29
|
+
};
|
|
30
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
1
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps/analytics';
|
|
2
2
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
3
3
|
import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
4
|
import { getAttributionKey } from '../decorations/colorSchemes/attributions';
|
|
@@ -1,18 +1,40 @@
|
|
|
1
|
+
import { getParticipantColor } from '@atlaskit/editor-shared-styles/utils';
|
|
1
2
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
2
3
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { PARTICIPANT_COLOR_SCHEMES } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* Normalise the attribution identity once so a valid lookup key always has a valid participant
|
|
7
|
+
* colour seed. `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared
|
|
8
|
+
* users. The colour seed matches collaboration: the user ID for a human and the agent ID for an
|
|
9
|
+
* agent. The agent-type fallback includes the user so different users' agents do not collapse onto
|
|
10
|
+
* one colour when NCS omits an agent ID.
|
|
11
|
+
*/
|
|
12
|
+
const getAttributionIdentity = attribution => {
|
|
7
13
|
var _attribution$userId, _attribution$agentId, _attribution$agentTyp;
|
|
8
14
|
const userId = attribution === null || attribution === void 0 ? void 0 : (_attribution$userId = attribution.userId) === null || _attribution$userId === void 0 ? void 0 : _attribution$userId.trim();
|
|
9
15
|
const agentId = attribution === null || attribution === void 0 ? void 0 : (_attribution$agentId = attribution.agentId) === null || _attribution$agentId === void 0 ? void 0 : _attribution$agentId.trim();
|
|
10
16
|
const agentType = attribution === null || attribution === void 0 ? void 0 : (_attribution$agentTyp = attribution.agentType) === null || _attribution$agentTyp === void 0 ? void 0 : _attribution$agentTyp.trim();
|
|
11
|
-
|
|
17
|
+
let colorSeed;
|
|
18
|
+
if (agentId) {
|
|
19
|
+
colorSeed = agentId;
|
|
20
|
+
} else if (agentType) {
|
|
21
|
+
colorSeed = userId ? `user:${userId}|agent:type:${agentType}` : `agent:type:${agentType}`;
|
|
22
|
+
} else if (userId) {
|
|
23
|
+
colorSeed = userId;
|
|
24
|
+
} else {
|
|
12
25
|
return undefined;
|
|
13
26
|
}
|
|
14
27
|
const agentIdentity = agentId || (agentType ? `type:${agentType}` : '');
|
|
15
|
-
return
|
|
28
|
+
return {
|
|
29
|
+
colorSeed,
|
|
30
|
+
key: `user:${userId !== null && userId !== void 0 ? userId : ''}|agent:${agentIdentity}`
|
|
31
|
+
};
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/** `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared users. */
|
|
35
|
+
export const getAttributionKey = attribution => {
|
|
36
|
+
var _getAttributionIdenti;
|
|
37
|
+
return (_getAttributionIdenti = getAttributionIdentity(attribution)) === null || _getAttributionIdenti === void 0 ? void 0 : _getAttributionIdenti.key;
|
|
16
38
|
};
|
|
17
39
|
export const areAttributionColorGatesEnabled = () => fg('confluence_ncs_step_diffing_version_history') && isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor');
|
|
18
40
|
export const isAttributionColoringEnabled = stepAttributions => {
|
|
@@ -23,8 +45,21 @@ export const isAttributionColoringEnabled = stepAttributions => {
|
|
|
23
45
|
return attributionKeys.size > 1;
|
|
24
46
|
};
|
|
25
47
|
export const createAttributionColorMap = stepAttributions => {
|
|
26
|
-
const
|
|
27
|
-
|
|
48
|
+
const colors = new Map();
|
|
49
|
+
for (const attribution of stepAttributions) {
|
|
50
|
+
const identity = getAttributionIdentity(attribution);
|
|
51
|
+
if (!identity || colors.has(identity.key)) {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const {
|
|
55
|
+
index
|
|
56
|
+
} = getParticipantColor(identity.colorSeed);
|
|
57
|
+
const participantColorScheme = PARTICIPANT_COLOR_SCHEMES[index];
|
|
58
|
+
if (participantColorScheme) {
|
|
59
|
+
colors.set(identity.key, participantColorScheme);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return colors;
|
|
28
63
|
};
|
|
29
64
|
const getLatestAttribution = changes => {
|
|
30
65
|
const data = changes.flatMap(change => [...change.deleted, ...change.inserted]).map(span => span.data).filter(value => typeof value === 'object' && value !== null && 'stepIndex' in value && typeof value.stepIndex === 'number');
|
|
@@ -36,8 +71,17 @@ const changesOverlap = (change, attributedChange) => {
|
|
|
36
71
|
const deletedOverlap = change.deleted.length > 0 && attributedChange.deleted.length > 0 && rangesOverlap(change.fromA, change.toA, attributedChange.fromA, attributedChange.toA);
|
|
37
72
|
return insertedOverlap || deletedOverlap;
|
|
38
73
|
};
|
|
74
|
+
const getParticipantColorSchemeForChanges = (changes, attributionColors) => {
|
|
75
|
+
const key = getAttributionKey(getLatestAttribution(changes));
|
|
76
|
+
return key ? attributionColors.get(key) : undefined;
|
|
77
|
+
};
|
|
39
78
|
export const getColorSchemeForChange = (change, attributedChanges, attributionColors, fallback) => {
|
|
40
|
-
var
|
|
41
|
-
|
|
42
|
-
|
|
79
|
+
var _ref, _getParticipantColorS;
|
|
80
|
+
return (// Inline and step changes retain their own attribution spans. Resolve those first so a broader
|
|
81
|
+
// change is not recoloured by a later contributor whose nested range happens to overlap it.
|
|
82
|
+
(_ref = (_getParticipantColorS = getParticipantColorSchemeForChanges([change], attributionColors)) !== null && _getParticipantColorS !== void 0 ? _getParticipantColorS :
|
|
83
|
+
// Grouping and smart classification can produce changes without direct attribution data. For
|
|
84
|
+
// those transformed changes, retain the overlap-based lookup as a fallback.
|
|
85
|
+
getParticipantColorSchemeForChanges(attributedChanges.filter(attributedChange => changesOverlap(change, attributedChange)), attributionColors)) !== null && _ref !== void 0 ? _ref : fallback
|
|
86
|
+
);
|
|
43
87
|
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
+
import { participantColors } from '@atlaskit/editor-shared-styles/constants';
|
|
3
|
+
import { PARTICIPANT_COLOR_SCHEMES } from './types';
|
|
4
|
+
|
|
2
5
|
// token() is a build-time transform needing static literals, so pre-compute every colour's
|
|
3
6
|
// tokens here and index by name at runtime.
|
|
4
7
|
|
|
@@ -11,7 +14,8 @@ const bgSubtlestMap = {
|
|
|
11
14
|
orange: "var(--ds-background-accent-orange-subtlest, #FFF5DB)",
|
|
12
15
|
yellow: "var(--ds-background-accent-yellow-subtlest, #FEF7C8)",
|
|
13
16
|
magenta: "var(--ds-background-accent-magenta-subtlest, #FFECF8)",
|
|
14
|
-
gray: "var(--ds-background-accent-gray-subtlest, #F0F1F2)"
|
|
17
|
+
gray: "var(--ds-background-accent-gray-subtlest, #F0F1F2)",
|
|
18
|
+
lime: "var(--ds-background-accent-lime-subtlest, #EFFFD6)"
|
|
15
19
|
};
|
|
16
20
|
const bgSubtlestPressedMap = {
|
|
17
21
|
green: "var(--ds-background-accent-green-subtlest-pressed, #97EDC9)",
|
|
@@ -22,7 +26,8 @@ const bgSubtlestPressedMap = {
|
|
|
22
26
|
orange: "var(--ds-background-accent-orange-subtlest-pressed, #FBD779)",
|
|
23
27
|
yellow: "var(--ds-background-accent-yellow-subtlest-pressed, #EFDD4E)",
|
|
24
28
|
magenta: "var(--ds-background-accent-magenta-subtlest-pressed, #FCB6E1)",
|
|
25
|
-
gray: "var(--ds-background-accent-gray-subtlest-pressed, #B7B9BE)"
|
|
29
|
+
gray: "var(--ds-background-accent-gray-subtlest-pressed, #B7B9BE)",
|
|
30
|
+
lime: "var(--ds-background-accent-lime-subtlest-pressed, #BDE97C)"
|
|
26
31
|
};
|
|
27
32
|
const bgSubtlerMap = {
|
|
28
33
|
green: "var(--ds-background-accent-green-subtler, #BAF3DB)",
|
|
@@ -33,7 +38,8 @@ const bgSubtlerMap = {
|
|
|
33
38
|
orange: "var(--ds-background-accent-orange-subtler, #FCE4A6)",
|
|
34
39
|
yellow: "var(--ds-background-accent-yellow-subtler, #F5E989)",
|
|
35
40
|
magenta: "var(--ds-background-accent-magenta-subtler, #FDD0EC)",
|
|
36
|
-
gray: "var(--ds-background-accent-gray-subtler, #DDDEE1)"
|
|
41
|
+
gray: "var(--ds-background-accent-gray-subtler, #DDDEE1)",
|
|
42
|
+
lime: "var(--ds-background-accent-lime-subtler, #D3F1A7)"
|
|
37
43
|
};
|
|
38
44
|
const bgSubtlerPressedMap = {
|
|
39
45
|
green: "var(--ds-background-accent-green-subtler-pressed, #7EE2B8)",
|
|
@@ -44,7 +50,8 @@ const bgSubtlerPressedMap = {
|
|
|
44
50
|
orange: "var(--ds-background-accent-orange-subtler-pressed, #FBC828)",
|
|
45
51
|
yellow: "var(--ds-background-accent-yellow-subtler-pressed, #EED12B)",
|
|
46
52
|
magenta: "var(--ds-background-accent-magenta-subtler-pressed, #F797D2)",
|
|
47
|
-
gray: "var(--ds-background-accent-gray-subtler-pressed, #8C8F97)"
|
|
53
|
+
gray: "var(--ds-background-accent-gray-subtler-pressed, #8C8F97)",
|
|
54
|
+
lime: "var(--ds-background-accent-lime-subtler-pressed, #B3DF72)"
|
|
48
55
|
};
|
|
49
56
|
const borderAccentMap = {
|
|
50
57
|
green: "var(--ds-border-accent-green, #22A06B)",
|
|
@@ -55,7 +62,8 @@ const borderAccentMap = {
|
|
|
55
62
|
orange: "var(--ds-border-accent-orange, #E06C00)",
|
|
56
63
|
yellow: "var(--ds-border-accent-yellow, #B38600)",
|
|
57
64
|
magenta: "var(--ds-border-accent-magenta, #CD519D)",
|
|
58
|
-
gray: "var(--ds-border-accent-gray, #7D818A)"
|
|
65
|
+
gray: "var(--ds-border-accent-gray, #7D818A)",
|
|
66
|
+
lime: "var(--ds-border-accent-lime, #6A9A23)"
|
|
59
67
|
};
|
|
60
68
|
const textAccentMap = {
|
|
61
69
|
green: "var(--ds-text-accent-green, #216E4E)",
|
|
@@ -66,25 +74,72 @@ const textAccentMap = {
|
|
|
66
74
|
orange: "var(--ds-text-accent-orange, #9E4C00)",
|
|
67
75
|
yellow: "var(--ds-text-accent-yellow, #7F5F01)",
|
|
68
76
|
magenta: "var(--ds-text-accent-magenta, #943D73)",
|
|
69
|
-
gray: "var(--ds-text-accent-gray, #505258)"
|
|
77
|
+
gray: "var(--ds-text-accent-gray, #505258)",
|
|
78
|
+
lime: "var(--ds-text-accent-lime, #4C6B1F)"
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/** Pressed counterpart of each participant's diff-safe SVG background tint. */
|
|
82
|
+
const participantPressedBackgroundMap = {
|
|
83
|
+
'red-bolder': bgSubtlerPressedMap.red,
|
|
84
|
+
'blue-bolder': bgSubtlerPressedMap.blue,
|
|
85
|
+
'green-bolder': bgSubtlerPressedMap.green,
|
|
86
|
+
'yellow-bolder': bgSubtlerPressedMap.yellow,
|
|
87
|
+
'purple-bolder': bgSubtlerPressedMap.purple,
|
|
88
|
+
'magenta-bolder': bgSubtlerPressedMap.magenta,
|
|
89
|
+
'teal-bolder': bgSubtlerPressedMap.teal,
|
|
90
|
+
'orange-bolder': bgSubtlerPressedMap.orange,
|
|
91
|
+
'lime-bolder': bgSubtlerPressedMap.lime,
|
|
92
|
+
'gray-bolder': bgSubtlerPressedMap.gray,
|
|
93
|
+
'blue-subtle': bgSubtlestPressedMap.blue,
|
|
94
|
+
'red-subtle': bgSubtlestPressedMap.red,
|
|
95
|
+
'orange-subtle': bgSubtlestPressedMap.orange,
|
|
96
|
+
'yellow-subtle': bgSubtlestPressedMap.yellow,
|
|
97
|
+
'green-subtle': bgSubtlestPressedMap.green,
|
|
98
|
+
'teal-subtle': bgSubtlestPressedMap.teal,
|
|
99
|
+
'purple-subtle': bgSubtlestPressedMap.purple,
|
|
100
|
+
'magenta-subtle': bgSubtlestPressedMap.magenta
|
|
70
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Telepointers can put inverse text directly on their bolder colour. Diff colours sit behind
|
|
104
|
+
* arbitrary document content, so use the participant SVG tint and its matching pressed token for
|
|
105
|
+
* diff backgrounds. Borders and rings use the exact participant colour, preserving all 18
|
|
106
|
+
* bolder/subtle slots while keeping every value in the shared ADS participant palette.
|
|
107
|
+
*/
|
|
108
|
+
const participantColorTokenSets = Object.fromEntries(PARTICIPANT_COLOR_SCHEMES.map((scheme, index) => {
|
|
109
|
+
const participantColor = participantColors[index];
|
|
110
|
+
if (!participantColor) {
|
|
111
|
+
throw new Error(`Missing shared participant colour for show-diff slot ${index}`);
|
|
112
|
+
}
|
|
113
|
+
return [scheme, {
|
|
114
|
+
backgroundSubtlest: participantColor.svgBackgroundColor,
|
|
115
|
+
backgroundSubtlestPressed: participantPressedBackgroundMap[scheme],
|
|
116
|
+
backgroundSubtler: participantColor.svgBackgroundColor,
|
|
117
|
+
backgroundSubtlerPressed: participantPressedBackgroundMap[scheme],
|
|
118
|
+
borderAccent: participantColor.backgroundColor,
|
|
119
|
+
// The first ten bolder colours are safe as accents on the editor surface. The
|
|
120
|
+
// remaining subtle colours use their paired dark participant text colour.
|
|
121
|
+
textAccent: index < 10 ? participantColor.backgroundColor : participantColor.textColor
|
|
122
|
+
}];
|
|
123
|
+
}));
|
|
124
|
+
const participantColorSchemeSet = new Set(PARTICIPANT_COLOR_SCHEMES);
|
|
125
|
+
const isParticipantColorScheme = color => participantColorSchemeSet.has(color);
|
|
71
126
|
function bgSubtlest(color) {
|
|
72
|
-
return bgSubtlestMap[color];
|
|
127
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlest : bgSubtlestMap[color];
|
|
73
128
|
}
|
|
74
129
|
function bgSubtlestPressed(color) {
|
|
75
|
-
return bgSubtlestPressedMap[color];
|
|
130
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlestPressed : bgSubtlestPressedMap[color];
|
|
76
131
|
}
|
|
77
132
|
function bgSubtler(color) {
|
|
78
|
-
return bgSubtlerMap[color];
|
|
133
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtler : bgSubtlerMap[color];
|
|
79
134
|
}
|
|
80
135
|
function bgSubtlerPressed(color) {
|
|
81
|
-
return bgSubtlerPressedMap[color];
|
|
136
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlerPressed : bgSubtlerPressedMap[color];
|
|
82
137
|
}
|
|
83
138
|
function borderAccent(color) {
|
|
84
|
-
return borderAccentMap[color];
|
|
139
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].borderAccent : borderAccentMap[color];
|
|
85
140
|
}
|
|
86
141
|
function textAccent(color) {
|
|
87
|
-
return textAccentMap[color];
|
|
142
|
+
return isParticipantColorScheme(color) ? participantColorTokenSets[color].textAccent : textAccentMap[color];
|
|
88
143
|
}
|
|
89
144
|
|
|
90
145
|
/** Ring colour for an active (scroll-target) deleted block outline. */
|