@atlaskit/editor-plugin-show-diff 17.1.4 → 17.1.6

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 (33) hide show
  1. package/CHANGELOG.md +15 -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 +5 -1
  5. package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
  6. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +5 -1
  7. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -1
  8. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +8 -3
  9. package/dist/cjs/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  10. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +12 -1
  11. package/dist/es2019/pm-plugins/decorations/createAnchorDecorationWidgets.js +131 -12
  12. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +5 -1
  13. package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
  14. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +5 -1
  15. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -1
  16. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +7 -0
  17. package/dist/es2019/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  18. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +12 -1
  19. package/dist/esm/pm-plugins/decorations/createAnchorDecorationWidgets.js +165 -32
  20. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +5 -1
  21. package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +4 -1
  22. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +5 -1
  23. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -1
  24. package/dist/esm/pm-plugins/decorations/decorationKeys.js +8 -3
  25. package/dist/esm/ui/IndicatorBar/IndicatorBarContentComponent.js +5 -3
  26. package/dist/types/pm-plugins/decorations/createAnchorDecorationWidgets.d.ts +14 -4
  27. package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +2 -1
  28. package/dist/types/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +2 -1
  29. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  30. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -1
  31. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +3 -1
  32. package/dist/types/showDiffPluginType.d.ts +1 -0
  33. package/package.json +3 -3
@@ -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
 
@@ -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
@@ -126,6 +126,7 @@ export const createInlineChangedDecoration = ({
126
126
  colorScheme,
127
127
  isActive = false,
128
128
  isInserted = true,
129
+ leftAnchorId,
129
130
  isAtomicInlineNode = false,
130
131
  shouldHideDeleted = false,
131
132
  showContributorTags = false,
@@ -157,6 +158,7 @@ export const createInlineChangedDecoration = ({
157
158
  colorScheme,
158
159
  decorationType: 'inline',
159
160
  diffId,
161
+ leftAnchorId,
160
162
  isActive,
161
163
  isInserted
162
164
  }))];
@@ -227,6 +229,7 @@ export const createInlineChangedDecoration = ({
227
229
  colorScheme,
228
230
  decorationType: 'inline',
229
231
  diffId,
232
+ leftAnchorId,
230
233
  isActive,
231
234
  isInserted
232
235
  }))];
@@ -262,7 +265,8 @@ export const createInlineChangedDecoration = ({
262
265
  doc,
263
266
  from: anchorFrom,
264
267
  to: anchorTo,
265
- diffId
268
+ diffId,
269
+ leftAnchorId
266
270
  }));
267
271
  }
268
272
 
@@ -29,6 +29,7 @@ const createTableCellContentWidgets = ({
29
29
  nodeViewSerializer,
30
30
  colorScheme,
31
31
  isInserted,
32
+ leftAnchorId,
32
33
  diffType
33
34
  }) => {
34
35
  // Collect the inner content position of each cell in the new document within
@@ -87,6 +88,7 @@ const createTableCellContentWidgets = ({
87
88
  colorScheme,
88
89
  decorationType: 'widget',
89
90
  diffId: crypto.randomUUID(),
91
+ leftAnchorId,
90
92
  isInserted,
91
93
  diffType,
92
94
  ...(isExtendedEnabled(diffType) && {
@@ -113,6 +115,7 @@ export const createNodeChangedDecorationWidget = ({
113
115
  activeIndexPos,
114
116
  // This is false by default as this is generally used to show deleted content
115
117
  isInserted = false,
118
+ leftAnchorId,
116
119
  showContributorTags = false,
117
120
  showIndicators = false,
118
121
  // When true, render the deleted content *after* (below) the new content instead of
@@ -177,6 +180,7 @@ export const createNodeChangedDecorationWidget = ({
177
180
  nodeViewSerializer,
178
181
  colorScheme,
179
182
  isInserted,
183
+ leftAnchorId,
180
184
  diffType
181
185
  });
182
186
  }
@@ -193,6 +197,7 @@ export const createNodeChangedDecorationWidget = ({
193
197
  colorScheme,
194
198
  isActive,
195
199
  isInserted,
200
+ leftAnchorId,
196
201
  diffType,
197
202
  intl,
198
203
  // Needed for the row's own indicator anchor; this path returns before the
@@ -485,7 +490,14 @@ export const createNodeChangedDecorationWidget = ({
485
490
  const leftAnchor = createLeftAnchorWidget({
486
491
  doc: newDoc,
487
492
  from: safeInsertPos,
488
- diffId
493
+ diffId,
494
+ leftAnchorId,
495
+ measureElement: fg('platform_editor_ai_show_diff_patch_2') ? dom : undefined,
496
+ sliceOverride: fg('platform_editor_ai_show_diff_patch_2') ? slice : undefined,
497
+ underlyingRange: fg('platform_editor_ai_show_diff_patch_2') ? {
498
+ from: change.fromB,
499
+ to: change.toB
500
+ } : undefined
489
501
  });
490
502
  if (leftAnchor) {
491
503
  decorations.push(leftAnchor);
@@ -497,6 +509,7 @@ export const createNodeChangedDecorationWidget = ({
497
509
  colorScheme,
498
510
  decorationType: 'widget',
499
511
  diffId,
512
+ leftAnchorId,
500
513
  isActive,
501
514
  isInserted,
502
515
  diffType,
@@ -73,6 +73,7 @@ export const buildDiffDecorationSpec = ({
73
73
  diffId,
74
74
  isActive,
75
75
  isInserted,
76
+ leftAnchorId,
76
77
  nodeName,
77
78
  side,
78
79
  diffType
@@ -96,6 +97,9 @@ export const buildDiffDecorationSpec = ({
96
97
  ...(isInserted !== undefined ? {
97
98
  isInserted
98
99
  } : {}),
100
+ ...(leftAnchorId ? {
101
+ leftAnchorId
102
+ } : {}),
99
103
  ...(colorScheme ? {
100
104
  colorScheme
101
105
  } : {}),
@@ -154,6 +158,9 @@ export const extractDiffDescriptors = decorations => decorations.find(undefined,
154
158
  colorScheme: spec.colorScheme
155
159
  } : {}),
156
160
  id: spec.diffId,
161
+ ...(spec.leftAnchorId ? {
162
+ leftAnchorId: spec.leftAnchorId
163
+ } : {}),
157
164
  ...(spec.isInserted !== undefined ? {
158
165
  isInserted: spec.isInserted
159
166
  } : {}),
@@ -5,6 +5,8 @@ import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks'
5
5
  import { buildAnchorDecorationKey, AnchorTypeKey } from '../../pm-plugins/decorations/decorationKeys';
6
6
  import { IndicatorBar } from './IndicatorBar';
7
7
  const renderIndicatorBar = descriptor => {
8
+ var _descriptor$leftAncho;
9
+ const leftAnchorId = (_descriptor$leftAncho = descriptor.leftAnchorId) !== null && _descriptor$leftAncho !== void 0 ? _descriptor$leftAncho : descriptor.id;
8
10
  switch (descriptor.type) {
9
11
  case 'inline':
10
12
  {
@@ -21,7 +23,7 @@ const renderIndicatorBar = descriptor => {
21
23
  anchorType: AnchorTypeKey.to
22
24
  }),
23
25
  anchorLeft: buildAnchorDecorationKey({
24
- diffId: descriptor.id,
26
+ diffId: leftAnchorId,
25
27
  anchorType: AnchorTypeKey.left
26
28
  })
27
29
  });
@@ -41,7 +43,7 @@ const renderIndicatorBar = descriptor => {
41
43
  anchorTop: blockAnchor,
42
44
  anchorBottom: blockAnchor,
43
45
  anchorLeft: buildAnchorDecorationKey({
44
- diffId: descriptor.id,
46
+ diffId: leftAnchorId,
45
47
  anchorType: AnchorTypeKey.left
46
48
  })
47
49
  });
@@ -59,7 +61,7 @@ const renderIndicatorBar = descriptor => {
59
61
  diffId: descriptor.id
60
62
  }),
61
63
  anchorLeft: buildAnchorDecorationKey({
62
- diffId: descriptor.id,
64
+ diffId: leftAnchorId,
63
65
  anchorType: AnchorTypeKey.left
64
66
  }),
65
67
  anchorLeftFallback: buildAnchorDecorationKey({
@@ -185,6 +185,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
185
185
  colorScheme = _ref5.colorScheme,
186
186
  _ref5$isInserted = _ref5.isInserted,
187
187
  isInserted = _ref5$isInserted === void 0 ? true : _ref5$isInserted,
188
+ leftAnchorId = _ref5.leftAnchorId,
188
189
  activeIndexPos = _ref5.activeIndexPos,
189
190
  _ref5$shouldHideDelet = _ref5.shouldHideDeleted,
190
191
  shouldHideDeleted = _ref5$shouldHideDelet === void 0 ? false : _ref5$shouldHideDelet,
@@ -223,6 +224,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
223
224
  },
224
225
  colorScheme: colorScheme,
225
226
  isInserted: isInserted,
227
+ leftAnchorId: leftAnchorId,
226
228
  isActive: isActive,
227
229
  shouldHideDeleted: shouldHideDeleted,
228
230
  showContributorTags: showContributorTags,
@@ -264,6 +266,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
264
266
  },
265
267
  colorScheme: colorScheme,
266
268
  isInserted: isInserted,
269
+ leftAnchorId: leftAnchorId,
267
270
  isActive: _isActive,
268
271
  shouldHideDeleted: shouldHideDeleted,
269
272
  showContributorTags: showContributorTags,
@@ -546,6 +549,10 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
546
549
  });
547
550
  };
548
551
  var createDecorationsForChange = function createDecorationsForChange(change) {
552
+ // Patch 2 makes all decorations generated for one replacement share this anchor. Their own
553
+ // IDs still identify their top/bottom bounds, while this ID makes their bars agree on one
554
+ // left edge. When the gate is off, factories retain their existing per-decoration anchors.
555
+ var leftAnchorId = fg('platform_editor_ai_show_diff_patch_2') ? "replacement-".concat(change.fromA, "-").concat(change.toA, "-").concat(change.fromB, "-").concat(change.toB) : undefined;
549
556
  var changeColorScheme = attributionColors ? getColorSchemeForChange(change, attributedChanges, attributionColors, colorScheme) : colorScheme;
550
557
  var attributionKey = showContributorTags ? getAttributionKeyForChange(change, attributedChanges) : undefined;
551
558
  var isActive = isRangeActive(activeIndexPos, change.fromB, change.toB);
@@ -678,6 +685,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
678
685
  fromB: from,
679
686
  toB: to
680
687
  },
688
+ leftAnchorId: leftAnchorId,
681
689
  doc: tr.doc,
682
690
  colorScheme: changeColorScheme,
683
691
  isActive: isActive,
@@ -703,6 +711,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
703
711
  decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration(_objectSpread({
704
712
  attributionKey: attributionKey,
705
713
  change: change,
714
+ leftAnchorId: leftAnchorId,
706
715
  doc: tr.doc,
707
716
  colorScheme: changeColorScheme,
708
717
  isActive: isActive,
@@ -737,7 +746,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
737
746
  activeIndexPos: activeIndexPos,
738
747
  intl: intl,
739
748
  diffType: diffType,
740
- coarseTableCellsOnly: useCoarseTableDecoration
749
+ coarseTableCellsOnly: useCoarseTableDecoration,
750
+ leftAnchorId: leftAnchorId
741
751
  }))));
742
752
  }
743
753
  if (change.deleted.length > 0 && !isMarkOnly && !hasNoDeletedContent) {
@@ -762,6 +772,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
762
772
  newDoc: tr.doc,
763
773
  intl: intl,
764
774
  activeIndexPos: activeIndexPos,
775
+ leftAnchorId: leftAnchorId,
765
776
  showContributorTags: showContributorTags,
766
777
  tagMountContext: tagMountContext
767
778
  }, isExtendedEnabled(diffType) && {