@atlaskit/editor-plugin-show-diff 16.1.0 → 16.2.0

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 (64) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/afm-products/tsconfig.json +3 -0
  3. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +67 -22
  4. package/dist/cjs/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +242 -26
  5. package/dist/cjs/pm-plugins/decorations/colorSchemes/factory.js +71 -37
  6. package/dist/cjs/pm-plugins/decorations/colorSchemes/schemes.js +5 -1
  7. package/dist/cjs/pm-plugins/decorations/colorSchemes/types.js +0 -2
  8. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +21 -14
  9. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
  10. package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +123 -43
  11. package/dist/cjs/pm-plugins/decorations/revealStyles.js +5 -1
  12. package/dist/cjs/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +33 -0
  13. package/dist/cjs/pm-plugins/decorations/utils/createMarginAbsorber.js +43 -0
  14. package/dist/cjs/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +76 -0
  15. package/dist/cjs/pm-plugins/decorations/utils/safeResolve.js +24 -0
  16. package/dist/cjs/pm-plugins/getScrollableDecorations.js +48 -19
  17. package/dist/cjs/pm-plugins/utils/baseNodeName.js +25 -0
  18. package/dist/cjs/pm-plugins/utils/taggableBlockNodes.js +37 -0
  19. package/dist/cjs/ui/ContributorTag/contributorTagController.js +4 -4
  20. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +39 -2
  21. package/dist/es2019/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +196 -10
  22. package/dist/es2019/pm-plugins/decorations/colorSchemes/factory.js +51 -19
  23. package/dist/es2019/pm-plugins/decorations/colorSchemes/schemes.js +3 -0
  24. package/dist/es2019/pm-plugins/decorations/colorSchemes/types.js +0 -2
  25. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +23 -14
  26. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
  27. package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +60 -7
  28. package/dist/es2019/pm-plugins/decorations/revealStyles.js +5 -1
  29. package/dist/es2019/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +29 -0
  30. package/dist/es2019/pm-plugins/decorations/utils/createMarginAbsorber.js +39 -0
  31. package/dist/es2019/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +69 -0
  32. package/dist/es2019/pm-plugins/decorations/utils/safeResolve.js +18 -0
  33. package/dist/es2019/pm-plugins/getScrollableDecorations.js +44 -19
  34. package/dist/es2019/pm-plugins/utils/baseNodeName.js +18 -0
  35. package/dist/es2019/pm-plugins/utils/taggableBlockNodes.js +28 -0
  36. package/dist/es2019/ui/ContributorTag/contributorTagController.js +4 -4
  37. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +67 -22
  38. package/dist/esm/pm-plugins/calculateDiff/simplifyChangesWithAttribution.js +243 -26
  39. package/dist/esm/pm-plugins/decorations/colorSchemes/factory.js +71 -37
  40. package/dist/esm/pm-plugins/decorations/colorSchemes/schemes.js +5 -1
  41. package/dist/esm/pm-plugins/decorations/colorSchemes/types.js +0 -2
  42. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +21 -14
  43. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +83 -3
  44. package/dist/esm/pm-plugins/decorations/extractContributorTags.js +123 -43
  45. package/dist/esm/pm-plugins/decorations/revealStyles.js +5 -1
  46. package/dist/esm/pm-plugins/decorations/utils/absorbFirstChildMarginReset.js +28 -0
  47. package/dist/esm/pm-plugins/decorations/utils/createMarginAbsorber.js +37 -0
  48. package/dist/esm/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.js +70 -0
  49. package/dist/esm/pm-plugins/decorations/utils/safeResolve.js +18 -0
  50. package/dist/esm/pm-plugins/getScrollableDecorations.js +48 -19
  51. package/dist/esm/pm-plugins/utils/baseNodeName.js +20 -0
  52. package/dist/esm/pm-plugins/utils/taggableBlockNodes.js +32 -0
  53. package/dist/esm/ui/ContributorTag/contributorTagController.js +4 -4
  54. package/dist/types/pm-plugins/calculateDiff/simplifyChangesWithAttribution.d.ts +20 -1
  55. package/dist/types/pm-plugins/decorations/colorSchemes/factory.d.ts +4 -11
  56. package/dist/types/pm-plugins/decorations/colorSchemes/types.d.ts +9 -8
  57. package/dist/types/pm-plugins/decorations/utils/absorbFirstChildMarginReset.d.ts +23 -0
  58. package/dist/types/pm-plugins/decorations/utils/createMarginAbsorber.d.ts +23 -0
  59. package/dist/types/pm-plugins/decorations/utils/createNodeShapedMarginSpacer.d.ts +26 -0
  60. package/dist/types/pm-plugins/decorations/utils/safeResolve.d.ts +13 -0
  61. package/dist/types/pm-plugins/getScrollableDecorations.d.ts +2 -2
  62. package/dist/types/pm-plugins/utils/baseNodeName.d.ts +16 -0
  63. package/dist/types/pm-plugins/utils/taggableBlockNodes.d.ts +14 -0
  64. package/package.json +14 -5
@@ -73,6 +73,7 @@ exports.getDeletedHighlightHoverColor = getDeletedHighlightHoverColor;
73
73
  exports.getDeletedInlineRevealColors = getDeletedInlineRevealColors;
74
74
  exports.getInsertedInlineRevealColors = getInsertedInlineRevealColors;
75
75
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
76
+ var _agentBrandColorSchemes = require("@atlaskit/agent-color/agent-brand-color-schemes");
76
77
  var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
77
78
  var _getStandardDeletedTextDecorationStyle = require("./getStandardDeletedTextDecorationStyle");
78
79
  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; }
@@ -191,40 +192,48 @@ var textAccentMap = {
191
192
  gray: "var(--ds-text-accent-gray, #505258)",
192
193
  lime: "var(--ds-text-accent-lime, #4C6B1F)"
193
194
  };
195
+ var getBrand = function getBrand(color) {
196
+ return Object.prototype.hasOwnProperty.call(_agentBrandColorSchemes.agentBrandColorSchemes, color) ? _agentBrandColorSchemes.agentBrandColorSchemes[color] : undefined;
197
+ };
194
198
  function bgSubtlest(color) {
195
- return bgSubtlestMap[color];
199
+ var _getBrand$background, _getBrand;
200
+ return (_getBrand$background = (_getBrand = getBrand(color)) === null || _getBrand === void 0 ? void 0 : _getBrand.background) !== null && _getBrand$background !== void 0 ? _getBrand$background : bgSubtlestMap[color];
196
201
  }
197
202
  function bgSubtlestPressed(color) {
198
- return bgSubtlestPressedMap[color];
203
+ var _getBrand$background2, _getBrand2;
204
+ return (_getBrand$background2 = (_getBrand2 = getBrand(color)) === null || _getBrand2 === void 0 ? void 0 : _getBrand2.background) !== null && _getBrand$background2 !== void 0 ? _getBrand$background2 : bgSubtlestPressedMap[color];
199
205
  }
200
206
  function bgSubtler(color) {
201
- return bgSubtlerMap[color];
207
+ var _getBrand$border, _getBrand3;
208
+ return (_getBrand$border = (_getBrand3 = getBrand(color)) === null || _getBrand3 === void 0 ? void 0 : _getBrand3.border) !== null && _getBrand$border !== void 0 ? _getBrand$border : bgSubtlerMap[color];
202
209
  }
203
210
  function bgBolder(color) {
204
- return bgBolderMap[color];
211
+ var _getBrand$bold, _getBrand4;
212
+ return (_getBrand$bold = (_getBrand4 = getBrand(color)) === null || _getBrand4 === void 0 ? void 0 : _getBrand4.bold) !== null && _getBrand$bold !== void 0 ? _getBrand$bold : bgBolderMap[color];
205
213
  }
206
214
  function bgSubtlerPressed(color) {
207
- return bgSubtlerPressedMap[color];
215
+ var _getBrand$background3, _getBrand5;
216
+ return (_getBrand$background3 = (_getBrand5 = getBrand(color)) === null || _getBrand5 === void 0 ? void 0 : _getBrand5.background) !== null && _getBrand$background3 !== void 0 ? _getBrand$background3 : bgSubtlerPressedMap[color];
208
217
  }
209
218
  function borderAccent(color) {
210
- return borderAccentMap[color];
219
+ var _getBrand$border2, _getBrand6;
220
+ return (_getBrand$border2 = (_getBrand6 = getBrand(color)) === null || _getBrand6 === void 0 ? void 0 : _getBrand6.border) !== null && _getBrand$border2 !== void 0 ? _getBrand$border2 : borderAccentMap[color];
211
221
  }
212
222
  function textAccent(color) {
213
- return textAccentMap[color];
223
+ var _getBrand$accentText, _getBrand7;
224
+ return (_getBrand$accentText = (_getBrand7 = getBrand(color)) === null || _getBrand7 === void 0 ? void 0 : _getBrand7.accentText) !== null && _getBrand$accentText !== void 0 ? _getBrand$accentText : textAccentMap[color];
225
+ }
226
+ function deletedBackground(color) {
227
+ var _getBrand$emphasisBac, _getBrand8;
228
+ return (_getBrand$emphasisBac = (_getBrand8 = getBrand(color)) === null || _getBrand8 === void 0 ? void 0 : _getBrand8.emphasisBackground) !== null && _getBrand$emphasisBac !== void 0 ? _getBrand$emphasisBac : bgSubtlest(color);
214
229
  }
215
230
 
216
- /**
217
- * Presentation tokens for a contributor tag in one diff colour.
218
- *
219
- * A `bolder` fill rather than the `subtlest` tint the highlight uses: the tag is a label on the
220
- * change, and at tag size a tint reads as a second, weaker highlight sitting above the real one.
221
- * `inverse` is the only text tone that reads on a bolder fill, and it needs no per-colour map —
222
- * which is also why the tag carries no border: the fill alone bounds it.
223
- */
231
+ /** Contributor tags use a bold fill with a contrasting foreground, including branded schemes. */
224
232
  function getAccentTokens(color) {
233
+ var _getBrand$boldText, _getBrand9;
225
234
  return {
226
235
  background: bgBolder(color),
227
- text: "var(--ds-text-inverse, #FFFFFF)"
236
+ text: (_getBrand$boldText = (_getBrand9 = getBrand(color)) === null || _getBrand9 === void 0 ? void 0 : _getBrand9.boldText) !== null && _getBrand$boldText !== void 0 ? _getBrand$boldText : "var(--ds-text-inverse, #FFFFFF)"
228
237
  };
229
238
  }
230
239
 
@@ -246,18 +255,23 @@ function deletedCellOutline(colors) {
246
255
  // --- Inserted content styles ---
247
256
 
248
257
  function insertedInlineBorderColor(colors) {
249
- return colors.insertedInlineBorderTone === 'backgroundHovered' ? bgSubtlestHoveredMap[colors.insertColor] : borderAccent(colors.insertColor);
258
+ var _getBrand$border3, _getBrand0;
259
+ return colors.insertedInlineBorderTone === 'backgroundHovered' ? (_getBrand$border3 = (_getBrand0 = getBrand(colors.insertColor)) === null || _getBrand0 === void 0 ? void 0 : _getBrand0.border) !== null && _getBrand$border3 !== void 0 ? _getBrand$border3 : bgSubtlestHoveredMap[colors.insertColor] : borderAccent(colors.insertColor);
250
260
  }
251
261
 
252
262
  /** Inline inserted content — default state. */
253
263
  function buildInsertStyle(colors) {
254
- return (0, _lazyNodeView.convertToInlineCss)({
255
- background: bgSubtlest(colors.insertColor),
264
+ var brand = getBrand(colors.insertColor);
265
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
266
+ background: bgSubtlest(colors.insertColor)
267
+ }, brand ? {
268
+ color: brand.text
269
+ } : {}), {}, {
256
270
  textDecoration: 'underline',
257
271
  textDecorationStyle: colors.insertUnderlineStyle,
258
272
  textDecorationThickness: "var(--ds-space-025, 2px)",
259
273
  textDecorationColor: borderAccent(colors.insertColor)
260
- });
274
+ }));
261
275
  }
262
276
 
263
277
  /** Inline insert style for content within a block node (no background, underline only). */
@@ -272,11 +286,15 @@ function buildInsertStyleInBlock(colors) {
272
286
 
273
287
  /** Extended insert style — background + border-bottom underline. */
274
288
  function buildInsertStyleExtended(colors) {
275
- return (0, _lazyNodeView.convertToInlineCss)({
276
- background: bgSubtlest(colors.insertColor),
289
+ var brand = getBrand(colors.insertColor);
290
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
291
+ background: bgSubtlest(colors.insertColor)
292
+ }, brand ? {
293
+ color: brand.text
294
+ } : {}), {}, {
277
295
  borderBottom: "2px solid ".concat(insertedInlineBorderColor(colors)),
278
296
  padding: "1px 0 2px"
279
- });
297
+ }));
280
298
  }
281
299
 
282
300
  /** Extended insert style for content within a block node (border-bottom only, no background). */
@@ -289,27 +307,39 @@ function buildInsertStyleInBlockExtended(colors) {
289
307
 
290
308
  /** Active state of the extended insert style. */
291
309
  function buildInsertStyleExtendedActive(colors) {
292
- return (0, _lazyNodeView.convertToInlineCss)({
293
- background: bgSubtlerPressed(colors.insertActiveColor),
310
+ var brand = getBrand(colors.insertColor);
311
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
312
+ background: bgSubtlerPressed(colors.insertActiveColor)
313
+ }, brand ? {
314
+ color: brand.text
315
+ } : {}), {}, {
294
316
  borderBottom: "2px solid ".concat(borderAccent(colors.insertColor)),
295
317
  padding: "1px 0 2px"
296
- });
318
+ }));
297
319
  }
298
320
 
299
321
  /** Extended insert style without underline — background + padding only. */
300
322
  function buildInsertStyleExtendedNoUnderline(colors) {
301
- return (0, _lazyNodeView.convertToInlineCss)({
302
- background: bgSubtlest(colors.insertColor),
323
+ var brand = getBrand(colors.insertColor);
324
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
325
+ background: bgSubtlest(colors.insertColor)
326
+ }, brand ? {
327
+ color: brand.text
328
+ } : {}), {}, {
303
329
  padding: "1px 0 2px"
304
- });
330
+ }));
305
331
  }
306
332
 
307
333
  /** Active state of the no-underline extended insert style. */
308
334
  function buildInsertStyleExtendedNoUnderlineActive(colors) {
309
- return (0, _lazyNodeView.convertToInlineCss)({
310
- background: bgSubtlerPressed(colors.insertActiveColor),
335
+ var brand = getBrand(colors.insertColor);
336
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
337
+ background: bgSubtlerPressed(colors.insertActiveColor)
338
+ }, brand ? {
339
+ color: brand.text
340
+ } : {}), {}, {
311
341
  padding: "1px 0 2px"
312
- });
342
+ }));
313
343
  }
314
344
 
315
345
  /** No-underline extended insert style for block content (padding only). */
@@ -321,13 +351,17 @@ function buildInsertStyleInBlockExtendedNoUnderline(_colors) {
321
351
 
322
352
  /** Inline inserted content — active/focused state. */
323
353
  function buildInsertStyleActive(colors) {
324
- return (0, _lazyNodeView.convertToInlineCss)({
325
- background: bgSubtlerPressed(colors.insertActiveColor),
354
+ var brand = getBrand(colors.insertColor);
355
+ return (0, _lazyNodeView.convertToInlineCss)(_objectSpread(_objectSpread({
356
+ background: bgSubtlerPressed(colors.insertActiveColor)
357
+ }, brand ? {
358
+ color: brand.text
359
+ } : {}), {}, {
326
360
  textDecoration: 'underline',
327
361
  textDecorationStyle: colors.insertUnderlineStyle,
328
362
  textDecorationThickness: "var(--ds-space-025, 2px)",
329
363
  textDecorationColor: textAccent(colors.insertActiveColor)
330
- });
364
+ }));
331
365
  }
332
366
 
333
367
  // --- Deleted inline content styles ---
@@ -685,7 +719,7 @@ function buildDeletedInlineContentStyleExtended(colors) {
685
719
  // Under 'underline' emphasis the highlight stays on its resting tint — the same one hover paints —
686
720
  // so only the border carries the emphasis.
687
721
  var isUnderlineEmphasis = isActive && usesUnderlineEmphasis(colors);
688
- var backgroundColor = isActive && !isUnderlineEmphasis && colors.deletedInlineBorderTone === 'background' ? bgSubtlerPressed(colors.deleteActiveColor) : bgSubtlest(colors.deleteColor);
722
+ var backgroundColor = isActive && !isUnderlineEmphasis && colors.deletedInlineBorderTone === 'background' ? bgSubtlerPressed(colors.deleteActiveColor) : deletedBackground(colors.deleteColor);
689
723
  var borderColor = isUnderlineEmphasis ? borderAccent(colors.deleteActiveColor) : colors.deletedInlineBorderTone === 'background' ? backgroundColor : borderAccent(colors.deleteColor);
690
724
  return (0, _lazyNodeView.convertToInlineCss)({
691
725
  backgroundColor: backgroundColor,
@@ -895,7 +929,7 @@ function getDeletedInlineRevealColors(colors) {
895
929
  * paints at rest, so hovering restores the appearance rather than introducing a third one.
896
930
  */
897
931
  function getDeletedHighlightHoverColor(colors) {
898
- return bgSubtlest(colors.deleteColor);
932
+ return deletedBackground(colors.deleteColor);
899
933
  }
900
934
 
901
935
  /**
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  });
7
7
  exports.traditionalScheme = exports.standardScheme = exports.getLegacyColorScheme = exports.colorSchemeRegistry = void 0;
8
8
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _agentBrandColorSchemes = require("@atlaskit/agent-color/agent-brand-color-schemes");
9
10
  var _types = require("./types");
10
11
  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; }
11
12
  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; }
@@ -84,9 +85,12 @@ var createAttributionScheme = function createAttributionScheme(color) {
84
85
  var attributionColorSchemes = Object.fromEntries(_types.PARTICIPANT_COLOR_SCHEMES.map(function (color) {
85
86
  return [color, createAttributionScheme(color)];
86
87
  }));
88
+ var brandSchemes = Object.fromEntries(Object.keys(_agentBrandColorSchemes.agentBrandColorSchemes).map(function (scheme) {
89
+ return [scheme, createAttributionScheme(scheme)];
90
+ }));
87
91
 
88
92
  /** Maps public schemes and attribution-only participant slots to their data objects. */
89
- var colorSchemeRegistry = exports.colorSchemeRegistry = _objectSpread(_objectSpread({}, attributionColorSchemes), {}, {
93
+ var colorSchemeRegistry = exports.colorSchemeRegistry = _objectSpread(_objectSpread(_objectSpread({}, attributionColorSchemes), brandSchemes), {}, {
90
94
  traditional: traditionalScheme,
91
95
  standard: standardScheme
92
96
  });
@@ -11,8 +11,6 @@ var PARTICIPANT_COLOR_SCHEMES = exports.PARTICIPANT_COLOR_SCHEMES = ['red', 'blu
11
11
 
12
12
  /** ADS accent hues used by the public and participant colour schemes. */
13
13
 
14
- /** A public scheme or an attribution participant slot resolved internally for one change. */
15
-
16
14
  /**
17
15
  * A show-diff colour scheme. Colour fields are ADS hues that `factory.ts` expands into token paths;
18
16
  * the rest encode structural differences no colour can express. Ring widths, padding, radius and
@@ -13,6 +13,7 @@ var _view = require("@atlaskit/editor-prosemirror/view");
13
13
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
14
14
  var _fg = require("@atlaskit/platform-feature-flags/fg");
15
15
  var _isExtendedEnabled = require("../isExtendedEnabled");
16
+ var _taggableBlockNodes = require("../utils/taggableBlockNodes");
16
17
  var _factory = require("./colorSchemes/factory");
17
18
  var _schemes = require("./colorSchemes/schemes");
18
19
  var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
@@ -34,13 +35,6 @@ var UNSTYLED_NODES = ['mediaSingle', 'mediaGroup', 'table',
34
35
  'heading', 'hardBreak', 'decisionList', 'taskList', 'bulletList', 'orderedList', 'layoutSection'];
35
36
  var CELL_NODES = ['tableCell', 'tableHeader'];
36
37
 
37
- /**
38
- * Block nodes that host a contributor tag of their own — those whose whole box reads as one change.
39
- * Lists and tables are excluded: they decorate per item and per cell, with no one-tag-per-block
40
- * design yet. `blockCard` covers the datasource variant, which is the same node type.
41
- */
42
- var TAGGABLE_BLOCK_NODES = new Set(['blockCard', 'blockquote', 'bodiedExtension', 'codeBlock', 'embedCard', 'expand', 'extension', 'media', 'multiBodiedExtension', 'panel', 'rule']);
43
-
44
38
  /** Panels, rules and media can also sit in a table cell, which is out of scope for block tags. */
45
39
  var isInsideTable = function isInsideTable(doc, pos) {
46
40
  return (0, _utils.findParentNodeClosestToPos)(doc.resolve(pos), function (node) {
@@ -48,13 +42,23 @@ var isInsideTable = function isInsideTable(doc, pos) {
48
42
  }) !== undefined;
49
43
  };
50
44
 
51
- /** Whether this block can host a contributor tag of its own. */
45
+ /**
46
+ * Whether this block can host a contributor tag of its own.
47
+ *
48
+ * The node type is resolved from the document rather than matched on `change.name`, so a schema
49
+ * variant is recognised as the type it varies — see `isTaggableBlockNode`. `from` is the node's own
50
+ * position, so `nodeAt` returns exactly the node being decorated.
51
+ */
52
52
  var canTagBlock = function canTagBlock(_ref) {
53
+ var _doc$nodeAt;
53
54
  var diffType = _ref.diffType,
54
55
  doc = _ref.doc,
55
- from = _ref.from,
56
- name = _ref.name;
57
- return doc !== undefined && (0, _isExtendedEnabled.isExtendedEnabled)(diffType) && TAGGABLE_BLOCK_NODES.has(name) && !isInsideTable(doc, from);
56
+ from = _ref.from;
57
+ if (doc === undefined || !(0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
58
+ return false;
59
+ }
60
+ var nodeType = (_doc$nodeAt = doc.nodeAt(from)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type;
61
+ return nodeType !== undefined && (0, _taggableBlockNodes.isTaggableBlockNode)(nodeType) && !isInsideTable(doc, from);
58
62
  };
59
63
 
60
64
  /** Positioning context for the cell overlay widget decorations. */
@@ -196,8 +200,7 @@ var createBlockChangedDecoration = exports.createBlockChangedDecoration = functi
196
200
  var shouldTagBlock = showContributorTags && canTagBlock({
197
201
  diffType: diffType,
198
202
  doc: doc,
199
- from: change.from,
200
- name: change.name
203
+ from: change.from
201
204
  });
202
205
  // Named so this block's own tag can position against it; see `createContributorTagWidget`.
203
206
  var tagAnchorName = shouldTagBlock && (0, _createContributorTagWidget.isContributorTagWidgetEnabled)() ? (0, _decorationKeys.buildAnchorDecorationKey)({
@@ -241,7 +244,9 @@ var createBlockChangedDecoration = exports.createBlockChangedDecoration = functi
241
244
  key: 'cell-overlay-decoration'
242
245
  }));
243
246
  }
244
- // isInserted is only read under the extended experience, so pass it unconditionally.
247
+ // isInserted is only read under the extended experience, so pass it unconditionally. `change.name`
248
+ // verbatim: base-name resolution stays in `canTagBlock`, which needs tags on, so a schema
249
+ // variant's legacy style is untouched — see `resolveBaseNodeName`.
245
250
  var nodeStyle = getBlockNodeStyle({
246
251
  nodeName: change.name,
247
252
  colorScheme: colorScheme,
@@ -272,6 +277,8 @@ var createBlockChangedDecoration = exports.createBlockChangedDecoration = functi
272
277
  })));
273
278
  }
274
279
  if (decorations.length === 0) {
280
+ // An unstyled node type (paragraph, heading, list, layout, …) emits no decoration at all, so
281
+ // there is nothing for a tag to hang off even when the node type would otherwise be taggable.
275
282
  return decorations;
276
283
  }
277
284
  if (showIndicators && doc && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
@@ -14,7 +14,11 @@ var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
14
14
  var _createChangedRowDecorationWidgets = require("./createChangedRowDecorationWidgets");
15
15
  var _createContributorTagWidget = require("./createContributorTagWidget");
16
16
  var _decorationKeys = require("./decorationKeys");
17
+ var _absorbFirstChildMarginReset = require("./utils/absorbFirstChildMarginReset");
18
+ var _createMarginAbsorber = require("./utils/createMarginAbsorber");
19
+ var _createNodeShapedMarginSpacer = require("./utils/createNodeShapedMarginSpacer");
17
20
  var _findSafeInsertPos = require("./utils/findSafeInsertPos");
21
+ var _safeResolve = require("./utils/safeResolve");
18
22
  var _wrapBlockNodeView = require("./utils/wrapBlockNodeView");
19
23
  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; }
20
24
  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; }
@@ -190,6 +194,14 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
190
194
  // For non-table content, use the existing span wrapper approach
191
195
  var dom = document.createElement('span');
192
196
  var $safeInsertPos = newDoc.resolve(safeInsertPos);
197
+
198
+ // Whether the widget renders above the very start of its parent's content — the document, a
199
+ // layout column, a table cell, a panel.
200
+ //
201
+ // `parentOffset === 0` is the whole test on the position side: prosemirror-view paints every
202
+ // widget at a position before the node starting there, so a leading widget at the parent's start
203
+ // always renders above its content.
204
+ var isVisuallyFirstInParent = !placeBelow && $safeInsertPos.parentOffset === 0;
193
205
  var isTopLevelInsert = $safeInsertPos.depth === 0;
194
206
  var hasPreviousBlock = ((_$safeInsertPos$nodeB = $safeInsertPos.nodeBefore) === null || _$safeInsertPos$nodeB === void 0 ? void 0 : _$safeInsertPos$nodeB.isBlock) === true;
195
207
  var isFirstDocHeadingReplacement = (0, _isExtendedEnabled.isExtendedEnabled)(diffType) && !placeBelow && change.fromB === 0 && ((_slice$content$firstC = slice.content.firstChild) === null || _slice$content$firstC === void 0 ? void 0 : _slice$content$firstC.type.name) === 'heading' && ((_newDoc$firstChild = newDoc.firstChild) === null || _newDoc$firstChild === void 0 ? void 0 : _newDoc$firstChild.type.name) === 'heading';
@@ -241,6 +253,20 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
241
253
  var firstReplacedNode = slice.content.firstChild;
242
254
  var lastReplacedNode = slice.content.lastChild;
243
255
  var showDiffPatch1 = (0, _fg.fg)('platform_editor_ai_show_diff_patch_1');
256
+ // Whether the slice's outermost textblocks still hold all of their original content.
257
+ //
258
+ // `openStart`/`openEnd` say whether the cut landed inside a block, but not whether it took
259
+ // any text with it — a deletion stopping exactly at a block's content boundary is still
260
+ // reported as open. Resolving the change's own ends separates the two, so a block whose text
261
+ // survived intact can render as a block even though its boundary was open.
262
+ //
263
+ // Both resolves sit behind the gate that consumes them, so this adds no position arithmetic to
264
+ // the ungated path, and an unresolvable position degrades to the `openStart`/`openEnd` test on
265
+ // its own — the block is then treated as partial, which is what it rendered as before the gate.
266
+ var $changeFromA = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? (0, _safeResolve.safeResolve)(doc, change.fromA) : null;
267
+ var $changeToA = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? (0, _safeResolve.safeResolve)(doc, change.toA) : null;
268
+ var isFirstNodeContentComplete = slice.openStart === 0 || ($changeFromA === null || $changeFromA === void 0 ? void 0 : $changeFromA.parentOffset) === 0;
269
+ var isLastNodeContentComplete = slice.openEnd === 0 || $changeToA !== null && $changeToA.parentOffset === $changeToA.parent.content.size;
244
270
  var isCompleteSameTypeReplacement = slice.content.childCount === 1 && firstReplacedNode !== null && replacementNode !== null && firstReplacedNode.type === replacementNode.type && replacementNode.nodeSize === change.toB - change.fromB;
245
271
 
246
272
  /*
@@ -253,10 +279,16 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
253
279
  var isLast = lastReplacedNode === node;
254
280
  var isOpenAtSliceBoundary = isFirst && slice.openStart > 0 || isLast && slice.openEnd > 0;
255
281
  var shouldPreserveCompleteMultiInlineBlock = showDiffPatch1 && node.isBlock && node.type.inlineContent && node.content.childCount > 1 && !isOpenAtSliceBoundary && isCompleteSameTypeReplacement;
282
+ // A textblock is otherwise serialized as its inline content only, with no `<p>`/`<h2>` wrapper.
283
+ // That is right when the diff cuts into an existing block — the deleted text belongs on the same
284
+ // line as the text that replaced it — but when the whole block went away it drops the very
285
+ // element that carries the block's margin, so the deleted block renders flush against its
286
+ // neighbours. Only the first and last children can be partial; middle ones are always complete.
287
+ var shouldRenderAsBlockNode = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && node.isTextblock && (!isFirst || isFirstNodeContentComplete) && (!isLast || isLastNodeContentComplete);
256
288
 
257
289
  // Helper function to handle multiple child nodes
258
290
  var handleMultipleChildNodes = function handleMultipleChildNodes(node) {
259
- if (!shouldPreserveCompleteMultiInlineBlock && node.content.childCount > 1 && node.type.inlineContent) {
291
+ if (!shouldPreserveCompleteMultiInlineBlock && !shouldRenderAsBlockNode && node.content.childCount > 1 && node.type.inlineContent) {
260
292
  node.content.forEach(function (childNode) {
261
293
  var childNodeView = serializer.tryCreateNodeView(childNode);
262
294
  if (childNodeView) {
@@ -286,7 +318,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
286
318
  if (handleMultipleChildNodes(node)) {
287
319
  return;
288
320
  }
289
- if (shouldPreserveCompleteMultiInlineBlock) {
321
+ if (shouldPreserveCompleteMultiInlineBlock || shouldRenderAsBlockNode) {
290
322
  fallbackSerialization = function fallbackSerialization() {
291
323
  return serializer.serializeNode(node);
292
324
  };
@@ -363,6 +395,21 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
363
395
  dom.style.setProperty('scroll-margin-top', _decorationKeys.scrollMarginTopValue);
364
396
  }
365
397
 
398
+ // A block node serialized into the widget is the widget's first child, and the editor's
399
+ // first-child reset is written against the parent element rather than the document position — so
400
+ // it zeroes the margin the block wrapper was kept for in the first place.
401
+ //
402
+ // Only away from the parent's start. There the reset is the correct outcome: the widget is the
403
+ // first thing in the document, column, cell or panel, and a leading gap above it would be wrong.
404
+ // The margin that matters at that position belongs to the node *below* the widget, which the
405
+ // shaped spacer pair supplies instead.
406
+ if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && !isVisuallyFirstInParent) {
407
+ (0, _absorbFirstChildMarginReset.absorbFirstChildMarginReset)({
408
+ dom: dom,
409
+ testId: 'show-diff-widget-margin-absorber'
410
+ });
411
+ }
412
+
366
413
  // Needed even when the indicator bar is off, because a contributor tag also anchors against the
367
414
  // widget.
368
415
  if ((showIndicators || showContributorTags) && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
@@ -425,7 +472,40 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
425
472
  var isPureDeletion = change.fromB === change.toB;
426
473
  var isSingleBlock = slice.content.childCount === 1 && ((_slice$content$firstC2 = slice.content.firstChild) === null || _slice$content$firstC2 === void 0 ? void 0 : _slice$content$firstC2.isBlock);
427
474
  var isDiffWidgetAtStartOfDoc = $safeInsertPos.depth === 0 && $safeInsertPos.index(0) === 0;
428
- if (isDiffWidgetAtStartOfDoc && isSingleBlock && isPureDeletion && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
475
+
476
+ // A node at the start of its parent has its top margin reset, so a diff widget rendered above
477
+ // it sits flush against it. This applies wherever that parent is — the document, a layout
478
+ // column, a table cell — so it is decided from the anchor rather than from the document root
479
+ // (see `isVisuallyFirstInParent` above).
480
+ //
481
+ // Away from the parent's start the node below keeps its own margin, and it is the block *inside*
482
+ // the widget that loses one — handled by `absorbFirstChildMarginReset` above, not here.
483
+ var nodeAfterWidget = $safeInsertPos.nodeAfter;
484
+ if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && (0, _isExtendedEnabled.isExtendedEnabled)(diffType) && isVisuallyFirstInParent && nodeAfterWidget) {
485
+ var shapedSpacer = (0, _createNodeShapedMarginSpacer.createNodeShapedMarginSpacer)({
486
+ node: nodeAfterWidget,
487
+ serializer: serializer,
488
+ testId: 'show-diff-shaped-margin-spacer'
489
+ });
490
+ if (shapedSpacer) {
491
+ // Two elements, because the two families of reset have to be handled differently. The
492
+ // absorber takes the document-level adjacent-sibling reset for a leading widget, whose
493
+ // `!important` would otherwise zero the shaped spacer's margin; the shaped spacer, now one
494
+ // position further along, is out of that rule's reach and keeps the margin it supplies.
495
+ // Inside containers the counting selectors skip both, so only the shaped one has an effect.
496
+ //
497
+ // Sides order the widgets against each other only — both still paint before the real node.
498
+ decorations.push(_view.Decoration.widget(safeInsertPos, (0, _createMarginAbsorber.createMarginAbsorber)({
499
+ testId: 'show-diff-margin-absorber'
500
+ }), {
501
+ side: 0
502
+ }));
503
+ decorations.push(_view.Decoration.widget(safeInsertPos, shapedSpacer, {
504
+ side: 1
505
+ }));
506
+ }
507
+ }
508
+ if (!(0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && isDiffWidgetAtStartOfDoc && isSingleBlock && isPureDeletion && (0, _isExtendedEnabled.isExtendedEnabled)(diffType)) {
429
509
  var followingNode = $safeInsertPos.nodeAfter;
430
510
  var headingLevel = (followingNode === null || followingNode === void 0 ? void 0 : followingNode.type.name) === 'heading' ? followingNode.attrs.level : undefined;
431
511
  if (isHeadingLevel(headingLevel)) {