@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
@@ -1,4 +1,8 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
1
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
4
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
5
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
2
6
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
7
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
8
  import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
@@ -30,21 +34,21 @@ var resolveDocLevelNode = function resolveDocLevelNode(doc, from) {
30
34
  beforePos: nodeStart - 1
31
35
  };
32
36
  };
33
-
34
37
  /**
35
38
  * Handles edge cases for block nodes whose inline content can exceed the doc
36
39
  * margin (tables, layouts, expands). Returns the position whose DOM should be
37
40
  * measured to size the left anchor, or `undefined` when the diff is not inside
38
41
  * such a node.
39
42
  */
40
- var edgeCases = function edgeCases(doc, from) {
43
+ var edgeCases = function edgeCases(doc, from, nodeOverride) {
41
44
  var resolved = resolveDocLevelNode(doc, from);
42
45
  if (!resolved) {
43
46
  return undefined;
44
47
  }
45
- var node = resolved.node,
48
+ var resolvedNode = resolved.node,
46
49
  nodeStart = resolved.nodeStart,
47
50
  beforePos = resolved.beforePos;
51
+ var node = fg('platform_editor_ai_show_diff_patch_2') ? nodeOverride !== null && nodeOverride !== void 0 ? nodeOverride : resolvedNode : resolvedNode;
48
52
  if (node.type.name === 'layoutSection' && fg('platform_editor_ai_show_diff_patch_1')) {
49
53
  // Columns extend past the node-view wrapper via negative margins (12px or 20px).
50
54
  // Measure their container so the indicator stays outside the diff outline, including
@@ -112,6 +116,45 @@ var edgeCases = function edgeCases(doc, from) {
112
116
  return undefined;
113
117
  }
114
118
  };
119
+ var getEdgeCasesForSlice = function getEdgeCasesForSlice(doc, from, slice, measureElement) {
120
+ var _targets$find;
121
+ var resolved = resolveDocLevelNode(doc, from);
122
+ if (!resolved) {
123
+ return [];
124
+ }
125
+ var targets = [];
126
+ // edge cases can only be top level nodes, so we only care about the top level nodes in the slice
127
+ slice.content.forEach(function (node, offset) {
128
+ var edgeCase = edgeCases(doc, from + offset, node);
129
+ if (edgeCase) {
130
+ targets.push(_objectSpread(_objectSpread({}, edgeCase), {}, {
131
+ measureElement: measureElement
132
+ }));
133
+ }
134
+ });
135
+ return targets.length > 0 ? [{
136
+ beforePos: resolved.beforePos,
137
+ leftOffset: (_targets$find = targets.find(function (target) {
138
+ return target.leftOffset !== undefined;
139
+ })) === null || _targets$find === void 0 ? void 0 : _targets$find.leftOffset,
140
+ widthMeasureTargets: targets
141
+ }] : [];
142
+ };
143
+
144
+ /**
145
+ * Finds the edge cases in the current document for either a whole range or one position.
146
+ * A missing `to` intentionally means the single-position lookup is the fallback.
147
+ */
148
+ var getEdgeCasesForDocument = function getEdgeCasesForDocument(doc, from, to) {
149
+ if (to !== undefined) {
150
+ var edgeCasesForSlice = getEdgeCasesForSlice(doc, from, doc.slice(from, to));
151
+ if (edgeCasesForSlice.length > 0) {
152
+ return edgeCasesForSlice;
153
+ }
154
+ }
155
+ var edgeCase = edgeCases(doc, from);
156
+ return edgeCase ? [edgeCase] : [];
157
+ };
115
158
 
116
159
  /**
117
160
  * Create a widget that marks the start of the doc margin.
@@ -142,10 +185,23 @@ export var createDocMarginAnchorWidget = function createDocMarginAnchorWidget()
142
185
  * anchor positioning. Shared by inline and node (widget) diff decorations.
143
186
  */
144
187
  export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
188
+ var _range$from;
145
189
  var doc = _ref.doc,
146
190
  from = _ref.from,
147
- diffId = _ref.diffId;
148
- var edgeCase = edgeCases(doc, from);
191
+ to = _ref.to,
192
+ diffId = _ref.diffId,
193
+ leftAnchorId = _ref.leftAnchorId,
194
+ measureElement = _ref.measureElement,
195
+ sliceOverride = _ref.sliceOverride,
196
+ underlyingRange = _ref.underlyingRange;
197
+ var overrideEdgeCases = sliceOverride ? getEdgeCasesForSlice(doc, from, sliceOverride, measureElement) : [];
198
+ var range = underlyingRange !== null && underlyingRange !== void 0 ? underlyingRange : to !== undefined ? {
199
+ from: from,
200
+ to: to
201
+ } : undefined;
202
+ var 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);
203
+ var allEdgeCases = [].concat(_toConsumableArray(overrideEdgeCases), _toConsumableArray(documentEdgeCases));
204
+ var edgeCase = fg('platform_editor_ai_show_diff_patch_2') ? allEdgeCases[0] : edgeCases(doc, from);
149
205
  if (edgeCase === undefined) {
150
206
  return undefined;
151
207
  }
@@ -154,7 +210,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
154
210
  // resizable block container.
155
211
  var beforePos = edgeCase.beforePos;
156
212
  var leftAnchorKey = buildAnchorDecorationKey({
157
- diffId: diffId,
213
+ diffId: leftAnchorId !== null && leftAnchorId !== void 0 ? leftAnchorId : diffId,
158
214
  anchorType: AnchorTypeKey.left
159
215
  });
160
216
  var leftResizeObserver;
@@ -172,15 +228,87 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
172
228
  anchor.style.setProperty('left', "calc(50% - ".concat((edgeCase === null || edgeCase === void 0 ? void 0 : edgeCase.leftOffset) || 0, "px)"));
173
229
  anchor.style.setProperty('transform', 'translateX(-50%)');
174
230
  wrapper.appendChild(anchor);
175
- var measureWidth = function measureWidth() {
231
+ var _measureWidth = function measureWidth() {
176
232
  var _nodeDOM$querySelecto;
233
+ if (fg('platform_editor_ai_show_diff_patch_2')) {
234
+ var widthMeasureTargets = allEdgeCases.flatMap(function (target) {
235
+ var _target$widthMeasureT;
236
+ return (_target$widthMeasureT = target.widthMeasureTargets) !== null && _target$widthMeasureT !== void 0 ? _target$widthMeasureT : [target];
237
+ });
238
+ if (getPos() === undefined || widthMeasureTargets.length === 0) {
239
+ return;
240
+ }
241
+ var measuredElements = widthMeasureTargets.flatMap(function (_ref2) {
242
+ var targetMeasureElement = _ref2.measureElement,
243
+ measureLeft = _ref2.measureLeft,
244
+ measurePos = _ref2.measurePos,
245
+ measureSelector = _ref2.measureSelector;
246
+ if (measurePos === undefined) {
247
+ return [];
248
+ }
249
+ var nodeDOM = targetMeasureElement !== null && targetMeasureElement !== void 0 ? targetMeasureElement : view.nodeDOM(measurePos);
250
+ var elements = nodeDOM instanceof HTMLElement ? measureSelector ? Array.from(nodeDOM.querySelectorAll(measureSelector)) : [nodeDOM] : [];
251
+ return elements.map(function (element) {
252
+ return {
253
+ element: element,
254
+ measureLeft: measureLeft
255
+ };
256
+ });
257
+ });
258
+
259
+ // A single diff can include multiple edge-case nodes, so measure the widest one.
260
+ var widest;
261
+ var _iterator = _createForOfIteratorHelper(measuredElements),
262
+ _step;
263
+ try {
264
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
265
+ var target = _step.value;
266
+ if (!widest || target.element.offsetWidth > widest.element.offsetWidth) {
267
+ widest = target;
268
+ }
269
+ }
270
+ } catch (err) {
271
+ _iterator.e(err);
272
+ } finally {
273
+ _iterator.f();
274
+ }
275
+ if (widest) {
276
+ var updateAnchor = function updateAnchor() {
277
+ if (getPos() === undefined) {
278
+ return;
279
+ }
280
+ if (widest.measureLeft) {
281
+ var left = widest.element.getBoundingClientRect().left - wrapper.getBoundingClientRect().left;
282
+ anchor.style.setProperty('left', "".concat(left, "px"));
283
+ anchor.style.setProperty('transform', 'none');
284
+ }
285
+ anchor.style.setProperty('width', "".concat(widest.element.offsetWidth, "px"));
286
+ };
287
+ updateAnchor();
288
+
289
+ // Observe the measured elements for size changes (e.g. page
290
+ // resize) so the indicator stays aligned.
291
+ if (!leftResizeObserver) {
292
+ leftResizeObserver = new ResizeObserver(_measureWidth);
293
+ measuredElements.forEach(function (_ref3) {
294
+ var _leftResizeObserver;
295
+ var element = _ref3.element;
296
+ return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.observe(element);
297
+ });
298
+ if (widest.measureLeft) {
299
+ leftResizeObserver.observe(wrapper);
300
+ }
301
+ }
302
+ }
303
+ return;
304
+ }
177
305
  if (getPos() === undefined || edgeCase.measurePos === undefined) {
178
306
  return;
179
307
  }
180
308
  var nodeDOM = view.nodeDOM(edgeCase.measurePos);
181
309
  var dom = edgeCase.measureSelector && nodeDOM instanceof HTMLElement ? (_nodeDOM$querySelecto = nodeDOM.querySelector(edgeCase.measureSelector)) !== null && _nodeDOM$querySelecto !== void 0 ? _nodeDOM$querySelecto : nodeDOM : nodeDOM;
182
310
  if (dom instanceof HTMLElement) {
183
- var updateAnchor = function updateAnchor() {
311
+ var _updateAnchor = function _updateAnchor() {
184
312
  if (getPos() === undefined) {
185
313
  return;
186
314
  }
@@ -192,12 +320,12 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
192
320
  anchor.style.setProperty('width', "".concat(dom.offsetWidth, "px"));
193
321
  };
194
322
  // Align against the block's horizontal extent.
195
- updateAnchor();
323
+ _updateAnchor();
196
324
 
197
325
  // Observe the measured element for size changes (e.g. page
198
326
  // resize) so the indicator stays aligned. CCI-17981
199
327
  if (!leftResizeObserver) {
200
- leftResizeObserver = new ResizeObserver(updateAnchor);
328
+ leftResizeObserver = new ResizeObserver(_updateAnchor);
201
329
  leftResizeObserver.observe(dom);
202
330
  if (edgeCase.measureLeft) {
203
331
  leftResizeObserver.observe(wrapper);
@@ -208,7 +336,7 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
208
336
 
209
337
  // The block DOM may not be settled synchronously (e.g. after a
210
338
  // transaction), so defer the measurement like the gap cursor does.
211
- requestAnimationFrame(measureWidth);
339
+ requestAnimationFrame(_measureWidth);
212
340
  return wrapper;
213
341
  }, _objectSpread(_objectSpread({}, buildAnchorDecorationSpec({
214
342
  diffId: diffId,
@@ -216,8 +344,8 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
216
344
  side: -999
217
345
  })), {}, {
218
346
  destroy: function destroy() {
219
- var _leftResizeObserver;
220
- return (_leftResizeObserver = leftResizeObserver) === null || _leftResizeObserver === void 0 ? void 0 : _leftResizeObserver.disconnect();
347
+ var _leftResizeObserver2;
348
+ return (_leftResizeObserver2 = leftResizeObserver) === null || _leftResizeObserver2 === void 0 ? void 0 : _leftResizeObserver2.disconnect();
221
349
  }
222
350
  }));
223
351
  };
@@ -233,16 +361,18 @@ export var createLeftAnchorWidget = function createLeftAnchorWidget(_ref) {
233
361
  * layout, expand) so the bar aligns within the container boundary.
234
362
  *
235
363
  */
236
- export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnchorWidgets(_ref2) {
237
- var _ref3, _parentTable$pos;
238
- var doc = _ref2.doc,
239
- from = _ref2.from,
240
- to = _ref2.to,
241
- diffId = _ref2.diffId;
364
+ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnchorWidgets(_ref4) {
365
+ var _ref5, _parentTable$pos;
366
+ var doc = _ref4.doc,
367
+ from = _ref4.from,
368
+ to = _ref4.to,
369
+ diffId = _ref4.diffId,
370
+ leftAnchorId = _ref4.leftAnchorId;
242
371
  var leftAnchor = createLeftAnchorWidget({
243
372
  doc: doc,
244
373
  from: from,
245
- diffId: diffId
374
+ diffId: diffId,
375
+ leftAnchorId: leftAnchorId
246
376
  });
247
377
  var maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
248
378
 
@@ -281,7 +411,7 @@ export var createBlockIndicatorAnchorWidgets = function createBlockIndicatorAnch
281
411
  // bounding box or positioning context, so measuring its top produces an offset from the
282
412
  // viewport origin and displaces the indicator into content below the editor. Keep the
283
413
  // wrapper outside the layout, just as we do for tables, but still measure the target node.
284
- var widgetPos = (_ref3 = (_parentTable$pos = parentTable === null || parentTable === void 0 ? void 0 : parentTable.pos) !== null && _parentTable$pos !== void 0 ? _parentTable$pos : parentLayout === null || parentLayout === void 0 ? void 0 : parentLayout.pos) !== null && _ref3 !== void 0 ? _ref3 : from;
414
+ var widgetPos = (_ref5 = (_parentTable$pos = parentTable === null || parentTable === void 0 ? void 0 : parentTable.pos) !== null && _parentTable$pos !== void 0 ? _parentTable$pos : parentLayout === null || parentLayout === void 0 ? void 0 : parentLayout.pos) !== null && _ref5 !== void 0 ? _ref5 : from;
285
415
  // Measure the actual cell/row DOM when inside one; otherwise measure the
286
416
  // widget's own position.
287
417
  var measurePos = parentCellOrRow ? parentCellOrRow.pos : from;
@@ -380,11 +510,11 @@ export var createAnchorNameSpan = function createAnchorNameSpan(anchorKey) {
380
510
  span.style.setProperty('anchor-name', "--".concat(anchorKey));
381
511
  return span;
382
512
  };
383
- var createAnchorSpanWidget = function createAnchorSpanWidget(_ref4) {
384
- var pos = _ref4.pos,
385
- diffId = _ref4.diffId,
386
- anchorType = _ref4.anchorType,
387
- side = _ref4.side;
513
+ var createAnchorSpanWidget = function createAnchorSpanWidget(_ref6) {
514
+ var pos = _ref6.pos,
515
+ diffId = _ref6.diffId,
516
+ anchorType = _ref6.anchorType,
517
+ side = _ref6.side;
388
518
  return Decoration.widget(pos, function () {
389
519
  return createAnchorNameSpan(buildAnchorDecorationKey({
390
520
  diffId: diffId,
@@ -401,15 +531,18 @@ var createAnchorSpanWidget = function createAnchorSpanWidget(_ref4) {
401
531
  * Invisible `from`/`to` (and optional `left`) anchor widgets for one inline diff
402
532
  * range, so the `IndicatorBar` can align itself via CSS anchor positioning.
403
533
  */
404
- export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAnchorWidgets(_ref5) {
405
- var doc = _ref5.doc,
406
- from = _ref5.from,
407
- to = _ref5.to,
408
- diffId = _ref5.diffId;
534
+ export var createInlineIndicatorAnchorWidgets = function createInlineIndicatorAnchorWidgets(_ref7) {
535
+ var doc = _ref7.doc,
536
+ from = _ref7.from,
537
+ to = _ref7.to,
538
+ diffId = _ref7.diffId,
539
+ leftAnchorId = _ref7.leftAnchorId;
409
540
  var leftAnchor = createLeftAnchorWidget({
410
541
  doc: doc,
411
542
  from: from,
412
- diffId: diffId
543
+ to: fg('platform_editor_ai_show_diff_patch_2') ? to : undefined,
544
+ diffId: diffId,
545
+ leftAnchorId: leftAnchorId
413
546
  });
414
547
  var maybeLeftAnchor = leftAnchor ? [leftAnchor] : [];
415
548
 
@@ -177,6 +177,7 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
177
177
  isInserted = _ref3$isInserted === void 0 ? true : _ref3$isInserted,
178
178
  _ref3$isActive = _ref3.isActive,
179
179
  isActive = _ref3$isActive === void 0 ? false : _ref3$isActive,
180
+ leftAnchorId = _ref3.leftAnchorId,
180
181
  _ref3$shouldHideDelet = _ref3.shouldHideDeleted,
181
182
  shouldHideDeleted = _ref3$shouldHideDelet === void 0 ? false : _ref3$shouldHideDelet,
182
183
  _ref3$showContributor = _ref3.showContributorTags,
@@ -207,6 +208,7 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
207
208
  colorScheme: colorScheme,
208
209
  decorationType: 'block',
209
210
  diffId: diffId,
211
+ leftAnchorId: leftAnchorId,
210
212
  isActive: isActive,
211
213
  isInserted: isInserted,
212
214
  nodeName: change.name,
@@ -263,6 +265,7 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
263
265
  colorScheme: colorScheme,
264
266
  decorationType: 'block',
265
267
  diffId: diffId,
268
+ leftAnchorId: leftAnchorId,
266
269
  isActive: isActive,
267
270
  isInserted: isInserted,
268
271
  nodeName: change.name,
@@ -279,7 +282,8 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
279
282
  doc: doc,
280
283
  from: change.from,
281
284
  to: change.to,
282
- diffId: diffId
285
+ diffId: diffId,
286
+ leftAnchorId: leftAnchorId
283
287
  })));
284
288
  }
285
289
 
@@ -297,7 +301,7 @@ export var createBlockChangedDecoration = function createBlockChangedDecoration(
297
301
  mountContext: tagMountContext
298
302
  });
299
303
  if (tagWidget) {
300
- decorations.push(tagWidget);
304
+ decorations.push.apply(decorations, _toConsumableArray(tagWidget));
301
305
  }
302
306
  }
303
307
  return decorations;
@@ -305,6 +305,7 @@ export var createChangedRowDecorationWidgets = function createChangedRowDecorati
305
305
  isActive = _ref6.isActive,
306
306
  _ref6$isInserted = _ref6.isInserted,
307
307
  isInserted = _ref6$isInserted === void 0 ? false : _ref6$isInserted,
308
+ leftAnchorId = _ref6.leftAnchorId,
308
309
  diffType = _ref6.diffType,
309
310
  intl = _ref6.intl,
310
311
  _ref6$showIndicators = _ref6.showIndicators,
@@ -359,7 +360,8 @@ export var createChangedRowDecorationWidgets = function createChangedRowDecorati
359
360
  var leftAnchor = createLeftAnchorWidget({
360
361
  doc: newDoc,
361
362
  from: safeInsertPos,
362
- diffId: diffId
363
+ diffId: diffId,
364
+ leftAnchorId: leftAnchorId
363
365
  });
364
366
  if (leftAnchor) {
365
367
  decorations.push(leftAnchor);
@@ -401,6 +403,7 @@ export var createChangedRowDecorationWidgets = function createChangedRowDecorati
401
403
  colorScheme: colorScheme,
402
404
  decorationType: 'widget',
403
405
  diffId: diffId,
406
+ leftAnchorId: leftAnchorId,
404
407
  isActive: isActive,
405
408
  isInserted: isInserted,
406
409
  diffType: diffType
@@ -416,7 +419,7 @@ export var createChangedRowDecorationWidgets = function createChangedRowDecorati
416
419
  }));
417
420
  }
418
421
  if (tagWidget) {
419
- decorations.push(tagWidget);
422
+ decorations.push.apply(decorations, _toConsumableArray(tagWidget));
420
423
  }
421
424
  return decorations;
422
425
  });
@@ -6,7 +6,7 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
6
6
  import { ContributorTagController } from '../../ui/ContributorTag/contributorTagController';
7
7
  import { buildCharsByOffset, isWhitespaceChar } from '../utils/charsByOffset';
8
8
  import { clampAnchorPosIntoCell } from './createAnchorDecorationWidgets';
9
- import { buildContributorTagDecorationSpec } from './decorationKeys';
9
+ import { AnchorTypeKey, buildAnchorDecorationKey, buildContributorTagDecorationSpec } from './decorationKeys';
10
10
 
11
11
  /** Marks the host element of one tag, so a tag can be found in the document by its own diff. */
12
12
  export var CONTRIBUTOR_TAG_HOST_ATTRIBUTE = 'data-contributor-tag-host';
@@ -168,13 +168,12 @@ var resolveTagAnchorPos = function resolveTagAnchorPos(doc, from, to) {
168
168
  };
169
169
 
170
170
  /**
171
- * The position just before the code block enclosing `pos`, or `undefined` when nothing does.
171
+ * Position just before the code block enclosing `pos`, or `undefined` if there is none.
172
172
  *
173
- * `.code-block-content-wrapper` hides its block-axis overflow, so a host left inside the code has
174
- * its tag clipped away. Hosting it before the block puts the tag on the block's top-left corner,
175
- * where a whole-code-block change is tagged too (EDITOR-8766).
173
+ * Code blocks clip/scroll their own content, so a tag hosted inside one gets clipped away. Hoisting
174
+ * it before the block avoids that (EDITOR-9045, EDITOR-8766).
176
175
  */
177
- var resolveCodeBlockStart = function resolveCodeBlockStart(doc, pos) {
176
+ export var resolveCodeBlockStart = function resolveCodeBlockStart(doc, pos) {
178
177
  var $pos = doc.resolve(pos);
179
178
  for (var depth = $pos.depth; depth > 0; depth--) {
180
179
  if ($pos.node(depth).type.name === 'codeBlock') {
@@ -185,14 +184,47 @@ var resolveCodeBlockStart = function resolveCodeBlockStart(doc, pos) {
185
184
  };
186
185
 
187
186
  /**
188
- * A widget hosting the contributor tag of one diff range, placed on the first visible character the
189
- * range highlights or, with `anchorAtRangeStart`, at `from` itself. Either way a host that would
190
- * land inside a code block is hoisted out in front of it; see `resolveCodeBlockStart`.
187
+ * If `pos` is inside a code block: a marker decoration to anchor the hoisted tag against, plus the
188
+ * position just before the block to host that tag at (EDITOR-9045).
189
+ */
190
+ export var resolveHoistedCodeBlockAnchor = function resolveHoistedCodeBlockAnchor(doc, pos, diffId) {
191
+ var codeBlockStart = resolveCodeBlockStart(doc, pos);
192
+ if (codeBlockStart === undefined) {
193
+ return undefined;
194
+ }
195
+ var anchorName = buildAnchorDecorationKey({
196
+ diffId: diffId,
197
+ anchorType: AnchorTypeKey.tag
198
+ });
199
+ var marker = Decoration.widget(pos, function () {
200
+ var el = document.createElement('span');
201
+ el.style.setProperty('anchor-name', "--".concat(anchorName));
202
+ return el;
203
+ }, {
204
+ key: "contributor-tag-anchor-".concat(diffId),
205
+ side: -1,
206
+ marks: [],
207
+ ignoreSelection: true
208
+ });
209
+ return {
210
+ anchorName: anchorName,
211
+ codeBlockStart: codeBlockStart,
212
+ marker: marker
213
+ };
214
+ };
215
+
216
+ /**
217
+ * The contributor tag widget for one diff range, placed on the first visible character the range
218
+ * highlights — or, with `anchorAtRangeStart`, at `from` itself. A host inside a code block is
219
+ * hoisted in front of it instead, anchored via `resolveHoistedCodeBlockAnchor` (EDITOR-9045).
220
+ *
221
+ * Returns one decoration normally, two (marker + tag) when hoisted out of a code block.
191
222
  *
192
223
  * The tag is mounted in `toDOM` and taken down in `destroy`, so it lives exactly as long as the host
193
224
  * element ProseMirror drew it into — see `mountContributorTag`.
194
225
  */
195
226
  export var createContributorTagWidget = function createContributorTagWidget(_ref4) {
227
+ var _hoisted$anchorName, _hoisted$codeBlockSta;
196
228
  var _ref4$anchorAtRangeSt = _ref4.anchorAtRangeStart,
197
229
  anchorAtRangeStart = _ref4$anchorAtRangeSt === void 0 ? false : _ref4$anchorAtRangeSt,
198
230
  anchorName = _ref4.anchorName,
@@ -204,17 +236,23 @@ export var createContributorTagWidget = function createContributorTagWidget(_ref
204
236
  if (!isContributorTagWidgetEnabled()) {
205
237
  return undefined;
206
238
  }
207
- var tagAnchorName = anchorName && supportsAnchorPositioning() ? anchorName : undefined;
208
239
 
209
240
  // Reassigned when ProseMirror redraws this decoration, which it may do more than once for the
210
241
  // same `Decoration` instance.
211
242
  var mount;
212
243
  var anchorPos = anchorAtRangeStart ? from : resolveTagAnchorPos(doc, from, to);
213
- // A change inside a code block is hoisted out of it; anything else keeps its own anchor.
214
- var codeBlockPos = resolveCodeBlockStart(doc, anchorPos);
215
- return Decoration.widget(
244
+ // A change inside a code block is hoisted out of it, anchored to its own marker; anything else
245
+ // keeps its own anchor.
246
+ var hoisted = resolveHoistedCodeBlockAnchor(doc, anchorPos, diffId);
247
+ var effectiveAnchorName = (_hoisted$anchorName = hoisted === null || hoisted === void 0 ? void 0 : hoisted.anchorName) !== null && _hoisted$anchorName !== void 0 ? _hoisted$anchorName : anchorName;
248
+ var tagAnchorName = effectiveAnchorName && supportsAnchorPositioning() ? effectiveAnchorName : undefined;
249
+ var decorations = [];
250
+ if (hoisted) {
251
+ decorations.push(hoisted.marker);
252
+ }
253
+ decorations.push(Decoration.widget(
216
254
  // Keep the host out of the table row's grid (EDITOR-8442).
217
- clampAnchorPosIntoCell(doc, codeBlockPos !== null && codeBlockPos !== void 0 ? codeBlockPos : anchorPos, 1), function () {
255
+ clampAnchorPosIntoCell(doc, (_hoisted$codeBlockSta = hoisted === null || hoisted === void 0 ? void 0 : hoisted.codeBlockStart) !== null && _hoisted$codeBlockSta !== void 0 ? _hoisted$codeBlockSta : anchorPos, 1), function () {
218
256
  var host = buildContributorTagHost(diffId, tagAnchorName);
219
257
  mount = mountContributorTag({
220
258
  anchorName: tagAnchorName,
@@ -236,5 +274,6 @@ export var createContributorTagWidget = function createContributorTagWidget(_ref
236
274
  unmountContributorTag(mount);
237
275
  mount = undefined;
238
276
  }
239
- }));
277
+ })));
278
+ return decorations;
240
279
  };
@@ -139,6 +139,7 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
139
139
  isActive = _ref2$isActive === void 0 ? false : _ref2$isActive,
140
140
  _ref2$isInserted = _ref2.isInserted,
141
141
  isInserted = _ref2$isInserted === void 0 ? true : _ref2$isInserted,
142
+ leftAnchorId = _ref2.leftAnchorId,
142
143
  _ref2$isAtomicInlineN = _ref2.isAtomicInlineNode,
143
144
  isAtomicInlineNode = _ref2$isAtomicInlineN === void 0 ? false : _ref2$isAtomicInlineN,
144
145
  _ref2$shouldHideDelet = _ref2.shouldHideDeleted,
@@ -175,6 +176,7 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
175
176
  colorScheme: colorScheme,
176
177
  decorationType: 'inline',
177
178
  diffId: diffId,
179
+ leftAnchorId: leftAnchorId,
178
180
  isActive: isActive,
179
181
  isInserted: isInserted
180
182
  }))];
@@ -238,6 +240,7 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
238
240
  colorScheme: colorScheme,
239
241
  decorationType: 'inline',
240
242
  diffId: diffId,
243
+ leftAnchorId: leftAnchorId,
241
244
  isActive: isActive,
242
245
  isInserted: isInserted
243
246
  }))];
@@ -273,14 +276,15 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
273
276
  doc: doc,
274
277
  from: anchorFrom,
275
278
  to: anchorTo,
276
- diffId: diffId
279
+ diffId: diffId,
280
+ leftAnchorId: leftAnchorId
277
281
  })));
278
282
  }
279
283
 
280
284
  // Pushed after the indicator anchors so the decoration order is unchanged — see `tagWidget` above
281
285
  // for why it is built before them.
282
286
  if (tagWidget) {
283
- decorations.push(tagWidget);
287
+ decorations.push.apply(decorations, _toConsumableArray(tagWidget));
284
288
  }
285
289
  return decorations;
286
290
  };