@atlaskit/editor-plugin-show-diff 16.0.0 → 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 (48) hide show
  1. package/CHANGELOG.md +29 -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/colorSchemes/attributions.js +1 -1
  5. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
  6. package/dist/cjs/pm-plugins/decorations/utils/getMarkChangeRanges.js +18 -4
  7. package/dist/cjs/pm-plugins/decorations/utils/mapStepRangeToFinal.js +34 -0
  8. package/dist/cjs/pm-plugins/main.js +18 -0
  9. package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +26 -4
  10. package/dist/cjs/ui/ContributorTag/contributorLabel.js +55 -0
  11. package/dist/cjs/ui/ContributorTag/contributorTagController.js +14 -39
  12. package/dist/cjs/ui/ContributorTag/messages.js +5 -0
  13. package/dist/cjs/ui/DiffNavigation/announceActiveDiff.js +54 -0
  14. package/dist/cjs/ui/DiffNavigation/messages.js +19 -0
  15. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +43 -12
  16. package/dist/es2019/pm-plugins/decorations/colorSchemes/attributions.js +1 -1
  17. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +16 -0
  18. package/dist/es2019/pm-plugins/decorations/utils/getMarkChangeRanges.js +12 -4
  19. package/dist/es2019/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
  20. package/dist/es2019/pm-plugins/main.js +18 -0
  21. package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +24 -4
  22. package/dist/es2019/ui/ContributorTag/contributorLabel.js +49 -0
  23. package/dist/es2019/ui/ContributorTag/contributorTagController.js +14 -39
  24. package/dist/es2019/ui/ContributorTag/messages.js +5 -0
  25. package/dist/es2019/ui/DiffNavigation/announceActiveDiff.js +49 -0
  26. package/dist/es2019/ui/DiffNavigation/messages.js +13 -0
  27. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +86 -50
  28. package/dist/esm/pm-plugins/decorations/colorSchemes/attributions.js +1 -1
  29. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
  30. package/dist/esm/pm-plugins/decorations/utils/getMarkChangeRanges.js +17 -4
  31. package/dist/esm/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
  32. package/dist/esm/pm-plugins/main.js +18 -0
  33. package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +26 -4
  34. package/dist/esm/ui/ContributorTag/contributorLabel.js +49 -0
  35. package/dist/esm/ui/ContributorTag/contributorTagController.js +14 -39
  36. package/dist/esm/ui/ContributorTag/messages.js +5 -0
  37. package/dist/esm/ui/DiffNavigation/announceActiveDiff.js +48 -0
  38. package/dist/esm/ui/DiffNavigation/messages.js +13 -0
  39. package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +3 -0
  40. package/dist/types/pm-plugins/decorations/utils/getMarkChangeRanges.d.ts +4 -1
  41. package/dist/types/pm-plugins/decorations/utils/mapStepRangeToFinal.d.ts +8 -0
  42. package/dist/types/showDiffPluginType.d.ts +7 -1
  43. package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +5 -2
  44. package/dist/types/ui/ContributorTag/contributorLabel.d.ts +13 -0
  45. package/dist/types/ui/ContributorTag/messages.d.ts +1 -0
  46. package/dist/types/ui/DiffNavigation/announceActiveDiff.d.ts +18 -0
  47. package/dist/types/ui/DiffNavigation/messages.d.ts +5 -0
  48. package/package.json +5 -4
@@ -5,22 +5,7 @@ import { getAccentTokens } from '../../pm-plugins/decorations/colorSchemes/facto
5
5
  import { colorSchemeRegistry } from '../../pm-plugins/decorations/colorSchemes/schemes';
6
6
  import { buildContributorTagDom, CONTRIBUTOR_TAG_REVEALED_ATTRIBUTE, TAG_EXIT_FALLBACK_MS } from './buildContributorTagDom';
7
7
  import { contributorAvatarRenderer } from './contributorAvatarRenderer';
8
- import { contributorTagMessages } from './messages';
9
- const getContributorName = (contributor, formatMessage) => {
10
- var _contributor$name, _contributor$agentKin;
11
- const name = (_contributor$name = contributor.name) === null || _contributor$name === void 0 ? void 0 : _contributor$name.trim();
12
- if (name) {
13
- return name;
14
- }
15
-
16
- // `agentKind` defaults to `'external'` per the plugin type contract; an unidentified external
17
- // agent falls back to a generic label rather than rendering a nameless tag.
18
- if (contributor.kind === 'agent' && ((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external') === 'external') {
19
- return formatMessage(contributorTagMessages.externalAgentName);
20
- }
21
- return '';
22
- };
23
-
8
+ import { formatContributorLabel } from './contributorLabel';
24
9
  /**
25
10
  * Resolves the tag's accent from the same scheme value the highlight was drawn from, so the colour
26
11
  * the two carry can never drift — only the tone does, which is `getAccentTokens`'s to pick.
@@ -99,8 +84,8 @@ const fadeTagOut = (tag, release) => {
99
84
 
100
85
  /** The contributors a tag draws, keyed so a republished model can be recognised as the same pair. */
101
86
  const identityOf = model => [model === null || model === void 0 ? void 0 : model.contributor, model === null || model === void 0 ? void 0 : model.connectedContributor].map(contributor => {
102
- var _contributor$agentKin2, _contributor$avatarUr;
103
- return contributor ? `${contributor.kind}:${(_contributor$agentKin2 = contributor.agentKind) !== null && _contributor$agentKin2 !== void 0 ? _contributor$agentKin2 : ''}:${contributor.name}:${(_contributor$avatarUr = contributor.avatarUrl) !== null && _contributor$avatarUr !== void 0 ? _contributor$avatarUr : ''}` : '';
87
+ var _contributor$agentKin, _contributor$avatarUr;
88
+ return contributor ? `${contributor.kind}:${(_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : ''}:${contributor.name}:${(_contributor$avatarUr = contributor.avatarUrl) !== null && _contributor$avatarUr !== void 0 ? _contributor$avatarUr : ''}` : '';
104
89
  }).join('|');
105
90
 
106
91
  /**
@@ -322,24 +307,12 @@ export class ContributorTagController {
322
307
  return;
323
308
  }
324
309
  const {
325
- formatMessage
326
- } = this.options.getIntl();
327
- const isPrimaryAgent = model.contributor.kind === 'agent';
328
- const primaryName = getContributorName(model.contributor, formatMessage);
329
- const secondaryName = model.connectedContributor ? getContributorName(model.connectedContributor, formatMessage) : '';
330
- const agentName = isPrimaryAgent ? primaryName : secondaryName;
331
- const userName = isPrimaryAgent ? secondaryName : primaryName;
332
-
333
- // A connected pair only ever shows the agent; the pair is spelled out in the label, because the
334
- // tag is capped at `MAX_TAG_WIDTH` and two names rarely fit inside it.
335
- this.dom.name.textContent = model.connectedContributor ? agentName || primaryName : primaryName;
336
- this.fullLabel = model.connectedContributor ? formatMessage(contributorTagMessages.changedByConnected, {
337
- agentName,
338
- userName
339
- }) : formatMessage(contributorTagMessages.changedBy, {
340
- name: primaryName
341
- });
342
- this.dom.srLabel.textContent = this.fullLabel;
310
+ fullLabel,
311
+ visibleName
312
+ } = formatContributorLabel(model, this.options.getIntl().formatMessage);
313
+ this.dom.name.textContent = visibleName;
314
+ this.fullLabel = fullLabel;
315
+ this.dom.srLabel.textContent = fullLabel;
343
316
  }
344
317
  accentOf(model) {
345
318
  var _model$isInserted;
@@ -384,7 +357,7 @@ export class ContributorTagController {
384
357
  * shape of `syncVanillaDisabledTooltip` in `mentionNodeView`.
385
358
  */
386
359
  syncTooltip() {
387
- var _this$tooltip2;
360
+ var _this$tooltip2, _this$dom$tag$querySe;
388
361
  const content = this.dom ? this.fullLabel : undefined;
389
362
  if (content === this.tooltipContent) {
390
363
  return;
@@ -401,9 +374,11 @@ export class ContributorTagController {
401
374
  // renaming. Those styles are scoped under `.ProseMirror`, and the tag renders inside it.
402
375
  'ak-editor-vanilla-tooltip-default');
403
376
  // `VanillaTooltip` sets `aria-describedby` on its trigger, which would announce the label a
404
- // second time — the visually hidden child already announces it, after the change as design
405
- // requires.
377
+ // second time — the hidden child already announces it, and names the tag with it.
406
378
  this.dom.tag.removeAttribute('aria-describedby');
379
+ // The popover is a child of the trigger, so its text would be a third copy of the same
380
+ // sentence. It stays visible for sighted users, who need the part of the name the tag clipped.
381
+ (_this$dom$tag$querySe = this.dom.tag.querySelector(':scope > [role="tooltip"]')) === null || _this$dom$tag$querySe === void 0 ? void 0 : _this$dom$tag$querySe.setAttribute('aria-hidden', 'true');
407
382
  }
408
383
 
409
384
  /**
@@ -5,6 +5,11 @@ export const contributorTagMessages = defineMessages({
5
5
  defaultMessage: 'Changed by {name}',
6
6
  description: 'Screen-reader label and tooltip for the tag pinned to a highlighted change in the version-history diff, naming the single person or agent that made the change. The name placeholder is the contributor display name.'
7
7
  },
8
+ changedByAgent: {
9
+ id: 'editor-plugin-show-diff.ContributorTag.changedByAgent',
10
+ defaultMessage: 'Changed by {name}, an AI agent',
11
+ description: 'Screen-reader label and tooltip for the tag pinned to a highlighted change in the version-history diff, when a named AI agent made the change rather than a person. The name placeholder is the agent display name.'
12
+ },
8
13
  changedByConnected: {
9
14
  id: 'editor-plugin-show-diff.ContributorTag.changedByConnected',
10
15
  defaultMessage: 'Changed by {agentName} with {userName}',
@@ -0,0 +1,49 @@
1
+ import { isDiffDecoration } from '../../pm-plugins/decorations/decorationKeys';
2
+ import { formatContributorLabel } from '../ContributorTag/contributorLabel';
3
+ import { diffNavigationMessages } from './messages';
4
+
5
+ /**
6
+ * The tag that captions the given decoration, if any. `linkedDiffIds` is checked as well as
7
+ * `diffId`, because a replacement's two decorations share one tag and navigation can land on either.
8
+ */
9
+ const findTagFor = (decoration, contributorTags) => {
10
+ if (!(contributorTags !== null && contributorTags !== void 0 && contributorTags.length) || !isDiffDecoration(decoration)) {
11
+ return undefined;
12
+ }
13
+ const {
14
+ diffId
15
+ } = decoration.spec;
16
+ return contributorTags.find(tag => {
17
+ var _tag$linkedDiffIds;
18
+ return tag.diffId === diffId || ((_tag$linkedDiffIds = tag.linkedDiffIds) === null || _tag$linkedDiffIds === void 0 ? void 0 : _tag$linkedDiffIds.includes(diffId));
19
+ });
20
+ };
21
+
22
+ /**
23
+ * What a screen reader should say once the reader has stepped onto a change: where they are in the
24
+ * diff, and — when the plugin can credit the change — who made it. Stepping otherwise only scrolls,
25
+ * which is silent.
26
+ *
27
+ * Returns `undefined` for an index that resolves no change, so the caller says nothing at all
28
+ * rather than "Change 4 of 3".
29
+ */
30
+ export const getActiveDiffAnnouncement = ({
31
+ activeIndex,
32
+ contributorTags,
33
+ decorations,
34
+ intl
35
+ }) => {
36
+ const activeDecoration = decorations[activeIndex];
37
+ if (!activeDecoration) {
38
+ return undefined;
39
+ }
40
+ const position = {
41
+ index: activeIndex + 1,
42
+ total: decorations.length
43
+ };
44
+ const tag = findTagFor(activeDecoration, contributorTags);
45
+ return tag ? intl.formatMessage(diffNavigationMessages.activeChangeWithContributor, {
46
+ ...position,
47
+ contributor: formatContributorLabel(tag, intl.formatMessage).fullLabel
48
+ }) : intl.formatMessage(diffNavigationMessages.activeChange, position);
49
+ };
@@ -0,0 +1,13 @@
1
+ import { defineMessages } from 'react-intl';
2
+ export const diffNavigationMessages = defineMessages({
3
+ activeChange: {
4
+ id: 'editor-plugin-show-diff.DiffNavigation.activeChange',
5
+ defaultMessage: 'Change {index} of {total}',
6
+ description: 'Announced to screen readers when the reader steps to the next or previous change in the version-history diff. The index placeholder is the position of the change stepped to, counting from 1; total is how many changes the diff has.'
7
+ },
8
+ activeChangeWithContributor: {
9
+ id: 'editor-plugin-show-diff.DiffNavigation.activeChangeWithContributor',
10
+ defaultMessage: 'Change {index} of {total}. {contributor}',
11
+ description: 'Announced to screen readers when the reader steps to the next or previous change in the version-history diff and that change is credited to someone. The index and total placeholders are as in activeChange. The contributor placeholder is an already-translated sentence (changedBy, changedByAgent or changedByConnected), so it must be kept whole and only repositioned.'
12
+ }
13
+ });
@@ -337,15 +337,18 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
337
337
  }
338
338
  var pendingAttrSteps = [];
339
339
  var stepMaps = [];
340
- var _iterator = _createForOfIteratorHelper(simplifiedSteps),
340
+ var _iterator = _createForOfIteratorHelper(simplifiedSteps.entries()),
341
341
  _step;
342
342
  try {
343
343
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
344
- var step = _step.value;
344
+ var _step$value = _slicedToArray(_step.value, 2),
345
+ stepIndex = _step$value[0],
346
+ step = _step$value[1];
345
347
  var result = step.apply(steppedDoc);
346
348
  if (result.failed === null && result.doc) {
347
349
  if (stepIsValidAttrChange(step, steppedDoc, result.doc)) {
348
350
  pendingAttrSteps.push({
351
+ attributionKey: getAttributionKey(simplifiedStepAttributions[stepIndex]),
349
352
  afterNode: result.doc.nodeAt(step.pos),
350
353
  beforeNode: steppedDoc.nodeAt(step.pos),
351
354
  mapIndex: stepMaps.length,
@@ -365,6 +368,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
365
368
  }
366
369
  var attrStepContexts = fg('platform_editor_reduce_diff_attr_sensitivity') ? pendingAttrSteps.flatMap(function (_ref1) {
367
370
  var afterNode = _ref1.afterNode,
371
+ attributionKey = _ref1.attributionKey,
368
372
  beforeNode = _ref1.beforeNode,
369
373
  mapIndex = _ref1.mapIndex,
370
374
  step = _ref1.step;
@@ -374,6 +378,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
374
378
  }
375
379
  var originalPosition = new Mapping(stepMaps.slice(0, mapIndex)).invert().mapResult(step.pos);
376
380
  return [_objectSpread(_objectSpread({
381
+ attributionKey: attributionKey,
377
382
  afterNode: afterNode,
378
383
  beforeNode: beforeNode,
379
384
  finalPos: finalPosition.pos
@@ -383,8 +388,10 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
383
388
  step: step
384
389
  })];
385
390
  }) : pendingAttrSteps.map(function (_ref10) {
386
- var step = _ref10.step;
391
+ var attributionKey = _ref10.attributionKey,
392
+ step = _ref10.step;
387
393
  return {
394
+ attributionKey: attributionKey,
388
395
  afterNode: tr.doc.nodeAt(step.pos),
389
396
  beforeNode: originalDoc.nodeAt(step.pos),
390
397
  finalPos: step.pos,
@@ -649,34 +656,54 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
649
656
  // smart path. Only add the legacy step-range decoration when no equivalent changeset range was
650
657
  // produced; otherwise the same content receives two inline decorations (and two navigation
651
658
  // changes), usually one attribution colour and one default purple decoration.
652
- getMarkChangeRanges(steps).filter(function (_ref11) {
659
+ getMarkChangeRanges(simplifiedSteps, simplifiedStepAttributions, fg('confluence_ncs_step_diffing_version_history') ? stepMaps : undefined).filter(function (_ref11) {
653
660
  var fromB = _ref11.fromB,
654
661
  toB = _ref11.toB;
655
662
  return !fg('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
656
663
  return change.fromB === fromB && change.toB === toB;
657
664
  });
658
665
  }).forEach(function (change) {
666
+ var _attributionColors$ge, _attributionColors;
667
+ 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;
668
+ var attributionKey = showContributorTags ? change.attributionKey : undefined;
659
669
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
660
670
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
671
+ attributionKey: attributionKey,
661
672
  change: change,
662
- colorScheme: colorScheme,
673
+ colorScheme: changeColorScheme,
674
+ doc: tr.doc,
663
675
  diffType: diffType,
664
676
  isActive: isActive,
665
677
  isInserted: true,
666
- reveal: reveal
678
+ reveal: reveal,
679
+ showContributorTags: showContributorTags,
680
+ tagMountContext: tagMountContext
667
681
  })));
668
682
  });
669
- getAttrChangeRanges(tr.doc, attrStepContexts, originalDoc).forEach(function (change) {
683
+ getAttrChangeRanges(tr.doc, attrStepContexts, originalDoc).filter(function (_ref12) {
684
+ var fromB = _ref12.fromB,
685
+ toB = _ref12.toB;
686
+ return !fg('confluence_ncs_step_diffing_version_history') || !changes.some(function (change) {
687
+ return change.fromB === fromB && change.toB === toB;
688
+ });
689
+ }).forEach(function (change) {
690
+ var _attributionColors$ge2, _attributionColors2;
691
+ 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;
692
+ var attributionKey = showContributorTags ? change.attributionKey : undefined;
670
693
  if (change.isInline) {
671
694
  // Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
672
695
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
673
696
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
697
+ attributionKey: attributionKey,
674
698
  change: change,
675
- colorScheme: colorScheme,
699
+ colorScheme: changeColorScheme,
700
+ doc: tr.doc,
676
701
  isActive: isActive,
677
702
  isInserted: true,
678
703
  isAtomicInlineNode: true,
679
704
  inlineNodeName: change.inlineNodeName,
705
+ showContributorTags: showContributorTags,
706
+ tagMountContext: tagMountContext,
680
707
  // Suppress the border-bottom underline for atomic inline nodeviews —
681
708
  // it doesn't render on custom nodeview DOM elements and is unnecessary noise.
682
709
  hideAddedDiffsUnderline: true,
@@ -694,12 +721,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
694
721
  deleted: []
695
722
  },
696
723
  doc: originalDoc,
724
+ attributionKey: attributionKey,
697
725
  nodeViewSerializer: nodeViewSerializer,
698
- colorScheme: colorScheme,
726
+ colorScheme: changeColorScheme,
699
727
  newDoc: tr.doc,
700
728
  intl: intl,
701
729
  activeIndexPos: activeIndexPos,
702
- isInserted: false
730
+ isInserted: false,
731
+ showContributorTags: showContributorTags,
732
+ tagMountContext: tagMountContext
703
733
  })));
704
734
  }
705
735
  } else {
@@ -707,11 +737,14 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
707
737
  doc: tr.doc,
708
738
  from: change.fromB,
709
739
  to: change.toB,
710
- colorScheme: colorScheme,
740
+ attributionKey: attributionKey,
741
+ colorScheme: changeColorScheme,
711
742
  isInserted: true,
712
743
  activeIndexPos: activeIndexPos,
713
744
  intl: intl,
714
- showIndicators: showIndicators
745
+ showContributorTags: showContributorTags,
746
+ showIndicators: showIndicators,
747
+ tagMountContext: tagMountContext
715
748
  })));
716
749
  // If the original node position is known (e.g. a panel type change), also render
717
750
  // the old block node as a "deleted" widget so the reviewer sees the before/after.
@@ -728,7 +761,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
728
761
  },
729
762
  doc: originalDoc,
730
763
  nodeViewSerializer: nodeViewSerializer,
731
- colorScheme: colorScheme,
764
+ attributionKey: attributionKey,
765
+ colorScheme: changeColorScheme,
732
766
  newDoc: tr.doc,
733
767
  intl: intl,
734
768
  activeIndexPos: activeIndexPos,
@@ -738,7 +772,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
738
772
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
739
773
  placeBelow: placeBelow
740
774
  }), {}, {
741
- showIndicators: showIndicators
775
+ showIndicators: showIndicators,
776
+ showContributorTags: showContributorTags,
777
+ tagMountContext: tagMountContext
742
778
  }))));
743
779
  }
744
780
  }
@@ -753,49 +789,49 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
753
789
  export var calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
754
790
  // Cache results unless relevant inputs change. `tagMountContext` is deliberately absent: it is
755
791
  // built once per plugin instance, so it can never be the reason a diff needs recalculating.
756
- function (_ref12, _ref13) {
757
- var _ref17;
758
- var _ref14 = _slicedToArray(_ref12, 1),
759
- _ref14$ = _ref14[0],
760
- pluginState = _ref14$.pluginState,
761
- state = _ref14$.state,
762
- colorScheme = _ref14$.colorScheme,
763
- intl = _ref14$.intl,
764
- activeIndexPos = _ref14$.activeIndexPos,
765
- isInverted = _ref14$.isInverted,
766
- diffType = _ref14$.diffType,
767
- hideDeletedDiffs = _ref14$.hideDeletedDiffs,
768
- hideAddedDiffsUnderline = _ref14$.hideAddedDiffsUnderline,
769
- showIndicators = _ref14$.showIndicators,
770
- smartThresholds = _ref14$.smartThresholds,
771
- deletedDiffPlacement = _ref14$.deletedDiffPlacement,
772
- inlineDeletedDiffPlacement = _ref14$.inlineDeletedDiffPlacement,
773
- reveal = _ref14$.reveal;
792
+ function (_ref13, _ref14) {
793
+ var _ref18;
774
794
  var _ref15 = _slicedToArray(_ref13, 1),
775
795
  _ref15$ = _ref15[0],
776
- lastPluginState = _ref15$.pluginState,
777
- lastState = _ref15$.state,
778
- lastColorScheme = _ref15$.colorScheme,
779
- lastIntl = _ref15$.intl,
780
- lastActiveIndexPos = _ref15$.activeIndexPos,
781
- lastIsInverted = _ref15$.isInverted,
782
- lastDiffType = _ref15$.diffType,
783
- lastHideDeletedDiffs = _ref15$.hideDeletedDiffs,
784
- lastHideAddedDiffsUnderline = _ref15$.hideAddedDiffsUnderline,
785
- lastShowIndicators = _ref15$.showIndicators,
786
- lastSmartThresholds = _ref15$.smartThresholds,
787
- lastDeletedDiffPlacement = _ref15$.deletedDiffPlacement,
788
- lastInlineDeletedDiffPlacement = _ref15$.inlineDeletedDiffPlacement,
789
- lastReveal = _ref15$.reveal;
796
+ pluginState = _ref15$.pluginState,
797
+ state = _ref15$.state,
798
+ colorScheme = _ref15$.colorScheme,
799
+ intl = _ref15$.intl,
800
+ activeIndexPos = _ref15$.activeIndexPos,
801
+ isInverted = _ref15$.isInverted,
802
+ diffType = _ref15$.diffType,
803
+ hideDeletedDiffs = _ref15$.hideDeletedDiffs,
804
+ hideAddedDiffsUnderline = _ref15$.hideAddedDiffsUnderline,
805
+ showIndicators = _ref15$.showIndicators,
806
+ smartThresholds = _ref15$.smartThresholds,
807
+ deletedDiffPlacement = _ref15$.deletedDiffPlacement,
808
+ inlineDeletedDiffPlacement = _ref15$.inlineDeletedDiffPlacement,
809
+ reveal = _ref15$.reveal;
810
+ var _ref16 = _slicedToArray(_ref14, 1),
811
+ _ref16$ = _ref16[0],
812
+ lastPluginState = _ref16$.pluginState,
813
+ lastState = _ref16$.state,
814
+ lastColorScheme = _ref16$.colorScheme,
815
+ lastIntl = _ref16$.intl,
816
+ lastActiveIndexPos = _ref16$.activeIndexPos,
817
+ lastIsInverted = _ref16$.isInverted,
818
+ lastDiffType = _ref16$.diffType,
819
+ lastHideDeletedDiffs = _ref16$.hideDeletedDiffs,
820
+ lastHideAddedDiffsUnderline = _ref16$.hideAddedDiffsUnderline,
821
+ lastShowIndicators = _ref16$.showIndicators,
822
+ lastSmartThresholds = _ref16$.smartThresholds,
823
+ lastDeletedDiffPlacement = _ref16$.deletedDiffPlacement,
824
+ lastInlineDeletedDiffPlacement = _ref16$.inlineDeletedDiffPlacement,
825
+ lastReveal = _ref16$.reveal;
790
826
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
791
827
  if (isExtendedEnabled(diffType)) {
792
- var _ref16;
793
- return (_ref16 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) &&
828
+ var _ref17;
829
+ return (_ref17 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && isEqual(pluginState.stepAttributions, lastPluginState.stepAttributions) &&
794
830
  // Contributors can arrive after the first calculation; without this, tags never appear.
795
831
  isEqual(pluginState.contributors, lastPluginState.contributors) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement &&
796
832
  // Turning the reveal on or off changes the emitted styles, so a cached result from the
797
833
  // other setting would leave the diff painted in the wrong resting state.
798
- isEqual(reveal, lastReveal)) !== null && _ref16 !== void 0 ? _ref16 : false;
834
+ isEqual(reveal, lastReveal)) !== null && _ref17 !== void 0 ? _ref17 : false;
799
835
  }
800
- return (_ref17 = 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 && _ref17 !== void 0 ? _ref17 : false;
836
+ return (_ref18 = 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 && _ref18 !== void 0 ? _ref18 : false;
801
837
  });
@@ -160,7 +160,7 @@ export var createAttributionColorMap = function createAttributionColorMap(stepAt
160
160
  if (!_identity || colors.has(_identity.key)) {
161
161
  continue;
162
162
  }
163
- var _getParticipantColor2 = getParticipantColor(_identity.colorSeed),
163
+ var _getParticipantColor2 = getParticipantColor(_identity.colorSeed, _attribution === null || _attribution === void 0 ? void 0 : _attribution.agentType),
164
164
  _index = _getParticipantColor2.index;
165
165
  var hashedColor = HASHED_PARTICIPANT_COLOR_SCHEMES[_index];
166
166
  if (!hashedColor) {
@@ -59,6 +59,7 @@ var getStepAttrs = function getStepAttrs(step) {
59
59
  export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepContexts, originalDoc) {
60
60
  return attrStepContexts.map(function (attrStepContext) {
61
61
  var afterNode = attrStepContext.afterNode,
62
+ attributionKey = attrStepContext.attributionKey,
62
63
  beforeNode = attrStepContext.beforeNode,
63
64
  finalPos = attrStepContext.finalPos,
64
65
  originalPos = attrStepContext.originalPos,
@@ -86,7 +87,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
86
87
  if (attrsToCheck.some(function (v) {
87
88
  return watchedAttrs.includes(v);
88
89
  })) {
89
- return _objectSpread({
90
+ return _objectSpread(_objectSpread({}, attributionKey ? {
91
+ attributionKey: attributionKey
92
+ } : {}), {}, {
90
93
  fromB: finalPos,
91
94
  toB: finalPos + nodeAtPos.nodeSize,
92
95
  isInline: true,
@@ -103,10 +106,12 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
103
106
  if (attrsToCheck.some(function (v) {
104
107
  return taskItemAttrs.includes(v);
105
108
  }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'taskItem') {
106
- return {
109
+ return _objectSpread(_objectSpread({}, attributionKey ? {
110
+ attributionKey: attributionKey
111
+ } : {}), {}, {
107
112
  fromB: finalPos,
108
113
  toB: finalPos + nodeAtPos.nodeSize
109
- };
114
+ });
110
115
  }
111
116
 
112
117
  // panel node (incl. variants like panel_c1): type/colour/icon attribute change
@@ -116,7 +121,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
116
121
  if (attrsToCheck.some(function (v) {
117
122
  return panelAttrs.includes(v);
118
123
  }) && nodeAtPos && getBaseNodeTypeName(nodeAtPos.type) === 'panel') {
119
- return _objectSpread({
124
+ return _objectSpread(_objectSpread({}, attributionKey ? {
125
+ attributionKey: attributionKey
126
+ } : {}), {}, {
120
127
  fromB: finalPos,
121
128
  toB: finalPos + nodeAtPos.nodeSize
122
129
  }, originalPos !== undefined && originalNodeAtPos && {
@@ -134,11 +141,13 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
134
141
  return undefined;
135
142
  }
136
143
  var isInline = nodeAtPos.type.name === 'inlineExtension';
137
- return {
144
+ return _objectSpread(_objectSpread({}, attributionKey ? {
145
+ attributionKey: attributionKey
146
+ } : {}), {}, {
138
147
  fromB: finalPos,
139
148
  toB: finalPos + nodeAtPos.nodeSize,
140
149
  isInline: isInline
141
- };
150
+ });
142
151
  }
143
152
 
144
153
  // media node: id/collection/url attribute change — highlight the mediaSingle parent
@@ -146,10 +155,12 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, attrStepConte
146
155
  return mediaAttrs.includes(v);
147
156
  }) && $pos.parent.type === doc.type.schema.nodes.mediaSingle) {
148
157
  var startPos = $pos.pos + $pos.parentOffset;
149
- return {
158
+ return _objectSpread(_objectSpread({}, attributionKey ? {
159
+ attributionKey: attributionKey
160
+ } : {}), {}, {
150
161
  fromB: startPos,
151
162
  toB: startPos + $pos.parent.nodeSize - 1
152
- };
163
+ });
153
164
  }
154
165
  return undefined;
155
166
  }).filter(filterUndefined)
@@ -1,7 +1,10 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
1
2
  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; } } }; }
2
3
  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; } }
3
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; }
4
5
  import { AddMarkStep, RemoveMarkStep } from '@atlaskit/editor-prosemirror/transform';
6
+ import { getAttributionKey } from '../colorSchemes/attributions';
7
+ import { mapStepRangeToFinal } from './mapStepRangeToFinal';
5
8
  var extractMarkStep = function extractMarkStep(step) {
6
9
  if (step instanceof AddMarkStep) {
7
10
  return {
@@ -22,13 +25,17 @@ var extractMarkStep = function extractMarkStep(step) {
22
25
  return undefined;
23
26
  };
24
27
  export var getMarkChangeRanges = function getMarkChangeRanges(steps) {
28
+ var stepAttributions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
29
+ var stepMaps = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
25
30
  var resultRanges = [];
26
31
  var lastOp;
27
- var _iterator = _createForOfIteratorHelper(steps),
32
+ var _iterator = _createForOfIteratorHelper(steps.entries()),
28
33
  _step;
29
34
  try {
30
35
  for (_iterator.s(); !(_step = _iterator.n()).done;) {
31
- var step = _step.value;
36
+ var _step$value = _slicedToArray(_step.value, 2),
37
+ stepIndex = _step$value[0],
38
+ step = _step$value[1];
32
39
  var op = extractMarkStep(step);
33
40
  if (!op) {
34
41
  continue;
@@ -38,9 +45,15 @@ export var getMarkChangeRanges = function getMarkChangeRanges(steps) {
38
45
  if (lastOp && lastOp.from === op.from && lastOp.to === op.to && lastOp.markName === op.markName && lastOp.type !== op.type) {
39
46
  resultRanges.pop();
40
47
  } else {
48
+ var finalRange = mapStepRangeToFinal(op.from, op.to, stepIndex, stepMaps);
49
+ if (!finalRange) {
50
+ lastOp = op;
51
+ continue;
52
+ }
41
53
  resultRanges.push({
42
- fromB: op.from,
43
- toB: op.to
54
+ attributionKey: getAttributionKey(stepAttributions[stepIndex]),
55
+ fromB: finalRange.fromB,
56
+ toB: finalRange.toB
44
57
  });
45
58
  }
46
59
  lastOp = op;
@@ -0,0 +1,28 @@
1
+ import { Mapping } from '@atlaskit/editor-prosemirror/transform';
2
+ // ProseMirror's assoc value chooses which side of an insertion a mapped boundary stays on.
3
+ var FROM_ASSOC = -1;
4
+ var TO_ASSOC = 1;
5
+
6
+ /** Maps a step's range into final-document coordinates when the rollout path supplies step maps. */
7
+ export var mapStepRangeToFinal = function mapStepRangeToFinal(from, to, stepIndex, stepMaps) {
8
+ if (!stepMaps) {
9
+ return {
10
+ fromB: from,
11
+ toB: to
12
+ };
13
+ }
14
+
15
+ // The range is already in the document immediately after this step, so skip its own map and
16
+ // apply only the maps from subsequent steps.
17
+ var firstSubsequentStepIndex = stepIndex + 1;
18
+ var finalRange = new Mapping(stepMaps.slice(firstSubsequentStepIndex));
19
+ var fromB = finalRange.mapResult(from, FROM_ASSOC);
20
+ var toB = finalRange.mapResult(to, TO_ASSOC);
21
+ if (fromB.deleted && toB.deleted) {
22
+ return undefined;
23
+ }
24
+ return {
25
+ fromB: fromB.pos,
26
+ toB: toB.pos
27
+ };
28
+ };
@@ -7,6 +7,7 @@ import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
7
7
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
8
8
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform-override';
9
9
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
10
+ import { getActiveDiffAnnouncement } from '../ui/DiffNavigation/announceActiveDiff';
10
11
  import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
11
12
  import { isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
12
13
  import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
@@ -272,6 +273,23 @@ export var createPlugin = function createPlugin(config, getIntl, api, onEditorVi
272
273
  api === null || api === void 0 || api.core.actions.execute(toggleExpandRange(activeDecoration.from, activeDecoration.to, true));
273
274
  }
274
275
  cancelPendingScrollToDecoration = scrollToDecoration(view, scrollableDecorations, pluginState.activeIndex);
276
+
277
+ // Stepping only scrolls — no focus moves and no content changes — so without this a
278
+ // screen-reader user gets silence. Announced through the live region rather than by
279
+ // focusing the change, since the "next change" control has to stay focused to be
280
+ // pressed again. After the scroll above, so the announcement never precedes it.
281
+ if (isExtendedEnabled(pluginState === null || pluginState === void 0 ? void 0 : pluginState.diffType)) {
282
+ var announcement = getActiveDiffAnnouncement({
283
+ activeIndex: pluginState.activeIndex,
284
+ contributorTags: pluginState.contributorTags,
285
+ decorations: scrollableDecorations,
286
+ intl: getIntl()
287
+ });
288
+ if (announcement) {
289
+ var _api$accessibilityUti;
290
+ api === null || api === void 0 || (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 || _api$accessibilityUti.actions.ariaNotify(announcement);
291
+ }
292
+ }
275
293
  }
276
294
  },
277
295
  destroy: function destroy() {