@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.
Files changed (55) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/afm-cc/tsconfig.json +3 -0
  3. package/afm-products/tsconfig.json +3 -0
  4. package/dist/cjs/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +2 -22
  5. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +18 -7
  6. package/dist/cjs/pm-plugins/calculateDiff/computeDiffChanges.js +5 -6
  7. package/dist/cjs/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +44 -0
  8. package/dist/cjs/pm-plugins/calculateDiff/isMarkOnlyChange.js +50 -0
  9. package/dist/cjs/pm-plugins/calculateDiff/markAwareTokenEncoder.js +38 -0
  10. package/dist/cjs/pm-plugins/calculateDiff/selectTokenEncoder.js +36 -0
  11. package/dist/cjs/pm-plugins/calculateDiff/simplifySteps.js +3 -3
  12. package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +68 -17
  13. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +68 -12
  14. package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
  15. package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +16 -1
  16. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
  17. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +3 -3
  18. package/dist/es2019/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +1 -21
  19. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +19 -7
  20. package/dist/es2019/pm-plugins/calculateDiff/computeDiffChanges.js +6 -6
  21. package/dist/es2019/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +36 -0
  22. package/dist/es2019/pm-plugins/calculateDiff/isMarkOnlyChange.js +47 -0
  23. package/dist/es2019/pm-plugins/calculateDiff/markAwareTokenEncoder.js +25 -0
  24. package/dist/es2019/pm-plugins/calculateDiff/selectTokenEncoder.js +30 -0
  25. package/dist/es2019/pm-plugins/calculateDiff/simplifySteps.js +1 -1
  26. package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +55 -11
  27. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +67 -12
  28. package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
  29. package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +14 -1
  30. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +7 -0
  31. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +1 -1
  32. package/dist/esm/pm-plugins/calculateDiff/attrAwareTokenEncoder.js +1 -21
  33. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +18 -7
  34. package/dist/esm/pm-plugins/calculateDiff/computeDiffChanges.js +5 -6
  35. package/dist/esm/pm-plugins/calculateDiff/encodeCharacterWithMarks.js +38 -0
  36. package/dist/esm/pm-plugins/calculateDiff/isMarkOnlyChange.js +44 -0
  37. package/dist/esm/pm-plugins/calculateDiff/markAwareTokenEncoder.js +33 -0
  38. package/dist/esm/pm-plugins/calculateDiff/selectTokenEncoder.js +30 -0
  39. package/dist/esm/pm-plugins/calculateDiff/simplifySteps.js +1 -1
  40. package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +68 -17
  41. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +69 -12
  42. package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +19 -7
  43. package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +14 -1
  44. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
  45. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +1 -1
  46. package/dist/types/pm-plugins/calculateDiff/encodeCharacterWithMarks.d.ts +9 -0
  47. package/dist/types/pm-plugins/calculateDiff/isMarkOnlyChange.d.ts +15 -0
  48. package/dist/types/pm-plugins/calculateDiff/markAwareTokenEncoder.d.ts +9 -0
  49. package/dist/types/pm-plugins/calculateDiff/selectTokenEncoder.d.ts +17 -0
  50. package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +3 -3
  51. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +1 -1
  52. package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +1 -1
  53. package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +19 -19
  54. package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +1 -1
  55. package/package.json +7 -39
@@ -61,14 +61,26 @@ const createAttributionScheme = color => ({
61
61
  deletedCellColor: color
62
62
  });
63
63
 
64
- /** Maps public schemes and attribution-only accents to their data objects. */
64
+ /** Maps public schemes and attribution-only participant slots to their data objects. */
65
65
  export const colorSchemeRegistry = {
66
- blue: createAttributionScheme('blue'),
67
- green: createAttributionScheme('green'),
68
- magenta: createAttributionScheme('magenta'),
69
- orange: createAttributionScheme('orange'),
70
- purple: createAttributionScheme('purple'),
71
- teal: createAttributionScheme('teal'),
66
+ 'red-bolder': createAttributionScheme('red-bolder'),
67
+ 'blue-bolder': createAttributionScheme('blue-bolder'),
68
+ 'green-bolder': createAttributionScheme('green-bolder'),
69
+ 'yellow-bolder': createAttributionScheme('yellow-bolder'),
70
+ 'purple-bolder': createAttributionScheme('purple-bolder'),
71
+ 'magenta-bolder': createAttributionScheme('magenta-bolder'),
72
+ 'teal-bolder': createAttributionScheme('teal-bolder'),
73
+ 'orange-bolder': createAttributionScheme('orange-bolder'),
74
+ 'lime-bolder': createAttributionScheme('lime-bolder'),
75
+ 'gray-bolder': createAttributionScheme('gray-bolder'),
76
+ 'blue-subtle': createAttributionScheme('blue-subtle'),
77
+ 'red-subtle': createAttributionScheme('red-subtle'),
78
+ 'orange-subtle': createAttributionScheme('orange-subtle'),
79
+ 'yellow-subtle': createAttributionScheme('yellow-subtle'),
80
+ 'green-subtle': createAttributionScheme('green-subtle'),
81
+ 'teal-subtle': createAttributionScheme('teal-subtle'),
82
+ 'purple-subtle': createAttributionScheme('purple-subtle'),
83
+ 'magenta-subtle': createAttributionScheme('magenta-subtle'),
72
84
  traditional: traditionalScheme,
73
85
  standard: standardScheme
74
86
  };
@@ -1 +1,14 @@
1
- export {};
1
+ /** Attribution-only participant slots selected by the plugin, never by consumers. */
2
+ export const 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'];
3
+
4
+ /** ADS accent hues used by the public and participant colour schemes. */
5
+
6
+ /** A public scheme or an attribution participant slot resolved internally for one change. */
7
+
8
+ /** A colour value that the factory expands into a complete set of diff-safe ADS tokens. */
9
+
10
+ /**
11
+ * A show-diff colour scheme. Colour fields are ADS hues or shared participant slots that
12
+ * `factory.ts` expands into token paths; the rest encode structural differences no colour can
13
+ * express. Ring widths, padding, radius and pointer-events are fixed in the factory, not per scheme.
14
+ */
@@ -338,6 +338,13 @@ export const createNodeChangedDecorationWidget = ({
338
338
  side: placeBelow ? 1 : -1
339
339
  })
340
340
  }),
341
+ // Without an explicit mark set, prosemirror-view wraps the widget in the marks of the
342
+ // adjacent text in the NEW document. `dom` already carries the original marks, so a
343
+ // formatting change would render the deleted side wrapped in the very mark the edit
344
+ // introduced — unbolded text shown struck through but still bold.
345
+ ...(fg('platform_editor_diff_inline_mark_changes') && {
346
+ marks: []
347
+ }),
341
348
  destroy: () => {
342
349
  var _constrainMediaObserv2;
343
350
  return (_constrainMediaObserv2 = constrainMediaObserver) === null || _constrainMediaObserv2 === void 0 ? void 0 : _constrainMediaObserv2.disconnect();
@@ -1,6 +1,6 @@
1
1
  import isEqual from 'lodash/isEqual';
2
2
  import omit from 'lodash/omit';
3
- import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
3
+ import { SetAttrsStep } from '@atlaskit/adf-schema/steps/set-attrs';
4
4
  import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
5
5
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
6
6
  import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
@@ -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 @@ var encodeNodeWithAttrs = function encodeNodeWithAttrs(node, attrNames) {
20
21
  return "".concat(node.type.name, "|").concat(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
- var encodeCharacterWithMarks = function 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
- var markKey = marks.map(function (mark) {
33
- var _mark$attrs;
34
- var attrs = (_mark$attrs = mark.attrs) !== null && _mark$attrs !== void 0 ? _mark$attrs : {};
35
- var attrParts = Object.keys(attrs).sort().map(function (key) {
36
- var _attrs$key;
37
- return "".concat(key, "=").concat(JSON.stringify((_attrs$key = attrs[key]) !== null && _attrs$key !== void 0 ? _attrs$key : null));
38
- });
39
- return attrParts.length > 0 ? "".concat(mark.type.name, "(").concat(attrParts.join(','), ")") : mark.type.name;
40
- }).sort().join('&');
41
- return "".concat(char, "\0").concat(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`.
@@ -25,10 +25,11 @@ import { extractDiffDescriptors } from '../decorations/decorationKeys';
25
25
  import { getAttrChangeRanges, stepIsValidAttrChange } from '../decorations/utils/getAttrChangeRanges';
26
26
  import { getMarkChangeRanges } from '../decorations/utils/getMarkChangeRanges';
27
27
  import { getDefaultDiffType, isExtendedEnabled } from '../isExtendedEnabled';
28
- import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
29
28
  import { diffBySteps } from './diffBySteps';
30
29
  import { groupChangesByBlock } from './groupChangesByBlock';
30
+ import { isMarkOnlyChange } from './isMarkOnlyChange';
31
31
  import { optimizeChanges } from './optimizeChanges';
32
+ import { selectTokenEncoder } from './selectTokenEncoder';
32
33
  import { simplifyChangesWithAttribution } from './simplifyChangesWithAttribution';
33
34
  import { simplifySteps, simplifyStepsWithAttribution } from './simplifySteps';
34
35
  import { classifySmartChanges } from './smart/classifySmartChanges';
@@ -382,10 +383,10 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
382
383
  };
383
384
  }
384
385
  }
385
- // The attribute-aware encoder is only needed by the smart classifier and is
386
- // gated with it; other diff types keep the library default so their output is
387
- // unchanged.
388
- var tokenEncoder = diffType === 'smart' && fg('platform_editor_ai_smart_diff') ? attrAwareTokenEncoder : undefined;
386
+ // The attribute-aware encoder is only needed by the smart classifier and is gated with it.
387
+ var _selectTokenEncoder = selectTokenEncoder(diffType === 'smart' && fg('platform_editor_ai_smart_diff')),
388
+ tokenEncoder = _selectTokenEncoder.tokenEncoder,
389
+ shouldHideMarkOnlyDeletions = _selectTokenEncoder.shouldHideMarkOnlyDeletions;
389
390
  var changes;
390
391
  var attributedChanges = [];
391
392
  var attributionColors;
@@ -440,6 +441,16 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
440
441
  var changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
441
442
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
442
443
 
444
+ // The deleted side of a mark-only change is a byte-identical copy of the new text, so it is
445
+ // suppressed in the clean view. `hideDeletedDiffs` is load-bearing: when false the reviewer
446
+ // asked to compare against the original, and the deleted side is the only place the
447
+ // previous formatting is visible.
448
+ var isMarkOnly = shouldHideMarkOnlyDeletions && hideDeletedDiffs && change.deleted.length > 0 && isMarkOnlyChange({
449
+ change: change,
450
+ originalDoc: originalDoc,
451
+ newDoc: tr.doc
452
+ });
453
+
443
454
  // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
444
455
  // widget pins whichever end of the range it sits at — how the indicator anchors below are
445
456
  // allowed to move.
@@ -470,7 +481,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
470
481
  // change. Used to decide if indicator anchor positions should be adjusted
471
482
  // inward — when the widget is present the anchor must stay at the block
472
483
  // boundary to keep the indicator bar continuous with the deleted content.
473
- var willRenderDeletedWidget = change.deleted.length > 0 && !(isExtendedEnabled(diffType) && !isInverted && hideDeletedDiffs && change.inserted.length > 0);
484
+ var willRenderDeletedWidget = change.deleted.length > 0 && !isMarkOnly && !(isExtendedEnabled(diffType) && !isInverted && hideDeletedDiffs && change.inserted.length > 0);
474
485
  if (isSmartNodeLevel) {
475
486
  // For a large inserted table, skip the O(cells) inline decorations inside the
476
487
  // table (the cell overlays added below provide the highlight without the
@@ -541,7 +552,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
541
552
  coarseTableCellsOnly: useCoarseTableDecoration
542
553
  }))));
543
554
  }
544
- if (change.deleted.length > 0) {
555
+ if (change.deleted.length > 0 && !isMarkOnly) {
545
556
  var _shouldHideDeleted = isExtendedEnabled(diffType) ? !isInverted && hideDeletedDiffs && change.inserted.length > 0 : false;
546
557
  if (!_shouldHideDeleted) {
547
558
  decorations.push.apply(decorations, _toConsumableArray(createNodeChangedDecorationWidget(_objectSpread(_objectSpread({
@@ -17,10 +17,10 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
17
17
  * reconstructed by applying the (simplified) steps to `originalDoc`.
18
18
  */
19
19
  import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
20
- import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
21
20
  import { diffBySteps } from './diffBySteps';
22
21
  import { groupChangesByBlock } from './groupChangesByBlock';
23
22
  import { optimizeChanges } from './optimizeChanges';
23
+ import { selectTokenEncoder } from './selectTokenEncoder';
24
24
  import { simplifySteps } from './simplifySteps';
25
25
  import { classifySmartChanges } from './smart/classifySmartChanges';
26
26
  /**
@@ -77,11 +77,10 @@ export var computeDiffChanges = function computeDiffChanges(_ref) {
77
77
  };
78
78
  }
79
79
 
80
- // The attribute-aware encoder only affects the `smart` classification, so it is
81
- // applied only for that type. (This utility intentionally applies no feature
82
- // gate — see the file docstring — but a caller requesting `smart` is already
83
- // behind the smart-diff gate.)
84
- var tokenEncoder = diffType === 'smart' ? attrAwareTokenEncoder : undefined;
80
+ // This utility does not apply the smart-diff gate (see the file docstring); a caller
81
+ // requesting `smart` is already behind it.
82
+ var _selectTokenEncoder = selectTokenEncoder(diffType === 'smart'),
83
+ tokenEncoder = _selectTokenEncoder.tokenEncoder;
85
84
  var changeset = ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, steppedDoc);
86
85
  if (diffType === 'smart') {
87
86
  return {
@@ -0,0 +1,38 @@
1
+ /** U+0000 cannot occur in ProseMirror text content, so a token can never be ambiguous. */
2
+ var MARK_KEY_SEPARATOR = "\0";
3
+ var buildMarkKey = function buildMarkKey(marks) {
4
+ return marks.map(function (mark) {
5
+ var _mark$attrs;
6
+ var attrs = (_mark$attrs = mark.attrs) !== null && _mark$attrs !== void 0 ? _mark$attrs : {};
7
+ var attrParts = Object.keys(attrs).sort().map(function (key) {
8
+ var _attrs$key;
9
+ return "".concat(key, "=").concat(JSON.stringify((_attrs$key = attrs[key]) !== null && _attrs$key !== void 0 ? _attrs$key : null));
10
+ });
11
+ return attrParts.length > 0 ? "".concat(mark.type.name, "(").concat(attrParts.join(','), ")") : mark.type.name;
12
+ }).sort().join('&');
13
+ };
14
+
15
+ /**
16
+ * Keyed on array identity: `prosemirror-changeset` passes the same `child.marks` reference for
17
+ * every character in a text node, so this collapses the key building to once per node.
18
+ */
19
+ var markKeyCache = new WeakMap();
20
+
21
+ /**
22
+ * Folds a character's marks into its `prosemirror-changeset` token. The library default returns
23
+ * only the char code, so marked and unmarked text tokenise identically and a formatting-only edit
24
+ * is invisible to the changeset.
25
+ *
26
+ * Marks and attrs are sorted so the token is order-independent.
27
+ */
28
+ export var encodeCharacterWithMarks = function encodeCharacterWithMarks(char, marks) {
29
+ if (marks.length === 0) {
30
+ return char;
31
+ }
32
+ var markKey = markKeyCache.get(marks);
33
+ if (markKey === undefined) {
34
+ markKey = buildMarkKey(marks);
35
+ markKeyCache.set(marks, markKey);
36
+ }
37
+ return "".concat(char).concat(MARK_KEY_SEPARATOR).concat(markKey);
38
+ };
@@ -0,0 +1,44 @@
1
+ /** U+0000 cannot occur in ProseMirror text content, so this cannot collide with document text. */
2
+ var NODE_MARKER = "\0";
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
+ var markFreeSignature = function markFreeSignature(doc, from, to) {
12
+ var parts = [];
13
+ doc.nodesBetween(from, to, function (node, pos) {
14
+ if (node.isText) {
15
+ var _node$text;
16
+ var start = Math.max(pos, from) - pos;
17
+ var 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("".concat(NODE_MARKER).concat(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 var isMarkOnlyChange = function isMarkOnlyChange(_ref) {
32
+ var change = _ref.change,
33
+ newDoc = _ref.newDoc,
34
+ originalDoc = _ref.originalDoc;
35
+ var fromA = change.fromA,
36
+ toA = change.toA,
37
+ fromB = change.fromB,
38
+ toB = change.toB;
39
+ var isPureInsertionOrDeletion = toA === fromA || toB === fromB;
40
+ if (isPureInsertionOrDeletion || toA - fromA !== toB - fromB) {
41
+ return false;
42
+ }
43
+ return markFreeSignature(originalDoc, fromA, toA) === markFreeSignature(newDoc, fromB, toB);
44
+ };
@@ -0,0 +1,33 @@
1
+ import { encodeCharacterWithMarks } from './encodeCharacterWithMarks';
2
+
3
+ /** Mirrors the library's private (unexported) `typeID` so node-end tokens match. */
4
+ var typeID = function typeID(type) {
5
+ var cache = type.schema.cached.changeSetIDs || (type.schema.cached.changeSetIDs = Object.create(null));
6
+ var 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 var markAwareTokenEncoder = {
21
+ encodeCharacter: function encodeCharacter(char, marks) {
22
+ return encodeCharacterWithMarks(char, marks);
23
+ },
24
+ encodeNodeStart: function encodeNodeStart(node) {
25
+ return node.type.name;
26
+ },
27
+ encodeNodeEnd: function encodeNodeEnd(node) {
28
+ return -typeID(node.type);
29
+ },
30
+ compareTokens: function compareTokens(a, b) {
31
+ return a === b;
32
+ }
33
+ };
@@ -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 var selectTokenEncoder = function 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
+ };
@@ -4,7 +4,7 @@ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r)
4
4
  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; }
5
5
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
6
6
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
7
- import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
7
+ import { AnalyticsStep } from '@atlaskit/adf-schema/steps/analytics';
8
8
  import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
9
9
  import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
10
10
  import { getAttributionKey } from '../decorations/colorSchemes/attributions';
@@ -1,20 +1,45 @@
1
1
  import _typeof from "@babel/runtime/helpers/typeof";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
4
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
5
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
6
+ import { getParticipantColor } from '@atlaskit/editor-shared-styles/utils';
3
7
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
4
8
  import { fg } from '@atlaskit/platform-feature-flags/fg';
5
- var ATTRIBUTION_COLOR_PALETTE = ['purple', 'blue', 'teal', 'magenta', 'orange', 'green'];
6
-
7
- /** `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared users. */
8
- export var getAttributionKey = function getAttributionKey(attribution) {
9
+ import { PARTICIPANT_COLOR_SCHEMES } from './types';
10
+ /**
11
+ * Normalise the attribution identity once so a valid lookup key always has a valid participant
12
+ * colour seed. `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared
13
+ * users. The colour seed matches collaboration: the user ID for a human and the agent ID for an
14
+ * agent. The agent-type fallback includes the user so different users' agents do not collapse onto
15
+ * one colour when NCS omits an agent ID.
16
+ */
17
+ var getAttributionIdentity = function getAttributionIdentity(attribution) {
9
18
  var _attribution$userId, _attribution$agentId, _attribution$agentTyp;
10
19
  var userId = attribution === null || attribution === void 0 || (_attribution$userId = attribution.userId) === null || _attribution$userId === void 0 ? void 0 : _attribution$userId.trim();
11
20
  var agentId = attribution === null || attribution === void 0 || (_attribution$agentId = attribution.agentId) === null || _attribution$agentId === void 0 ? void 0 : _attribution$agentId.trim();
12
21
  var agentType = attribution === null || attribution === void 0 || (_attribution$agentTyp = attribution.agentType) === null || _attribution$agentTyp === void 0 ? void 0 : _attribution$agentTyp.trim();
13
- if (!userId && !agentId && !agentType) {
22
+ var colorSeed;
23
+ if (agentId) {
24
+ colorSeed = agentId;
25
+ } else if (agentType) {
26
+ colorSeed = userId ? "user:".concat(userId, "|agent:type:").concat(agentType) : "agent:type:".concat(agentType);
27
+ } else if (userId) {
28
+ colorSeed = userId;
29
+ } else {
14
30
  return undefined;
15
31
  }
16
32
  var agentIdentity = agentId || (agentType ? "type:".concat(agentType) : '');
17
- return "user:".concat(userId !== null && userId !== void 0 ? userId : '', "|agent:").concat(agentIdentity);
33
+ return {
34
+ colorSeed: colorSeed,
35
+ key: "user:".concat(userId !== null && userId !== void 0 ? userId : '', "|agent:").concat(agentIdentity)
36
+ };
37
+ };
38
+
39
+ /** `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared users. */
40
+ export var getAttributionKey = function getAttributionKey(attribution) {
41
+ var _getAttributionIdenti;
42
+ return (_getAttributionIdenti = getAttributionIdentity(attribution)) === null || _getAttributionIdenti === void 0 ? void 0 : _getAttributionIdenti.key;
18
43
  };
19
44
  export var areAttributionColorGatesEnabled = function areAttributionColorGatesEnabled() {
20
45
  return fg('confluence_ncs_step_diffing_version_history') && isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor');
@@ -29,12 +54,29 @@ export var isAttributionColoringEnabled = function isAttributionColoringEnabled(
29
54
  return attributionKeys.size > 1;
30
55
  };
31
56
  export var createAttributionColorMap = function createAttributionColorMap(stepAttributions) {
32
- var keys = Array.from(new Set(stepAttributions.map(getAttributionKey).filter(function (key) {
33
- return key !== undefined;
34
- }))).sort();
35
- return new Map(keys.map(function (key, index) {
36
- return [key, ATTRIBUTION_COLOR_PALETTE[index % ATTRIBUTION_COLOR_PALETTE.length]];
37
- }));
57
+ var colors = new Map();
58
+ var _iterator = _createForOfIteratorHelper(stepAttributions),
59
+ _step;
60
+ try {
61
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
62
+ var attribution = _step.value;
63
+ var identity = getAttributionIdentity(attribution);
64
+ if (!identity || colors.has(identity.key)) {
65
+ continue;
66
+ }
67
+ var _getParticipantColor = getParticipantColor(identity.colorSeed),
68
+ index = _getParticipantColor.index;
69
+ var participantColorScheme = PARTICIPANT_COLOR_SCHEMES[index];
70
+ if (participantColorScheme) {
71
+ colors.set(identity.key, participantColorScheme);
72
+ }
73
+ }
74
+ } catch (err) {
75
+ _iterator.e(err);
76
+ } finally {
77
+ _iterator.f();
78
+ }
79
+ return colors;
38
80
  };
39
81
  var getLatestAttribution = function getLatestAttribution(changes) {
40
82
  var data = changes.flatMap(function (change) {
@@ -56,10 +98,19 @@ var changesOverlap = function changesOverlap(change, attributedChange) {
56
98
  var deletedOverlap = change.deleted.length > 0 && attributedChange.deleted.length > 0 && rangesOverlap(change.fromA, change.toA, attributedChange.fromA, attributedChange.toA);
57
99
  return insertedOverlap || deletedOverlap;
58
100
  };
101
+ var getParticipantColorSchemeForChanges = function getParticipantColorSchemeForChanges(changes, attributionColors) {
102
+ var key = getAttributionKey(getLatestAttribution(changes));
103
+ return key ? attributionColors.get(key) : undefined;
104
+ };
59
105
  export var getColorSchemeForChange = function getColorSchemeForChange(change, attributedChanges, attributionColors, fallback) {
60
- var _attributionColors$ge;
61
- var key = getAttributionKey(getLatestAttribution(attributedChanges.filter(function (attributedChange) {
62
- return changesOverlap(change, attributedChange);
63
- })));
64
- return key ? (_attributionColors$ge = attributionColors.get(key)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : fallback : fallback;
106
+ var _ref, _getParticipantColorS;
107
+ return (// Inline and step changes retain their own attribution spans. Resolve those first so a broader
108
+ // change is not recoloured by a later contributor whose nested range happens to overlap it.
109
+ (_ref = (_getParticipantColorS = getParticipantColorSchemeForChanges([change], attributionColors)) !== null && _getParticipantColorS !== void 0 ? _getParticipantColorS :
110
+ // Grouping and smart classification can produce changes without direct attribution data. For
111
+ // those transformed changes, retain the overlap-based lookup as a fallback.
112
+ getParticipantColorSchemeForChanges(attributedChanges.filter(function (attributedChange) {
113
+ return changesOverlap(change, attributedChange);
114
+ }), attributionColors)) !== null && _ref !== void 0 ? _ref : fallback
115
+ );
65
116
  };
@@ -2,6 +2,9 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
5
+ import { participantColors } from '@atlaskit/editor-shared-styles/constants';
6
+ import { PARTICIPANT_COLOR_SCHEMES } from './types';
7
+
5
8
  // token() is a build-time transform needing static literals, so pre-compute every colour's
6
9
  // tokens here and index by name at runtime.
7
10
 
@@ -14,7 +17,8 @@ var bgSubtlestMap = {
14
17
  orange: "var(--ds-background-accent-orange-subtlest, #FFF5DB)",
15
18
  yellow: "var(--ds-background-accent-yellow-subtlest, #FEF7C8)",
16
19
  magenta: "var(--ds-background-accent-magenta-subtlest, #FFECF8)",
17
- gray: "var(--ds-background-accent-gray-subtlest, #F0F1F2)"
20
+ gray: "var(--ds-background-accent-gray-subtlest, #F0F1F2)",
21
+ lime: "var(--ds-background-accent-lime-subtlest, #EFFFD6)"
18
22
  };
19
23
  var bgSubtlestPressedMap = {
20
24
  green: "var(--ds-background-accent-green-subtlest-pressed, #97EDC9)",
@@ -25,7 +29,8 @@ var bgSubtlestPressedMap = {
25
29
  orange: "var(--ds-background-accent-orange-subtlest-pressed, #FBD779)",
26
30
  yellow: "var(--ds-background-accent-yellow-subtlest-pressed, #EFDD4E)",
27
31
  magenta: "var(--ds-background-accent-magenta-subtlest-pressed, #FCB6E1)",
28
- gray: "var(--ds-background-accent-gray-subtlest-pressed, #B7B9BE)"
32
+ gray: "var(--ds-background-accent-gray-subtlest-pressed, #B7B9BE)",
33
+ lime: "var(--ds-background-accent-lime-subtlest-pressed, #BDE97C)"
29
34
  };
30
35
  var bgSubtlerMap = {
31
36
  green: "var(--ds-background-accent-green-subtler, #BAF3DB)",
@@ -36,7 +41,8 @@ var bgSubtlerMap = {
36
41
  orange: "var(--ds-background-accent-orange-subtler, #FCE4A6)",
37
42
  yellow: "var(--ds-background-accent-yellow-subtler, #F5E989)",
38
43
  magenta: "var(--ds-background-accent-magenta-subtler, #FDD0EC)",
39
- gray: "var(--ds-background-accent-gray-subtler, #DDDEE1)"
44
+ gray: "var(--ds-background-accent-gray-subtler, #DDDEE1)",
45
+ lime: "var(--ds-background-accent-lime-subtler, #D3F1A7)"
40
46
  };
41
47
  var bgSubtlerPressedMap = {
42
48
  green: "var(--ds-background-accent-green-subtler-pressed, #7EE2B8)",
@@ -47,7 +53,8 @@ var bgSubtlerPressedMap = {
47
53
  orange: "var(--ds-background-accent-orange-subtler-pressed, #FBC828)",
48
54
  yellow: "var(--ds-background-accent-yellow-subtler-pressed, #EED12B)",
49
55
  magenta: "var(--ds-background-accent-magenta-subtler-pressed, #F797D2)",
50
- gray: "var(--ds-background-accent-gray-subtler-pressed, #8C8F97)"
56
+ gray: "var(--ds-background-accent-gray-subtler-pressed, #8C8F97)",
57
+ lime: "var(--ds-background-accent-lime-subtler-pressed, #B3DF72)"
51
58
  };
52
59
  var borderAccentMap = {
53
60
  green: "var(--ds-border-accent-green, #22A06B)",
@@ -58,7 +65,8 @@ var borderAccentMap = {
58
65
  orange: "var(--ds-border-accent-orange, #E06C00)",
59
66
  yellow: "var(--ds-border-accent-yellow, #B38600)",
60
67
  magenta: "var(--ds-border-accent-magenta, #CD519D)",
61
- gray: "var(--ds-border-accent-gray, #7D818A)"
68
+ gray: "var(--ds-border-accent-gray, #7D818A)",
69
+ lime: "var(--ds-border-accent-lime, #6A9A23)"
62
70
  };
63
71
  var textAccentMap = {
64
72
  green: "var(--ds-text-accent-green, #216E4E)",
@@ -69,25 +77,74 @@ var textAccentMap = {
69
77
  orange: "var(--ds-text-accent-orange, #9E4C00)",
70
78
  yellow: "var(--ds-text-accent-yellow, #7F5F01)",
71
79
  magenta: "var(--ds-text-accent-magenta, #943D73)",
72
- gray: "var(--ds-text-accent-gray, #505258)"
80
+ gray: "var(--ds-text-accent-gray, #505258)",
81
+ lime: "var(--ds-text-accent-lime, #4C6B1F)"
82
+ };
83
+
84
+ /** Pressed counterpart of each participant's diff-safe SVG background tint. */
85
+ var participantPressedBackgroundMap = {
86
+ 'red-bolder': bgSubtlerPressedMap.red,
87
+ 'blue-bolder': bgSubtlerPressedMap.blue,
88
+ 'green-bolder': bgSubtlerPressedMap.green,
89
+ 'yellow-bolder': bgSubtlerPressedMap.yellow,
90
+ 'purple-bolder': bgSubtlerPressedMap.purple,
91
+ 'magenta-bolder': bgSubtlerPressedMap.magenta,
92
+ 'teal-bolder': bgSubtlerPressedMap.teal,
93
+ 'orange-bolder': bgSubtlerPressedMap.orange,
94
+ 'lime-bolder': bgSubtlerPressedMap.lime,
95
+ 'gray-bolder': bgSubtlerPressedMap.gray,
96
+ 'blue-subtle': bgSubtlestPressedMap.blue,
97
+ 'red-subtle': bgSubtlestPressedMap.red,
98
+ 'orange-subtle': bgSubtlestPressedMap.orange,
99
+ 'yellow-subtle': bgSubtlestPressedMap.yellow,
100
+ 'green-subtle': bgSubtlestPressedMap.green,
101
+ 'teal-subtle': bgSubtlestPressedMap.teal,
102
+ 'purple-subtle': bgSubtlestPressedMap.purple,
103
+ 'magenta-subtle': bgSubtlestPressedMap.magenta
104
+ };
105
+ /**
106
+ * Telepointers can put inverse text directly on their bolder colour. Diff colours sit behind
107
+ * arbitrary document content, so use the participant SVG tint and its matching pressed token for
108
+ * diff backgrounds. Borders and rings use the exact participant colour, preserving all 18
109
+ * bolder/subtle slots while keeping every value in the shared ADS participant palette.
110
+ */
111
+ var participantColorTokenSets = Object.fromEntries(PARTICIPANT_COLOR_SCHEMES.map(function (scheme, index) {
112
+ var participantColor = participantColors[index];
113
+ if (!participantColor) {
114
+ throw new Error("Missing shared participant colour for show-diff slot ".concat(index));
115
+ }
116
+ return [scheme, {
117
+ backgroundSubtlest: participantColor.svgBackgroundColor,
118
+ backgroundSubtlestPressed: participantPressedBackgroundMap[scheme],
119
+ backgroundSubtler: participantColor.svgBackgroundColor,
120
+ backgroundSubtlerPressed: participantPressedBackgroundMap[scheme],
121
+ borderAccent: participantColor.backgroundColor,
122
+ // The first ten bolder colours are safe as accents on the editor surface. The
123
+ // remaining subtle colours use their paired dark participant text colour.
124
+ textAccent: index < 10 ? participantColor.backgroundColor : participantColor.textColor
125
+ }];
126
+ }));
127
+ var participantColorSchemeSet = new Set(PARTICIPANT_COLOR_SCHEMES);
128
+ var isParticipantColorScheme = function isParticipantColorScheme(color) {
129
+ return participantColorSchemeSet.has(color);
73
130
  };
74
131
  function bgSubtlest(color) {
75
- return bgSubtlestMap[color];
132
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlest : bgSubtlestMap[color];
76
133
  }
77
134
  function bgSubtlestPressed(color) {
78
- return bgSubtlestPressedMap[color];
135
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlestPressed : bgSubtlestPressedMap[color];
79
136
  }
80
137
  function bgSubtler(color) {
81
- return bgSubtlerMap[color];
138
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtler : bgSubtlerMap[color];
82
139
  }
83
140
  function bgSubtlerPressed(color) {
84
- return bgSubtlerPressedMap[color];
141
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].backgroundSubtlerPressed : bgSubtlerPressedMap[color];
85
142
  }
86
143
  function borderAccent(color) {
87
- return borderAccentMap[color];
144
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].borderAccent : borderAccentMap[color];
88
145
  }
89
146
  function textAccent(color) {
90
- return textAccentMap[color];
147
+ return isParticipantColorScheme(color) ? participantColorTokenSets[color].textAccent : textAccentMap[color];
91
148
  }
92
149
 
93
150
  /** Ring colour for an active (scroll-target) deleted block outline. */