@atlaskit/editor-plugin-show-diff 14.3.2 → 14.4.2

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 (77) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/afm-cc/tsconfig.json +18 -0
  3. package/afm-products/tsconfig.json +18 -0
  4. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +47 -26
  5. package/dist/cjs/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +61 -9
  6. package/dist/cjs/pm-plugins/decorations/colorSchemes/attributions.js +77 -20
  7. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +10 -0
  8. package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +2 -0
  9. package/dist/cjs/pm-plugins/decorations/createAnchorDecorationWidgets.js +52 -7
  10. package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +172 -0
  11. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +37 -5
  12. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +40 -7
  13. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +31 -5
  14. package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +128 -0
  15. package/dist/cjs/pm-plugins/main.js +57 -6
  16. package/dist/cjs/pm-plugins/resolveDiffContributors.js +143 -0
  17. package/dist/cjs/showDiffPlugin.js +21 -6
  18. package/dist/cjs/ui/ContributorTag/ContributorTag.compiled.css +29 -0
  19. package/dist/cjs/ui/ContributorTag/ContributorTag.js +383 -0
  20. package/dist/cjs/ui/ContributorTag/ContributorTagWidget.js +50 -0
  21. package/dist/cjs/ui/ContributorTag/messages.js +24 -0
  22. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +48 -27
  23. package/dist/es2019/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +39 -0
  24. package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +53 -11
  25. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +9 -0
  26. package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +2 -0
  27. package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +43 -1
  28. package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +163 -0
  29. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +38 -5
  30. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +38 -6
  31. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +30 -2
  32. package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +101 -0
  33. package/dist/es2019/pm-plugins/main.js +52 -3
  34. package/dist/es2019/pm-plugins/resolveDiffContributors.js +128 -0
  35. package/dist/es2019/showDiffPlugin.js +20 -5
  36. package/dist/es2019/ui/ContributorTag/ContributorTag.compiled.css +29 -0
  37. package/dist/es2019/ui/ContributorTag/ContributorTag.js +312 -0
  38. package/dist/es2019/ui/ContributorTag/ContributorTagWidget.js +43 -0
  39. package/dist/es2019/ui/ContributorTag/messages.js +18 -0
  40. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +49 -28
  41. package/dist/esm/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +60 -8
  42. package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +77 -19
  43. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +9 -0
  44. package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +2 -0
  45. package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +51 -6
  46. package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +166 -0
  47. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +37 -5
  48. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +40 -7
  49. package/dist/esm/pm-plugins/decorations/decorationKeys.js +30 -5
  50. package/dist/esm/pm-plugins/decorations/extractContributorTags.js +122 -0
  51. package/dist/esm/pm-plugins/main.js +57 -6
  52. package/dist/esm/pm-plugins/resolveDiffContributors.js +137 -0
  53. package/dist/esm/showDiffPlugin.js +21 -6
  54. package/dist/esm/ui/ContributorTag/ContributorTag.compiled.css +29 -0
  55. package/dist/esm/ui/ContributorTag/ContributorTag.js +375 -0
  56. package/dist/esm/ui/ContributorTag/ContributorTagWidget.js +43 -0
  57. package/dist/esm/ui/ContributorTag/messages.js +18 -0
  58. package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
  59. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +7 -1
  60. package/dist/types/pm-plugins/calculateDiff/simplifyChangesWithAttribution.d.ts +10 -0
  61. package/dist/types/pm-plugins/decorations/colorSchemes/attributions.d.ts +24 -2
  62. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +7 -1
  63. package/dist/types/pm-plugins/decorations/colorSchemes/schemes.d.ts +1 -2
  64. package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +2 -1
  65. package/dist/types/pm-plugins/decorations/createAnchorDecorationWidgets.d.ts +14 -0
  66. package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +55 -0
  67. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +5 -1
  68. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +5 -1
  69. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +28 -3
  70. package/dist/types/pm-plugins/decorations/extractContributorTags.d.ts +9 -0
  71. package/dist/types/pm-plugins/main.d.ts +8 -2
  72. package/dist/types/pm-plugins/resolveDiffContributors.d.ts +7 -0
  73. package/dist/types/showDiffPluginType.d.ts +65 -2
  74. package/dist/types/ui/ContributorTag/ContributorTag.d.ts +37 -0
  75. package/dist/types/ui/ContributorTag/ContributorTagWidget.d.ts +22 -0
  76. package/dist/types/ui/ContributorTag/messages.d.ts +6 -0
  77. package/package.json +17 -8
@@ -20,8 +20,9 @@ import { createDocMarginAnchorWidget } from '../decorations/createAnchorDecorati
20
20
  import { createBlockChangedDecoration } from '../decorations/createBlockChangedDecoration';
21
21
  import { createInlineChangedDecoration } from '../decorations/createInlineChangedDecoration';
22
22
  import { createNodeChangedDecorationWidget } from '../decorations/createNodeChangedDecorationWidget';
23
- import { createAttributionColorMap, getAttributionKey, getColorSchemeForChange, isAttributionColoringEnabled } from '../decorations/colorSchemes/attributions';
23
+ import { createAttributionColorMap, getAttributionKey, getAttributionKeyForChange, getColorSchemeForChange, isAttributionColoringEnabled, isContributorTagsEnabled } from '../decorations/colorSchemes/attributions';
24
24
  import { extractDiffDescriptors } from '../decorations/decorationKeys';
25
+ import { extractContributorTags } from '../decorations/extractContributorTags';
25
26
  import { getAttrChangeRanges, stepIsValidAttrChange } from '../decorations/utils/getAttrChangeRanges';
26
27
  import { getMarkChangeRanges } from '../decorations/utils/getMarkChangeRanges';
27
28
  import { getDefaultDiffType, isExtendedEnabled } from '../isExtendedEnabled';
@@ -30,7 +31,7 @@ import { groupChangesByBlock } from './groupChangesByBlock';
30
31
  import { isMarkOnlyChange } from './isMarkOnlyChange';
31
32
  import { optimizeChanges } from './optimizeChanges';
32
33
  import { selectTokenEncoder } from './selectTokenEncoder';
33
- import { simplifyChangesWithAttribution } from './simplifyChangesWithAttribution';
34
+ import { collapseOverlappingChanges, simplifyChangesWithAttribution } from './simplifyChangesWithAttribution';
34
35
  import { simplifySteps, simplifyStepsWithAttribution } from './simplifySteps';
35
36
  import { classifySmartChanges } from './smart/classifySmartChanges';
36
37
  import { smartChangeLevel } from './smart/helpers';
@@ -75,19 +76,12 @@ var getAttributedChanges = function getAttributedChanges(_ref2) {
75
76
  originalDoc = _ref2.originalDoc,
76
77
  steppedDoc = _ref2.steppedDoc,
77
78
  diffType = _ref2.diffType,
78
- tr = _ref2.tr,
79
- intl = _ref2.intl,
80
- smartThresholds = _ref2.smartThresholds;
79
+ tr = _ref2.tr;
80
+ // `smart` is deliberately absent here, even though `getChanges` applies it: the classifier drops
81
+ // the step attribution and promotes ranges to sentence/paragraph/node granularity, so a promoted
82
+ // range covers several actors' steps and the latest-writer rule credits all of it to one of them.
83
+ // The attributed changeset keeps step granularity instead.
81
84
  if (isExtendedEnabled(diffType)) {
82
- if (diffType === 'smart' && fg('platform_editor_ai_smart_diff')) {
83
- return classifySmartChanges({
84
- changes: simplifyChangesWithAttribution(attributedChanges, tr.doc),
85
- originalDoc: originalDoc,
86
- newDoc: tr.doc,
87
- locale: intl.locale,
88
- thresholds: smartThresholds
89
- });
90
- }
91
85
  if (diffType === 'step') {
92
86
  return attributedChanges;
93
87
  }
@@ -270,13 +264,16 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
270
264
  _ref7$deletedDiffPlac = _ref7.deletedDiffPlacement,
271
265
  deletedDiffPlacement = _ref7$deletedDiffPlac === void 0 ? 'top' : _ref7$deletedDiffPlac,
272
266
  _ref7$inlineDeletedDi = _ref7.inlineDeletedDiffPlacement,
273
- inlineDeletedDiffPlacement = _ref7$inlineDeletedDi === void 0 ? 'before' : _ref7$inlineDeletedDi;
267
+ inlineDeletedDiffPlacement = _ref7$inlineDeletedDi === void 0 ? 'before' : _ref7$inlineDeletedDi,
268
+ tagMountContext = _ref7.tagMountContext;
274
269
  var originalDoc = pluginState.originalDoc,
275
270
  steps = pluginState.steps,
276
271
  stepAttributions = pluginState.stepAttributions,
272
+ contributors = pluginState.contributors,
277
273
  isDisplayingChanges = pluginState.isDisplayingChanges;
278
274
  if (!originalDoc || !isDisplayingChanges) {
279
275
  return {
276
+ contributorTags: [],
280
277
  decorations: DecorationSet.empty,
281
278
  diffDescriptors: []
282
279
  };
@@ -288,9 +285,12 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
288
285
  var tr = state.tr;
289
286
  var steppedDoc = originalDoc;
290
287
  var attributionColoringEnabled = isAttributionColoringEnabled(stepAttributions);
288
+ var showContributorTags = isContributorTagsEnabled(stepAttributions, contributors);
289
+ // Tags need the attributed changeset even on diffs with too few actors to be worth colouring.
290
+ var attributedChangesetEnabled = attributionColoringEnabled || showContributorTags;
291
291
  var simplifiedSteps;
292
292
  var simplifiedStepAttributions = [];
293
- if (attributionColoringEnabled) {
293
+ if (attributedChangesetEnabled) {
294
294
  var simplifiedStepsWithAttribution = simplifyStepsWithAttribution(steps, stepAttributions !== null && stepAttributions !== void 0 ? stepAttributions : [], originalDoc);
295
295
  simplifiedSteps = simplifiedStepsWithAttribution.map(function (_ref8) {
296
296
  var step = _ref8.step;
@@ -378,6 +378,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
378
378
  });
379
379
  if (!recoveredViaContentEquality) {
380
380
  return {
381
+ contributorTags: [],
381
382
  decorations: DecorationSet.empty,
382
383
  diffDescriptors: []
383
384
  };
@@ -390,7 +391,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
390
391
  var changes;
391
392
  var attributedChanges = [];
392
393
  var attributionColors;
393
- if (attributionColoringEnabled) {
394
+ if (attributedChangesetEnabled) {
394
395
  var changeset = ChangeSet.create(originalDoc, function (left, right) {
395
396
  return getAttributionKey(left) === getAttributionKey(right) ? left.stepIndex > right.stepIndex ? left : right :
396
397
  // `prosemirror-changeset` uses null as its incompatible-data sentinel even
@@ -402,17 +403,22 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
402
403
  });
403
404
  }));
404
405
  attributedChanges = diffBySteps(originalDoc, simplifiedSteps, simplifiedStepAttributions);
405
- changes = getAttributedChanges({
406
+ // The attributed pipeline gives no guarantee that its output ranges are disjoint — see
407
+ // `collapseOverlappingChanges`.
408
+ var uncollapsedChanges = getAttributedChanges({
406
409
  changeset: changeset,
407
410
  originalDoc: originalDoc,
408
411
  steppedDoc: steppedDoc,
409
412
  diffType: diffType,
410
413
  tr: tr,
411
- attributedChanges: attributedChanges,
412
- intl: intl,
413
- smartThresholds: smartThresholds
414
+ attributedChanges: attributedChanges
414
415
  });
415
- attributionColors = createAttributionColorMap(simplifiedStepAttributions);
416
+ changes = collapseOverlappingChanges(uncollapsedChanges);
417
+
418
+ // Still colours-only: a tags-only diff keeps the plain colour scheme.
419
+ if (attributionColoringEnabled) {
420
+ attributionColors = createAttributionColorMap(simplifiedStepAttributions);
421
+ }
416
422
  } else {
417
423
  var _changeset = ChangeSet.create(originalDoc, undefined, tokenEncoder).addSteps(steppedDoc, stepMaps, tr.doc);
418
424
  changes = getChanges({
@@ -439,6 +445,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
439
445
  var isInserted = !isInverted;
440
446
  var createDecorationsForChange = function createDecorationsForChange(change) {
441
447
  var changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
448
+ var attributionKey = showContributorTags ? getAttributionKeyForChange(change, attributedChanges) : undefined;
442
449
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
443
450
 
444
451
  // The deleted side of a mark-only change is a byte-identical copy of the new text, so it is
@@ -498,6 +505,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
498
505
  continue;
499
506
  }
500
507
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration(_objectSpread({
508
+ attributionKey: attributionKey,
501
509
  change: {
502
510
  fromB: from,
503
511
  toB: to
@@ -509,10 +517,12 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
509
517
  }, isExtendedEnabled(diffType) && {
510
518
  isInserted: isInserted,
511
519
  shouldHideDeleted: shouldHideDeleted,
520
+ showContributorTags: showContributorTags,
512
521
  showIndicators: showIndicators,
513
522
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
514
523
  hasDeletedWidget: willRenderDeletedWidget,
515
- isDeletedWidgetBelow: isDeletedWidgetBelow
524
+ isDeletedWidgetBelow: isDeletedWidgetBelow,
525
+ tagMountContext: tagMountContext
516
526
  }))));
517
527
  }
518
528
  } catch (err) {
@@ -522,6 +532,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
522
532
  }
523
533
  } else {
524
534
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration(_objectSpread({
535
+ attributionKey: attributionKey,
525
536
  change: change,
526
537
  doc: tr.doc,
527
538
  colorScheme: changeColorScheme,
@@ -530,10 +541,12 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
530
541
  }, isExtendedEnabled(diffType) && {
531
542
  isInserted: isInserted,
532
543
  shouldHideDeleted: shouldHideDeleted,
544
+ showContributorTags: showContributorTags,
533
545
  showIndicators: showIndicators,
534
546
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
535
547
  hasDeletedWidget: willRenderDeletedWidget,
536
- isDeletedWidgetBelow: isDeletedWidgetBelow
548
+ isDeletedWidgetBelow: isDeletedWidgetBelow,
549
+ tagMountContext: tagMountContext
537
550
  }))));
538
551
  }
539
552
  decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration(_objectSpread(_objectSpread({
@@ -556,13 +569,17 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
556
569
  var _shouldHideDeleted = isExtendedEnabled(diffType) ? !isInverted && hideDeletedDiffs && change.inserted.length > 0 : false;
557
570
  if (!_shouldHideDeleted) {
558
571
  decorations.push.apply(decorations, _toConsumableArray(createNodeChangedDecorationWidget(_objectSpread(_objectSpread({
572
+ // The deleted side has no inline decoration, so the widget carries the actor.
573
+ attributionKey: attributionKey,
559
574
  change: change,
560
575
  doc: originalDoc,
561
576
  nodeViewSerializer: nodeViewSerializer,
562
577
  colorScheme: changeColorScheme,
563
578
  newDoc: tr.doc,
564
579
  intl: intl,
565
- activeIndexPos: activeIndexPos
580
+ activeIndexPos: activeIndexPos,
581
+ showContributorTags: showContributorTags,
582
+ tagMountContext: tagMountContext
566
583
  }, isExtendedEnabled(diffType) && {
567
584
  isInserted: !isInserted,
568
585
  diffType: diffType,
@@ -681,12 +698,14 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref7
681
698
  });
682
699
  var decorationSet = DecorationSet.empty.add(tr.doc, decorations);
683
700
  return {
701
+ contributorTags: showContributorTags ? extractContributorTags(decorationSet, contributors) : [],
684
702
  decorations: decorationSet,
685
703
  diffDescriptors: extractDiffDescriptors(decorationSet)
686
704
  };
687
705
  };
688
706
  export var calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
689
- // Cache results unless relevant inputs change
707
+ // Cache results unless relevant inputs change. `tagMountContext` is deliberately absent: it is
708
+ // built once per plugin instance, so it can never be the reason a diff needs recalculating.
690
709
  function (_ref11, _ref12) {
691
710
  var _ref16;
692
711
  var _ref13 = _slicedToArray(_ref11, 1),
@@ -722,7 +741,9 @@ function (_ref11, _ref12) {
722
741
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
723
742
  if (isExtendedEnabled(diffType)) {
724
743
  var _ref15;
725
- return (_ref15 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref15 !== void 0 ? _ref15 : false;
744
+ return (_ref15 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) &&
745
+ // Contributors can arrive after the first calculation; without this, tags never appear.
746
+ isEqual(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref15 !== void 0 ? _ref15 : false;
726
747
  }
727
- return (_ref16 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref16 !== void 0 ? _ref16 : false;
748
+ return (_ref16 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) && isEqual(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref16 !== void 0 ? _ref16 : false;
728
749
  });
@@ -1,10 +1,10 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
5
  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
6
  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
7
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
6
- function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
8
8
  import { simplifyChanges } from 'prosemirror-changeset';
9
9
  import { getAttributionKey } from '../decorations/colorSchemes/attributions';
10
10
  import { optimizeChanges } from './optimizeChanges';
@@ -25,6 +25,58 @@ var getAttributionIdentity = function getAttributionIdentity(change) {
25
25
  mergeable: true
26
26
  };
27
27
  };
28
+ var byNewDocRange = function byNewDocRange(left, right) {
29
+ return left.fromB - right.fromB || left.toB - right.toB;
30
+ };
31
+
32
+ /**
33
+ * Collapses changes whose new-document ranges strictly overlap. Attribution runs are simplified
34
+ * independently, so runs either side of an unattributed step can come back covering the same
35
+ * characters — which stacks two inline decorations and renders one contributor tag per copy.
36
+ *
37
+ * Merging keeps every span from both sides, so the latest-writer rule still decides whose tag is
38
+ * shown. Ranges that merely touch are left alone, so an unattributed edit next to an attributed one
39
+ * is not credited to it.
40
+ */
41
+ export var collapseOverlappingChanges = function collapseOverlappingChanges(changes) {
42
+ if (changes.length <= 1) {
43
+ return changes;
44
+ }
45
+
46
+ // A zero-length new-document range paints no inline decoration, so it is kept aside rather than
47
+ // folded into a neighbouring insertion.
48
+ var emptyRanges = changes.filter(function (change) {
49
+ return change.toB <= change.fromB;
50
+ });
51
+ var collapsed = [];
52
+ var _iterator = _createForOfIteratorHelper(changes.filter(function (change) {
53
+ return change.toB > change.fromB;
54
+ }).sort(byNewDocRange)),
55
+ _step;
56
+ try {
57
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
58
+ var change = _step.value;
59
+ var current = collapsed[collapsed.length - 1];
60
+ if (current && change.fromB < current.toB) {
61
+ collapsed[collapsed.length - 1] = {
62
+ fromA: Math.min(current.fromA, change.fromA),
63
+ toA: Math.max(current.toA, change.toA),
64
+ fromB: Math.min(current.fromB, change.fromB),
65
+ toB: Math.max(current.toB, change.toB),
66
+ deleted: [].concat(_toConsumableArray(current.deleted), _toConsumableArray(change.deleted)),
67
+ inserted: [].concat(_toConsumableArray(current.inserted), _toConsumableArray(change.inserted))
68
+ };
69
+ } else {
70
+ collapsed.push(_objectSpread({}, change));
71
+ }
72
+ }
73
+ } catch (err) {
74
+ _iterator.e(err);
75
+ } finally {
76
+ _iterator.f();
77
+ }
78
+ return [].concat(collapsed, _toConsumableArray(emptyRanges)).sort(byNewDocRange);
79
+ };
28
80
 
29
81
  /**
30
82
  * Simplifies and optimizes consecutive changes without crossing an attribution boundary.
@@ -55,12 +107,12 @@ export var simplifyChangesWithAttribution = function simplifyChangesWithAttribut
55
107
  run = [];
56
108
  runIdentity = undefined;
57
109
  };
58
- var _iterator = _createForOfIteratorHelper(changes),
59
- _step;
110
+ var _iterator2 = _createForOfIteratorHelper(changes),
111
+ _step2;
60
112
  try {
61
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
113
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
62
114
  var _runIdentity;
63
- var change = _step.value;
115
+ var change = _step2.value;
64
116
  var identity = getAttributionIdentity(change);
65
117
  var canJoinRun = ((_runIdentity = runIdentity) === null || _runIdentity === void 0 ? void 0 : _runIdentity.mergeable) === true && identity.mergeable && runIdentity.key === identity.key;
66
118
  if (run.length > 0 && !canJoinRun) {
@@ -73,9 +125,9 @@ export var simplifyChangesWithAttribution = function simplifyChangesWithAttribut
73
125
  }
74
126
  }
75
127
  } catch (err) {
76
- _iterator.e(err);
128
+ _iterator2.e(err);
77
129
  } finally {
78
- _iterator.f();
130
+ _iterator2.f();
79
131
  }
80
132
  flush();
81
133
  return result;
@@ -1,5 +1,10 @@
1
1
  import _typeof from "@babel/runtime/helpers/typeof";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ import _objectWithoutProperties from "@babel/runtime/helpers/objectWithoutProperties";
5
+ var _excluded = ["attribution", "connectedTo"];
6
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
7
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
8
  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
9
  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
10
  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; }
@@ -7,6 +12,11 @@ import { getParticipantColor } from '@atlaskit/editor-shared-styles/utils';
7
12
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
8
13
  import { fg } from '@atlaskit/platform-feature-flags/fg';
9
14
  import { PARTICIPANT_COLOR_SCHEMES } from './types';
15
+
16
+ /** A contributor with both of its identities collapsed to internal attribution keys. */
17
+
18
+ /** Contributors addressed by attribution key. The key format is internal. */
19
+
10
20
  /**
11
21
  * Normalise the attribution identity once so a valid lookup key always has a valid participant
12
22
  * colour seed. `userId` is primary; `agentId`, or `agentType` as its fallback, separates shared
@@ -41,6 +51,40 @@ export var getAttributionKey = function getAttributionKey(attribution) {
41
51
  var _getAttributionIdenti;
42
52
  return (_getAttributionIdenti = getAttributionIdentity(attribution)) === null || _getAttributionIdenti === void 0 ? void 0 : _getAttributionIdenti.key;
43
53
  };
54
+
55
+ /**
56
+ * Public contributor list to internal key-addressed record. A contributor whose attribution carries
57
+ * no identity is dropped, since it could never match a step. Later entries win.
58
+ */
59
+ export var resolveContributors = function resolveContributors(contributors) {
60
+ if (!(contributors !== null && contributors !== void 0 && contributors.length)) {
61
+ return undefined;
62
+ }
63
+ var resolved = {};
64
+ var _iterator = _createForOfIteratorHelper(contributors),
65
+ _step;
66
+ try {
67
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
68
+ var _ref = _step.value;
69
+ var attribution = _ref.attribution,
70
+ connectedTo = _ref.connectedTo,
71
+ tagContributor = _objectWithoutProperties(_ref, _excluded);
72
+ var key = getAttributionKey(attribution);
73
+ if (!key) {
74
+ continue;
75
+ }
76
+ var connectedToKey = connectedTo ? getAttributionKey(connectedTo) : undefined;
77
+ resolved[key] = _objectSpread(_objectSpread({}, tagContributor), connectedToKey ? {
78
+ connectedToKey: connectedToKey
79
+ } : {});
80
+ }
81
+ } catch (err) {
82
+ _iterator.e(err);
83
+ } finally {
84
+ _iterator.f();
85
+ }
86
+ return Object.keys(resolved).length > 0 ? resolved : undefined;
87
+ };
44
88
  export var areAttributionColorGatesEnabled = function areAttributionColorGatesEnabled() {
45
89
  return fg('confluence_ncs_step_diffing_version_history') && isExperimentEnabled('platform_editor_show_diff_color_scheme_refactor');
46
90
  };
@@ -53,13 +97,23 @@ export var isAttributionColoringEnabled = function isAttributionColoringEnabled(
53
97
  }));
54
98
  return attributionKeys.size > 1;
55
99
  };
100
+
101
+ /**
102
+ * Shares the colours' gates, but with a lower bar: colouring needs two actors to tell apart, whereas
103
+ * a tag only has to name one.
104
+ */
105
+ export var isContributorTagsEnabled = function isContributorTagsEnabled(stepAttributions, contributors) {
106
+ return areAttributionColorGatesEnabled() && Boolean(stepAttributions === null || stepAttributions === void 0 ? void 0 : stepAttributions.some(function (attribution) {
107
+ return getAttributionKey(attribution) !== undefined;
108
+ })) && contributors !== undefined && Object.keys(contributors).length > 0;
109
+ };
56
110
  export var createAttributionColorMap = function createAttributionColorMap(stepAttributions) {
57
111
  var colors = new Map();
58
- var _iterator = _createForOfIteratorHelper(stepAttributions),
59
- _step;
112
+ var _iterator2 = _createForOfIteratorHelper(stepAttributions),
113
+ _step2;
60
114
  try {
61
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
62
- var attribution = _step.value;
115
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
116
+ var attribution = _step2.value;
63
117
  var identity = getAttributionIdentity(attribution);
64
118
  if (!identity || colors.has(identity.key)) {
65
119
  continue;
@@ -72,9 +126,9 @@ export var createAttributionColorMap = function createAttributionColorMap(stepAt
72
126
  }
73
127
  }
74
128
  } catch (err) {
75
- _iterator.e(err);
129
+ _iterator2.e(err);
76
130
  } finally {
77
- _iterator.f();
131
+ _iterator2.f();
78
132
  }
79
133
  return colors;
80
134
  };
@@ -98,19 +152,23 @@ var changesOverlap = function changesOverlap(change, attributedChange) {
98
152
  var deletedOverlap = change.deleted.length > 0 && attributedChange.deleted.length > 0 && rangesOverlap(change.fromA, change.toA, attributedChange.fromA, attributedChange.toA);
99
153
  return insertedOverlap || deletedOverlap;
100
154
  };
101
- var getParticipantColorSchemeForChanges = function getParticipantColorSchemeForChanges(changes, attributionColors) {
102
- var key = getAttributionKey(getLatestAttribution(changes));
103
- return key ? attributionColors.get(key) : undefined;
155
+ var getAttributionKeyForChanges = function getAttributionKeyForChanges(changes) {
156
+ return getAttributionKey(getLatestAttribution(changes));
157
+ };
158
+
159
+ /**
160
+ * The attribution key owning a change. Inline and step changes retain direct attribution spans, so
161
+ * resolve those first. Grouped and smart-classified changes can lose that data; for those, fall
162
+ * back to the latest overlapping attributed step.
163
+ */
164
+ export var getAttributionKeyForChange = function getAttributionKeyForChange(change, attributedChanges) {
165
+ var _getAttributionKeyFor;
166
+ return (_getAttributionKeyFor = getAttributionKeyForChanges([change])) !== null && _getAttributionKeyFor !== void 0 ? _getAttributionKeyFor : getAttributionKeyForChanges(attributedChanges.filter(function (attributedChange) {
167
+ return changesOverlap(change, attributedChange);
168
+ }));
104
169
  };
105
170
  export var getColorSchemeForChange = function getColorSchemeForChange(change, attributedChanges, attributionColors, 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
- );
171
+ var _attributionColors$ge;
172
+ var key = getAttributionKeyForChange(change, attributedChanges);
173
+ return key ? (_attributionColors$ge = attributionColors.get(key)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : fallback : fallback;
116
174
  };
@@ -147,6 +147,15 @@ function textAccent(color) {
147
147
  return isParticipantColorScheme(color) ? participantColorTokenSets[color].textAccent : textAccentMap[color];
148
148
  }
149
149
 
150
+ /** Presentation tokens for one diff colour, shared by highlights and contributor tags. */
151
+ export function getAccentTokens(color) {
152
+ return {
153
+ background: bgSubtlest(color),
154
+ border: borderAccent(color),
155
+ text: textAccent(color)
156
+ };
157
+ }
158
+
150
159
  /** Ring colour for an active (scroll-target) deleted block outline. */
151
160
  function deletedBlockOutlineActiveRing(colors) {
152
161
  return colors.deletedBlockOutlineActiveEmphasis === 'border' ? borderAccent(colors.deleteActiveColor) : bgSubtlerPressed(colors.deleteActiveColor);
@@ -1,3 +1,5 @@
1
+ /** Schemes consumers may explicitly request through the show-diff API. */
2
+
1
3
  /** Attribution-only participant slots selected by the plugin, never by consumers. */
2
4
  export var 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
5
 
@@ -3,6 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
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 { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
5
5
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
6
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
6
7
  import { buildAnchorDecorationKey, buildAnchorDecorationSpec, AnchorDocMarginKey, AnchorTypeKey } from './decorationKeys';
7
8
 
8
9
  /**
@@ -316,7 +317,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
316
317
  * inward into the neighbouring cell (`direction: 1` forward, `-1` back). Positions
317
318
  * not on a row boundary are returned as-is.
318
319
  */
319
- var clampAnchorPosIntoCell = function clampAnchorPosIntoCell(doc, pos, direction) {
320
+ export var clampAnchorPosIntoCell = function clampAnchorPosIntoCell(doc, pos, direction) {
320
321
  var $pos = doc.resolve(pos);
321
322
  if ($pos.parent.type.name !== 'tableRow') {
322
323
  return pos;
@@ -330,15 +331,43 @@ var clampAnchorPosIntoCell = function clampAnchorPosIntoCell(doc, pos, direction
330
331
  return direction === 1 ? pos + 2 : pos - 2;
331
332
  };
332
333
 
334
+ /**
335
+ * A zero-size inline span carrying nothing but the `anchor-name` an overlay aligns against. A
336
+ * fragmented inline element reports the union of its line fragments, so aligning against one
337
+ * horizontally gives the enclosing block's content edge; a zero-size span is always a single
338
+ * fragment.
339
+ */
340
+ export var createAnchorNameSpan = function createAnchorNameSpan(anchorKey) {
341
+ var span = document.createElement('span');
342
+ span.style.setProperty('anchor-name', "--".concat(anchorKey));
343
+ return span;
344
+ };
345
+ var createAnchorSpanWidget = function createAnchorSpanWidget(_ref3) {
346
+ var pos = _ref3.pos,
347
+ diffId = _ref3.diffId,
348
+ anchorType = _ref3.anchorType,
349
+ side = _ref3.side;
350
+ return Decoration.widget(pos, function () {
351
+ return createAnchorNameSpan(buildAnchorDecorationKey({
352
+ diffId: diffId,
353
+ anchorType: anchorType
354
+ }));
355
+ }, buildAnchorDecorationSpec({
356
+ diffId: diffId,
357
+ anchorType: anchorType,
358
+ side: side
359
+ }));
360
+ };
361
+
333
362
  /**
334
363
  * Invisible `from`/`to` (and optional `left`) anchor widgets for one inline diff
335
364
  * range, so the `IndicatorBar` can align itself via CSS anchor positioning.
336
365
  */
337
- export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAnchorWidgets(_ref3) {
338
- var doc = _ref3.doc,
339
- from = _ref3.from,
340
- to = _ref3.to,
341
- diffId = _ref3.diffId;
366
+ export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAnchorWidgets(_ref4) {
367
+ var doc = _ref4.doc,
368
+ from = _ref4.from,
369
+ to = _ref4.to,
370
+ diffId = _ref4.diffId;
342
371
  var leftAnchor = createLeftAnchorWidget({
343
372
  doc: doc,
344
373
  from: from,
@@ -355,6 +384,22 @@ export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAn
355
384
  * IndicatorBar can determine top/bottom even if
356
385
  * the inline decoration is broken up by marks / between blocks.
357
386
  */
387
+ // Gated purely so the `createAnchorSpanWidget` rewrite can be rolled back independently of the
388
+ // contributor-tag anchors it was extracted for: both branches build the same two widgets at the
389
+ // same positions. Drop the fallback with the gate.
390
+ if (fg('confluence_ncs_step_diffing_version_history')) {
391
+ return [createAnchorSpanWidget({
392
+ pos: fromPos,
393
+ diffId: diffId,
394
+ anchorType: AnchorTypeKey.from,
395
+ side: 1
396
+ }), createAnchorSpanWidget({
397
+ pos: toPos,
398
+ diffId: diffId,
399
+ anchorType: AnchorTypeKey.to,
400
+ side: -1
401
+ })].concat(maybeLeftAnchor);
402
+ }
358
403
  var fromAnchorKey = buildAnchorDecorationKey({
359
404
  diffId: diffId,
360
405
  anchorType: AnchorTypeKey.from