@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.
- package/CHANGELOG.md +20 -0
- package/afm-products/tsconfig.json +3 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +86 -50
- package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
- package/dist/cjs/pm-plugins/decorations/utils/getMarkChangeRanges.js +18 -4
- package/dist/cjs/pm-plugins/decorations/utils/mapStepRangeToFinal.js +34 -0
- package/dist/cjs/pm-plugins/main.js +18 -0
- package/dist/cjs/ui/ContributorTag/buildContributorTagDom.js +26 -4
- package/dist/cjs/ui/ContributorTag/contributorLabel.js +55 -0
- package/dist/cjs/ui/ContributorTag/contributorTagController.js +14 -39
- package/dist/cjs/ui/ContributorTag/messages.js +5 -0
- package/dist/cjs/ui/DiffNavigation/announceActiveDiff.js +54 -0
- package/dist/cjs/ui/DiffNavigation/messages.js +19 -0
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +43 -12
- package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +16 -0
- package/dist/es2019/pm-plugins/decorations/utils/getMarkChangeRanges.js +12 -4
- package/dist/es2019/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
- package/dist/es2019/pm-plugins/main.js +18 -0
- package/dist/es2019/ui/ContributorTag/buildContributorTagDom.js +24 -4
- package/dist/es2019/ui/ContributorTag/contributorLabel.js +49 -0
- package/dist/es2019/ui/ContributorTag/contributorTagController.js +14 -39
- package/dist/es2019/ui/ContributorTag/messages.js +5 -0
- package/dist/es2019/ui/DiffNavigation/announceActiveDiff.js +49 -0
- package/dist/es2019/ui/DiffNavigation/messages.js +13 -0
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +86 -50
- package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +19 -8
- package/dist/esm/pm-plugins/decorations/utils/getMarkChangeRanges.js +17 -4
- package/dist/esm/pm-plugins/decorations/utils/mapStepRangeToFinal.js +28 -0
- package/dist/esm/pm-plugins/main.js +18 -0
- package/dist/esm/ui/ContributorTag/buildContributorTagDom.js +26 -4
- package/dist/esm/ui/ContributorTag/contributorLabel.js +49 -0
- package/dist/esm/ui/ContributorTag/contributorTagController.js +14 -39
- package/dist/esm/ui/ContributorTag/messages.js +5 -0
- package/dist/esm/ui/DiffNavigation/announceActiveDiff.js +48 -0
- package/dist/esm/ui/DiffNavigation/messages.js +13 -0
- package/dist/types/pm-plugins/decorations/utils/getAttrChangeRanges.d.ts +3 -0
- package/dist/types/pm-plugins/decorations/utils/getMarkChangeRanges.d.ts +4 -1
- package/dist/types/pm-plugins/decorations/utils/mapStepRangeToFinal.d.ts +8 -0
- package/dist/types/showDiffPluginType.d.ts +7 -1
- package/dist/types/ui/ContributorTag/buildContributorTagDom.d.ts +5 -2
- package/dist/types/ui/ContributorTag/contributorLabel.d.ts +13 -0
- package/dist/types/ui/ContributorTag/messages.d.ts +1 -0
- package/dist/types/ui/DiffNavigation/announceActiveDiff.d.ts +18 -0
- package/dist/types/ui/DiffNavigation/messages.d.ts +5 -0
- package/package.json +3 -2
|
@@ -125,6 +125,19 @@ var srLabelStyle = convertToInlineCss({
|
|
|
125
125
|
userSelect: 'none',
|
|
126
126
|
whiteSpace: 'nowrap'
|
|
127
127
|
});
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Ids for the hidden label that the tag's `aria-labelledby` points at. Namespaced and random because
|
|
131
|
+
* the tag renders inside the document and shares the host page's id space — the same reason
|
|
132
|
+
* `VanillaTooltip` does it this way. The counter is a fallback for non-secure contexts, where
|
|
133
|
+
* `crypto.randomUUID` is unavailable.
|
|
134
|
+
*/
|
|
135
|
+
var generateLabelId = function () {
|
|
136
|
+
var count = 0;
|
|
137
|
+
return function () {
|
|
138
|
+
return typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function' ? "".concat(CONTRIBUTOR_TAG_CLASS, "-label-").concat(crypto.randomUUID()) : "".concat(CONTRIBUTOR_TAG_CLASS, "-label-").concat(count += 1);
|
|
139
|
+
};
|
|
140
|
+
}();
|
|
128
141
|
var createSpan = function createSpan(doc, style) {
|
|
129
142
|
var attributes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
130
143
|
var span = doc.createElement('span');
|
|
@@ -144,21 +157,30 @@ var createSpan = function createSpan(doc, style) {
|
|
|
144
157
|
* would need a cast per reference below.
|
|
145
158
|
*/
|
|
146
159
|
export var buildContributorTagDom = function buildContributorTagDom(doc) {
|
|
160
|
+
var labelId = generateLabelId();
|
|
147
161
|
var root = createSpan(doc, constraintStyle);
|
|
148
162
|
var tag = createSpan(doc, tagStyle, {
|
|
149
163
|
class: CONTRIBUTOR_TAG_CLASS,
|
|
150
164
|
'data-testid': CONTRIBUTOR_TAG_TESTID,
|
|
151
|
-
//
|
|
152
|
-
//
|
|
165
|
+
// Named by the hidden label rather than `aria-label`, which would be a second copy of the same
|
|
166
|
+
// sentence. `role="note"` takes its name from the author, not its contents, so without this
|
|
167
|
+
// the tag is a focus stop with no accessible name.
|
|
168
|
+
'aria-labelledby': labelId,
|
|
153
169
|
role: 'note',
|
|
154
|
-
// Focusable so keyboard and screen-reader users can reach the tag and its tooltip.
|
|
170
|
+
// Focusable so keyboard and screen-reader users can reach the tag and its tooltip. Its focus
|
|
171
|
+
// ring is drawn inward — see `contributorTagStyles` in editor-core.
|
|
155
172
|
tabindex: '0'
|
|
156
173
|
});
|
|
157
174
|
var avatars = createSpan(doc, avatarsStyle);
|
|
175
|
+
// `aria-hidden`: the hidden label restates this name in a full sentence, so leaving it in the
|
|
176
|
+
// tree announced the contributor twice ("Priya Changed by Priya").
|
|
158
177
|
var name = createSpan(doc, nameStyle, {
|
|
178
|
+
'aria-hidden': 'true',
|
|
159
179
|
'data-testid': CONTRIBUTOR_TAG_NAME_TESTID
|
|
160
180
|
});
|
|
161
|
-
var srLabel = createSpan(doc, srLabelStyle
|
|
181
|
+
var srLabel = createSpan(doc, srLabelStyle, {
|
|
182
|
+
id: labelId
|
|
183
|
+
});
|
|
162
184
|
tag.append(avatars, name, srLabel);
|
|
163
185
|
root.appendChild(tag);
|
|
164
186
|
return {
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { contributorTagMessages } from './messages';
|
|
2
|
+
var getContributorName = function getContributorName(contributor, formatMessage) {
|
|
3
|
+
var _contributor$name, _contributor$agentKin;
|
|
4
|
+
var name = (_contributor$name = contributor.name) === null || _contributor$name === void 0 ? void 0 : _contributor$name.trim();
|
|
5
|
+
if (name) {
|
|
6
|
+
return name;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// `agentKind` defaults to `'external'` per the plugin type contract; an unidentified external
|
|
10
|
+
// agent falls back to a generic label rather than rendering a nameless tag.
|
|
11
|
+
if (contributor.kind === 'agent' && ((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external') === 'external') {
|
|
12
|
+
return formatMessage(contributorTagMessages.externalAgentName);
|
|
13
|
+
}
|
|
14
|
+
return '';
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Whether the label has to spell out that the contributor is an agent. A sighted user reads that off
|
|
19
|
+
* the `aria-hidden` avatar, so the label is the only other carrier.
|
|
20
|
+
*
|
|
21
|
+
* Excluded: a connected pair, which says it via `changedByConnected`, and an unnamed external agent,
|
|
22
|
+
* whose name `getContributorName` has already resolved to "External agent".
|
|
23
|
+
*/
|
|
24
|
+
var isUnaccompaniedNamedAgent = function isUnaccompaniedNamedAgent(model) {
|
|
25
|
+
var _model$contributor$na;
|
|
26
|
+
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());
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The two strings a tag's model resolves to. Shared with `getActiveDiffAnnouncement`, so stepping
|
|
30
|
+
* onto a change says the same sentence as the tag pinned to it rather than a copy free to drift.
|
|
31
|
+
*/
|
|
32
|
+
export var formatContributorLabel = function formatContributorLabel(model, formatMessage) {
|
|
33
|
+
var isPrimaryAgent = model.contributor.kind === 'agent';
|
|
34
|
+
var primaryName = getContributorName(model.contributor, formatMessage);
|
|
35
|
+
var secondaryName = model.connectedContributor ? getContributorName(model.connectedContributor, formatMessage) : '';
|
|
36
|
+
var agentName = isPrimaryAgent ? primaryName : secondaryName;
|
|
37
|
+
var userName = isPrimaryAgent ? secondaryName : primaryName;
|
|
38
|
+
return {
|
|
39
|
+
fullLabel: model.connectedContributor ? formatMessage(contributorTagMessages.changedByConnected, {
|
|
40
|
+
agentName: agentName,
|
|
41
|
+
userName: userName
|
|
42
|
+
}) : formatMessage(isUnaccompaniedNamedAgent(model) ? contributorTagMessages.changedByAgent : contributorTagMessages.changedBy, {
|
|
43
|
+
name: primaryName
|
|
44
|
+
}),
|
|
45
|
+
// A connected pair only ever shows the agent; the pair is spelled out in `fullLabel`, because
|
|
46
|
+
// the tag is capped at `MAX_TAG_WIDTH` and two names rarely fit inside it.
|
|
47
|
+
visibleName: model.connectedContributor ? agentName || primaryName : primaryName
|
|
48
|
+
};
|
|
49
|
+
};
|
|
@@ -8,22 +8,7 @@ import { getAccentTokens } from '../../pm-plugins/decorations/colorSchemes/facto
|
|
|
8
8
|
import { colorSchemeRegistry } from '../../pm-plugins/decorations/colorSchemes/schemes';
|
|
9
9
|
import { buildContributorTagDom, CONTRIBUTOR_TAG_REVEALED_ATTRIBUTE, TAG_EXIT_FALLBACK_MS } from './buildContributorTagDom';
|
|
10
10
|
import { contributorAvatarRenderer } from './contributorAvatarRenderer';
|
|
11
|
-
import {
|
|
12
|
-
var getContributorName = function getContributorName(contributor, formatMessage) {
|
|
13
|
-
var _contributor$name, _contributor$agentKin;
|
|
14
|
-
var name = (_contributor$name = contributor.name) === null || _contributor$name === void 0 ? void 0 : _contributor$name.trim();
|
|
15
|
-
if (name) {
|
|
16
|
-
return name;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// `agentKind` defaults to `'external'` per the plugin type contract; an unidentified external
|
|
20
|
-
// agent falls back to a generic label rather than rendering a nameless tag.
|
|
21
|
-
if (contributor.kind === 'agent' && ((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : 'external') === 'external') {
|
|
22
|
-
return formatMessage(contributorTagMessages.externalAgentName);
|
|
23
|
-
}
|
|
24
|
-
return '';
|
|
25
|
-
};
|
|
26
|
-
|
|
11
|
+
import { formatContributorLabel } from './contributorLabel';
|
|
27
12
|
/**
|
|
28
13
|
* Resolves the tag's accent from the same scheme value the highlight was drawn from, so the colour
|
|
29
14
|
* the two carry can never drift — only the tone does, which is `getAccentTokens`'s to pick.
|
|
@@ -106,8 +91,8 @@ var fadeTagOut = function fadeTagOut(tag, release) {
|
|
|
106
91
|
/** The contributors a tag draws, keyed so a republished model can be recognised as the same pair. */
|
|
107
92
|
var identityOf = function identityOf(model) {
|
|
108
93
|
return [model === null || model === void 0 ? void 0 : model.contributor, model === null || model === void 0 ? void 0 : model.connectedContributor].map(function (contributor) {
|
|
109
|
-
var _contributor$
|
|
110
|
-
return contributor ? "".concat(contributor.kind, ":").concat((_contributor$
|
|
94
|
+
var _contributor$agentKin, _contributor$avatarUr;
|
|
95
|
+
return contributor ? "".concat(contributor.kind, ":").concat((_contributor$agentKin = contributor.agentKind) !== null && _contributor$agentKin !== void 0 ? _contributor$agentKin : '', ":").concat(contributor.name, ":").concat((_contributor$avatarUr = contributor.avatarUrl) !== null && _contributor$avatarUr !== void 0 ? _contributor$avatarUr : '') : '';
|
|
111
96
|
}).join('|');
|
|
112
97
|
};
|
|
113
98
|
|
|
@@ -348,24 +333,12 @@ export var ContributorTagController = /*#__PURE__*/function () {
|
|
|
348
333
|
if (!this.dom) {
|
|
349
334
|
return;
|
|
350
335
|
}
|
|
351
|
-
var
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
var userName = isPrimaryAgent ? secondaryName : primaryName;
|
|
358
|
-
|
|
359
|
-
// A connected pair only ever shows the agent; the pair is spelled out in the label, because the
|
|
360
|
-
// tag is capped at `MAX_TAG_WIDTH` and two names rarely fit inside it.
|
|
361
|
-
this.dom.name.textContent = model.connectedContributor ? agentName || primaryName : primaryName;
|
|
362
|
-
this.fullLabel = model.connectedContributor ? formatMessage(contributorTagMessages.changedByConnected, {
|
|
363
|
-
agentName: agentName,
|
|
364
|
-
userName: userName
|
|
365
|
-
}) : formatMessage(contributorTagMessages.changedBy, {
|
|
366
|
-
name: primaryName
|
|
367
|
-
});
|
|
368
|
-
this.dom.srLabel.textContent = this.fullLabel;
|
|
336
|
+
var _formatContributorLab = formatContributorLabel(model, this.options.getIntl().formatMessage),
|
|
337
|
+
fullLabel = _formatContributorLab.fullLabel,
|
|
338
|
+
visibleName = _formatContributorLab.visibleName;
|
|
339
|
+
this.dom.name.textContent = visibleName;
|
|
340
|
+
this.fullLabel = fullLabel;
|
|
341
|
+
this.dom.srLabel.textContent = fullLabel;
|
|
369
342
|
}
|
|
370
343
|
}, {
|
|
371
344
|
key: "accentOf",
|
|
@@ -420,7 +393,7 @@ export var ContributorTagController = /*#__PURE__*/function () {
|
|
|
420
393
|
}, {
|
|
421
394
|
key: "syncTooltip",
|
|
422
395
|
value: function syncTooltip() {
|
|
423
|
-
var _this$tooltip2;
|
|
396
|
+
var _this$tooltip2, _this$dom$tag$querySe;
|
|
424
397
|
var content = this.dom ? this.fullLabel : undefined;
|
|
425
398
|
if (content === this.tooltipContent) {
|
|
426
399
|
return;
|
|
@@ -437,9 +410,11 @@ export var ContributorTagController = /*#__PURE__*/function () {
|
|
|
437
410
|
// renaming. Those styles are scoped under `.ProseMirror`, and the tag renders inside it.
|
|
438
411
|
'ak-editor-vanilla-tooltip-default');
|
|
439
412
|
// `VanillaTooltip` sets `aria-describedby` on its trigger, which would announce the label a
|
|
440
|
-
// second time — the
|
|
441
|
-
// requires.
|
|
413
|
+
// second time — the hidden child already announces it, and names the tag with it.
|
|
442
414
|
this.dom.tag.removeAttribute('aria-describedby');
|
|
415
|
+
// The popover is a child of the trigger, so its text would be a third copy of the same
|
|
416
|
+
// sentence. It stays visible for sighted users, who need the part of the name the tag clipped.
|
|
417
|
+
(_this$dom$tag$querySe = this.dom.tag.querySelector(':scope > [role="tooltip"]')) === null || _this$dom$tag$querySe === void 0 || _this$dom$tag$querySe.setAttribute('aria-hidden', 'true');
|
|
443
418
|
}
|
|
444
419
|
|
|
445
420
|
/**
|
|
@@ -5,6 +5,11 @@ export var 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,48 @@
|
|
|
1
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
3
|
+
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
|
+
import { isDiffDecoration } from '../../pm-plugins/decorations/decorationKeys';
|
|
5
|
+
import { formatContributorLabel } from '../ContributorTag/contributorLabel';
|
|
6
|
+
import { diffNavigationMessages } from './messages';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The tag that captions the given decoration, if any. `linkedDiffIds` is checked as well as
|
|
10
|
+
* `diffId`, because a replacement's two decorations share one tag and navigation can land on either.
|
|
11
|
+
*/
|
|
12
|
+
var findTagFor = function findTagFor(decoration, contributorTags) {
|
|
13
|
+
if (!(contributorTags !== null && contributorTags !== void 0 && contributorTags.length) || !isDiffDecoration(decoration)) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
var diffId = decoration.spec.diffId;
|
|
17
|
+
return contributorTags.find(function (tag) {
|
|
18
|
+
var _tag$linkedDiffIds;
|
|
19
|
+
return tag.diffId === diffId || ((_tag$linkedDiffIds = tag.linkedDiffIds) === null || _tag$linkedDiffIds === void 0 ? void 0 : _tag$linkedDiffIds.includes(diffId));
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* What a screen reader should say once the reader has stepped onto a change: where they are in the
|
|
25
|
+
* diff, and — when the plugin can credit the change — who made it. Stepping otherwise only scrolls,
|
|
26
|
+
* which is silent.
|
|
27
|
+
*
|
|
28
|
+
* Returns `undefined` for an index that resolves no change, so the caller says nothing at all
|
|
29
|
+
* rather than "Change 4 of 3".
|
|
30
|
+
*/
|
|
31
|
+
export var getActiveDiffAnnouncement = function getActiveDiffAnnouncement(_ref) {
|
|
32
|
+
var activeIndex = _ref.activeIndex,
|
|
33
|
+
contributorTags = _ref.contributorTags,
|
|
34
|
+
decorations = _ref.decorations,
|
|
35
|
+
intl = _ref.intl;
|
|
36
|
+
var activeDecoration = decorations[activeIndex];
|
|
37
|
+
if (!activeDecoration) {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
var position = {
|
|
41
|
+
index: activeIndex + 1,
|
|
42
|
+
total: decorations.length
|
|
43
|
+
};
|
|
44
|
+
var tag = findTagFor(activeDecoration, contributorTags);
|
|
45
|
+
return tag ? intl.formatMessage(diffNavigationMessages.activeChangeWithContributor, _objectSpread(_objectSpread({}, position), {}, {
|
|
46
|
+
contributor: formatContributorLabel(tag, intl.formatMessage).fullLabel
|
|
47
|
+
})) : intl.formatMessage(diffNavigationMessages.activeChange, position);
|
|
48
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { defineMessages } from 'react-intl';
|
|
2
|
+
export var 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
|
+
});
|
|
@@ -5,6 +5,7 @@ import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
|
5
5
|
export type InlineAttrChangeNodeName = 'date' | 'emoji' | 'mention' | 'status';
|
|
6
6
|
type AttrChangeStep = AttrStep | SetAttrsStep;
|
|
7
7
|
export type AttrStepContext = {
|
|
8
|
+
attributionKey?: string;
|
|
8
9
|
afterNode: PMNode | null;
|
|
9
10
|
beforeNode: PMNode | null;
|
|
10
11
|
finalPos: number;
|
|
@@ -12,6 +13,8 @@ export type AttrStepContext = {
|
|
|
12
13
|
step: AttrChangeStep;
|
|
13
14
|
};
|
|
14
15
|
type StepRange = {
|
|
16
|
+
/** Attribution key for the step that produced this range. */
|
|
17
|
+
attributionKey?: string;
|
|
15
18
|
/**
|
|
16
19
|
* Position of the original (before) node in the original doc.
|
|
17
20
|
* Populated for inline attr changes (e.g. emoji, date) so the caller can
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform-override';
|
|
2
|
+
import { type StepMap } from '@atlaskit/editor-prosemirror/transform';
|
|
3
|
+
import type { DiffStepAttribution } from '../../../showDiffPluginType';
|
|
2
4
|
type StepRange = {
|
|
5
|
+
attributionKey?: string;
|
|
3
6
|
fromB: number;
|
|
4
7
|
toB: number;
|
|
5
8
|
};
|
|
6
|
-
export declare const getMarkChangeRanges: (steps: ProseMirrorStep[]) => StepRange[];
|
|
9
|
+
export declare const getMarkChangeRanges: (steps: ProseMirrorStep[], stepAttributions?: Array<DiffStepAttribution | undefined>, stepMaps?: StepMap[]) => StepRange[];
|
|
7
10
|
export {};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type StepMap } from '@atlaskit/editor-prosemirror/transform';
|
|
2
|
+
type StepRange = {
|
|
3
|
+
fromB: number;
|
|
4
|
+
toB: number;
|
|
5
|
+
};
|
|
6
|
+
/** Maps a step's range into final-document coordinates when the rollout path supplies step maps. */
|
|
7
|
+
export declare const mapStepRangeToFinal: (from: number, to: number, stepIndex: number, stepMaps?: StepMap[]) => StepRange | undefined;
|
|
8
|
+
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { StepJson } from '@atlaskit/editor-common/collab';
|
|
2
2
|
import type { NextEditorPlugin, EditorCommand, OptionalPlugin } from '@atlaskit/editor-common/types';
|
|
3
3
|
import type { JSONDocNode } from '@atlaskit/editor-json-transformer/types';
|
|
4
|
+
import type { AccessibilityUtilsPlugin } from '@atlaskit/editor-plugin-accessibility-utils';
|
|
4
5
|
import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
|
|
5
6
|
import type { UserIntentPlugin } from '@atlaskit/editor-plugin-user-intent';
|
|
6
7
|
import type { Node } from '@atlaskit/editor-prosemirror/model';
|
|
@@ -226,7 +227,12 @@ export type ShowDiffPlugin = NextEditorPlugin<'showDiff', {
|
|
|
226
227
|
scrollToPrevious: EditorCommand;
|
|
227
228
|
showDiff: (config: ShowDiffParams) => EditorCommand;
|
|
228
229
|
};
|
|
229
|
-
dependencies: [
|
|
230
|
+
dependencies: [
|
|
231
|
+
OptionalPlugin<AnalyticsPlugin>,
|
|
232
|
+
OptionalPlugin<UserIntentPlugin>,
|
|
233
|
+
/** Carries the live-region announcement made when stepping between changes. */
|
|
234
|
+
OptionalPlugin<AccessibilityUtilsPlugin>
|
|
235
|
+
];
|
|
230
236
|
pluginConfiguration: DiffParams | undefined;
|
|
231
237
|
sharedState: {
|
|
232
238
|
/**
|
|
@@ -39,8 +39,11 @@ export type ContributorTagDom = {
|
|
|
39
39
|
name: HTMLSpanElement;
|
|
40
40
|
root: HTMLSpanElement;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
42
|
+
* The tag's single announcement: it names the tag via `aria-labelledby` and is the only child
|
|
43
|
+
* left in the accessibility tree.
|
|
44
|
+
*
|
|
45
|
+
* `VanillaTooltip` appends its popover to the tag as well, so this is the last *content* child
|
|
46
|
+
* rather than the last node.
|
|
44
47
|
*/
|
|
45
48
|
srLabel: HTMLSpanElement;
|
|
46
49
|
tag: HTMLSpanElement;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { IntlShape } from 'react-intl';
|
|
2
|
+
import type { ContributorTagModel } from '../../showDiffPluginType';
|
|
3
|
+
export type ContributorLabel = {
|
|
4
|
+
/** One sentence crediting everyone the change is attributed to — the tag's announcement. */
|
|
5
|
+
fullLabel: string;
|
|
6
|
+
/** The name the tag paints, which `MAX_TAG_WIDTH` may ellipsise. */
|
|
7
|
+
visibleName: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* The two strings a tag's model resolves to. Shared with `getActiveDiffAnnouncement`, so stepping
|
|
11
|
+
* onto a change says the same sentence as the tag pinned to it rather than a copy free to drift.
|
|
12
|
+
*/
|
|
13
|
+
export declare const formatContributorLabel: (model: ContributorTagModel, formatMessage: IntlShape['formatMessage']) => ContributorLabel;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { IntlShape } from 'react-intl';
|
|
2
|
+
import type { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
3
|
+
import type { ContributorTagModel } from '../../showDiffPluginType';
|
|
4
|
+
/**
|
|
5
|
+
* What a screen reader should say once the reader has stepped onto a change: where they are in the
|
|
6
|
+
* diff, and — when the plugin can credit the change — who made it. Stepping otherwise only scrolls,
|
|
7
|
+
* which is silent.
|
|
8
|
+
*
|
|
9
|
+
* Returns `undefined` for an index that resolves no change, so the caller says nothing at all
|
|
10
|
+
* rather than "Change 4 of 3".
|
|
11
|
+
*/
|
|
12
|
+
export declare const getActiveDiffAnnouncement: ({ activeIndex, contributorTags, decorations, intl, }: {
|
|
13
|
+
activeIndex: number;
|
|
14
|
+
contributorTags: ContributorTagModel[] | undefined;
|
|
15
|
+
/** The navigable changes, in document order — `getScrollableDecorations`'s result. */
|
|
16
|
+
decorations: Decoration[];
|
|
17
|
+
intl: IntlShape;
|
|
18
|
+
}) => string | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.2",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"@atlaskit/adf-schema": "^57.4.0",
|
|
24
24
|
"@atlaskit/avatar": "^28.0.0",
|
|
25
25
|
"@atlaskit/custom-steps": "^1.1.0",
|
|
26
|
+
"@atlaskit/editor-plugin-accessibility-utils": "^18.0.0",
|
|
26
27
|
"@atlaskit/editor-plugin-analytics": "^18.0.0",
|
|
27
28
|
"@atlaskit/editor-plugin-user-intent": "^16.0.0",
|
|
28
29
|
"@atlaskit/editor-prosemirror": "^8.0.0",
|
|
@@ -31,7 +32,7 @@
|
|
|
31
32
|
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
32
33
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
33
34
|
"@atlaskit/primitives": "^22.5.0",
|
|
34
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
35
|
+
"@atlaskit/tmp-editor-statsig": "^189.0.0",
|
|
35
36
|
"@atlaskit/tokens": "^16.12.0",
|
|
36
37
|
"@babel/runtime": "^7.0.0",
|
|
37
38
|
"@compiled/react": "^1.0.2",
|