@atlaskit/editor-plugin-show-diff 16.0.1 → 16.0.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 (45) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/afm-products/tsconfig.json +3 -0
  3. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +86 -50
  4. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
  5. package/dist/cjs/pm-plugins/decorations/utils/getMarkChangeRanges.js +18 -4
  6. package/dist/cjs/pm-plugins/decorations/utils/mapStepRangeToFinal.js +34 -0
  7. package/dist/cjs/pm-plugins/main.js +18 -0
  8. package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +26 -4
  9. package/dist/cjs/ui/ContributorTag/contributorLabel.js +55 -0
  10. package/dist/cjs/ui/ContributorTag/contributorTagController.js +14 -39
  11. package/dist/cjs/ui/ContributorTag/messages.js +5 -0
  12. package/dist/cjs/ui/DiffNavigation/announceActiveDiff.js +54 -0
  13. package/dist/cjs/ui/DiffNavigation/messages.js +19 -0
  14. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +43 -12
  15. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +16 -0
  16. package/dist/es2019/pm-plugins/decorations/utils/getMarkChangeRanges.js +12 -4
  17. package/dist/es2019/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
  18. package/dist/es2019/pm-plugins/main.js +18 -0
  19. package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +24 -4
  20. package/dist/es2019/ui/ContributorTag/contributorLabel.js +49 -0
  21. package/dist/es2019/ui/ContributorTag/contributorTagController.js +14 -39
  22. package/dist/es2019/ui/ContributorTag/messages.js +5 -0
  23. package/dist/es2019/ui/DiffNavigation/announceActiveDiff.js +49 -0
  24. package/dist/es2019/ui/DiffNavigation/messages.js +13 -0
  25. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +86 -50
  26. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
  27. package/dist/esm/pm-plugins/decorations/utils/getMarkChangeRanges.js +17 -4
  28. package/dist/esm/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
  29. package/dist/esm/pm-plugins/main.js +18 -0
  30. package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +26 -4
  31. package/dist/esm/ui/ContributorTag/contributorLabel.js +49 -0
  32. package/dist/esm/ui/ContributorTag/contributorTagController.js +14 -39
  33. package/dist/esm/ui/ContributorTag/messages.js +5 -0
  34. package/dist/esm/ui/DiffNavigation/announceActiveDiff.js +48 -0
  35. package/dist/esm/ui/DiffNavigation/messages.js +13 -0
  36. package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +3 -0
  37. package/dist/types/pm-plugins/decorations/utils/getMarkChangeRanges.d.ts +4 -1
  38. package/dist/types/pm-plugins/decorations/utils/mapStepRangeToFinal.d.ts +8 -0
  39. package/dist/types/showDiffPluginType.d.ts +7 -1
  40. package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +5 -2
  41. package/dist/types/ui/ContributorTag/contributorLabel.d.ts +13 -0
  42. package/dist/types/ui/ContributorTag/messages.d.ts +1 -0
  43. package/dist/types/ui/DiffNavigation/announceActiveDiff.d.ts +18 -0
  44. package/dist/types/ui/DiffNavigation/messages.d.ts +5 -0
  45. package/package.json +3 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 16.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`44acf8971ef0e`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/44acf8971ef0e) -
8
+ Preserve contributor attribution for attribute-only diff decorations so they use the correct
9
+ colour and contributor tags.
10
+ - [`683c1a024bcb3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/683c1a024bcb3) -
11
+ Improve the accessibility of contributor diff tags, behind the
12
+ `confluence_ncs_step_diffing_version_history` gate. A tag now announces its contributor once
13
+ rather than three times over, names itself through `aria-labelledby` so it is no longer a focus
14
+ stop without an accessible name, says in its label when the contributor is an AI agent, and draws
15
+ an inset focus ring that reads against every accent fill.
16
+
17
+ Stepping to the next or previous change now announces the reader's position in the diff and who
18
+ made the change, through the editor's shared live region. Behind the
19
+ `platform_editor_diff_plugin_extended` experiment.
20
+
21
+ - Updated dependencies
22
+
3
23
  ## 16.0.1
4
24
 
5
25
  ### Patch Changes
@@ -26,6 +26,9 @@
26
26
  {
27
27
  "path": "../../custom-steps/afm-products/tsconfig.json"
28
28
  },
29
+ {
30
+ "path": "../../editor-plugin-accessibility-utils/afm-products/tsconfig.json"
31
+ },
29
32
  {
30
33
  "path": "../../editor-plugin-analytics/afm-products/tsconfig.json"
31
34
  },
@@ -344,15 +344,18 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
344
344
  }
345
345
  var pendingAttrSteps = [];
346
346
  var stepMaps = [];
347
- var _iterator = _createForOfIteratorHelper(simplifiedSteps),
347
+ var _iterator = _createForOfIteratorHelper(simplifiedSteps.entries()),
348
348
  _step;
349
349
  try {
350
350
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
351
- var step = _step.value;
351
+ var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
352
+ stepIndex = _step$value[0],
353
+ step = _step$value[1];
352
354
  var result = step.apply(steppedDoc);
353
355
  if (result.failed === null && result.doc) {
354
356
  if ((0, _getAttrChangeRanges.stepIsValidAttrChange)(step, steppedDoc, result.doc)) {
355
357
  pendingAttrSteps.push({
358
+ attributionKey: (0, _attributions.getAttributionKey)(simplifiedStepAttributions[stepIndex]),
356
359
  afterNode: result.doc.nodeAt(step.pos),
357
360
  beforeNode: steppedDoc.nodeAt(step.pos),
358
361
  mapIndex: stepMaps.length,
@@ -372,6 +375,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
372
375
  }
373
376
  var attrStepContexts = (0, _fg.fg)('platform_editor_reduce_diff_attr_sensitivity') ? pendingAttrSteps.flatMap(function (_ref1) {
374
377
  var afterNode = _ref1.afterNode,
378
+ attributionKey = _ref1.attributionKey,
375
379
  beforeNode = _ref1.beforeNode,
376
380
  mapIndex = _ref1.mapIndex,
377
381
  step = _ref1.step;
@@ -381,6 +385,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
381
385
  }
382
386
  var originalPosition = new _transform.Mapping(stepMaps.slice(0, mapIndex)).invert().mapResult(step.pos);
383
387
  return [_objectSpread(_objectSpread({
388
+ attributionKey: attributionKey,
384
389
  afterNode: afterNode,
385
390
  beforeNode: beforeNode,
386
391
  finalPos: finalPosition.pos
@@ -390,8 +395,10 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
390
395
  step: step
391
396
  })];
392
397
  }) : pendingAttrSteps.map(function (_ref10) {
393
- var step = _ref10.step;
398
+ var attributionKey = _ref10.attributionKey,
399
+ step = _ref10.step;
394
400
  return {
401
+ attributionKey: attributionKey,
395
402
  afterNode: tr.doc.nodeAt(step.pos),
396
403
  beforeNode: originalDoc.nodeAt(step.pos),
397
404
  finalPos: step.pos,
@@ -656,34 +663,54 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
656
663
  // smart path. Only add the legacy step-range decoration when no equivalent changeset range was
657
664
  // produced; otherwise the same content receives two inline decorations (and two navigation
658
665
  // changes), usually one attribution colour and one default purple decoration.
659
- (0, _getMarkChangeRanges.getMarkChangeRanges)(steps).filter(function (_ref11) {
666
+ (0, _getMarkChangeRanges.getMarkChangeRanges)(simplifiedSteps, simplifiedStepAttributions, (0, _fg.fg)('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref11) {
660
667
  var fromB = _ref11.fromB,
661
668
  toB = _ref11.toB;
662
669
  return !(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
663
670
  return change.fromB === fromB && change.toB === toB;
664
671
  });
665
672
  }).forEach(function (change) {
673
+ var _attributionColors$ge, _attributionColors;
674
+ var changeColorScheme = change.attributionKey ? (_attributionColors$ge = (_attributionColors = attributionColors) === null || _attributionColors === void 0 ? void 0 : _attributionColors.get(change.attributionKey)) !== null && _attributionColors$ge !== void 0 ? _attributionColors$ge : colorScheme : colorScheme;
675
+ var attributionKey = showContributorTags ? change.attributionKey : undefined;
666
676
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
667
677
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
678
+ attributionKey: attributionKey,
668
679
  change: change,
669
- colorScheme: colorScheme,
680
+ colorScheme: changeColorScheme,
681
+ doc: tr.doc,
670
682
  diffType: diffType,
671
683
  isActive: isActive,
672
684
  isInserted: true,
673
- reveal: reveal
685
+ reveal: reveal,
686
+ showContributorTags: showContributorTags,
687
+ tagMountContext: tagMountContext
674
688
  })));
675
689
  });
676
- (0, _getAttrChangeRanges.getAttrChangeRanges)(tr.doc, attrStepContexts, originalDoc).forEach(function (change) {
690
+ (0, _getAttrChangeRanges.getAttrChangeRanges)(tr.doc, attrStepContexts, originalDoc).filter(function (_ref12) {
691
+ var fromB = _ref12.fromB,
692
+ toB = _ref12.toB;
693
+ return !(0, _fg.fg)('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
694
+ return change.fromB === fromB && change.toB === toB;
695
+ });
696
+ }).forEach(function (change) {
697
+ var _attributionColors$ge2, _attributionColors2;
698
+ var changeColorScheme = change.attributionKey ? (_attributionColors$ge2 = (_attributionColors2 = attributionColors) === null || _attributionColors2 === void 0 ? void 0 : _attributionColors2.get(change.attributionKey)) !== null && _attributionColors$ge2 !== void 0 ? _attributionColors$ge2 : colorScheme : colorScheme;
699
+ var attributionKey = showContributorTags ? change.attributionKey : undefined;
677
700
  if (change.isInline) {
678
701
  // Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
679
702
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
680
703
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
704
+ attributionKey: attributionKey,
681
705
  change: change,
682
- colorScheme: colorScheme,
706
+ colorScheme: changeColorScheme,
707
+ doc: tr.doc,
683
708
  isActive: isActive,
684
709
  isInserted: true,
685
710
  isAtomicInlineNode: true,
686
711
  inlineNodeName: change.inlineNodeName,
712
+ showContributorTags: showContributorTags,
713
+ tagMountContext: tagMountContext,
687
714
  // Suppress the border-bottom underline for atomic inline nodeviews —
688
715
  // it doesn't render on custom nodeview DOM elements and is unnecessary noise.
689
716
  hideAddedDiffsUnderline: true,
@@ -701,12 +728,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
701
728
  deleted: []
702
729
  },
703
730
  doc: originalDoc,
731
+ attributionKey: attributionKey,
704
732
  nodeViewSerializer: nodeViewSerializer,
705
- colorScheme: colorScheme,
733
+ colorScheme: changeColorScheme,
706
734
  newDoc: tr.doc,
707
735
  intl: intl,
708
736
  activeIndexPos: activeIndexPos,
709
- isInserted: false
737
+ isInserted: false,
738
+ showContributorTags: showContributorTags,
739
+ tagMountContext: tagMountContext
710
740
  })));
711
741
  }
712
742
  } else {
@@ -714,11 +744,14 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
714
744
  doc: tr.doc,
715
745
  from: change.fromB,
716
746
  to: change.toB,
717
- colorScheme: colorScheme,
747
+ attributionKey: attributionKey,
748
+ colorScheme: changeColorScheme,
718
749
  isInserted: true,
719
750
  activeIndexPos: activeIndexPos,
720
751
  intl: intl,
721
- showIndicators: showIndicators
752
+ showContributorTags: showContributorTags,
753
+ showIndicators: showIndicators,
754
+ tagMountContext: tagMountContext
722
755
  })));
723
756
  // If the original node position is known (e.g. a panel type change), also render
724
757
  // the old block node as a "deleted" widget so the reviewer sees the before/after.
@@ -735,7 +768,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
735
768
  },
736
769
  doc: originalDoc,
737
770
  nodeViewSerializer: nodeViewSerializer,
738
- colorScheme: colorScheme,
771
+ attributionKey: attributionKey,
772
+ colorScheme: changeColorScheme,
739
773
  newDoc: tr.doc,
740
774
  intl: intl,
741
775
  activeIndexPos: activeIndexPos,
@@ -745,7 +779,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
745
779
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
746
780
  placeBelow: placeBelow
747
781
  }), {}, {
748
- showIndicators: showIndicators
782
+ showIndicators: showIndicators,
783
+ showContributorTags: showContributorTags,
784
+ tagMountContext: tagMountContext
749
785
  }))));
750
786
  }
751
787
  }
@@ -760,49 +796,49 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
760
796
  var calculateDiffDecorations = exports.calculateDiffDecorations = (0, _memoizeOne.default)(calculateDiffDecorationsInner,
761
797
  // Cache results unless relevant inputs change. `tagMountContext` is deliberately absent: it is
762
798
  // built once per plugin instance, so it can never be the reason a diff needs recalculating.
763
- function (_ref12, _ref13) {
764
- var _ref17;
765
- var _ref14 = (0, _slicedToArray2.default)(_ref12, 1),
766
- _ref14$ = _ref14[0],
767
- pluginState = _ref14$.pluginState,
768
- state = _ref14$.state,
769
- colorScheme = _ref14$.colorScheme,
770
- intl = _ref14$.intl,
771
- activeIndexPos = _ref14$.activeIndexPos,
772
- isInverted = _ref14$.isInverted,
773
- diffType = _ref14$.diffType,
774
- hideDeletedDiffs = _ref14$.hideDeletedDiffs,
775
- hideAddedDiffsUnderline = _ref14$.hideAddedDiffsUnderline,
776
- showIndicators = _ref14$.showIndicators,
777
- smartThresholds = _ref14$.smartThresholds,
778
- deletedDiffPlacement = _ref14$.deletedDiffPlacement,
779
- inlineDeletedDiffPlacement = _ref14$.inlineDeletedDiffPlacement,
780
- reveal = _ref14$.reveal;
799
+ function (_ref13, _ref14) {
800
+ var _ref18;
781
801
  var _ref15 = (0, _slicedToArray2.default)(_ref13, 1),
782
802
  _ref15$ = _ref15[0],
783
- lastPluginState = _ref15$.pluginState,
784
- lastState = _ref15$.state,
785
- lastColorScheme = _ref15$.colorScheme,
786
- lastIntl = _ref15$.intl,
787
- lastActiveIndexPos = _ref15$.activeIndexPos,
788
- lastIsInverted = _ref15$.isInverted,
789
- lastDiffType = _ref15$.diffType,
790
- lastHideDeletedDiffs = _ref15$.hideDeletedDiffs,
791
- lastHideAddedDiffsUnderline = _ref15$.hideAddedDiffsUnderline,
792
- lastShowIndicators = _ref15$.showIndicators,
793
- lastSmartThresholds = _ref15$.smartThresholds,
794
- lastDeletedDiffPlacement = _ref15$.deletedDiffPlacement,
795
- lastInlineDeletedDiffPlacement = _ref15$.inlineDeletedDiffPlacement,
796
- lastReveal = _ref15$.reveal;
803
+ pluginState = _ref15$.pluginState,
804
+ state = _ref15$.state,
805
+ colorScheme = _ref15$.colorScheme,
806
+ intl = _ref15$.intl,
807
+ activeIndexPos = _ref15$.activeIndexPos,
808
+ isInverted = _ref15$.isInverted,
809
+ diffType = _ref15$.diffType,
810
+ hideDeletedDiffs = _ref15$.hideDeletedDiffs,
811
+ hideAddedDiffsUnderline = _ref15$.hideAddedDiffsUnderline,
812
+ showIndicators = _ref15$.showIndicators,
813
+ smartThresholds = _ref15$.smartThresholds,
814
+ deletedDiffPlacement = _ref15$.deletedDiffPlacement,
815
+ inlineDeletedDiffPlacement = _ref15$.inlineDeletedDiffPlacement,
816
+ reveal = _ref15$.reveal;
817
+ var _ref16 = (0, _slicedToArray2.default)(_ref14, 1),
818
+ _ref16$ = _ref16[0],
819
+ lastPluginState = _ref16$.pluginState,
820
+ lastState = _ref16$.state,
821
+ lastColorScheme = _ref16$.colorScheme,
822
+ lastIntl = _ref16$.intl,
823
+ lastActiveIndexPos = _ref16$.activeIndexPos,
824
+ lastIsInverted = _ref16$.isInverted,
825
+ lastDiffType = _ref16$.diffType,
826
+ lastHideDeletedDiffs = _ref16$.hideDeletedDiffs,
827
+ lastHideAddedDiffsUnderline = _ref16$.hideAddedDiffsUnderline,
828
+ lastShowIndicators = _ref16$.showIndicators,
829
+ lastSmartThresholds = _ref16$.smartThresholds,
830
+ lastDeletedDiffPlacement = _ref16$.deletedDiffPlacement,
831
+ lastInlineDeletedDiffPlacement = _ref16$.inlineDeletedDiffPlacement,
832
+ lastReveal = _ref16$.reveal;
797
833
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
798
834
  if ((0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
799
- var _ref16;
800
- return (_ref16 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && (0, _isEqual.default)(pluginState.stepAttributions, lastPluginState.stepAttributions) &&
835
+ var _ref17;
836
+ return (_ref17 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && (0, _isEqual.default)(pluginState.stepAttributions, lastPluginState.stepAttributions) &&
801
837
  // Contributors can arrive after the first calculation; without this, tags never appear.
802
838
  (0, _isEqual.default)(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && (0, _isEqual.default)(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement &&
803
839
  // Turning the reveal on or off changes the emitted styles, so a cached result from the
804
840
  // other setting would leave the diff painted in the wrong resting state.
805
- (0, _isEqual.default)(reveal, lastReveal)) !== null && _ref16 !== void 0 ? _ref16 : false;
841
+ (0, _isEqual.default)(reveal, lastReveal)) !== null && _ref17 !== void 0 ? _ref17 : false;
806
842
  }
807
- return (_ref17 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && (0, _isEqual.default)(pluginState.stepAttributions, lastPluginState.stepAttributions) && (0, _isEqual.default)(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref17 !== void 0 ? _ref17 : false;
843
+ return (_ref18 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && (0, _isEqual.default)(pluginState.stepAttributions, lastPluginState.stepAttributions) && (0, _isEqual.default)(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref18 !== void 0 ? _ref18 : false;
808
844
  });
@@ -66,6 +66,7 @@ var getStepAttrs = function getStepAttrs(step) {
66
66
  var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepContexts, originalDoc) {
67
67
  return attrStepContexts.map(function (attrStepContext) {
68
68
  var afterNode = attrStepContext.afterNode,
69
+ attributionKey = attrStepContext.attributionKey,
69
70
  beforeNode = attrStepContext.beforeNode,
70
71
  finalPos = attrStepContext.finalPos,
71
72
  originalPos = attrStepContext.originalPos,
@@ -93,7 +94,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
93
94
  if (attrsToCheck.some(function (v) {
94
95
  return watchedAttrs.includes(v);
95
96
  })) {
96
- return _objectSpread({
97
+ return _objectSpread(_objectSpread({}, attributionKey ? {
98
+ attributionKey: attributionKey
99
+ } : {}), {}, {
97
100
  fromB: finalPos,
98
101
  toB: finalPos + nodeAtPos.nodeSize,
99
102
  isInline: true,
@@ -110,10 +113,12 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
110
113
  if (attrsToCheck.some(function (v) {
111
114
  return taskItemAttrs.includes(v);
112
115
  }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'taskItem') {
113
- return {
116
+ return _objectSpread(_objectSpread({}, attributionKey ? {
117
+ attributionKey: attributionKey
118
+ } : {}), {}, {
114
119
  fromB: finalPos,
115
120
  toB: finalPos + nodeAtPos.nodeSize
116
- };
121
+ });
117
122
  }
118
123
 
119
124
  // panel node (incl. variants like panel_c1): type/colour/icon attribute change
@@ -123,7 +128,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
123
128
  if (attrsToCheck.some(function (v) {
124
129
  return panelAttrs.includes(v);
125
130
  }) && nodeAtPos && (0, _nodeTypeUtils.getBaseNodeTypeName)(nodeAtPos.type) === 'panel') {
126
- return _objectSpread({
131
+ return _objectSpread(_objectSpread({}, attributionKey ? {
132
+ attributionKey: attributionKey
133
+ } : {}), {}, {
127
134
  fromB: finalPos,
128
135
  toB: finalPos + nodeAtPos.nodeSize
129
136
  }, originalPos !== undefined && originalNodeAtPos && {
@@ -141,11 +148,13 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
141
148
  return undefined;
142
149
  }
143
150
  var isInline = nodeAtPos.type.name === 'inlineExtension';
144
- return {
151
+ return _objectSpread(_objectSpread({}, attributionKey ? {
152
+ attributionKey: attributionKey
153
+ } : {}), {}, {
145
154
  fromB: finalPos,
146
155
  toB: finalPos + nodeAtPos.nodeSize,
147
156
  isInline: isInline
148
- };
157
+ });
149
158
  }
150
159
 
151
160
  // media node: id/collection/url attribute change — highlight the mediaSingle parent
@@ -153,10 +162,12 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
153
162
  return mediaAttrs.includes(v);
154
163
  }) && $pos.parent.type === doc.type.schema.nodes.mediaSingle) {
155
164
  var startPos = $pos.pos + $pos.parentOffset;
156
- return {
165
+ return _objectSpread(_objectSpread({}, attributionKey ? {
166
+ attributionKey: attributionKey
167
+ } : {}), {}, {
157
168
  fromB: startPos,
158
169
  toB: startPos + $pos.parent.nodeSize - 1
159
- };
170
+ });
160
171
  }
161
172
  return undefined;
162
173
  }).filter(filterUndefined)
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.getMarkChangeRanges = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
7
9
  var _transform = require("@atlaskit/editor-prosemirror/transform");
10
+ var _attributions = require("../colorSchemes/attributions");
11
+ var _mapStepRangeToFinal = require("./mapStepRangeToFinal");
8
12
  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; } } }; }
9
13
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
14
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -28,13 +32,17 @@ var extractMarkStep = function extractMarkStep(step) {
28
32
  return undefined;
29
33
  };
30
34
  var getMarkChangeRanges = exports.getMarkChangeRanges = function getMarkChangeRanges(steps) {
35
+ var stepAttributions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
36
+ var stepMaps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
31
37
  var resultRanges = [];
32
38
  var lastOp;
33
- var _iterator = _createForOfIteratorHelper(steps),
39
+ var _iterator = _createForOfIteratorHelper(steps.entries()),
34
40
  _step;
35
41
  try {
36
42
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
37
- var step = _step.value;
43
+ var _step$value = (0, _slicedToArray2.default)(_step.value, 2),
44
+ stepIndex = _step$value[0],
45
+ step = _step$value[1];
38
46
  var op = extractMarkStep(step);
39
47
  if (!op) {
40
48
  continue;
@@ -44,9 +52,15 @@ var getMarkChangeRanges = exports.getMarkChangeRanges = function getMarkChangeRa
44
52
  if (lastOp && lastOp.from === op.from && lastOp.to === op.to && lastOp.markName === op.markName && lastOp.type !== op.type) {
45
53
  resultRanges.pop();
46
54
  } else {
55
+ var finalRange = (0, _mapStepRangeToFinal.mapStepRangeToFinal)(op.from, op.to, stepIndex, stepMaps);
56
+ if (!finalRange) {
57
+ lastOp = op;
58
+ continue;
59
+ }
47
60
  resultRanges.push({
48
- fromB: op.from,
49
- toB: op.to
61
+ attributionKey: (0, _attributions.getAttributionKey)(stepAttributions[stepIndex]),
62
+ fromB: finalRange.fromB,
63
+ toB: finalRange.toB
50
64
  });
51
65
  }
52
66
  lastOp = op;
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.mapStepRangeToFinal = void 0;
7
+ var _transform = require("@atlaskit/editor-prosemirror/transform");
8
+ // ProseMirror's assoc value chooses which side of an insertion a mapped boundary stays on.
9
+ var FROM_ASSOC = -1;
10
+ var TO_ASSOC = 1;
11
+
12
+ /** Maps a step's range into final-document coordinates when the rollout path supplies step maps. */
13
+ var mapStepRangeToFinal = exports.mapStepRangeToFinal = function mapStepRangeToFinal(from, to, stepIndex, stepMaps) {
14
+ if (!stepMaps) {
15
+ return {
16
+ fromB: from,
17
+ toB: to
18
+ };
19
+ }
20
+
21
+ // The range is already in the document immediately after this step, so skip its own map and
22
+ // apply only the maps from subsequent steps.
23
+ var firstSubsequentStepIndex = stepIndex + 1;
24
+ var finalRange = new _transform.Mapping(stepMaps.slice(firstSubsequentStepIndex));
25
+ var fromB = finalRange.mapResult(from, FROM_ASSOC);
26
+ var toB = finalRange.mapResult(to, TO_ASSOC);
27
+ if (fromB.deleted && toB.deleted) {
28
+ return undefined;
29
+ }
30
+ return {
31
+ fromB: fromB.pos,
32
+ toB: toB.pos
33
+ };
34
+ };
@@ -12,6 +12,7 @@ var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
12
12
  var _state2 = require("@atlaskit/editor-prosemirror/state");
13
13
  var _transformOverride = require("@atlaskit/editor-prosemirror/transform-override");
14
14
  var _view = require("@atlaskit/editor-prosemirror/view");
15
+ var _announceActiveDiff = require("../ui/DiffNavigation/announceActiveDiff");
15
16
  var _calculateDiffDecorations = require("./calculateDiff/calculateDiffDecorations");
16
17
  var _decorationKeys = require("./decorations/decorationKeys");
17
18
  var _enforceCustomStepRegisters = require("./enforceCustomStepRegisters");
@@ -279,6 +280,23 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
279
280
  api === null || api === void 0 || api.core.actions.execute((0, _expand.toggleExpandRange)(activeDecoration.from, activeDecoration.to, true));
280
281
  }
281
282
  cancelPendingScrollToDecoration = (0, _scrollToDiff.scrollToDecoration)(view, scrollableDecorations, pluginState.activeIndex);
283
+
284
+ // Stepping only scrolls — no focus moves and no content changes — so without this a
285
+ // screen-reader user gets silence. Announced through the live region rather than by
286
+ // focusing the change, since the "next change" control has to stay focused to be
287
+ // pressed again. After the scroll above, so the announcement never precedes it.
288
+ if ((0, _isExtendedEnabled.isExtendedEnabled)(pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType)) {
289
+ var announcement = (0, _announceActiveDiff.getActiveDiffAnnouncement)({
290
+ activeIndex: pluginState.activeIndex,
291
+ contributorTags: pluginState.contributorTags,
292
+ decorations: scrollableDecorations,
293
+ intl: getIntl()
294
+ });
295
+ if (announcement) {
296
+ var _api$accessibilityUti;
297
+ api === null || api === void 0 || (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 || _api$accessibilityUti.actions.ariaNotify(announcement);
298
+ }
299
+ }
282
300
  }
283
301
  },
284
302
  destroy: function destroy() {
@@ -132,6 +132,19 @@ var srLabelStyle = (0, _lazyNodeView.convertToInlineCss)({
132
132
  userSelect: 'none',
133
133
  whiteSpace: 'nowrap'
134
134
  });
135
+
136
+ /**
137
+ * Ids for the hidden label that the tag's `aria-labelledby` points at. Namespaced and random because
138
+ * the tag renders inside the document and shares the host page's id space — the same reason
139
+ * `VanillaTooltip` does it this way. The counter is a fallback for non-secure contexts, where
140
+ * `crypto.randomUUID` is unavailable.
141
+ */
142
+ var generateLabelId = function () {
143
+ var count = 0;
144
+ return function () {
145
+ return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? "".concat(CONTRIBUTOR_TAG_CLASS, "-label-").concat(crypto.randomUUID()) : "".concat(CONTRIBUTOR_TAG_CLASS, "-label-").concat(count += 1);
146
+ };
147
+ }();
135
148
  var createSpan = function createSpan(doc, style) {
136
149
  var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
137
150
  var span = doc.createElement('span');
@@ -151,21 +164,30 @@ var createSpan = function createSpan(doc, style) {
151
164
  * would need a cast per reference below.
152
165
  */
153
166
  var buildContributorTagDom = exports.buildContributorTagDom = function buildContributorTagDom(doc) {
167
+ var labelId = generateLabelId();
154
168
  var root = createSpan(doc, constraintStyle);
155
169
  var tag = createSpan(doc, tagStyle, {
156
170
  class: CONTRIBUTOR_TAG_CLASS,
157
171
  'data-testid': CONTRIBUTOR_TAG_TESTID,
158
- // Deliberately no `aria-label`: it would be announced ahead of the element's contents, but
159
- // design requires the contributor *after* the change — hence the visually hidden label.
172
+ // Named by the hidden label rather than `aria-label`, which would be a second copy of the same
173
+ // sentence. `role="note"` takes its name from the author, not its contents, so without this
174
+ // the tag is a focus stop with no accessible name.
175
+ 'aria-labelledby': labelId,
160
176
  role: 'note',
161
- // Focusable so keyboard and screen-reader users can reach the tag and its tooltip.
177
+ // Focusable so keyboard and screen-reader users can reach the tag and its tooltip. Its focus
178
+ // ring is drawn inward — see `contributorTagStyles` in editor-core.
162
179
  tabindex: '0'
163
180
  });
164
181
  var avatars = createSpan(doc, avatarsStyle);
182
+ // `aria-hidden`: the hidden label restates this name in a full sentence, so leaving it in the
183
+ // tree announced the contributor twice ("Priya Changed by Priya").
165
184
  var name = createSpan(doc, nameStyle, {
185
+ 'aria-hidden': 'true',
166
186
  'data-testid': CONTRIBUTOR_TAG_NAME_TESTID
167
187
  });
168
- var srLabel = createSpan(doc, srLabelStyle);
188
+ var srLabel = createSpan(doc, srLabelStyle, {
189
+ id: labelId
190
+ });
169
191
  tag.append(avatars, name, srLabel);
170
192
  root.appendChild(tag);
171
193
  return {
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.formatContributorLabel = void 0;
7
+ var _messages = require("./messages");
8
+ var getContributorName = function getContributorName(contributor, formatMessage) {
9
+ var _contributor$name, _contributor$agentKin;
10
+ var name = (_contributor$name = contributor.name) === null || _contributor$name === void 0 ? void 0 : _contributor$name.trim();
11
+ if (name) {
12
+ return name;
13
+ }
14
+
15
+ // `agentKind` defaults to `'external'` per the plugin type contract; an unidentified external
16
+ // agent falls back to a generic label rather than rendering a nameless tag.
17
+ if (contributor.kind === 'agent' && ((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external') === 'external') {
18
+ return formatMessage(_messages.contributorTagMessages.externalAgentName);
19
+ }
20
+ return '';
21
+ };
22
+
23
+ /**
24
+ * Whether the label has to spell out that the contributor is an agent. A sighted user reads that off
25
+ * the `aria-hidden` avatar, so the label is the only other carrier.
26
+ *
27
+ * Excluded: a connected pair, which says it via `changedByConnected`, and an unnamed external agent,
28
+ * whose name `getContributorName` has already resolved to "External agent".
29
+ */
30
+ var isUnaccompaniedNamedAgent = function isUnaccompaniedNamedAgent(model) {
31
+ var _model$contributor$na;
32
+ return !model.connectedContributor && model.contributor.kind === 'agent' && Boolean((_model$contributor$na = model.contributor.name) === null || _model$contributor$na === void 0 ? void 0 : _model$contributor$na.trim());
33
+ };
34
+ /**
35
+ * The two strings a tag's model resolves to. Shared with `getActiveDiffAnnouncement`, so stepping
36
+ * onto a change says the same sentence as the tag pinned to it rather than a copy free to drift.
37
+ */
38
+ var formatContributorLabel = exports.formatContributorLabel = function formatContributorLabel(model, formatMessage) {
39
+ var isPrimaryAgent = model.contributor.kind === 'agent';
40
+ var primaryName = getContributorName(model.contributor, formatMessage);
41
+ var secondaryName = model.connectedContributor ? getContributorName(model.connectedContributor, formatMessage) : '';
42
+ var agentName = isPrimaryAgent ? primaryName : secondaryName;
43
+ var userName = isPrimaryAgent ? secondaryName : primaryName;
44
+ return {
45
+ fullLabel: model.connectedContributor ? formatMessage(_messages.contributorTagMessages.changedByConnected, {
46
+ agentName: agentName,
47
+ userName: userName
48
+ }) : formatMessage(isUnaccompaniedNamedAgent(model) ? _messages.contributorTagMessages.changedByAgent : _messages.contributorTagMessages.changedBy, {
49
+ name: primaryName
50
+ }),
51
+ // A connected pair only ever shows the agent; the pair is spelled out in `fullLabel`, because
52
+ // the tag is capped at `MAX_TAG_WIDTH` and two names rarely fit inside it.
53
+ visibleName: model.connectedContributor ? agentName || primaryName : primaryName
54
+ };
55
+ };