@atlaskit/editor-plugin-show-diff 3.1.5 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/afm-cc/tsconfig.json +6 -0
  3. package/afm-jira/tsconfig.json +3 -0
  4. package/afm-products/tsconfig.json +3 -0
  5. package/dist/cjs/pm-plugins/calculateDiffDecorations.js +12 -7
  6. package/dist/cjs/pm-plugins/decorations.js +242 -10
  7. package/dist/cjs/pm-plugins/deletedRowsHandler.js +214 -0
  8. package/dist/cjs/pm-plugins/main.js +6 -5
  9. package/dist/cjs/showDiffPlugin.js +4 -3
  10. package/dist/es2019/pm-plugins/calculateDiffDecorations.js +12 -7
  11. package/dist/es2019/pm-plugins/decorations.js +238 -9
  12. package/dist/es2019/pm-plugins/deletedRowsHandler.js +185 -0
  13. package/dist/es2019/pm-plugins/main.js +4 -3
  14. package/dist/es2019/showDiffPlugin.js +4 -2
  15. package/dist/esm/pm-plugins/calculateDiffDecorations.js +12 -7
  16. package/dist/esm/pm-plugins/decorations.js +242 -10
  17. package/dist/esm/pm-plugins/deletedRowsHandler.js +207 -0
  18. package/dist/esm/pm-plugins/main.js +4 -3
  19. package/dist/esm/showDiffPlugin.js +4 -3
  20. package/dist/types/pm-plugins/calculateDiffDecorations.d.ts +3 -1
  21. package/dist/types/pm-plugins/decorations.d.ts +4 -2
  22. package/dist/types/pm-plugins/deletedRowsHandler.d.ts +30 -0
  23. package/dist/types/pm-plugins/main.d.ts +2 -1
  24. package/dist/types-ts4.5/pm-plugins/calculateDiffDecorations.d.ts +3 -1
  25. package/dist/types-ts4.5/pm-plugins/decorations.d.ts +4 -2
  26. package/dist/types-ts4.5/pm-plugins/deletedRowsHandler.d.ts +30 -0
  27. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
  28. package/package.json +13 -3
  29. package/afm-post-office/tsconfig.json +0 -27
  30. package/afm-townsquare/tsconfig.json +0 -27
@@ -89,7 +89,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
89
89
  var state = _ref.state,
90
90
  pluginState = _ref.pluginState,
91
91
  nodeViewSerializer = _ref.nodeViewSerializer,
92
- colourScheme = _ref.colourScheme;
92
+ colourScheme = _ref.colourScheme,
93
+ intl = _ref.intl;
93
94
  var originalDoc = pluginState.originalDoc,
94
95
  rawSteps = pluginState.steps;
95
96
  var steps = simplifySteps(rawSteps);
@@ -99,6 +100,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
99
100
  var tr = state.tr;
100
101
  var steppedDoc = originalDoc;
101
102
  var stepMaps = [];
103
+ var changeset = ChangeSet.create(originalDoc);
102
104
  var _iterator = _createForOfIteratorHelper(steps),
103
105
  _step;
104
106
  try {
@@ -108,6 +110,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
108
110
  if (result.failed === null && result.doc) {
109
111
  steppedDoc = result.doc;
110
112
  stepMaps.push(step.getMap());
113
+ changeset = changeset.addSteps(steppedDoc, [step.getMap()], step);
111
114
  }
112
115
  }
113
116
 
@@ -121,7 +124,6 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
121
124
  if (!areNodesEqualIgnoreAttrs(steppedDoc, tr.doc)) {
122
125
  return DecorationSet.empty;
123
126
  }
124
- var changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
125
127
  var changes = simplifyChanges(changeset.changes, tr.doc);
126
128
  var optimizedChanges = optimizeChanges(changes);
127
129
  var decorations = [];
@@ -136,10 +138,11 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
136
138
  doc: originalDoc,
137
139
  nodeViewSerializer: nodeViewSerializer,
138
140
  colourScheme: colourScheme,
139
- newDoc: tr.doc
141
+ newDoc: tr.doc,
142
+ intl: intl
140
143
  });
141
144
  if (decoration) {
142
- decorations.push(decoration);
145
+ decorations.push.apply(decorations, _toConsumableArray(decoration));
143
146
  }
144
147
  }
145
148
  });
@@ -159,12 +162,14 @@ function (_ref2, _ref3) {
159
162
  _ref4$ = _ref4[0],
160
163
  pluginState = _ref4$.pluginState,
161
164
  state = _ref4$.state,
162
- colourScheme = _ref4$.colourScheme;
165
+ colourScheme = _ref4$.colourScheme,
166
+ intl = _ref4$.intl;
163
167
  var _ref5 = _slicedToArray(_ref3, 1),
164
168
  _ref5$ = _ref5[0],
165
169
  lastPluginState = _ref5$.pluginState,
166
170
  lastState = _ref5$.state,
167
- lastColourScheme = _ref5$.colourScheme;
171
+ lastColourScheme = _ref5$.colourScheme,
172
+ lastIntl = _ref5$.intl;
168
173
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
169
- return (_ref6 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colourScheme === lastColourScheme) !== null && _ref6 !== void 0 ? _ref6 : false;
174
+ return (_ref6 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colourScheme === lastColourScheme && intl.locale === lastIntl.locale) !== null && _ref6 !== void 0 ? _ref6 : false;
170
175
  });
@@ -1,5 +1,8 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
+ import { trackChangesMessages } from '@atlaskit/editor-common/messages';
2
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
+ import { fg } from '@atlaskit/platform-feature-flags';
5
+ import { handleDeletedRows } from './deletedRowsHandler';
3
6
  import { findSafeInsertPos } from './findSafeInsertPos';
4
7
  var editingStyle = convertToInlineCss({
5
8
  background: "var(--ds-background-accent-purple-subtlest, #F3F0FF)",
@@ -70,6 +73,59 @@ var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
70
73
  return colourScheme === 'traditional' ? traditionalStyleNode : editingStyleNode;
71
74
  }
72
75
  };
76
+ var getDeletedStyleNode = function getDeletedStyleNode(nodeName) {
77
+ switch (nodeName) {
78
+ case 'blockquote':
79
+ return deletedStyleQuoteNode;
80
+ case 'expand':
81
+ case 'decisionList':
82
+ return deletedBlockOutline;
83
+ case 'panel':
84
+ case 'codeBlock':
85
+ return deletedBlockOutlineRounded;
86
+ default:
87
+ return undefined;
88
+ }
89
+ };
90
+ var shouldShowRemovedLozenge = function shouldShowRemovedLozenge(nodeName) {
91
+ switch (nodeName) {
92
+ case 'expand':
93
+ case 'codeBlock':
94
+ case 'mediaSingle':
95
+ case 'panel':
96
+ case 'decisionList':
97
+ return true;
98
+ default:
99
+ return false;
100
+ }
101
+ };
102
+ var shouldFitContentWidth = function shouldFitContentWidth(nodeName) {
103
+ switch (nodeName) {
104
+ case 'mediaSingle':
105
+ case 'embedCard':
106
+ case 'blockCard':
107
+ return true;
108
+ default:
109
+ return false;
110
+ }
111
+ };
112
+ var shouldAddShowDiffDeletedNodeClass = function shouldAddShowDiffDeletedNodeClass(nodeName) {
113
+ switch (nodeName) {
114
+ case 'mediaSingle':
115
+ case 'embedCard':
116
+ return true;
117
+ default:
118
+ return false;
119
+ }
120
+ };
121
+
122
+ /**
123
+ * Checks if a node should apply deleted styles directly without wrapper
124
+ * to preserve natural block-level margins
125
+ */
126
+ var shouldApplyDeletedStylesDirectly = function shouldApplyDeletedStylesDirectly(nodeName) {
127
+ return nodeName === 'blockquote' || nodeName === 'heading';
128
+ };
73
129
  var editingStyleQuoteNode = convertToInlineCss({
74
130
  borderLeft: "2px solid ".concat("var(--ds-border-accent-purple, #8270DB)")
75
131
  });
@@ -98,6 +154,18 @@ var traditionalStyleCardBlockNode = convertToInlineCss({
98
154
  boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-green, #22A06B)"),
99
155
  borderRadius: "var(--ds-radius-medium, 6px)"
100
156
  });
157
+ var deletedStyleQuoteNode = convertToInlineCss({
158
+ borderLeft: "2px solid ".concat("var(--ds-border-accent-gray, #758195)")
159
+ });
160
+ var deletedBlockOutline = convertToInlineCss({
161
+ boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-gray, #758195)"),
162
+ borderRadius: "var(--ds-radius-small, 4px)"
163
+ });
164
+ var deletedBlockOutlineRounded = convertToInlineCss({
165
+ boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-gray, #758195)"),
166
+ borderRadius: "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)")
167
+ });
168
+
101
169
  /**
102
170
  * Inline decoration used for insertions as the content already exists in the document
103
171
  *
@@ -140,35 +208,181 @@ var deletedTraditionalContentStyleUnbounded = convertToInlineCss({
140
208
  pointerEvents: 'none',
141
209
  zIndex: 1
142
210
  });
211
+ var lozengeStyle = convertToInlineCss({
212
+ display: 'inline-flex',
213
+ boxSizing: 'border-box',
214
+ position: 'static',
215
+ blockSize: 'min-content',
216
+ borderRadius: "var(--ds-radius-small, 4px)",
217
+ overflow: 'hidden',
218
+ paddingInlineStart: "var(--ds-space-050, 4px)",
219
+ paddingInlineEnd: "var(--ds-space-050, 4px)",
220
+ backgroundColor: "var(--ds-background-accent-gray-subtler, #DCDFE4)",
221
+ font: "var(--ds-font-body-small, normal 400 11px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
222
+ fontWeight: "var(--ds-font-weight-bold, 700)",
223
+ textOverflow: 'ellipsis',
224
+ whiteSpace: 'nowrap',
225
+ color: "var(--ds-text-warning-inverse, #172B4D)"
226
+ });
143
227
  var getDeletedContentStyleUnbounded = function getDeletedContentStyleUnbounded(colourScheme) {
144
228
  return colourScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
145
229
  };
146
230
  var getDeletedContentStyle = function getDeletedContentStyle(colourScheme) {
147
231
  return colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
148
232
  };
233
+
234
+ /**
235
+ * Creates a "Removed" lozenge to be displayed at the top right corner of deleted block nodes
236
+ */
237
+ var createRemovedLozenge = function createRemovedLozenge(intl, nodeName) {
238
+ var container = document.createElement('span');
239
+ var borderTopRightRadius;
240
+ var borderTopLeftRadius;
241
+ if (['expand', 'decisionList'].includes(nodeName || '')) {
242
+ borderTopRightRadius = "var(--ds-radius-small, 4px)";
243
+ } else if (['panel', 'codeBlock'].includes(nodeName || '')) {
244
+ borderTopRightRadius = "calc(".concat("var(--ds-radius-xsmall, 2px)", " + 1px)");
245
+ } else if (nodeName === 'mediaSingle') {
246
+ borderTopLeftRadius = "var(--ds-radius-small, 4px)";
247
+ }
248
+ var containerStyle = convertToInlineCss({
249
+ position: 'absolute',
250
+ top: nodeName === 'mediaSingle' ? "var(--ds-space-300, 24px)" : "var(--ds-space-0, 0px)",
251
+ right: nodeName === 'mediaSingle' ? undefined : "var(--ds-space-0, 0px)",
252
+ left: nodeName === 'mediaSingle' ? "var(--ds-space-0, 0px)" : undefined,
253
+ zIndex: 2,
254
+ pointerEvents: 'none',
255
+ display: 'flex',
256
+ overflow: 'hidden',
257
+ borderTopRightRadius: borderTopRightRadius,
258
+ borderTopLeftRadius: borderTopLeftRadius
259
+ });
260
+ container.setAttribute('style', containerStyle);
261
+ container.setAttribute('data-testid', 'show-diff-removed-lozenge');
262
+
263
+ // Create vanilla HTML lozenge element with Atlaskit Lozenge styling (visual refresh)
264
+ var lozengeElement = document.createElement('span');
265
+ lozengeElement.setAttribute('style', lozengeStyle);
266
+ lozengeElement.textContent = intl.formatMessage(trackChangesMessages.removed).toUpperCase();
267
+ container.appendChild(lozengeElement);
268
+ return container;
269
+ };
270
+
271
+ /**
272
+ * Wraps a block node in a container with relative positioning to support absolute positioned lozenge
273
+ */
274
+ var createBlockNodeWrapper = function createBlockNodeWrapper(nodeName) {
275
+ var wrapper = document.createElement('div');
276
+ var fitContent = shouldFitContentWidth(nodeName);
277
+ var baseStyle = convertToInlineCss({
278
+ position: 'relative',
279
+ display: fitContent ? 'inline-block' : 'block',
280
+ width: fitContent ? 'fit-content' : undefined,
281
+ height: fitContent ? 'fit-content' : undefined,
282
+ opacity: 1
283
+ });
284
+ wrapper.setAttribute('style', baseStyle);
285
+ return wrapper;
286
+ };
287
+
288
+ /**
289
+ * Wraps content with deleted styling without opacity (for use when content is a direct child of dom)
290
+ */
291
+ var createDeletedStyleWrapperWithoutOpacity = function createDeletedStyleWrapperWithoutOpacity(colourScheme) {
292
+ var wrapper = document.createElement('span');
293
+ wrapper.setAttribute('style', getDeletedContentStyle(colourScheme));
294
+ return wrapper;
295
+ };
296
+
297
+ /**
298
+ * Applies deleted styles directly to an HTML element by merging with existing styles
299
+ */
300
+ var applyDeletedStylesToElement = function applyDeletedStylesToElement(element, targetNode, colourScheme) {
301
+ var currentStyle = element.getAttribute('style') || '';
302
+ var deletedContentStyle = getDeletedContentStyle(colourScheme);
303
+ var nodeSpecificStyle = getDeletedStyleNode(targetNode.type.name) || '';
304
+ element.setAttribute('style', "".concat(currentStyle).concat(deletedContentStyle).concat(nodeSpecificStyle));
305
+ };
306
+
307
+ /**
308
+ * Appends a block node with wrapper, lozenge, and appropriate styling
309
+ */
310
+ var appendBlockNodeWithWrapper = function appendBlockNodeWithWrapper(dom, nodeView, targetNode, colourScheme, intl) {
311
+ var blockWrapper = createBlockNodeWrapper(targetNode.type.name);
312
+ if (shouldShowRemovedLozenge(targetNode.type.name)) {
313
+ var lozenge = createRemovedLozenge(intl, targetNode.type.name);
314
+ blockWrapper.append(lozenge);
315
+ }
316
+
317
+ // Wrap the nodeView in a content wrapper that has the opacity style AND the box-shadow
318
+ // This keeps the lozenge at full opacity while the content AND border are faded
319
+ var contentWrapper = document.createElement('div');
320
+ var nodeStyle = getDeletedStyleNode(targetNode.type.name);
321
+ contentWrapper.setAttribute('style', "".concat(getDeletedContentStyle(colourScheme)).concat(nodeStyle || ''));
322
+ contentWrapper.append(nodeView);
323
+ blockWrapper.append(contentWrapper);
324
+ if (nodeView instanceof HTMLElement) {
325
+ if (shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
326
+ nodeView.classList.add('show-diff-deleted-node');
327
+ }
328
+ }
329
+ dom.append(blockWrapper);
330
+ };
331
+
332
+ /**
333
+ * Handles all block node rendering with appropriate deleted styling.
334
+ * For blockquote and heading nodes, applies styles directly to preserve natural margins.
335
+ * For other block nodes, uses wrapper approach with optional lozenge.
336
+ */
337
+ var handleBlockNodeView = function handleBlockNodeView(dom, nodeView, targetNode, colourScheme, intl) {
338
+ if (shouldApplyDeletedStylesDirectly(targetNode.type.name) && nodeView instanceof HTMLElement) {
339
+ // Apply deleted styles directly to preserve natural block-level margins
340
+ applyDeletedStylesToElement(nodeView, targetNode, colourScheme);
341
+ dom.append(nodeView);
342
+ } else {
343
+ // Use wrapper approach for other block nodes
344
+ appendBlockNodeWithWrapper(dom, nodeView, targetNode, colourScheme, intl);
345
+ }
346
+ };
149
347
  export var createDeletedContentDecoration = function createDeletedContentDecoration(_ref) {
150
348
  var change = _ref.change,
151
349
  doc = _ref.doc,
152
350
  nodeViewSerializer = _ref.nodeViewSerializer,
153
351
  colourScheme = _ref.colourScheme,
154
- newDoc = _ref.newDoc;
352
+ newDoc = _ref.newDoc,
353
+ intl = _ref.intl;
155
354
  var slice = doc.slice(change.fromA, change.toA);
156
355
  if (slice.content.content.length === 0) {
157
356
  return;
158
357
  }
159
- var isTableContent = slice.content.content.some(function () {
358
+ var isTableCellContent = slice.content.content.some(function () {
160
359
  return slice.content.content.some(function (siblingNode) {
161
- return ['tableHeader', 'tableCell', 'tableRow'].includes(siblingNode.type.name);
360
+ return ['tableHeader', 'tableCell'].includes(siblingNode.type.name);
162
361
  });
163
362
  });
164
- if (isTableContent) {
363
+ var isTableRowContent = slice.content.content.some(function () {
364
+ return slice.content.content.some(function (siblingNode) {
365
+ return ['tableRow'].includes(siblingNode.type.name);
366
+ });
367
+ });
368
+ if (isTableCellContent) {
165
369
  return;
166
370
  }
371
+ if (isTableRowContent) {
372
+ if (!fg('platform_editor_ai_aifc_patch_ga')) {
373
+ return;
374
+ }
375
+ var _handleDeletedRows = handleDeletedRows([change], doc, newDoc, nodeViewSerializer, colourScheme),
376
+ decorations = _handleDeletedRows.decorations;
377
+ return decorations;
378
+ }
167
379
  var serializer = nodeViewSerializer;
168
380
 
169
381
  // For non-table content, use the existing span wrapper approach
170
382
  var dom = document.createElement('span');
171
- dom.setAttribute('style', getDeletedContentStyle(colourScheme));
383
+ if (!fg('platform_editor_ai_aifc_patch_beta_2')) {
384
+ dom.setAttribute('style', getDeletedContentStyle(colourScheme));
385
+ }
172
386
 
173
387
  /*
174
388
  * The thinking is we separate out the fragment we got from doc.slice
@@ -180,8 +394,11 @@ export var createDeletedContentDecoration = function createDeletedContentDecorat
180
394
  // Create a wrapper for each node with strikethrough
181
395
  var createWrapperWithStrikethrough = function createWrapperWithStrikethrough() {
182
396
  var wrapper = document.createElement('span');
183
- wrapper.style.position = 'relative';
184
- wrapper.style.width = 'fit-content';
397
+ var baseStyle = convertToInlineCss({
398
+ position: 'relative',
399
+ width: 'fit-content'
400
+ });
401
+ wrapper.setAttribute('style', "".concat(baseStyle).concat(getDeletedContentStyle(colourScheme)));
185
402
  var strikethrough = document.createElement('span');
186
403
  strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colourScheme));
187
404
  wrapper.append(strikethrough);
@@ -204,7 +421,13 @@ export var createDeletedContentDecoration = function createDeletedContentDecorat
204
421
  // Fallback to serializing the individual child node
205
422
  var serializedChild = serializer.serializeNode(childNode);
206
423
  if (serializedChild) {
207
- dom.append(serializedChild);
424
+ if (fg('platform_editor_ai_aifc_patch_beta_2')) {
425
+ var _wrapper = createWrapperWithStrikethrough();
426
+ _wrapper.append(serializedChild);
427
+ dom.append(_wrapper);
428
+ } else {
429
+ dom.append(serializedChild);
430
+ }
208
431
  }
209
432
  }
210
433
  });
@@ -260,6 +483,9 @@ export var createDeletedContentDecoration = function createDeletedContentDecorat
260
483
  var wrapper = createWrapperWithStrikethrough();
261
484
  wrapper.append(nodeView);
262
485
  dom.append(wrapper);
486
+ } else if (fg('platform_editor_ai_aifc_patch_beta_2')) {
487
+ // Handle all block nodes with unified function
488
+ handleBlockNodeView(dom, nodeView, targetNode, colourScheme, intl);
263
489
  } else {
264
490
  dom.append(nodeView);
265
491
  }
@@ -269,7 +495,13 @@ export var createDeletedContentDecoration = function createDeletedContentDecorat
269
495
  } else {
270
496
  var fallbackNode = fallbackSerialization();
271
497
  if (fallbackNode) {
272
- dom.append(fallbackNode);
498
+ if (fg('platform_editor_ai_aifc_patch_beta_2')) {
499
+ var _wrapper2 = createDeletedStyleWrapperWithoutOpacity(colourScheme);
500
+ _wrapper2.append(fallbackNode);
501
+ dom.append(_wrapper2);
502
+ } else {
503
+ dom.append(fallbackNode);
504
+ }
273
505
  }
274
506
  }
275
507
  });
@@ -278,5 +510,5 @@ export var createDeletedContentDecoration = function createDeletedContentDecorat
278
510
  // Widget decoration used for deletions as the content is not in the document
279
511
  // and we want to display the deleted content with a style.
280
512
  var safeInsertPos = findSafeInsertPos(newDoc, change.fromB, slice);
281
- return Decoration.widget(safeInsertPos, dom, {});
513
+ return [Decoration.widget(safeInsertPos, dom)];
282
514
  };
@@ -0,0 +1,207 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ 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; } } }; }
3
+ 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; } }
4
+ 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; }
5
+ import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
6
+ import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
7
+ import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
8
+ import { Decoration } from '@atlaskit/editor-prosemirror/view';
9
+ import { TableMap } from '@atlaskit/editor-tables/table-map';
10
+ import { findSafeInsertPos } from './findSafeInsertPos';
11
+ var deletedRowStyle = convertToInlineCss({
12
+ color: "var(--ds-text-accent-gray, #44546F)",
13
+ textDecoration: 'line-through',
14
+ opacity: 0.6,
15
+ display: 'table-row'
16
+ });
17
+ var deletedTraditionalRowStyle = convertToInlineCss({
18
+ textDecorationColor: "var(--ds-border-accent-red, #E2483D)",
19
+ textDecoration: 'line-through',
20
+ opacity: 0.6,
21
+ display: 'table-row'
22
+ });
23
+ /**
24
+ * Extracts information about deleted table rows from a change
25
+ */
26
+ var extractDeletedRows = function extractDeletedRows(change, originalDoc, newDoc) {
27
+ var deletedRows = [];
28
+
29
+ // Find the table in the original document
30
+ var $fromPos = originalDoc.resolve(change.fromA);
31
+ var tableOld = findParentNodeClosestToPos($fromPos, function (node) {
32
+ return node.type.name === 'table';
33
+ });
34
+ if (!tableOld) {
35
+ return deletedRows;
36
+ }
37
+ var oldTableMap = TableMap.get(tableOld.node);
38
+
39
+ // Find the table in the new document at the insertion point
40
+ var $newPos = newDoc.resolve(change.fromB);
41
+ var tableNew = findParentNodeClosestToPos($newPos, function (node) {
42
+ return node.type.name === 'table';
43
+ });
44
+ if (!tableNew) {
45
+ return deletedRows;
46
+ }
47
+ var newTableMap = TableMap.get(tableNew.node);
48
+
49
+ // If no rows were deleted, return empty
50
+ if (oldTableMap.height <= newTableMap.height ||
51
+ // For now ignore if there are column deletions as well
52
+ oldTableMap.width !== newTableMap.width) {
53
+ return deletedRows;
54
+ }
55
+
56
+ // Find which rows were deleted by analyzing the change range
57
+ var changeStartInTable = change.fromA - tableOld.pos - 1;
58
+ var changeEndInTable = change.toA - tableOld.pos - 1;
59
+ var currentOffset = 0;
60
+ var rowIndex = 0;
61
+ tableOld.node.content.forEach(function (rowNode, index) {
62
+ var rowStart = currentOffset;
63
+ var rowEnd = currentOffset + rowNode.nodeSize;
64
+
65
+ // Check if this row overlaps with the deletion range
66
+ var rowOverlapsChange = rowStart >= changeStartInTable && rowStart < changeEndInTable || rowEnd > changeStartInTable && rowEnd <= changeEndInTable || rowStart < changeStartInTable && rowEnd > changeEndInTable;
67
+ if (rowOverlapsChange && rowNode.type.name === 'tableRow' && !isEmptyRow(rowNode)) {
68
+ var startOfRow = newTableMap.mapByRow.slice().reverse().find(function (row) {
69
+ return row[0] + tableNew.pos < change.fromB && change.fromB < row[row.length - 1] + tableNew.pos;
70
+ });
71
+ deletedRows.push({
72
+ rowIndex: rowIndex,
73
+ rowNode: rowNode,
74
+ fromA: tableOld.pos + 1 + rowStart,
75
+ toA: tableOld.pos + 1 + rowEnd,
76
+ fromB: startOfRow ? startOfRow[0] + tableNew.start : change.fromB
77
+ });
78
+ }
79
+ currentOffset += rowNode.nodeSize;
80
+ if (rowNode.type.name === 'tableRow') {
81
+ rowIndex++;
82
+ }
83
+ });
84
+
85
+ // Filter changes that never truly got deleted
86
+ return deletedRows.filter(function (deletedRow) {
87
+ return !tableNew.node.children.some(function (newRow) {
88
+ return areNodesEqualIgnoreAttrs(newRow, deletedRow.rowNode);
89
+ });
90
+ });
91
+ };
92
+
93
+ /**
94
+ * Checks if a table row is empty (contains no meaningful content)
95
+ */
96
+ var isEmptyRow = function isEmptyRow(rowNode) {
97
+ var isEmpty = true;
98
+ rowNode.descendants(function (node) {
99
+ if (!isEmpty) {
100
+ return false;
101
+ }
102
+
103
+ // If we find any inline content with size > 0, the row is not empty
104
+ if (node.isInline && node.nodeSize > 0) {
105
+ isEmpty = false;
106
+ return false;
107
+ }
108
+
109
+ // If we find text content, the row is not empty
110
+ if (node.isText && node.text && node.text.trim() !== '') {
111
+ isEmpty = false;
112
+ return false;
113
+ }
114
+ return true;
115
+ });
116
+ return isEmpty;
117
+ };
118
+
119
+ /**
120
+ * Creates a DOM representation of a deleted table row
121
+ */
122
+ var createDeletedRowDOM = function createDeletedRowDOM(rowNode, nodeViewSerializer, colourScheme) {
123
+ var tr = document.createElement('tr');
124
+ tr.setAttribute('style', colourScheme === 'traditional' ? deletedTraditionalRowStyle : deletedRowStyle);
125
+ tr.setAttribute('data-testid', 'show-diff-deleted-row');
126
+
127
+ // Serialize each cell in the row
128
+ rowNode.content.forEach(function (cellNode) {
129
+ if (cellNode.type.name === 'tableCell' || cellNode.type.name === 'tableHeader') {
130
+ var nodeView = nodeViewSerializer.tryCreateNodeView(cellNode);
131
+ if (nodeView) {
132
+ tr.appendChild(nodeView);
133
+ } else {
134
+ // Fallback to fragment serialization
135
+ var serializedContent = nodeViewSerializer.serializeFragment(cellNode.content);
136
+ if (serializedContent) {
137
+ tr.appendChild(serializedContent);
138
+ }
139
+ }
140
+ }
141
+ });
142
+ return tr;
143
+ };
144
+
145
+ /**
146
+ * Expands a diff to include whole deleted rows when table rows are affected
147
+ */
148
+ var expandDiffForDeletedRows = function expandDiffForDeletedRows(changes, originalDoc, newDoc) {
149
+ var deletedRowInfo = [];
150
+ var _iterator = _createForOfIteratorHelper(changes),
151
+ _step;
152
+ try {
153
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
154
+ var change = _step.value;
155
+ // Check if this change affects table content
156
+ var deletedRows = extractDeletedRows(change, originalDoc, newDoc);
157
+ if (deletedRows.length > 0) {
158
+ deletedRowInfo.push.apply(deletedRowInfo, _toConsumableArray(deletedRows));
159
+ }
160
+ }
161
+ } catch (err) {
162
+ _iterator.e(err);
163
+ } finally {
164
+ _iterator.f();
165
+ }
166
+ return deletedRowInfo;
167
+ };
168
+
169
+ /**
170
+ * Creates decorations for deleted table rows
171
+ */
172
+ export var createDeletedRowsDecorations = function createDeletedRowsDecorations(_ref) {
173
+ var deletedRows = _ref.deletedRows,
174
+ originalDoc = _ref.originalDoc,
175
+ newDoc = _ref.newDoc,
176
+ nodeViewSerializer = _ref.nodeViewSerializer,
177
+ colourScheme = _ref.colourScheme;
178
+ return deletedRows.map(function (deletedRow) {
179
+ var rowDOM = createDeletedRowDOM(deletedRow.rowNode, nodeViewSerializer, colourScheme);
180
+
181
+ // Find safe insertion position for the deleted row
182
+ var safeInsertPos = findSafeInsertPos(newDoc, deletedRow.fromB - 1,
183
+ // -1 to find the first safe position from the table
184
+ originalDoc.slice(deletedRow.fromA, deletedRow.toA));
185
+ return Decoration.widget(safeInsertPos, rowDOM, {});
186
+ });
187
+ };
188
+
189
+ /**
190
+ * Main function to handle deleted rows - computes diff and creates decorations
191
+ */
192
+ export var handleDeletedRows = function handleDeletedRows(changes, originalDoc, newDoc, nodeViewSerializer, colourScheme) {
193
+ // First, expand the changes to include complete deleted rows
194
+ var deletedRows = expandDiffForDeletedRows(changes.filter(function (change) {
195
+ return change.deleted.length > 0;
196
+ }), originalDoc, newDoc);
197
+ var allDecorations = createDeletedRowsDecorations({
198
+ deletedRows: deletedRows,
199
+ originalDoc: originalDoc,
200
+ newDoc: newDoc,
201
+ nodeViewSerializer: nodeViewSerializer,
202
+ colourScheme: colourScheme
203
+ });
204
+ return {
205
+ decorations: allDecorations
206
+ };
207
+ };
@@ -9,7 +9,7 @@ import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
9
  import { calculateDiffDecorations } from './calculateDiffDecorations';
10
10
  import { NodeViewSerializer } from './NodeViewSerializer';
11
11
  export var showDiffPluginKey = new PluginKey('showDiffPlugin');
12
- export var createPlugin = function createPlugin(config) {
12
+ export var createPlugin = function createPlugin(config, getIntl) {
13
13
  var nodeViewSerializer = new NodeViewSerializer({});
14
14
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
15
15
  nodeViewSerializer.init({
@@ -19,7 +19,7 @@ export var createPlugin = function createPlugin(config) {
19
19
  return new SafePlugin({
20
20
  key: showDiffPluginKey,
21
21
  state: {
22
- init: function init(_, state) {
22
+ init: function init(_, _state) {
23
23
  // We do initial setup after we setup the editor view
24
24
  return {
25
25
  steps: [],
@@ -42,7 +42,8 @@ export var createPlugin = function createPlugin(config) {
42
42
  state: newState,
43
43
  pluginState: newPluginState,
44
44
  nodeViewSerializer: nodeViewSerializer,
45
- colourScheme: config === null || config === void 0 ? void 0 : config.colourScheme
45
+ colourScheme: config === null || config === void 0 ? void 0 : config.colourScheme,
46
+ intl: getIntl()
46
47
  });
47
48
  // Update the decorations
48
49
  newPluginState.decorations = decorations;
@@ -3,7 +3,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
3
  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
4
  import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
5
5
  export var showDiffPlugin = function showDiffPlugin(_ref) {
6
- var api = _ref.api,
6
+ var _api = _ref.api,
7
7
  config = _ref.config;
8
8
  return {
9
9
  name: 'showDiff',
@@ -27,8 +27,9 @@ export var showDiffPlugin = function showDiffPlugin(_ref) {
27
27
  pmPlugins: function pmPlugins() {
28
28
  return [{
29
29
  name: 'showDiffPlugin',
30
- plugin: function plugin() {
31
- return createPlugin(config);
30
+ plugin: function plugin(_ref4) {
31
+ var getIntl = _ref4.getIntl;
32
+ return createPlugin(config, getIntl);
32
33
  }
33
34
  }];
34
35
  },
@@ -1,9 +1,11 @@
1
+ import type { IntlShape } from 'react-intl-next';
1
2
  import { type EditorState } from '@atlaskit/editor-prosemirror/state';
2
3
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
3
4
  import type { ShowDiffPluginState } from './main';
4
5
  import type { NodeViewSerializer } from './NodeViewSerializer';
5
- export declare const calculateDiffDecorations: import("memoize-one").MemoizedFn<({ state, pluginState, nodeViewSerializer, colourScheme, }: {
6
+ export declare const calculateDiffDecorations: import("memoize-one").MemoizedFn<({ state, pluginState, nodeViewSerializer, colourScheme, intl, }: {
6
7
  colourScheme?: "standard" | "traditional";
8
+ intl: IntlShape;
7
9
  nodeViewSerializer: NodeViewSerializer;
8
10
  pluginState: Omit<ShowDiffPluginState, "decorations">;
9
11
  state: EditorState;