@atlaskit/editor-plugin-show-diff 12.0.3 → 12.1.1

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 (26) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +104 -77
  3. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +14 -3
  4. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -3
  5. package/dist/cjs/pm-plugins/getDeletedWidgets.js +48 -0
  6. package/dist/cjs/pm-plugins/main.js +3 -1
  7. package/dist/cjs/showDiffPlugin.js +13 -1
  8. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +41 -17
  9. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +13 -3
  10. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +4 -3
  11. package/dist/es2019/pm-plugins/getDeletedWidgets.js +40 -0
  12. package/dist/es2019/pm-plugins/main.js +3 -1
  13. package/dist/es2019/showDiffPlugin.js +86 -74
  14. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +103 -76
  15. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +14 -3
  16. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -3
  17. package/dist/esm/pm-plugins/getDeletedWidgets.js +43 -0
  18. package/dist/esm/pm-plugins/main.js +3 -1
  19. package/dist/esm/showDiffPlugin.js +13 -1
  20. package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
  21. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +17 -0
  22. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  23. package/dist/types/pm-plugins/getDeletedWidgets.d.ts +14 -0
  24. package/dist/types/pm-plugins/main.d.ts +2 -1
  25. package/dist/types/showDiffPluginType.d.ts +23 -0
  26. package/package.json +7 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 12.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`3a38a59a355f5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3a38a59a355f5) -
8
+ Add a feature-gated platform experiments strangler entry point and migrate the inline-diffs
9
+ experiment as its first consumer.
10
+
11
+ ```ts
12
+ import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
13
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
14
+
15
+ const isEnabled = isExperimentEnabled('platform_editor_example', () =>
16
+ expValEquals('platform_editor_example', 'isEnabled', true),
17
+ );
18
+ ```
19
+
20
+ - Updated dependencies
21
+
22
+ ## 12.1.0
23
+
24
+ ### Minor Changes
25
+
26
+ - [`0a96aa66ed44f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/0a96aa66ed44f) -
27
+ [ux] CCI-18372 Post Stream Review now renders deleted content below the added content at every
28
+ change level (gated behind `platform_editor_ai_smart_diff`), so reviewers read the new text first.
29
+
30
+ Deleted-content placement is split by change granularity, so consumers that want deleted content
31
+ after the new content everywhere must set both options (each defaults to rendering deleted content
32
+ first, and both require `diffType: 'smart'`):
33
+
34
+ ```ts
35
+ api?.showDiff?.commands?.showDiff({
36
+ originalDoc,
37
+ diffType: 'smart',
38
+ deletedDiffPlacement: 'bottom', // node/paragraph-level changes
39
+ inlineDeletedDiffPlacement: 'after', // inline/sentence-level changes
40
+ });
41
+ ```
42
+
43
+ `@atlaskit/editor-plugin-show-diff` also adds a `getDeletedWidgets` action (returning the
44
+ `DeletedDiffWidget` elements and positions), used by Post Stream Review to position the review
45
+ modal below relocated deleted content.
46
+
47
+ ### Patch Changes
48
+
49
+ - Updated dependencies
50
+
3
51
  ## 12.0.3
4
52
 
5
53
  ### Patch Changes
@@ -4,13 +4,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.calculateDiffDecorations = void 0;
7
+ exports.isDeletedContentPlacedBelow = exports.calculateDiffDecorations = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
10
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
11
11
  var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
12
12
  var _memoizeOne = _interopRequireDefault(require("memoize-one"));
13
13
  var _prosemirrorChangeset = require("prosemirror-changeset");
14
+ var _deprecatedPlatformFeatureExperiments = require("@atlaskit/editor-common/deprecated-platform-feature-experiments");
14
15
  var _document = require("@atlaskit/editor-common/utils/document");
15
16
  var _view = require("@atlaskit/editor-prosemirror/view");
16
17
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
@@ -131,29 +132,52 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
131
132
  });
132
133
  return decorations;
133
134
  };
134
- var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3) {
135
- var state = _ref3.state,
136
- pluginState = _ref3.pluginState,
137
- nodeViewSerializer = _ref3.nodeViewSerializer,
138
- colorScheme = _ref3.colorScheme,
139
- intl = _ref3.intl,
140
- activeIndexPos = _ref3.activeIndexPos,
141
- api = _ref3.api,
142
- _ref3$isInverted = _ref3.isInverted,
143
- isInverted = _ref3$isInverted === void 0 ? false : _ref3$isInverted,
144
- _ref3$diffType = _ref3.diffType,
145
- diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType,
146
- _ref3$hideDeletedDiff = _ref3.hideDeletedDiffs,
147
- hideDeletedDiffs = _ref3$hideDeletedDiff === void 0 ? false : _ref3$hideDeletedDiff,
148
- _ref3$hideAddedDiffsU = _ref3.hideAddedDiffsUnderline,
149
- hideAddedDiffsUnderlineParam = _ref3$hideAddedDiffsU === void 0 ? false : _ref3$hideAddedDiffsU,
150
- _ref3$showIndicators = _ref3.showIndicators,
151
- showIndicators = _ref3$showIndicators === void 0 ? false : _ref3$showIndicators,
152
- smartThresholds = _ref3.smartThresholds,
153
- _ref3$deletedDiffPlac = _ref3.deletedDiffPlacement,
154
- deletedDiffPlacement = _ref3$deletedDiffPlac === void 0 ? 'top' : _ref3$deletedDiffPlac,
155
- _ref3$inlineDeletedDi = _ref3.inlineDeletedDiffPlacement,
156
- inlineDeletedDiffPlacement = _ref3$inlineDeletedDi === void 0 ? 'before' : _ref3$inlineDeletedDi;
135
+ /**
136
+ * Whether deleted content for `change` renders after the new content instead of before it.
137
+ *
138
+ * show-diff splits this across two options by change granularity, so the level decides which one
139
+ * applies:
140
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
141
+ * node level, so they are governed here too.
142
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
143
+ *
144
+ * Callers are responsible for the `smart` diffType and gate checks.
145
+ */
146
+ var isDeletedContentPlacedBelow = exports.isDeletedContentPlacedBelow = function isDeletedContentPlacedBelow(_ref3) {
147
+ var change = _ref3.change,
148
+ deletedDiffPlacement = _ref3.deletedDiffPlacement,
149
+ inlineDeletedDiffPlacement = _ref3.inlineDeletedDiffPlacement;
150
+ var level = (0, _helpers.smartChangeLevel)(change);
151
+ if (level === 'node' || level === 'paragraph') {
152
+ return deletedDiffPlacement === 'bottom';
153
+ }
154
+
155
+ // Inline-level (undefined) and sentence-level changes.
156
+ return inlineDeletedDiffPlacement === 'after';
157
+ };
158
+ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref4) {
159
+ var state = _ref4.state,
160
+ pluginState = _ref4.pluginState,
161
+ nodeViewSerializer = _ref4.nodeViewSerializer,
162
+ colorScheme = _ref4.colorScheme,
163
+ intl = _ref4.intl,
164
+ activeIndexPos = _ref4.activeIndexPos,
165
+ api = _ref4.api,
166
+ _ref4$isInverted = _ref4.isInverted,
167
+ isInverted = _ref4$isInverted === void 0 ? false : _ref4$isInverted,
168
+ _ref4$diffType = _ref4.diffType,
169
+ diffType = _ref4$diffType === void 0 ? 'inline' : _ref4$diffType,
170
+ _ref4$hideDeletedDiff = _ref4.hideDeletedDiffs,
171
+ hideDeletedDiffs = _ref4$hideDeletedDiff === void 0 ? false : _ref4$hideDeletedDiff,
172
+ _ref4$hideAddedDiffsU = _ref4.hideAddedDiffsUnderline,
173
+ hideAddedDiffsUnderlineParam = _ref4$hideAddedDiffsU === void 0 ? false : _ref4$hideAddedDiffsU,
174
+ _ref4$showIndicators = _ref4.showIndicators,
175
+ showIndicators = _ref4$showIndicators === void 0 ? false : _ref4$showIndicators,
176
+ smartThresholds = _ref4.smartThresholds,
177
+ _ref4$deletedDiffPlac = _ref4.deletedDiffPlacement,
178
+ deletedDiffPlacement = _ref4$deletedDiffPlac === void 0 ? 'top' : _ref4$deletedDiffPlac,
179
+ _ref4$inlineDeletedDi = _ref4.inlineDeletedDiffPlacement,
180
+ inlineDeletedDiffPlacement = _ref4$inlineDeletedDi === void 0 ? 'before' : _ref4$inlineDeletedDi;
157
181
  var originalDoc = pluginState.originalDoc,
158
182
  steps = pluginState.steps,
159
183
  isDisplayingChanges = pluginState.isDisplayingChanges;
@@ -238,6 +262,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
238
262
  var isInserted = !isInverted;
239
263
  var createDecorationsForChange = function createDecorationsForChange(change, showGranularWithBlock) {
240
264
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
265
+
266
+ // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
267
+ // widget pins whichever end of the range it sits at — how the indicator anchors below are
268
+ // allowed to move.
269
+ var isDeletedWidgetBelow = diffType === 'smart' && (0, _platformFeatureFlags.fg)('platform_editor_ai_smart_diff') && isDeletedContentPlacedBelow({
270
+ change: change,
271
+ deletedDiffPlacement: deletedDiffPlacement,
272
+ inlineDeletedDiffPlacement: inlineDeletedDiffPlacement
273
+ });
241
274
  if (change.inserted.length > 0) {
242
275
  // shouldHideDeleted for block/node decorations: suppressed when isInverted + hideDeletedDiffs,
243
276
  // or when showGranularWithBlock (block reference widget is shown instead).
@@ -282,7 +315,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
282
315
  shouldHideDeleted: shouldHideDeleted,
283
316
  showIndicators: showIndicators,
284
317
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
285
- hasDeletedWidget: willRenderDeletedWidget
318
+ hasDeletedWidget: willRenderDeletedWidget,
319
+ isDeletedWidgetBelow: isDeletedWidgetBelow
286
320
  }))));
287
321
  }
288
322
  } catch (err) {
@@ -302,7 +336,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
302
336
  shouldHideDeleted: shouldHideDeleted,
303
337
  showIndicators: showIndicators,
304
338
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
305
- hasDeletedWidget: willRenderDeletedWidget
339
+ hasDeletedWidget: willRenderDeletedWidget,
340
+ isDeletedWidgetBelow: isDeletedWidgetBelow
306
341
  }))));
307
342
  }
308
343
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)(calculateNodesForBlockDecoration(_objectSpread(_objectSpread({
@@ -335,19 +370,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
335
370
  isInserted: !isInserted,
336
371
  diffType: diffType,
337
372
  hideAddedDiffsUnderline: hideAddedDiffsUnderline,
338
- // For `smart` changes, optionally render the deleted content after the new
339
- // content (gray + strikethrough) instead of before it. Two independent
340
- // controls, split by change level:
341
- // - node/paragraph-level: `deletedDiffPlacement` (default `'top'`).
342
- // - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
343
- placeBelow: diffType === 'smart' && (0, _platformFeatureFlags.fg)('platform_editor_ai_smart_diff') && function () {
344
- var level = (0, _helpers.smartChangeLevel)(change);
345
- if (level === 'node' || level === 'paragraph') {
346
- return deletedDiffPlacement === 'bottom';
347
- }
348
- // Inline-level (undefined) and sentence-level changes.
349
- return inlineDeletedDiffPlacement === 'after';
350
- }()
373
+ placeBelow: isDeletedWidgetBelow
351
374
  }), {}, {
352
375
  showIndicators: showIndicators
353
376
  }))));
@@ -361,9 +384,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
361
384
  // getChanges returns a flat Change[] with no per-step grouping, making this count impossible
362
385
  // to derive after the fact without re-introducing per-change metadata.
363
386
  var stepChanges = (0, _diffBySteps.getStepChanges)(originalDoc, steps);
364
- stepChanges.forEach(function (_ref4) {
365
- var isGranular = _ref4.isGranular,
366
- stepChangeList = _ref4.changes;
387
+ stepChanges.forEach(function (_ref5) {
388
+ var isGranular = _ref5.isGranular,
389
+ stepChangeList = _ref5.changes;
367
390
  var granularCount = isGranular ? stepChangeList.length : 0;
368
391
 
369
392
  // Calculate the average ratio of changed content on both A (original) and B (new)
@@ -449,7 +472,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
449
472
  if (change.isInline) {
450
473
  // Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
451
474
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
452
- var isAtomicInlineNodeFlag = (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
475
+ var isAtomicInlineNodeFlag = (0, _deprecatedPlatformFeatureExperiments.isExperimentEnabled)('platform_editor_improve_inline_diffs', function () {
476
+ return (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
477
+ });
453
478
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
454
479
  change: change,
455
480
  colorScheme: colorScheme,
@@ -464,7 +489,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
464
489
  })));
465
490
  // If we have the original node position, also render the old node as a "deleted" widget
466
491
  // so the user can see what it looked like before the change.
467
- if (change.fromA !== undefined && change.toA !== undefined && (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
492
+ if (change.fromA !== undefined && change.toA !== undefined && (0, _deprecatedPlatformFeatureExperiments.isExperimentEnabled)('platform_editor_improve_inline_diffs', function () {
493
+ return (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
494
+ })) {
468
495
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createNodeChangedDecorationWidget.createNodeChangedDecorationWidget)({
469
496
  change: {
470
497
  fromA: change.fromA,
@@ -503,42 +530,42 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
503
530
  };
504
531
  var calculateDiffDecorations = exports.calculateDiffDecorations = (0, _memoizeOne.default)(calculateDiffDecorationsInner,
505
532
  // Cache results unless relevant inputs change
506
- function (_ref5, _ref6) {
507
- var _ref0;
508
- var _ref7 = (0, _slicedToArray2.default)(_ref5, 1),
509
- _ref7$ = _ref7[0],
510
- pluginState = _ref7$.pluginState,
511
- state = _ref7$.state,
512
- colorScheme = _ref7$.colorScheme,
513
- intl = _ref7$.intl,
514
- activeIndexPos = _ref7$.activeIndexPos,
515
- isInverted = _ref7$.isInverted,
516
- diffType = _ref7$.diffType,
517
- hideDeletedDiffs = _ref7$.hideDeletedDiffs,
518
- hideAddedDiffsUnderline = _ref7$.hideAddedDiffsUnderline,
519
- showIndicators = _ref7$.showIndicators,
520
- smartThresholds = _ref7$.smartThresholds,
521
- deletedDiffPlacement = _ref7$.deletedDiffPlacement,
522
- inlineDeletedDiffPlacement = _ref7$.inlineDeletedDiffPlacement;
533
+ function (_ref6, _ref7) {
534
+ var _ref1;
523
535
  var _ref8 = (0, _slicedToArray2.default)(_ref6, 1),
524
536
  _ref8$ = _ref8[0],
525
- lastPluginState = _ref8$.pluginState,
526
- lastState = _ref8$.state,
527
- lastColorScheme = _ref8$.colorScheme,
528
- lastIntl = _ref8$.intl,
529
- lastActiveIndexPos = _ref8$.activeIndexPos,
530
- lastIsInverted = _ref8$.isInverted,
531
- lastDiffType = _ref8$.diffType,
532
- lastHideDeletedDiffs = _ref8$.hideDeletedDiffs,
533
- lastHideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
534
- lastShowIndicators = _ref8$.showIndicators,
535
- lastSmartThresholds = _ref8$.smartThresholds,
536
- lastDeletedDiffPlacement = _ref8$.deletedDiffPlacement,
537
- lastInlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
537
+ pluginState = _ref8$.pluginState,
538
+ state = _ref8$.state,
539
+ colorScheme = _ref8$.colorScheme,
540
+ intl = _ref8$.intl,
541
+ activeIndexPos = _ref8$.activeIndexPos,
542
+ isInverted = _ref8$.isInverted,
543
+ diffType = _ref8$.diffType,
544
+ hideDeletedDiffs = _ref8$.hideDeletedDiffs,
545
+ hideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
546
+ showIndicators = _ref8$.showIndicators,
547
+ smartThresholds = _ref8$.smartThresholds,
548
+ deletedDiffPlacement = _ref8$.deletedDiffPlacement,
549
+ inlineDeletedDiffPlacement = _ref8$.inlineDeletedDiffPlacement;
550
+ var _ref9 = (0, _slicedToArray2.default)(_ref7, 1),
551
+ _ref9$ = _ref9[0],
552
+ lastPluginState = _ref9$.pluginState,
553
+ lastState = _ref9$.state,
554
+ lastColorScheme = _ref9$.colorScheme,
555
+ lastIntl = _ref9$.intl,
556
+ lastActiveIndexPos = _ref9$.activeIndexPos,
557
+ lastIsInverted = _ref9$.isInverted,
558
+ lastDiffType = _ref9$.diffType,
559
+ lastHideDeletedDiffs = _ref9$.hideDeletedDiffs,
560
+ lastHideAddedDiffsUnderline = _ref9$.hideAddedDiffsUnderline,
561
+ lastShowIndicators = _ref9$.showIndicators,
562
+ lastSmartThresholds = _ref9$.smartThresholds,
563
+ lastDeletedDiffPlacement = _ref9$.deletedDiffPlacement,
564
+ lastInlineDeletedDiffPlacement = _ref9$.inlineDeletedDiffPlacement;
538
565
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
539
566
  if ((0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
540
- var _ref9;
541
- return (_ref9 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && (0, _isEqual.default)(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref9 !== void 0 ? _ref9 : false;
567
+ var _ref0;
568
+ return (_ref0 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && (0, _isEqual.default)(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement && inlineDeletedDiffPlacement === lastInlineDeletedDiffPlacement) !== null && _ref0 !== void 0 ? _ref0 : false;
542
569
  }
543
- return (_ref0 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref0 !== void 0 ? _ref0 : false;
570
+ return (_ref1 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref1 !== void 0 ? _ref1 : false;
544
571
  });
@@ -55,7 +55,9 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
55
55
  hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn,
56
56
  inlineNodeName = _ref.inlineNodeName,
57
57
  _ref$hasDeletedWidget = _ref.hasDeletedWidget,
58
- hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget;
58
+ hasDeletedWidget = _ref$hasDeletedWidget === void 0 ? false : _ref$hasDeletedWidget,
59
+ _ref$isDeletedWidgetB = _ref.isDeletedWidgetBelow,
60
+ isDeletedWidgetBelow = _ref$isDeletedWidgetB === void 0 ? false : _ref$isDeletedWidgetB;
59
61
  var diffId = crypto.randomUUID();
60
62
  if (shouldHideDeleted) {
61
63
  return [_view.Decoration.inline(change.fromB, change.toB, {
@@ -111,14 +113,23 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
111
113
  // bar doesn't extend into the preceding block's margin.
112
114
  // Skip when the deleted-content widget is rendered — the anchor must
113
115
  // stay at the boundary to keep the indicator continuous.
116
+ //
117
+ // The widget only pins the end of the range it is anchored to. It sits at `change.fromB`
118
+ // by default, but `deletedDiffPlacement: 'bottom'` / `inlineDeletedDiffPlacement: 'after'`
119
+ // move it to `change.toB` so the deleted content reads after the added content. In that
120
+ // case the `from` anchor has no widget beside it any more and must be adjusted inward
121
+ // again, otherwise the over-long indicator bar that CCI-18224 fixed comes back.
114
122
  var anchorFrom = change.fromB;
115
123
  var anchorTo = change.toB;
116
- if (!hasDeletedWidget) {
117
- var _$from$nodeAfter, _$to$nodeBefore;
124
+ if (!hasDeletedWidget || isDeletedWidgetBelow) {
125
+ var _$from$nodeAfter;
118
126
  var $from = doc.resolve(anchorFrom);
119
127
  if (!$from.parent.inlineContent && (_$from$nodeAfter = $from.nodeAfter) !== null && _$from$nodeAfter !== void 0 && _$from$nodeAfter.isTextblock) {
120
128
  anchorFrom = anchorFrom + 1;
121
129
  }
130
+ }
131
+ if (!hasDeletedWidget) {
132
+ var _$to$nodeBefore;
122
133
  var $to = doc.resolve(anchorTo);
123
134
  if (!$to.parent.inlineContent && (_$to$nodeBefore = $to.nodeBefore) !== null && _$to$nodeBefore !== void 0 && _$to$nodeBefore.isTextblock) {
124
135
  anchorTo = anchorTo - 1;
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
7
7
  exports.stepIsValidAttrChange = exports.getAttrChangeRanges = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _steps = require("@atlaskit/adf-schema/steps");
10
+ var _deprecatedPlatformFeatureExperiments = require("@atlaskit/editor-common/deprecated-platform-feature-experiments");
10
11
  var _transform = require("@atlaskit/editor-prosemirror/transform");
11
12
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
12
13
  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; }
@@ -70,7 +71,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
70
71
  // date node: timestamp attribute change — highlight the date node itself (inline)
71
72
  if (stepAttrs.some(function (v) {
72
73
  return dateAttrs.includes(v);
73
- }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !(0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
74
+ }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !(0, _deprecatedPlatformFeatureExperiments.isExperimentEnabled)('platform_editor_improve_inline_diffs', function () {
75
+ return (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
76
+ })) {
74
77
  return {
75
78
  fromB: step.pos,
76
79
  toB: step.pos + nodeAtPos.nodeSize,
@@ -82,7 +85,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
82
85
  // The following inline node attr changes are gated behind platform_editor_improve_inline_diffs.
83
86
  // The changeset path (createDecorationsForChange) handles the deletion widget via
84
87
  // prosemirror-changeset; we only need to add the inline insertion highlight here.
85
- if ((0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true) && nodeAtPos) {
88
+ if ((0, _deprecatedPlatformFeatureExperiments.isExperimentEnabled)('platform_editor_improve_inline_diffs', function () {
89
+ return (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
90
+ }) && nodeAtPos) {
86
91
  var nodeName = nodeAtPos.type.name;
87
92
  if (isInlineAttrChangeNodeName(nodeName)) {
88
93
  var watchedAttrs = inlineNodeAttrMap[nodeName];
@@ -143,7 +148,9 @@ var getAttrChangeRanges = exports.getAttrChangeRanges = function getAttrChangeRa
143
148
  // Gated behind the same experiment as the inline node attr changes that introduced
144
149
  // the possibility of multiple ranges for the same node position.
145
150
  .filter(function (range, i, arr) {
146
- return !(0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true) || arr.findIndex(function (r) {
151
+ return !(0, _deprecatedPlatformFeatureExperiments.isExperimentEnabled)('platform_editor_improve_inline_diffs', function () {
152
+ return (0, _expValEquals.expValEquals)('platform_editor_improve_inline_diffs', 'isEnabled', true);
153
+ }) || arr.findIndex(function (r) {
147
154
  return r.fromB === range.fromB;
148
155
  }) === i;
149
156
  });
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getDeletedWidgets = void 0;
7
+ var _decorationKeys = require("./decorations/decorationKeys");
8
+ var _main = require("./main");
9
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
10
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
11
+
12
+ // The element a deleted-content widget renders, or undefined if it renders via a factory.
13
+ var getWidgetElement = function getWidgetElement(decoration) {
14
+ var _type;
15
+ var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
16
+ toDOM = _ref.toDOM;
17
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
18
+ };
19
+
20
+ /**
21
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
22
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
23
+ * nodes, so this is how the element and the position it is anchored at are recovered.
24
+ *
25
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
26
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
27
+ */
28
+ var getDeletedWidgets = exports.getDeletedWidgets = function getDeletedWidgets(editorState, range) {
29
+ var _showDiffPluginKey$ge;
30
+ var decorations = (_showDiffPluginKey$ge = _main.showDiffPluginKey.getState(editorState)) === null || _showDiffPluginKey$ge === void 0 ? void 0 : _showDiffPluginKey$ge.decorations;
31
+ if (!decorations) {
32
+ return [];
33
+ }
34
+ return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, function (spec) {
35
+ return (0, _decorationKeys.isDiffDecorationSpec)(spec) && spec.decorationType === 'widget';
36
+ }).reduce(function (widgets, decoration) {
37
+ var element = getWidgetElement(decoration);
38
+ if (element) {
39
+ widgets.push({
40
+ element: element,
41
+ position: decoration.from
42
+ });
43
+ }
44
+ return widgets;
45
+ }, []).sort(function (a, b) {
46
+ return a.position - b.position;
47
+ });
48
+ };
@@ -21,7 +21,7 @@ var _scrollToDiff = require("./scrollToDiff");
21
21
  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; }
22
22
  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) { (0, _defineProperty2.default)(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; }
23
23
  var showDiffPluginKey = exports.showDiffPluginKey = new _state2.PluginKey('showDiffPlugin');
24
- var createPlugin = exports.createPlugin = function createPlugin(config, getIntl, api) {
24
+ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl, api, onEditorView) {
25
25
  (0, _enforceCustomStepRegisters.enforceCustomStepRegisters)();
26
26
  var nodeViewSerializer = new _NodeViewSerializer.NodeViewSerializer({});
27
27
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
@@ -162,6 +162,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
162
162
  },
163
163
  view: function view(editorView) {
164
164
  setNodeViewSerializer(editorView);
165
+ onEditorView === null || onEditorView === void 0 || onEditorView(editorView);
165
166
  var isFirst = true;
166
167
  var previousActiveIndex;
167
168
  var cancelPendingScrollToDecoration = null;
@@ -214,6 +215,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
214
215
  var _cancelPendingScrollT3;
215
216
  (_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
216
217
  cancelPendingScrollToDecoration = null;
218
+ onEditorView === null || onEditorView === void 0 || onEditorView(undefined);
217
219
  }
218
220
  };
219
221
  },
@@ -8,6 +8,7 @@ exports.showDiffPlugin = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
9
  var _react = _interopRequireDefault(require("react"));
10
10
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
11
+ var _getDeletedWidgets2 = require("./pm-plugins/getDeletedWidgets");
11
12
  var _getScrollableDecorations = require("./pm-plugins/getScrollableDecorations");
12
13
  var _main = require("./pm-plugins/main");
13
14
  var _IndicatorBarContentComponent = require("./ui/IndicatorBar/IndicatorBarContentComponent");
@@ -16,8 +17,19 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
16
17
  var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
17
18
  var api = _ref.api,
18
19
  config = _ref.config;
20
+ // Captured from the plugin's view lifecycle (see `createPlugin`) so read-only actions can access
21
+ // the current state without exposing the plugin key to consumers.
22
+ var editorView;
23
+ var setEditorView = function setEditorView(view) {
24
+ editorView = view;
25
+ };
19
26
  return {
20
27
  name: 'showDiff',
28
+ actions: {
29
+ getDeletedWidgets: function getDeletedWidgets(range) {
30
+ return editorView ? (0, _getDeletedWidgets2.getDeletedWidgets)(editorView.state, range) : [];
31
+ }
32
+ },
21
33
  commands: {
22
34
  showDiff: function showDiff(params) {
23
35
  return function (_ref2) {
@@ -64,7 +76,7 @@ var showDiffPlugin = exports.showDiffPlugin = function showDiffPlugin(_ref) {
64
76
  name: 'showDiffPlugin',
65
77
  plugin: function plugin(_ref6) {
66
78
  var getIntl = _ref6.getIntl;
67
- return (0, _main.createPlugin)(config, getIntl, api);
79
+ return (0, _main.createPlugin)(config, getIntl, api, setEditorView);
68
80
  }
69
81
  }];
70
82
  },
@@ -2,6 +2,7 @@
2
2
  import isEqual from 'lodash/isEqual';
3
3
  import memoizeOne from 'memoize-one';
4
4
  import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
5
+ import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
5
6
  import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
6
7
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
8
  import { fg } from '@atlaskit/platform-feature-flags';
@@ -116,6 +117,30 @@ const calculateNodesForBlockDecoration = ({
116
117
  });
117
118
  return decorations;
118
119
  };
120
+ /**
121
+ * Whether deleted content for `change` renders after the new content instead of before it.
122
+ *
123
+ * show-diff splits this across two options by change granularity, so the level decides which one
124
+ * applies:
125
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
126
+ * node level, so they are governed here too.
127
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
128
+ *
129
+ * Callers are responsible for the `smart` diffType and gate checks.
130
+ */
131
+ export const isDeletedContentPlacedBelow = ({
132
+ change,
133
+ deletedDiffPlacement,
134
+ inlineDeletedDiffPlacement
135
+ }) => {
136
+ const level = smartChangeLevel(change);
137
+ if (level === 'node' || level === 'paragraph') {
138
+ return deletedDiffPlacement === 'bottom';
139
+ }
140
+
141
+ // Inline-level (undefined) and sentence-level changes.
142
+ return inlineDeletedDiffPlacement === 'after';
143
+ };
119
144
  const calculateDiffDecorationsInner = ({
120
145
  state,
121
146
  pluginState,
@@ -212,6 +237,15 @@ const calculateDiffDecorationsInner = ({
212
237
  const isInserted = !isInverted;
213
238
  const createDecorationsForChange = (change, showGranularWithBlock) => {
214
239
  const isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
240
+
241
+ // Hoisted because it decides BOTH where the deleted widget is anchored and — since the
242
+ // widget pins whichever end of the range it sits at — how the indicator anchors below are
243
+ // allowed to move.
244
+ const isDeletedWidgetBelow = diffType === 'smart' && fg('platform_editor_ai_smart_diff') && isDeletedContentPlacedBelow({
245
+ change,
246
+ deletedDiffPlacement,
247
+ inlineDeletedDiffPlacement
248
+ });
215
249
  if (change.inserted.length > 0) {
216
250
  // shouldHideDeleted for block/node decorations: suppressed when isInverted + hideDeletedDiffs,
217
251
  // or when showGranularWithBlock (block reference widget is shown instead).
@@ -250,7 +284,8 @@ const calculateDiffDecorationsInner = ({
250
284
  shouldHideDeleted,
251
285
  showIndicators,
252
286
  hideAddedDiffsUnderline,
253
- hasDeletedWidget: willRenderDeletedWidget
287
+ hasDeletedWidget: willRenderDeletedWidget,
288
+ isDeletedWidgetBelow
254
289
  })
255
290
  }));
256
291
  }
@@ -266,7 +301,8 @@ const calculateDiffDecorationsInner = ({
266
301
  shouldHideDeleted,
267
302
  showIndicators,
268
303
  hideAddedDiffsUnderline,
269
- hasDeletedWidget: willRenderDeletedWidget
304
+ hasDeletedWidget: willRenderDeletedWidget,
305
+ isDeletedWidgetBelow
270
306
  })
271
307
  }));
272
308
  }
@@ -300,19 +336,7 @@ const calculateDiffDecorationsInner = ({
300
336
  isInserted: !isInserted,
301
337
  diffType,
302
338
  hideAddedDiffsUnderline,
303
- // For `smart` changes, optionally render the deleted content after the new
304
- // content (gray + strikethrough) instead of before it. Two independent
305
- // controls, split by change level:
306
- // - node/paragraph-level: `deletedDiffPlacement` (default `'top'`).
307
- // - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
308
- placeBelow: diffType === 'smart' && fg('platform_editor_ai_smart_diff') && (() => {
309
- const level = smartChangeLevel(change);
310
- if (level === 'node' || level === 'paragraph') {
311
- return deletedDiffPlacement === 'bottom';
312
- }
313
- // Inline-level (undefined) and sentence-level changes.
314
- return inlineDeletedDiffPlacement === 'after';
315
- })()
339
+ placeBelow: isDeletedWidgetBelow
316
340
  }),
317
341
  showIndicators
318
342
  }));
@@ -411,7 +435,7 @@ const calculateDiffDecorationsInner = ({
411
435
  if (change.isInline) {
412
436
  // Inline nodes (e.g. date, emoji, mention, status) need an inline decoration rather than a block decoration
413
437
  const isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
414
- const isAtomicInlineNodeFlag = expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
438
+ const isAtomicInlineNodeFlag = isExperimentEnabled('platform_editor_improve_inline_diffs', () => expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true));
415
439
  decorations.push(...createInlineChangedDecoration({
416
440
  change,
417
441
  colorScheme,
@@ -426,7 +450,7 @@ const calculateDiffDecorationsInner = ({
426
450
  }));
427
451
  // If we have the original node position, also render the old node as a "deleted" widget
428
452
  // so the user can see what it looked like before the change.
429
- if (change.fromA !== undefined && change.toA !== undefined && expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
453
+ if (change.fromA !== undefined && change.toA !== undefined && isExperimentEnabled('platform_editor_improve_inline_diffs', () => expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true))) {
430
454
  decorations.push(...createNodeChangedDecorationWidget({
431
455
  change: {
432
456
  fromA: change.fromA,