@atlaskit/editor-plugin-show-diff 10.2.0 → 10.4.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 (36) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/calculate-diff/package.json +8 -0
  3. package/dist/cjs/entry-points/calculate-diff.js +12 -0
  4. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +14 -3
  5. package/dist/cjs/pm-plugins/calculateDiff/computeDiffChanges.js +112 -0
  6. package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +19 -1
  7. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +4 -2
  8. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +5 -2
  9. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +40 -21
  10. package/dist/cjs/pm-plugins/main.js +11 -7
  11. package/dist/es2019/entry-points/calculate-diff.js +2 -0
  12. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +13 -3
  13. package/dist/es2019/pm-plugins/calculateDiff/computeDiffChanges.js +94 -0
  14. package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +18 -0
  15. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +4 -3
  16. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
  17. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +35 -25
  18. package/dist/es2019/pm-plugins/main.js +11 -7
  19. package/dist/esm/entry-points/calculate-diff.js +2 -0
  20. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +14 -3
  21. package/dist/esm/pm-plugins/calculateDiff/computeDiffChanges.js +107 -0
  22. package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +18 -0
  23. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +5 -3
  24. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +5 -2
  25. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +41 -22
  26. package/dist/esm/pm-plugins/main.js +11 -7
  27. package/dist/types/entry-points/calculate-diff.d.ts +2 -0
  28. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +2 -1
  29. package/dist/types/pm-plugins/calculateDiff/computeDiffChanges.d.ts +46 -0
  30. package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +9 -0
  31. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  32. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +2 -1
  33. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
  34. package/dist/types/pm-plugins/main.d.ts +1 -0
  35. package/dist/types/showDiffPluginType.d.ts +12 -5
  36. package/package.json +6 -6
@@ -0,0 +1,107 @@
1
+ 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; } } }; }
2
+ 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; } }
3
+ 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; }
4
+ /**
5
+ * Generic, editor-state-free diff-change computation.
6
+ *
7
+ * Turns an `originalDoc` + forward `steps` into the classified `Change[]` for the
8
+ * requested `diffType`, plus the reconstructed new document — the same classifier
9
+ * the diff overlay uses (`calculateDiffDecorations` → `getChanges`), exposed as a
10
+ * reusable utility (e.g. to derive reviewable segments without rendering
11
+ * decorations). It runs the requested `diffType` DIRECTLY and does NOT apply the
12
+ * overlay's `platform_editor_ai_smart_diff` gate, so a `smart` result here can
13
+ * differ from what the overlay draws when that gate is off (the overlay falls back
14
+ * to inline); callers that need overlay parity must account for that gate.
15
+ *
16
+ * Pure: no `EditorState`, no transactions, no React. The new document is
17
+ * reconstructed by applying the (simplified) steps to `originalDoc`.
18
+ */
19
+ import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
20
+ import { diffBySteps } from './diffBySteps';
21
+ import { groupChangesByBlock } from './groupChangesByBlock';
22
+ import { optimizeChanges } from './optimizeChanges';
23
+ import { simplifySteps } from './simplifySteps';
24
+ import { classifySmartChanges } from './smart/classifySmartChanges';
25
+ /**
26
+ * Apply the (simplified) steps to `originalDoc` to reconstruct the new doc, and
27
+ * compute the classified `Change[]` for the requested `diffType`. Mirrors the
28
+ * body of `calculateDiffDecorations` → `getChanges` so callers stay in lock-step
29
+ * with the rendered diff. Returns an empty change list (and `originalDoc` as the
30
+ * new doc) when there are no steps.
31
+ */
32
+ export var computeDiffChanges = function computeDiffChanges(_ref) {
33
+ var originalDoc = _ref.originalDoc,
34
+ steps = _ref.steps,
35
+ _ref$diffType = _ref.diffType,
36
+ diffType = _ref$diffType === void 0 ? 'smart' : _ref$diffType,
37
+ _ref$locale = _ref.locale,
38
+ locale = _ref$locale === void 0 ? 'en' : _ref$locale,
39
+ smartThresholds = _ref.smartThresholds;
40
+ if (!steps || steps.length === 0) {
41
+ return {
42
+ changes: [],
43
+ newDoc: originalDoc
44
+ };
45
+ }
46
+ var simplifiedSteps = simplifySteps(steps, originalDoc);
47
+ var steppedDoc = originalDoc;
48
+ var stepMaps = [];
49
+ try {
50
+ var _iterator = _createForOfIteratorHelper(simplifiedSteps),
51
+ _step;
52
+ try {
53
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
54
+ var step = _step.value;
55
+ var result = step.apply(steppedDoc);
56
+ if (result.failed === null && result.doc) {
57
+ stepMaps.push(step.getMap());
58
+ steppedDoc = result.doc;
59
+ }
60
+ }
61
+ } catch (err) {
62
+ _iterator.e(err);
63
+ } finally {
64
+ _iterator.f();
65
+ }
66
+ } catch (_unused) {
67
+ // A step's positions fell outside the current doc — `ReplaceStep.apply`
68
+ // throws a RangeError (rather than returning a failed result) when a
69
+ // position exceeds the doc size. This can happen for pathological or
70
+ // inconsistent step sequences. Bail with no changes rather than letting the
71
+ // error propagate to the caller (which, for the PSR, would crash the
72
+ // toolbar); the consumer then falls back to its non-diff segmenting path.
73
+ return {
74
+ changes: [],
75
+ newDoc: originalDoc
76
+ };
77
+ }
78
+ var changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, steppedDoc);
79
+ if (diffType === 'smart') {
80
+ return {
81
+ changes: classifySmartChanges({
82
+ changes: simplifyChanges(changeset.changes, steppedDoc),
83
+ originalDoc: originalDoc,
84
+ newDoc: steppedDoc,
85
+ locale: locale,
86
+ thresholds: smartThresholds
87
+ }),
88
+ newDoc: steppedDoc
89
+ };
90
+ }
91
+ if (diffType === 'block') {
92
+ return {
93
+ changes: groupChangesByBlock(changeset.changes, originalDoc, steppedDoc),
94
+ newDoc: steppedDoc
95
+ };
96
+ }
97
+ if (diffType === 'step') {
98
+ return {
99
+ changes: diffBySteps(originalDoc, simplifiedSteps),
100
+ newDoc: steppedDoc
101
+ };
102
+ }
103
+ return {
104
+ changes: optimizeChanges(simplifyChanges(changeset.changes, steppedDoc)),
105
+ newDoc: steppedDoc
106
+ };
107
+ };
@@ -38,6 +38,24 @@ export var editingStyleActiveExtended = convertToInlineCss({
38
38
  borderBottom: "2px solid ".concat("var(--ds-border-accent-purple, #AF59E1)"),
39
39
  padding: "1px 0 2px"
40
40
  });
41
+
42
+ /**
43
+ * Underline-free variants of the extended inserted-content styles. Used when the `showDiff`
44
+ * command is called with `hideAddedDiffsUnderline: true` to remove ONLY the dark-purple
45
+ * `borderBottom` underline from added/updated content while keeping the purple background
46
+ * highlight and padding. See the `editing*Extended` constants above for the full versions.
47
+ */
48
+ export var editingStyleExtendedNoUnderline = convertToInlineCss({
49
+ background: "var(--ds-background-accent-purple-subtlest, #F8EEFE)",
50
+ padding: "1px 0 2px"
51
+ });
52
+ export var editingStyleActiveExtendedNoUnderline = convertToInlineCss({
53
+ background: "var(--ds-background-accent-purple-subtler-pressed, #D8A0F7)",
54
+ padding: "1px 0 2px"
55
+ });
56
+ export var editingContentStyleInBlockExtendedNoUnderline = convertToInlineCss({
57
+ padding: "1px 0 2px"
58
+ });
41
59
  export var deletedContentStyle = convertToInlineCss({
42
60
  color: "var(--ds-text-accent-gray, #505258)",
43
61
  textDecoration: 'line-through',
@@ -2,7 +2,7 @@ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
2
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
3
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
4
  import { isExtendedEnabled } from '../isExtendedEnabled';
5
- import { editingStyle, editingStyleExtended, editingStyleActive, editingStyleActiveExtended, deletedContentStyle, deletedContentStyleActive, deletedInlineContentStyleExtended } from './colorSchemes/standard';
5
+ import { editingStyle, editingStyleExtended, editingStyleExtendedNoUnderline, editingStyleActive, editingStyleActiveExtended, editingStyleActiveExtendedNoUnderline, deletedContentStyle, deletedContentStyleActive, deletedInlineContentStyleExtended } from './colorSchemes/standard';
6
6
  import { traditionalInsertStyle, traditionalInsertStyleActive, getDeletedTraditionalInlineStyle } from './colorSchemes/traditional';
7
7
  import { createInlineIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
8
8
  import { buildDiffDecorationSpec } from './decorationKeys';
@@ -28,7 +28,9 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
28
28
  _ref$showIndicators = _ref.showIndicators,
29
29
  showIndicators = _ref$showIndicators === void 0 ? false : _ref$showIndicators,
30
30
  doc = _ref.doc,
31
- diffType = _ref.diffType;
31
+ diffType = _ref.diffType,
32
+ _ref$hideAddedDiffsUn = _ref.hideAddedDiffsUnderline,
33
+ hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn;
32
34
  var diffId = crypto.randomUUID();
33
35
  if (shouldHideDeleted) {
34
36
  return [Decoration.inline(change.fromB, change.toB, {
@@ -45,7 +47,7 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
45
47
  if (colorScheme === 'traditional') {
46
48
  style = isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
47
49
  } else {
48
- style = isActive ? editingStyleActiveExtended : editingStyleExtended;
50
+ style = isActive ? hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended : hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
49
51
  }
50
52
  } else {
51
53
  if (colorScheme === 'traditional') {
@@ -28,7 +28,9 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
28
28
  showIndicators = _ref$showIndicators === void 0 ? false : _ref$showIndicators,
29
29
  _ref$placeBelow = _ref.placeBelow,
30
30
  placeBelow = _ref$placeBelow === void 0 ? false : _ref$placeBelow,
31
- diffType = _ref.diffType;
31
+ diffType = _ref.diffType,
32
+ _ref$hideAddedDiffsUn = _ref.hideAddedDiffsUnderline,
33
+ hideAddedDiffsUnderline = _ref$hideAddedDiffsUn === void 0 ? false : _ref$hideAddedDiffsUn;
32
34
  var slice = doc.slice(change.fromA, change.toA);
33
35
  var shouldSkipDeletedEmptyParagraphDecoration = !isInserted && (slice === null || slice === void 0 || (_slice$content = slice.content) === null || _slice$content === void 0 ? void 0 : _slice$content.childCount) === 1 && (slice === null || slice === void 0 || (_slice$content2 = slice.content) === null || _slice$content2 === void 0 || (_slice$content2 = _slice$content2.firstChild) === null || _slice$content2 === void 0 ? void 0 : _slice$content2.type.name) === 'paragraph' && (slice === null || slice === void 0 || (_slice$content3 = slice.content) === null || _slice$content3 === void 0 || (_slice$content3 = _slice$content3.firstChild) === null || _slice$content3 === void 0 ? void 0 : _slice$content3.content.size) === 0;
34
36
  // Widget decoration used for deletions as the content is not in the document
@@ -177,7 +179,8 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
177
179
  intl: intl,
178
180
  isActive: isActive,
179
181
  isInserted: isInserted,
180
- diffType: diffType
182
+ diffType: diffType,
183
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
181
184
  });
182
185
  }
183
186
  } else if (nodeViewSerializer.getFilteredNodeViewBlocklist(['paragraph', 'tableRow']).has(node.type.name)) {
@@ -4,7 +4,7 @@ import { trackChangesMessages } from '@atlaskit/editor-common/messages';
4
4
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
5
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
6
  import { isExtendedEnabled } from '../../isExtendedEnabled';
7
- import { deletedBlockOutline, deletedBlockOutlineActive, deletedBlockOutlineRounded, deletedBlockOutlineRoundedActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleUnbounded, deletedInlineContentStyleExtended, deletedStyleQuoteNodeWithLozenge, deletedStyleQuoteNodeWithLozengeActive, editingContentStyleInBlockExtended, editingStyleExtended, editingStyleActiveExtended, editingStyleNode, addedCellOverlayStyle, deletedCellOverlayStyle } from '../colorSchemes/standard';
7
+ import { deletedBlockOutline, deletedBlockOutlineActive, deletedBlockOutlineRounded, deletedBlockOutlineRoundedActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleUnbounded, deletedInlineContentStyleExtended, deletedStyleQuoteNodeWithLozenge, deletedStyleQuoteNodeWithLozengeActive, editingContentStyleInBlockExtended, editingContentStyleInBlockExtendedNoUnderline, editingStyleExtended, editingStyleExtendedNoUnderline, editingStyleActiveExtended, editingStyleActiveExtendedNoUnderline, editingStyleNode, addedCellOverlayStyle, deletedCellOverlayStyle } from '../colorSchemes/standard';
8
8
  import { deletedTraditionalBlockOutlineActive, deletedTraditionalBlockOutlineNew, deletedTraditionalBlockOutlineRoundedActive, deletedTraditionalBlockOutlineRoundedNew, deletedTraditionalContentStyleUnbounded, deletedTraditionalContentStyleUnboundedActive, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, deletedTraditionalStyleQuoteNodeActive, traditionalInsertStyle, traditionalInsertStyleActive, traditionalStyleNodeActive, traditionalStyleNodeNew, traditionalAddedCellOverlayStyleNew, deletedTraditionalCellOverlayStyle } from '../colorSchemes/traditional';
9
9
  var lozengeStyle = convertToInlineCss({
10
10
  display: 'inline-flex',
@@ -58,11 +58,12 @@ var getChangedContentStyle = function getChangedContentStyle(colorScheme) {
58
58
  var isActive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
59
59
  var isInserted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
60
60
  var diffType = arguments.length > 3 ? arguments[3] : undefined;
61
+ var hideAddedDiffsUnderline = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
61
62
  if (isExtendedEnabled(diffType) && isInserted) {
62
63
  if (colorScheme === 'traditional') {
63
64
  return isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
64
65
  }
65
- return isActive ? editingStyleActiveExtended : editingStyleExtended;
66
+ return isActive ? hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended : hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
66
67
  }
67
68
  if (colorScheme === 'traditional') {
68
69
  return getDeletedTraditionalInlineStyle(isActive);
@@ -76,10 +77,11 @@ var getChangedNodeStyle = function getChangedNodeStyle(nodeName, colorScheme) {
76
77
  var isInserted = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
77
78
  var isActive = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
78
79
  var diffType = arguments.length > 4 ? arguments[4] : undefined;
80
+ var hideAddedDiffsUnderline = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
79
81
  var isTraditional = colorScheme === 'traditional';
80
82
  if (isExtendedEnabled(diffType) && isInserted) {
81
83
  if (isMultiContainerBlockNode(nodeName)) {
82
- return editingContentStyleInBlockExtended;
84
+ return hideAddedDiffsUnderline ? editingContentStyleInBlockExtendedNoUnderline : editingContentStyleInBlockExtended;
83
85
  }
84
86
  if (isTextLikeBlockNode(nodeName)) {
85
87
  return undefined;
@@ -227,11 +229,13 @@ var applyStylesToElement = function applyStylesToElement(_ref3) {
227
229
  colorScheme = _ref3.colorScheme,
228
230
  isActive = _ref3.isActive,
229
231
  isInserted = _ref3.isInserted,
230
- diffType = _ref3.diffType;
232
+ diffType = _ref3.diffType,
233
+ _ref3$hideAddedDiffsU = _ref3.hideAddedDiffsUnderline,
234
+ hideAddedDiffsUnderline = _ref3$hideAddedDiffsU === void 0 ? false : _ref3$hideAddedDiffsU;
231
235
  var currentStyle = element.getAttribute('style') || '';
232
- var contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
236
+ var contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
233
237
  var targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
234
- var nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType) || '';
238
+ var nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
235
239
  element.setAttribute('style', "".concat(currentStyle).concat(contentStyle).concat(nodeSpecificStyle));
236
240
  };
237
241
  var applyMultiContainerLikeStyles = function applyMultiContainerLikeStyles(_ref4) {
@@ -240,10 +244,12 @@ var applyMultiContainerLikeStyles = function applyMultiContainerLikeStyles(_ref4
240
244
  colorScheme = _ref4.colorScheme,
241
245
  isActive = _ref4.isActive,
242
246
  isInserted = _ref4.isInserted,
243
- diffType = _ref4.diffType;
247
+ diffType = _ref4.diffType,
248
+ _ref4$hideAddedDiffsU = _ref4.hideAddedDiffsUnderline,
249
+ hideAddedDiffsUnderline = _ref4$hideAddedDiffsU === void 0 ? false : _ref4$hideAddedDiffsU;
244
250
  var currentStyle = element.getAttribute('style') || '';
245
251
  var targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
246
- var nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType) || '';
252
+ var nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
247
253
  if (targetNode.type.name === 'decisionList') {
248
254
  element.querySelectorAll('li').forEach(function (listItem) {
249
255
  var currentListItemStyle = listItem.getAttribute('style') || '';
@@ -268,13 +274,15 @@ var applyTextLikeBlockNodeStyles = function applyTextLikeBlockNodeStyles(_ref5)
268
274
  colorScheme = _ref5.colorScheme,
269
275
  isActive = _ref5.isActive,
270
276
  isInserted = _ref5.isInserted,
271
- diffType = _ref5.diffType;
277
+ diffType = _ref5.diffType,
278
+ _ref5$hideAddedDiffsU = _ref5.hideAddedDiffsUnderline,
279
+ hideAddedDiffsUnderline = _ref5$hideAddedDiffsU === void 0 ? false : _ref5$hideAddedDiffsU;
272
280
  var currentStyle = element.getAttribute('style') || '';
273
- var nodeSpecificStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted, isActive, diffType) || '';
281
+ var nodeSpecificStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
274
282
  if (nodeSpecificStyle) {
275
283
  element.setAttribute('style', "".concat(currentStyle).concat(nodeSpecificStyle));
276
284
  }
277
- var contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
285
+ var contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
278
286
  var walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
279
287
  var textNodesToWrap = [];
280
288
  var currentNode = walker.nextNode();
@@ -301,16 +309,18 @@ var createBlockNodeContentWrapper = function createBlockNodeContentWrapper(_ref6
301
309
  colorScheme = _ref6.colorScheme,
302
310
  isActive = _ref6.isActive,
303
311
  isInserted = _ref6.isInserted,
304
- diffType = _ref6.diffType;
312
+ diffType = _ref6.diffType,
313
+ _ref6$hideAddedDiffsU = _ref6.hideAddedDiffsUnderline,
314
+ hideAddedDiffsUnderline = _ref6$hideAddedDiffsU === void 0 ? false : _ref6$hideAddedDiffsU;
305
315
  var contentWrapper = document.createElement('div');
306
316
  var targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
307
- var nodeStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType);
317
+ var nodeStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline);
308
318
 
309
319
  // When the extended experiment is enabled and the content is inserted,
310
320
  // block widget nodes that already have dedicated node-level styling (e.g. boxShadow outline)
311
321
  // should not also get the inline content style (borderBottom underline) on their container.
312
322
  var shouldSkipContentStyle = isExtendedEnabled(diffType) && isInserted && nodeStyle !== undefined;
313
- var contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
323
+ var contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
314
324
  contentWrapper.setAttribute('style', "".concat(contentStyle).concat(nodeStyle || ''));
315
325
  contentWrapper.append(nodeView);
316
326
  return contentWrapper;
@@ -425,7 +435,9 @@ var wrapBlockNode = function wrapBlockNode(_ref9) {
425
435
  isActive = _ref9$isActive === void 0 ? false : _ref9$isActive,
426
436
  _ref9$isInserted = _ref9.isInserted,
427
437
  isInserted = _ref9$isInserted === void 0 ? false : _ref9$isInserted,
428
- diffType = _ref9.diffType;
438
+ diffType = _ref9.diffType,
439
+ _ref9$hideAddedDiffsU = _ref9.hideAddedDiffsUnderline,
440
+ hideAddedDiffsUnderline = _ref9$hideAddedDiffsU === void 0 ? false : _ref9$hideAddedDiffsU;
429
441
  var blockWrapper = createBlockNodeWrapper();
430
442
  var targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
431
443
  if (shouldShowRemovedLozenge(targetNodeName) && (!isExtendedEnabled(diffType) || !isInserted)) {
@@ -458,7 +470,8 @@ var wrapBlockNode = function wrapBlockNode(_ref9) {
458
470
  colorScheme: colorScheme,
459
471
  isActive: isActive,
460
472
  isInserted: isInserted,
461
- diffType: diffType
473
+ diffType: diffType,
474
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
462
475
  });
463
476
  blockWrapper.append(contentWrapper);
464
477
  if (nodeView instanceof HTMLElement && shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
@@ -492,7 +505,9 @@ export var wrapBlockNodeView = function wrapBlockNodeView(_ref0) {
492
505
  isActive = _ref0$isActive === void 0 ? false : _ref0$isActive,
493
506
  _ref0$isInserted = _ref0.isInserted,
494
507
  isInserted = _ref0$isInserted === void 0 ? false : _ref0$isInserted,
495
- diffType = _ref0.diffType;
508
+ diffType = _ref0.diffType,
509
+ _ref0$hideAddedDiffsU = _ref0.hideAddedDiffsUnderline,
510
+ hideAddedDiffsUnderline = _ref0$hideAddedDiffsU === void 0 ? false : _ref0$hideAddedDiffsU;
496
511
  if (isExtendedEnabled(diffType)) {
497
512
  if (nodeView instanceof HTMLElement) {
498
513
  if (isInserted && isMultiContainerBlockNode(targetNode.type.name)) {
@@ -502,7 +517,8 @@ export var wrapBlockNodeView = function wrapBlockNodeView(_ref0) {
502
517
  colorScheme: colorScheme,
503
518
  isActive: isActive,
504
519
  isInserted: isInserted,
505
- diffType: diffType
520
+ diffType: diffType,
521
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
506
522
  });
507
523
  dom.append(nodeView);
508
524
  return;
@@ -514,7 +530,8 @@ export var wrapBlockNodeView = function wrapBlockNodeView(_ref0) {
514
530
  colorScheme: colorScheme,
515
531
  isActive: isActive,
516
532
  isInserted: isInserted,
517
- diffType: diffType
533
+ diffType: diffType,
534
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
518
535
  });
519
536
  dom.append(nodeView);
520
537
  return;
@@ -537,7 +554,8 @@ export var wrapBlockNodeView = function wrapBlockNodeView(_ref0) {
537
554
  intl: intl,
538
555
  isActive: isActive,
539
556
  isInserted: isInserted,
540
- diffType: diffType
557
+ diffType: diffType,
558
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
541
559
  });
542
560
  return;
543
561
  } else {
@@ -575,13 +593,14 @@ var getDeletedContentStyleUnbounded = function getDeletedContentStyleUnbounded(c
575
593
  };
576
594
  var getInsertedContentStyle = function getInsertedContentStyle(colorScheme) {
577
595
  var isActive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
596
+ var hideAddedDiffsUnderline = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
578
597
  if (colorScheme === 'traditional') {
579
598
  return isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
580
599
  }
581
600
  if (isActive) {
582
- return editingStyleActiveExtended;
601
+ return hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended;
583
602
  }
584
- return editingStyleExtended;
603
+ return hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
585
604
  };
586
605
  var getDeletedContentStyle = function getDeletedContentStyle(colorScheme) {
587
606
  var isActive = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -35,6 +35,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
35
35
  isInverted: false,
36
36
  diffType: 'inline',
37
37
  hideDeletedDiffs: false,
38
+ hideAddedDiffsUnderline: false,
38
39
  showIndicators: false,
39
40
  diffDescriptors: []
40
41
  } : {});
@@ -44,7 +45,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
44
45
  var newPluginState = currentPluginState;
45
46
  if (meta) {
46
47
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
47
- var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8;
48
+ var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9;
48
49
  // Update the plugin state with the new metadata
49
50
  newPluginState = _objectSpread(_objectSpread(_objectSpread({}, currentPluginState), meta), {}, {
50
51
  isDisplayingChanges: true,
@@ -63,15 +64,16 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
63
64
  isInverted: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.isInverted,
64
65
  diffType: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.diffType,
65
66
  hideDeletedDiffs: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.hideDeletedDiffs,
66
- showIndicators: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.showIndicators,
67
- smartThresholds: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.smartThresholds,
68
- deletedDiffPlacement: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.deletedDiffPlacement
67
+ hideAddedDiffsUnderline: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.hideAddedDiffsUnderline,
68
+ showIndicators: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.showIndicators,
69
+ smartThresholds: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.smartThresholds,
70
+ deletedDiffPlacement: (_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.deletedDiffPlacement
69
71
  } : {})),
70
72
  decorations = _calculateDiffDecorat.decorations,
71
73
  diffDescriptors = _calculateDiffDecorat.diffDescriptors;
72
74
  // Update the decorations and their ids
73
75
  newPluginState.decorations = decorations;
74
- if (isExtendedEnabled((_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.diffType)) {
76
+ if (isExtendedEnabled((_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.diffType)) {
75
77
  newPluginState.diffDescriptors = diffDescriptors;
76
78
  }
77
79
  } else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'HIDE_DIFF') {
@@ -83,12 +85,13 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
83
85
  isInverted: false,
84
86
  diffType: 'inline',
85
87
  hideDeletedDiffs: false,
88
+ hideAddedDiffsUnderline: false,
86
89
  diffDescriptors: []
87
90
  } : {});
88
91
  } else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') {
89
- var _newPluginState9;
92
+ var _newPluginState0;
90
93
  // Update the active index in plugin state and recalculate decorations
91
- var _decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.diffType);
94
+ var _decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState0 = newPluginState) === null || _newPluginState0 === void 0 ? void 0 : _newPluginState0.diffType);
92
95
  if (_decorations.length > 0) {
93
96
  var _currentPluginState$a;
94
97
  // Initialize to -1 if undefined so that the first "next" scroll takes us to index 0 (first change).
@@ -126,6 +129,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
126
129
  isInverted: newPluginState.isInverted,
127
130
  diffType: newPluginState.diffType,
128
131
  hideDeletedDiffs: newPluginState.hideDeletedDiffs,
132
+ hideAddedDiffsUnderline: newPluginState.hideAddedDiffsUnderline,
129
133
  showIndicators: newPluginState.showIndicators,
130
134
  smartThresholds: newPluginState.smartThresholds,
131
135
  deletedDiffPlacement: newPluginState.deletedDiffPlacement
@@ -0,0 +1,2 @@
1
+ export { computeDiffChanges } from '../pm-plugins/calculateDiff/computeDiffChanges';
2
+ export type { ComputeDiffChangesParams } from '../pm-plugins/calculateDiff/computeDiffChanges';
@@ -10,7 +10,7 @@ type CalculatedDiffs = {
10
10
  decorations: DecorationSet;
11
11
  diffDescriptors: DiffDescriptor[];
12
12
  };
13
- export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, hideDeletedDiffs, showIndicators, }: {
13
+ export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, hideDeletedDiffs, hideAddedDiffsUnderline, showIndicators, }: {
14
14
  activeIndexPos?: {
15
15
  from: number;
16
16
  to: number;
@@ -18,6 +18,7 @@ export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState,
18
18
  api: ExtractInjectionAPI<ShowDiffPlugin> | undefined;
19
19
  colorScheme?: ColorScheme;
20
20
  deletedDiffPlacement?: DeletedDiffPlacement;
21
+ hideAddedDiffsUnderline?: boolean;
21
22
  hideDeletedDiffs?: boolean;
22
23
  intl: IntlShape;
23
24
  nodeViewSerializer: NodeViewSerializer;
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Generic, editor-state-free diff-change computation.
3
+ *
4
+ * Turns an `originalDoc` + forward `steps` into the classified `Change[]` for the
5
+ * requested `diffType`, plus the reconstructed new document — the same classifier
6
+ * the diff overlay uses (`calculateDiffDecorations` → `getChanges`), exposed as a
7
+ * reusable utility (e.g. to derive reviewable segments without rendering
8
+ * decorations). It runs the requested `diffType` DIRECTLY and does NOT apply the
9
+ * overlay's `platform_editor_ai_smart_diff` gate, so a `smart` result here can
10
+ * differ from what the overlay draws when that gate is off (the overlay falls back
11
+ * to inline); callers that need overlay parity must account for that gate.
12
+ *
13
+ * Pure: no `EditorState`, no transactions, no React. The new document is
14
+ * reconstructed by applying the (simplified) steps to `originalDoc`.
15
+ */
16
+ import { type Change } from 'prosemirror-changeset';
17
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
18
+ import type { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
19
+ import type { DiffType, SmartDiffThresholds } from '../../showDiffPluginType';
20
+ export type ComputeDiffChangesParams = {
21
+ /**
22
+ * Which classification to run. Defaults to `smart` — the density-aware model.
23
+ * The other types are supported for parity with the diff overlay's
24
+ * `getChanges`.
25
+ */
26
+ diffType?: DiffType;
27
+ /** BCP-47 locale for `smart` sentence/word segmentation. Defaults to `en`. */
28
+ locale?: string;
29
+ /** The pre-edit document (the diff's left/original side). */
30
+ originalDoc: PMNode;
31
+ /** Optional overrides for the `smart` density thresholds. Ignored otherwise. */
32
+ smartThresholds?: Partial<SmartDiffThresholds>;
33
+ /** Forward `original → new` steps (the standard non-inverted contract). */
34
+ steps: ProseMirrorStep[];
35
+ };
36
+ /**
37
+ * Apply the (simplified) steps to `originalDoc` to reconstruct the new doc, and
38
+ * compute the classified `Change[]` for the requested `diffType`. Mirrors the
39
+ * body of `calculateDiffDecorations` → `getChanges` so callers stay in lock-step
40
+ * with the rendered diff. Returns an empty change list (and `originalDoc` as the
41
+ * new doc) when there are no steps.
42
+ */
43
+ export declare const computeDiffChanges: ({ originalDoc, steps, diffType, locale, smartThresholds, }: ComputeDiffChangesParams) => {
44
+ changes: Change[];
45
+ newDoc: PMNode;
46
+ };
@@ -4,6 +4,15 @@ export declare const editingStyleActive: string;
4
4
  export declare const editingStyleExtended: string;
5
5
  export declare const editingContentStyleInBlockExtended: string;
6
6
  export declare const editingStyleActiveExtended: string;
7
+ /**
8
+ * Underline-free variants of the extended inserted-content styles. Used when the `showDiff`
9
+ * command is called with `hideAddedDiffsUnderline: true` to remove ONLY the dark-purple
10
+ * `borderBottom` underline from added/updated content while keeping the purple background
11
+ * highlight and padding. See the `editing*Extended` constants above for the full versions.
12
+ */
13
+ export declare const editingStyleExtendedNoUnderline: string;
14
+ export declare const editingStyleActiveExtendedNoUnderline: string;
15
+ export declare const editingContentStyleInBlockExtendedNoUnderline: string;
7
16
  export declare const deletedContentStyle: string;
8
17
  export declare const deletedContentStyleActive: string;
9
18
  export declare const deletedContentStyleNew: string;
@@ -7,7 +7,7 @@ import type { ColorScheme, DiffType } from '../../showDiffPluginType';
7
7
  * @param change Changeset "change" containing information about the change content + range
8
8
  * @returns Prosemirror inline decoration
9
9
  */
10
- export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, shouldHideDeleted, showIndicators, doc, diffType, }: {
10
+ export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, shouldHideDeleted, showIndicators, doc, diffType, hideAddedDiffsUnderline, }: {
11
11
  change: {
12
12
  fromB: number;
13
13
  toB: number;
@@ -15,6 +15,7 @@ export declare const createInlineChangedDecoration: ({ change, colorScheme, isAc
15
15
  colorScheme?: ColorScheme;
16
16
  diffType?: DiffType;
17
17
  doc?: PMNode;
18
+ hideAddedDiffsUnderline?: boolean;
18
19
  isActive?: boolean;
19
20
  isInserted?: boolean;
20
21
  shouldHideDeleted?: boolean;
@@ -8,7 +8,7 @@ import type { NodeViewSerializer } from '../NodeViewSerializer';
8
8
  * This function is used to create a decoration widget to show content
9
9
  * that is not in the current document.
10
10
  */
11
- export declare const createNodeChangedDecorationWidget: ({ change, doc, nodeViewSerializer, colorScheme, newDoc, intl, activeIndexPos, isInserted, showIndicators, placeBelow, diffType, }: {
11
+ export declare const createNodeChangedDecorationWidget: ({ change, doc, nodeViewSerializer, colorScheme, newDoc, intl, activeIndexPos, isInserted, showIndicators, placeBelow, diffType, hideAddedDiffsUnderline, }: {
12
12
  activeIndexPos?: {
13
13
  from: number;
14
14
  to: number;
@@ -17,6 +17,7 @@ export declare const createNodeChangedDecorationWidget: ({ change, doc, nodeView
17
17
  colorScheme?: ColorScheme;
18
18
  diffType?: DiffType;
19
19
  doc: PMNode;
20
+ hideAddedDiffsUnderline?: boolean;
20
21
  intl: IntlShape;
21
22
  isInserted?: boolean;
22
23
  newDoc: PMNode;
@@ -6,10 +6,11 @@ import type { ColorScheme, DiffType } from '../../../showDiffPluginType';
6
6
  * For heading nodes, applies styles directly to preserve natural margins.
7
7
  * For other block nodes, uses wrapper approach with optional lozenge.
8
8
  */
9
- export declare const wrapBlockNodeView: ({ dom, nodeView, targetNode, colorScheme, intl, isActive, isInserted, diffType, }: {
9
+ export declare const wrapBlockNodeView: ({ dom, nodeView, targetNode, colorScheme, intl, isActive, isInserted, diffType, hideAddedDiffsUnderline, }: {
10
10
  colorScheme?: ColorScheme;
11
11
  diffType?: DiffType;
12
12
  dom: HTMLElement;
13
+ hideAddedDiffsUnderline?: boolean;
13
14
  intl: IntlShape;
14
15
  isActive?: boolean;
15
16
  isInserted: boolean;
@@ -26,6 +26,7 @@ export type ShowDiffPluginState = {
26
26
  diffDescriptors?: DiffDescriptor[];
27
27
  diffType?: DiffType;
28
28
  hideDeletedDiffs?: boolean;
29
+ hideAddedDiffsUnderline?: boolean;
29
30
  isDisplayingChanges: boolean;
30
31
  isInverted?: boolean;
31
32
  originalDoc: PMNode | undefined;
@@ -41,14 +41,16 @@ export type PMDiffParams = {
41
41
  */
42
42
  deletedDiffPlacement?: DeletedDiffPlacement;
43
43
  diffType?: DiffType;
44
+ /**
45
+ * When true, removes only the dark-purple underline (`border-bottom`) from added/updated
46
+ * (inserted) diff content, keeping the purple background highlight and all other styling.
47
+ * Only affects the extended (`smart`) styles. Defaults to `false`, and is a no-op unless the
48
+ * relevant gate is enabled.
49
+ */
50
+ hideAddedDiffsUnderline?: boolean;
44
51
  hideDeletedDiffs?: boolean;
45
52
  isInverted?: boolean;
46
53
  originalDoc: Node;
47
- /**
48
- * Optional overrides for the `smart` diffType density thresholds. Ignored for other
49
- * diff types. Partial — omitted fields fall back to defaults.
50
- */
51
- smartThresholds?: Partial<SmartDiffThresholds>;
52
54
  /**
53
55
  * When true, the editor will scroll to bring the first diff decoration into view
54
56
  * after the diff is shown.
@@ -58,6 +60,11 @@ export type PMDiffParams = {
58
60
  * Whether to show indicators at the doc margin for the diffs.
59
61
  */
60
62
  showIndicators?: boolean;
63
+ /**
64
+ * Optional overrides for the `smart` diffType density thresholds. Ignored for other
65
+ * diff types. Partial — omitted fields fall back to defaults.
66
+ */
67
+ smartThresholds?: Partial<SmartDiffThresholds>;
61
68
  /**
62
69
  * Prosemirror steps. This is used to calculate and show the diff in the editor
63
70
  */