@atlaskit/editor-plugin-show-diff 17.1.5 → 17.1.7

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 (40) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +12 -1
  3. package/dist/cjs/pm-plugins/decorations/createAnchorDecorationWidgets.js +165 -32
  4. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +6 -2
  5. package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +5 -2
  6. package/dist/cjs/pm-plugins/decorations/createContributorTagWidget.js +54 -15
  7. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +6 -2
  8. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +64 -13
  9. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +8 -3
  10. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +8 -3
  11. package/dist/cjs/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  12. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +12 -1
  13. package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +131 -12
  14. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +6 -2
  15. package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +5 -2
  16. package/dist/es2019/pm-plugins/decorations/createContributorTagWidget.js +54 -15
  17. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +6 -2
  18. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +66 -16
  19. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +7 -0
  20. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +8 -3
  21. package/dist/es2019/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  22. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +12 -1
  23. package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +165 -32
  24. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +6 -2
  25. package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +5 -2
  26. package/dist/esm/pm-plugins/decorations/createContributorTagWidget.js +54 -15
  27. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +6 -2
  28. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +67 -16
  29. package/dist/esm/pm-plugins/decorations/decorationKeys.js +8 -3
  30. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +8 -3
  31. package/dist/esm/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  32. package/dist/types/pm-plugins/decorations/createAnchorDecorationWidgets.d.ts +14 -4
  33. package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +2 -1
  34. package/dist/types/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +2 -1
  35. package/dist/types/pm-plugins/decorations/createContributorTagWidget.d.ts +24 -6
  36. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  37. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -1
  38. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +3 -1
  39. package/dist/types/showDiffPluginType.d.ts +1 -0
  40. package/package.json +2 -2
@@ -41,6 +41,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
41
41
  nodeViewSerializer = _ref.nodeViewSerializer,
42
42
  colorScheme = _ref.colorScheme,
43
43
  isInserted = _ref.isInserted,
44
+ leftAnchorId = _ref.leftAnchorId,
44
45
  diffType = _ref.diffType;
45
46
  // Collect the inner content position of each cell in the new document within
46
47
  // the change range. Whole-cell replacement preserves cell count/order, so the
@@ -97,6 +98,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
97
98
  colorScheme: colorScheme,
98
99
  decorationType: 'widget',
99
100
  diffId: crypto.randomUUID(),
101
+ leftAnchorId: leftAnchorId,
100
102
  isInserted: isInserted,
101
103
  diffType: diffType
102
104
  }, (0, _isExtendedEnabled.isExtendedEnabled)(diffType) && {
@@ -122,6 +124,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
122
124
  activeIndexPos = _ref2.activeIndexPos,
123
125
  _ref2$isInserted = _ref2.isInserted,
124
126
  isInserted = _ref2$isInserted === void 0 ? false : _ref2$isInserted,
127
+ leftAnchorId = _ref2.leftAnchorId,
125
128
  _ref2$showContributor = _ref2.showContributorTags,
126
129
  showContributorTags = _ref2$showContributor === void 0 ? false : _ref2$showContributor,
127
130
  _ref2$showIndicators = _ref2.showIndicators,
@@ -185,6 +188,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
185
188
  nodeViewSerializer: nodeViewSerializer,
186
189
  colorScheme: colorScheme,
187
190
  isInserted: isInserted,
191
+ leftAnchorId: leftAnchorId,
188
192
  diffType: diffType
189
193
  });
190
194
  }
@@ -201,6 +205,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
201
205
  colorScheme: colorScheme,
202
206
  isActive: isActive,
203
207
  isInserted: isInserted,
208
+ leftAnchorId: leftAnchorId,
204
209
  diffType: diffType,
205
210
  intl: intl,
206
211
  // Needed for the row's own indicator anchor; this path returns before the
@@ -414,7 +419,13 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
414
419
  }
415
420
  }
416
421
  });
417
- var contributorTagAnchorName;
422
+
423
+ // A change inside a code block hoists its tag out of the block (EDITOR-9045).
424
+ var hoistedCodeBlockAnchor = canTagWidget ? (0, _createContributorTagWidget.resolveHoistedCodeBlockAnchor)(newDoc, safeInsertPos, diffId) : undefined;
425
+ if (hoistedCodeBlockAnchor) {
426
+ decorations.push(hoistedCodeBlockAnchor.marker);
427
+ }
428
+ var contributorTagAnchorName = hoistedCodeBlockAnchor === null || hoistedCodeBlockAnchor === void 0 ? void 0 : hoistedCodeBlockAnchor.anchorName;
418
429
  if (!isInserted && deletedColumns !== null && deletedColumns !== void 0 && deletedColumns.length) {
419
430
  var table = dom.querySelector('table');
420
431
  var firstRow = table === null || table === void 0 ? void 0 : table.rows[0];
@@ -474,6 +485,13 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
474
485
  dom.style.setProperty('anchor-name', "--".concat((0, _decorationKeys.buildAnchorDecorationKey)({
475
486
  diffId: diffId
476
487
  })));
488
+ // The tag built below only anchors via `anchor()` if `contributorTagAnchorName` is set; without
489
+ // it the tag falls back to a non-anchored position (EDITOR-9045).
490
+ if ((0, _fg.fg)('confluence_ncs_step_diffing_version_history')) {
491
+ contributorTagAnchorName !== null && contributorTagAnchorName !== void 0 ? contributorTagAnchorName : contributorTagAnchorName = (0, _decorationKeys.buildAnchorDecorationKey)({
492
+ diffId: diffId
493
+ });
494
+ }
477
495
  }
478
496
 
479
497
  // Taken down in the widget's `destroy` below: `dom` is rebuilt on every recalculation, so the tag
@@ -482,24 +500,56 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
482
500
  if (canTagWidget) {
483
501
  // Lets the contributor tag find the deleted content on hover.
484
502
  dom.setAttribute('data-diff-id', diffId);
485
-
486
- // Hosted at the start of the deleted run rather than on `dom` itself: `dom` is inline, so once
487
- // the deleted content wraps its box is the union of its line fragments.
488
- var tagHost = (0, _createContributorTagWidget.createContributorTagHost)({
489
- anchorName: contributorTagAnchorName,
490
- diffId: diffId,
491
- mountContext: tagMountContext
492
- });
493
- if (tagHost) {
494
- dom.prepend(tagHost.host);
495
- tagMount = tagHost.mount;
503
+ if (hoistedCodeBlockAnchor) {
504
+ // Own widget just before the code block, anchored to the marker above, not `dom` (EDITOR-9045).
505
+ var hoistedTagMount;
506
+ decorations.push(_view.Decoration.widget((0, _createAnchorDecorationWidgets.clampAnchorPosIntoCell)(newDoc, hoistedCodeBlockAnchor.codeBlockStart, 1), function () {
507
+ var _tagHost$host;
508
+ var tagHost = (0, _createContributorTagWidget.createContributorTagHost)({
509
+ anchorName: contributorTagAnchorName,
510
+ diffId: diffId,
511
+ mountContext: tagMountContext
512
+ });
513
+ hoistedTagMount = tagHost === null || tagHost === void 0 ? void 0 : tagHost.mount;
514
+ return (_tagHost$host = tagHost === null || tagHost === void 0 ? void 0 : tagHost.host) !== null && _tagHost$host !== void 0 ? _tagHost$host : document.createElement('span');
515
+ }, _objectSpread(_objectSpread({}, (0, _decorationKeys.buildContributorTagDecorationSpec)(diffId)), {}, {
516
+ side: 1,
517
+ marks: [],
518
+ ignoreSelection: true,
519
+ stopEvent: function stopEvent() {
520
+ return true;
521
+ },
522
+ destroy: function destroy() {
523
+ (0, _createContributorTagWidget.unmountContributorTag)(hoistedTagMount);
524
+ hoistedTagMount = undefined;
525
+ }
526
+ })));
527
+ } else {
528
+ // Hosted at the start of the deleted run rather than on `dom` itself: `dom` is inline, so once
529
+ // the deleted content wraps its box is the union of its line fragments.
530
+ var tagHost = (0, _createContributorTagWidget.createContributorTagHost)({
531
+ anchorName: contributorTagAnchorName,
532
+ diffId: diffId,
533
+ mountContext: tagMountContext
534
+ });
535
+ if (tagHost) {
536
+ dom.prepend(tagHost.host);
537
+ tagMount = tagHost.mount;
538
+ }
496
539
  }
497
540
  }
498
541
  if (showIndicators && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
499
542
  var leftAnchor = (0, _createAnchorDecorationWidgets.createLeftAnchorWidget)({
500
543
  doc: newDoc,
501
544
  from: safeInsertPos,
502
- diffId: diffId
545
+ diffId: diffId,
546
+ leftAnchorId: leftAnchorId,
547
+ measureElement: (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? dom : undefined,
548
+ sliceOverride: (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? slice : undefined,
549
+ underlyingRange: (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? {
550
+ from: change.fromB,
551
+ to: change.toB
552
+ } : undefined
503
553
  });
504
554
  if (leftAnchor) {
505
555
  decorations.push(leftAnchor);
@@ -510,6 +560,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
510
560
  colorScheme: colorScheme,
511
561
  decorationType: 'widget',
512
562
  diffId: diffId,
563
+ leftAnchorId: leftAnchorId,
513
564
  isActive: isActive,
514
565
  isInserted: isInserted,
515
566
  diffType: diffType
@@ -84,10 +84,11 @@ var buildDiffDecorationSpec = exports.buildDiffDecorationSpec = function buildDi
84
84
  diffId = _ref3.diffId,
85
85
  isActive = _ref3.isActive,
86
86
  isInserted = _ref3.isInserted,
87
+ leftAnchorId = _ref3.leftAnchorId,
87
88
  nodeName = _ref3.nodeName,
88
89
  side = _ref3.side,
89
90
  diffType = _ref3.diffType;
90
- return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
91
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
91
92
  decorationFamily: DecorationFamily.diff,
92
93
  decorationType: decorationType,
93
94
  diffId: diffId,
@@ -103,6 +104,8 @@ var buildDiffDecorationSpec = exports.buildDiffDecorationSpec = function buildDi
103
104
  isActive: isActive
104
105
  } : {}), isInserted !== undefined ? {
105
106
  isInserted: isInserted
107
+ } : {}), leftAnchorId ? {
108
+ leftAnchorId: leftAnchorId
106
109
  } : {}), colorScheme ? {
107
110
  colorScheme: colorScheme
108
111
  } : {}), nodeName ? {
@@ -159,11 +162,13 @@ var isDiffDecoration = exports.isDiffDecoration = function isDiffDecoration(deco
159
162
  var extractDiffDescriptors = exports.extractDiffDescriptors = function extractDiffDescriptors(decorations) {
160
163
  return decorations.find(undefined, undefined, isDiffDecorationSpec).filter(isDiffDecoration).map(function (_ref5) {
161
164
  var spec = _ref5.spec;
162
- return _objectSpread(_objectSpread(_objectSpread({}, spec.colorScheme ? {
165
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, spec.colorScheme ? {
163
166
  colorScheme: spec.colorScheme
164
167
  } : {}), {}, {
165
168
  id: spec.diffId
166
- }, spec.isInserted !== undefined ? {
169
+ }, spec.leftAnchorId ? {
170
+ leftAnchorId: spec.leftAnchorId
171
+ } : {}), spec.isInserted !== undefined ? {
167
172
  isInserted: spec.isInserted
168
173
  } : {}), {}, {
169
174
  type: spec.decorationType
@@ -54,10 +54,15 @@ var getChangedContentStyleNext = function getChangedContentStyleNext(colorScheme
54
54
  if ((0, _isExtendedEnabled.isExtendedEnabled)(diffType) && isInserted) {
55
55
  return (0, _factory.buildInsertedInlineStyle)(colors, isActive, hideAddedDiffsUnderline);
56
56
  }
57
- if (isActive) {
58
- return (0, _factory.buildDeletedInlineContentStyle)(colors, 'active');
57
+ var base = (0, _factory.buildDeletedInlineContentStyle)(colors, isActive ? 'active' : (0, _expValEquals.expValEquals)('platform_editor_enghealth_a11y_jan_fixes', 'isEnabled', true) ? 'new' : 'default');
58
+
59
+ // Text-like blocks (heading, lists, blockquote) render their deleted content through this
60
+ // getter rather than `getDeletedContentStyle`, so without this they never receive the
61
+ // glyphTint background + underline that plain deleted text already gets.
62
+ if ((0, _fg.fg)('confluence_ncs_step_diffing_version_history') && colors.deletedInlineTreatment === 'glyphTint' && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
63
+ return base + (0, _factory.buildDeletedInlineContentStyleExtended)(colors, isActive);
59
64
  }
60
- return (0, _factory.buildDeletedInlineContentStyle)(colors, (0, _expValEquals.expValEquals)('platform_editor_enghealth_a11y_jan_fixes', 'isEnabled', true) ? 'new' : 'default');
65
+ return base;
61
66
  };
62
67
  var getChangedNodeStyleNext = function getChangedNodeStyleNext(nodeName, colorScheme) {
63
68
  var isInserted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
@@ -12,6 +12,8 @@ var _hooks = require("@atlaskit/editor-common/hooks");
12
12
  var _decorationKeys = require("../../pm-plugins/decorations/decorationKeys");
13
13
  var _IndicatorBar = require("./IndicatorBar");
14
14
  var renderIndicatorBar = function renderIndicatorBar(descriptor) {
15
+ var _descriptor$leftAncho;
16
+ var leftAnchorId = (_descriptor$leftAncho = descriptor.leftAnchorId) !== null && _descriptor$leftAncho !== void 0 ? _descriptor$leftAncho : descriptor.id;
15
17
  switch (descriptor.type) {
16
18
  case 'inline':
17
19
  {
@@ -28,7 +30,7 @@ var renderIndicatorBar = function renderIndicatorBar(descriptor) {
28
30
  anchorType: _decorationKeys.AnchorTypeKey.to
29
31
  }),
30
32
  anchorLeft: (0, _decorationKeys.buildAnchorDecorationKey)({
31
- diffId: descriptor.id,
33
+ diffId: leftAnchorId,
32
34
  anchorType: _decorationKeys.AnchorTypeKey.left
33
35
  })
34
36
  });
@@ -48,7 +50,7 @@ var renderIndicatorBar = function renderIndicatorBar(descriptor) {
48
50
  anchorTop: blockAnchor,
49
51
  anchorBottom: blockAnchor,
50
52
  anchorLeft: (0, _decorationKeys.buildAnchorDecorationKey)({
51
- diffId: descriptor.id,
53
+ diffId: leftAnchorId,
52
54
  anchorType: _decorationKeys.AnchorTypeKey.left
53
55
  })
54
56
  });
@@ -66,7 +68,7 @@ var renderIndicatorBar = function renderIndicatorBar(descriptor) {
66
68
  diffId: descriptor.id
67
69
  }),
68
70
  anchorLeft: (0, _decorationKeys.buildAnchorDecorationKey)({
69
- diffId: descriptor.id,
71
+ diffId: leftAnchorId,
70
72
  anchorType: _decorationKeys.AnchorTypeKey.left
71
73
  }),
72
74
  anchorLeftFallback: (0, _decorationKeys.buildAnchorDecorationKey)({
@@ -171,6 +171,7 @@ const calculateNodesForBlockDecoration = ({
171
171
  to,
172
172
  colorScheme,
173
173
  isInserted = true,
174
+ leftAnchorId,
174
175
  activeIndexPos,
175
176
  shouldHideDeleted = false,
176
177
  showContributorTags = false,
@@ -203,6 +204,7 @@ const calculateNodesForBlockDecoration = ({
203
204
  },
204
205
  colorScheme,
205
206
  isInserted,
207
+ leftAnchorId,
206
208
  isActive,
207
209
  shouldHideDeleted,
208
210
  showContributorTags,
@@ -239,6 +241,7 @@ const calculateNodesForBlockDecoration = ({
239
241
  },
240
242
  colorScheme,
241
243
  isInserted,
244
+ leftAnchorId,
242
245
  isActive,
243
246
  shouldHideDeleted,
244
247
  showContributorTags,
@@ -498,6 +501,10 @@ const calculateDiffDecorationsInner = ({
498
501
  const tableChanges = changes.filter(change => change.deletedColumns !== undefined);
499
502
  const isHandledByTable = (from, to) => tableChanges.some(change => from >= change.fromB && to <= change.toB);
500
503
  const createDecorationsForChange = change => {
504
+ // Patch 2 makes all decorations generated for one replacement share this anchor. Their own
505
+ // IDs still identify their top/bottom bounds, while this ID makes their bars agree on one
506
+ // left edge. When the gate is off, factories retain their existing per-decoration anchors.
507
+ const leftAnchorId = fg('platform_editor_ai_show_diff_patch_2') ? `replacement-${change.fromA}-${change.toA}-${change.fromB}-${change.toB}` : undefined;
501
508
  const changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
502
509
  const attributionKey = showContributorTags ? getAttributionKeyForChange(change, attributedChanges) : undefined;
503
510
  const isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
@@ -615,6 +622,7 @@ const calculateDiffDecorationsInner = ({
615
622
  fromB: from,
616
623
  toB: to
617
624
  },
625
+ leftAnchorId,
618
626
  doc: tr.doc,
619
627
  colorScheme: changeColorScheme,
620
628
  isActive,
@@ -636,6 +644,7 @@ const calculateDiffDecorationsInner = ({
636
644
  decorations.push(...createInlineChangedDecoration({
637
645
  attributionKey,
638
646
  change,
647
+ leftAnchorId,
639
648
  doc: tr.doc,
640
649
  colorScheme: changeColorScheme,
641
650
  isActive,
@@ -671,7 +680,8 @@ const calculateDiffDecorationsInner = ({
671
680
  activeIndexPos,
672
681
  intl,
673
682
  diffType,
674
- coarseTableCellsOnly: useCoarseTableDecoration
683
+ coarseTableCellsOnly: useCoarseTableDecoration,
684
+ leftAnchorId
675
685
  }));
676
686
  }
677
687
  if (change.deleted.length > 0 && !isMarkOnly && !hasNoDeletedContent) {
@@ -696,6 +706,7 @@ const calculateDiffDecorationsInner = ({
696
706
  newDoc: tr.doc,
697
707
  intl,
698
708
  activeIndexPos,
709
+ leftAnchorId,
699
710
  showContributorTags,
700
711
  tagMountContext,
701
712
  ...(isExtendedEnabled(diffType) && {
@@ -27,23 +27,23 @@ const resolveDocLevelNode = (doc, from) => {
27
27
  beforePos: nodeStart - 1
28
28
  };
29
29
  };
30
-
31
30
  /**
32
31
  * Handles edge cases for block nodes whose inline content can exceed the doc
33
32
  * margin (tables, layouts, expands). Returns the position whose DOM should be
34
33
  * measured to size the left anchor, or `undefined` when the diff is not inside
35
34
  * such a node.
36
35
  */
37
- const edgeCases = (doc, from) => {
36
+ const edgeCases = (doc, from, nodeOverride) => {
38
37
  const resolved = resolveDocLevelNode(doc, from);
39
38
  if (!resolved) {
40
39
  return undefined;
41
40
  }
42
41
  const {
43
- node,
42
+ node: resolvedNode,
44
43
  nodeStart,
45
44
  beforePos
46
45
  } = resolved;
46
+ const node = fg('platform_editor_ai_show_diff_patch_2') ? nodeOverride !== null && nodeOverride !== void 0 ? nodeOverride : resolvedNode : resolvedNode;
47
47
  if (node.type.name === 'layoutSection' && fg('platform_editor_ai_show_diff_patch_1')) {
48
48
  // Columns extend past the node-view wrapper via negative margins (12px or 20px).
49
49
  // Measure their container so the indicator stays outside the diff outline, including
@@ -109,6 +109,44 @@ const edgeCases = (doc, from) => {
109
109
  return undefined;
110
110
  }
111
111
  };
112
+ const getEdgeCasesForSlice = (doc, from, slice, measureElement) => {
113
+ var _targets$find;
114
+ const resolved = resolveDocLevelNode(doc, from);
115
+ if (!resolved) {
116
+ return [];
117
+ }
118
+ const targets = [];
119
+ // edge cases can only be top level nodes, so we only care about the top level nodes in the slice
120
+ slice.content.forEach((node, offset) => {
121
+ const edgeCase = edgeCases(doc, from + offset, node);
122
+ if (edgeCase) {
123
+ targets.push({
124
+ ...edgeCase,
125
+ measureElement
126
+ });
127
+ }
128
+ });
129
+ return targets.length > 0 ? [{
130
+ beforePos: resolved.beforePos,
131
+ leftOffset: (_targets$find = targets.find(target => target.leftOffset !== undefined)) === null || _targets$find === void 0 ? void 0 : _targets$find.leftOffset,
132
+ widthMeasureTargets: targets
133
+ }] : [];
134
+ };
135
+
136
+ /**
137
+ * Finds the edge cases in the current document for either a whole range or one position.
138
+ * A missing `to` intentionally means the single-position lookup is the fallback.
139
+ */
140
+ const getEdgeCasesForDocument = (doc, from, to) => {
141
+ if (to !== undefined) {
142
+ const edgeCasesForSlice = getEdgeCasesForSlice(doc, from, doc.slice(from, to));
143
+ if (edgeCasesForSlice.length > 0) {
144
+ return edgeCasesForSlice;
145
+ }
146
+ }
147
+ const edgeCase = edgeCases(doc, from);
148
+ return edgeCase ? [edgeCase] : [];
149
+ };
112
150
 
113
151
  /**
114
152
  * Create a widget that marks the start of the doc margin.
@@ -141,9 +179,22 @@ export const createDocMarginAnchorWidget = () => {
141
179
  export const createLeftAnchorWidget = ({
142
180
  doc,
143
181
  from,
144
- diffId
182
+ to,
183
+ diffId,
184
+ leftAnchorId,
185
+ measureElement,
186
+ sliceOverride,
187
+ underlyingRange
145
188
  }) => {
146
- const edgeCase = edgeCases(doc, from);
189
+ var _range$from;
190
+ const overrideEdgeCases = sliceOverride ? getEdgeCasesForSlice(doc, from, sliceOverride, measureElement) : [];
191
+ const range = underlyingRange !== null && underlyingRange !== void 0 ? underlyingRange : to !== undefined ? {
192
+ from,
193
+ to
194
+ } : undefined;
195
+ const documentEdgeCases = getEdgeCasesForDocument(doc, (_range$from = range === null || range === void 0 ? void 0 : range.from) !== null && _range$from !== void 0 ? _range$from : from, range === null || range === void 0 ? void 0 : range.to);
196
+ const allEdgeCases = [...overrideEdgeCases, ...documentEdgeCases];
197
+ const edgeCase = fg('platform_editor_ai_show_diff_patch_2') ? allEdgeCases[0] : edgeCases(doc, from);
147
198
  if (edgeCase === undefined) {
148
199
  return undefined;
149
200
  }
@@ -154,7 +205,7 @@ export const createLeftAnchorWidget = ({
154
205
  beforePos
155
206
  } = edgeCase;
156
207
  const leftAnchorKey = buildAnchorDecorationKey({
157
- diffId,
208
+ diffId: leftAnchorId !== null && leftAnchorId !== void 0 ? leftAnchorId : diffId,
158
209
  anchorType: AnchorTypeKey.left
159
210
  });
160
211
  let leftResizeObserver;
@@ -174,6 +225,69 @@ export const createLeftAnchorWidget = ({
174
225
  wrapper.appendChild(anchor);
175
226
  const measureWidth = () => {
176
227
  var _nodeDOM$querySelecto;
228
+ if (fg('platform_editor_ai_show_diff_patch_2')) {
229
+ const widthMeasureTargets = allEdgeCases.flatMap(target => {
230
+ var _target$widthMeasureT;
231
+ return (_target$widthMeasureT = target.widthMeasureTargets) !== null && _target$widthMeasureT !== void 0 ? _target$widthMeasureT : [target];
232
+ });
233
+ if (getPos() === undefined || widthMeasureTargets.length === 0) {
234
+ return;
235
+ }
236
+ const measuredElements = widthMeasureTargets.flatMap(({
237
+ measureElement: targetMeasureElement,
238
+ measureLeft,
239
+ measurePos,
240
+ measureSelector
241
+ }) => {
242
+ if (measurePos === undefined) {
243
+ return [];
244
+ }
245
+ const nodeDOM = targetMeasureElement !== null && targetMeasureElement !== void 0 ? targetMeasureElement : view.nodeDOM(measurePos);
246
+ const elements = nodeDOM instanceof HTMLElement ? measureSelector ? Array.from(nodeDOM.querySelectorAll(measureSelector)) : [nodeDOM] : [];
247
+ return elements.map(element => ({
248
+ element,
249
+ measureLeft
250
+ }));
251
+ });
252
+
253
+ // A single diff can include multiple edge-case nodes, so measure the widest one.
254
+ let widest;
255
+ for (const target of measuredElements) {
256
+ if (!widest || target.element.offsetWidth > widest.element.offsetWidth) {
257
+ widest = target;
258
+ }
259
+ }
260
+ if (widest) {
261
+ const updateAnchor = () => {
262
+ if (getPos() === undefined) {
263
+ return;
264
+ }
265
+ if (widest.measureLeft) {
266
+ const left = widest.element.getBoundingClientRect().left - wrapper.getBoundingClientRect().left;
267
+ anchor.style.setProperty('left', `${left}px`);
268
+ anchor.style.setProperty('transform', 'none');
269
+ }
270
+ anchor.style.setProperty('width', `${widest.element.offsetWidth}px`);
271
+ };
272
+ updateAnchor();
273
+
274
+ // Observe the measured elements for size changes (e.g. page
275
+ // resize) so the indicator stays aligned.
276
+ if (!leftResizeObserver) {
277
+ leftResizeObserver = new ResizeObserver(measureWidth);
278
+ measuredElements.forEach(({
279
+ element
280
+ }) => {
281
+ var _leftResizeObserver;
282
+ return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.observe(element);
283
+ });
284
+ if (widest.measureLeft) {
285
+ leftResizeObserver.observe(wrapper);
286
+ }
287
+ }
288
+ }
289
+ return;
290
+ }
177
291
  if (getPos() === undefined || edgeCase.measurePos === undefined) {
178
292
  return;
179
293
  }
@@ -217,8 +331,8 @@ export const createLeftAnchorWidget = ({
217
331
  side: -999
218
332
  }),
219
333
  destroy: () => {
220
- var _leftResizeObserver;
221
- return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
334
+ var _leftResizeObserver2;
335
+ return (_leftResizeObserver2 = leftResizeObserver) === null || _leftResizeObserver2 === void 0 ? void 0 : _leftResizeObserver2.disconnect();
222
336
  }
223
337
  });
224
338
  };
@@ -238,13 +352,15 @@ export const createBlockIndicatorAnchorWidgets = ({
238
352
  doc,
239
353
  from,
240
354
  to,
241
- diffId
355
+ diffId,
356
+ leftAnchorId
242
357
  }) => {
243
358
  var _ref, _parentTable$pos;
244
359
  const leftAnchor = createLeftAnchorWidget({
245
360
  doc,
246
361
  from,
247
- diffId
362
+ diffId,
363
+ leftAnchorId
248
364
  });
249
365
  const maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
250
366
 
@@ -399,12 +515,15 @@ export const createInlineIndicatorAnchorWidgets = ({
399
515
  doc,
400
516
  from,
401
517
  to,
402
- diffId
518
+ diffId,
519
+ leftAnchorId
403
520
  }) => {
404
521
  const leftAnchor = createLeftAnchorWidget({
405
522
  doc,
406
523
  from,
407
- diffId
524
+ to: fg('platform_editor_ai_show_diff_patch_2') ? to : undefined,
525
+ diffId,
526
+ leftAnchorId
408
527
  });
409
528
  const maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
410
529
 
@@ -168,6 +168,7 @@ export const createBlockChangedDecoration = ({
168
168
  colorScheme,
169
169
  isInserted = true,
170
170
  isActive = false,
171
+ leftAnchorId,
171
172
  shouldHideDeleted = false,
172
173
  showContributorTags = false,
173
174
  showIndicators = false,
@@ -196,6 +197,7 @@ export const createBlockChangedDecoration = ({
196
197
  colorScheme,
197
198
  decorationType: 'block',
198
199
  diffId,
200
+ leftAnchorId,
199
201
  isActive,
200
202
  isInserted,
201
203
  nodeName: change.name,
@@ -254,6 +256,7 @@ export const createBlockChangedDecoration = ({
254
256
  colorScheme,
255
257
  decorationType: 'block',
256
258
  diffId,
259
+ leftAnchorId,
257
260
  isActive,
258
261
  isInserted,
259
262
  nodeName: change.name,
@@ -270,7 +273,8 @@ export const createBlockChangedDecoration = ({
270
273
  doc,
271
274
  from: change.from,
272
275
  to: change.to,
273
- diffId
276
+ diffId,
277
+ leftAnchorId
274
278
  }));
275
279
  }
276
280
 
@@ -288,7 +292,7 @@ export const createBlockChangedDecoration = ({
288
292
  mountContext: tagMountContext
289
293
  });
290
294
  if (tagWidget) {
291
- decorations.push(tagWidget);
295
+ decorations.push(...tagWidget);
292
296
  }
293
297
  }
294
298
  return decorations;
@@ -279,6 +279,7 @@ export const createChangedRowDecorationWidgets = ({
279
279
  colorScheme,
280
280
  isActive,
281
281
  isInserted = false,
282
+ leftAnchorId,
282
283
  diffType,
283
284
  intl,
284
285
  showIndicators = false,
@@ -330,7 +331,8 @@ export const createChangedRowDecorationWidgets = ({
330
331
  const leftAnchor = createLeftAnchorWidget({
331
332
  doc: newDoc,
332
333
  from: safeInsertPos,
333
- diffId
334
+ diffId,
335
+ leftAnchorId
334
336
  });
335
337
  if (leftAnchor) {
336
338
  decorations.push(leftAnchor);
@@ -371,6 +373,7 @@ export const createChangedRowDecorationWidgets = ({
371
373
  colorScheme,
372
374
  decorationType: 'widget',
373
375
  diffId,
376
+ leftAnchorId,
374
377
  isActive,
375
378
  isInserted,
376
379
  diffType
@@ -387,7 +390,7 @@ export const createChangedRowDecorationWidgets = ({
387
390
  }));
388
391
  }
389
392
  if (tagWidget) {
390
- decorations.push(tagWidget);
393
+ decorations.push(...tagWidget);
391
394
  }
392
395
  return decorations;
393
396
  });