@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
@@ -127,6 +127,7 @@ const calculateDiffDecorationsInner = ({
127
127
  isInverted = false,
128
128
  diffType = 'inline',
129
129
  hideDeletedDiffs = false,
130
+ hideAddedDiffsUnderline: hideAddedDiffsUnderlineParam = false,
130
131
  showIndicators = false,
131
132
  smartThresholds,
132
133
  deletedDiffPlacement = 'top'
@@ -142,6 +143,10 @@ const calculateDiffDecorationsInner = ({
142
143
  diffDescriptors: []
143
144
  };
144
145
  }
146
+
147
+ // Resolve the option against its gate once here, so every downstream inline/block builder
148
+ // receives the same value. When the gate is off the option is a no-op.
149
+ const hideAddedDiffsUnderline = hideAddedDiffsUnderlineParam && fg('platform_editor_ai_smart_diff');
145
150
  const {
146
151
  tr
147
152
  } = state;
@@ -237,7 +242,8 @@ const calculateDiffDecorationsInner = ({
237
242
  ...(isExtendedEnabled(diffType) && {
238
243
  isInserted,
239
244
  shouldHideDeleted,
240
- showIndicators
245
+ showIndicators,
246
+ hideAddedDiffsUnderline
241
247
  })
242
248
  }));
243
249
  }
@@ -251,7 +257,8 @@ const calculateDiffDecorationsInner = ({
251
257
  ...(isExtendedEnabled(diffType) && {
252
258
  isInserted,
253
259
  shouldHideDeleted,
254
- showIndicators
260
+ showIndicators,
261
+ hideAddedDiffsUnderline
255
262
  })
256
263
  }));
257
264
  }
@@ -284,6 +291,7 @@ const calculateDiffDecorationsInner = ({
284
291
  ...(isExtendedEnabled(diffType) && {
285
292
  isInserted: !isInserted,
286
293
  diffType,
294
+ hideAddedDiffsUnderline,
287
295
  // For `smart` node- and paragraph-level changes, optionally render the
288
296
  // deleted content below the new content (gray + strikethrough) instead
289
297
  // of above it. Controlled by `deletedDiffPlacement` (default `'top'`).
@@ -422,6 +430,7 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
422
430
  isInverted,
423
431
  diffType,
424
432
  hideDeletedDiffs,
433
+ hideAddedDiffsUnderline,
425
434
  showIndicators,
426
435
  smartThresholds,
427
436
  deletedDiffPlacement
@@ -434,6 +443,7 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
434
443
  isInverted: lastIsInverted,
435
444
  diffType: lastDiffType,
436
445
  hideDeletedDiffs: lastHideDeletedDiffs,
446
+ hideAddedDiffsUnderline: lastHideAddedDiffsUnderline,
437
447
  showIndicators: lastShowIndicators,
438
448
  smartThresholds: lastSmartThresholds,
439
449
  deletedDiffPlacement: lastDeletedDiffPlacement
@@ -442,7 +452,7 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
442
452
  const originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
443
453
  if (isExtendedEnabled(diffType)) {
444
454
  var _ref;
445
- return (_ref = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement) !== null && _ref !== void 0 ? _ref : false;
455
+ return (_ref = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement) !== null && _ref !== void 0 ? _ref : false;
446
456
  }
447
457
  return (_ref2 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref2 !== void 0 ? _ref2 : false;
448
458
  });
@@ -0,0 +1,94 @@
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 { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
17
+ import { diffBySteps } from './diffBySteps';
18
+ import { groupChangesByBlock } from './groupChangesByBlock';
19
+ import { optimizeChanges } from './optimizeChanges';
20
+ import { simplifySteps } from './simplifySteps';
21
+ import { classifySmartChanges } from './smart/classifySmartChanges';
22
+ /**
23
+ * Apply the (simplified) steps to `originalDoc` to reconstruct the new doc, and
24
+ * compute the classified `Change[]` for the requested `diffType`. Mirrors the
25
+ * body of `calculateDiffDecorations` → `getChanges` so callers stay in lock-step
26
+ * with the rendered diff. Returns an empty change list (and `originalDoc` as the
27
+ * new doc) when there are no steps.
28
+ */
29
+ export const computeDiffChanges = ({
30
+ originalDoc,
31
+ steps,
32
+ diffType = 'smart',
33
+ locale = 'en',
34
+ smartThresholds
35
+ }) => {
36
+ if (!steps || steps.length === 0) {
37
+ return {
38
+ changes: [],
39
+ newDoc: originalDoc
40
+ };
41
+ }
42
+ const simplifiedSteps = simplifySteps(steps, originalDoc);
43
+ let steppedDoc = originalDoc;
44
+ const stepMaps = [];
45
+ try {
46
+ for (const step of simplifiedSteps) {
47
+ const result = step.apply(steppedDoc);
48
+ if (result.failed === null && result.doc) {
49
+ stepMaps.push(step.getMap());
50
+ steppedDoc = result.doc;
51
+ }
52
+ }
53
+ } catch {
54
+ // A step's positions fell outside the current doc — `ReplaceStep.apply`
55
+ // throws a RangeError (rather than returning a failed result) when a
56
+ // position exceeds the doc size. This can happen for pathological or
57
+ // inconsistent step sequences. Bail with no changes rather than letting the
58
+ // error propagate to the caller (which, for the PSR, would crash the
59
+ // toolbar); the consumer then falls back to its non-diff segmenting path.
60
+ return {
61
+ changes: [],
62
+ newDoc: originalDoc
63
+ };
64
+ }
65
+ const changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, steppedDoc);
66
+ if (diffType === 'smart') {
67
+ return {
68
+ changes: classifySmartChanges({
69
+ changes: simplifyChanges(changeset.changes, steppedDoc),
70
+ originalDoc,
71
+ newDoc: steppedDoc,
72
+ locale,
73
+ thresholds: smartThresholds
74
+ }),
75
+ newDoc: steppedDoc
76
+ };
77
+ }
78
+ if (diffType === 'block') {
79
+ return {
80
+ changes: groupChangesByBlock(changeset.changes, originalDoc, steppedDoc),
81
+ newDoc: steppedDoc
82
+ };
83
+ }
84
+ if (diffType === 'step') {
85
+ return {
86
+ changes: diffBySteps(originalDoc, simplifiedSteps),
87
+ newDoc: steppedDoc
88
+ };
89
+ }
90
+ return {
91
+ changes: optimizeChanges(simplifyChanges(changeset.changes, steppedDoc)),
92
+ newDoc: steppedDoc
93
+ };
94
+ };
@@ -38,6 +38,24 @@ export const editingStyleActiveExtended = convertToInlineCss({
38
38
  borderBottom: `2px solid ${"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 const editingStyleExtendedNoUnderline = convertToInlineCss({
49
+ background: "var(--ds-background-accent-purple-subtlest, #F8EEFE)",
50
+ padding: `1px 0 2px`
51
+ });
52
+ export const editingStyleActiveExtendedNoUnderline = convertToInlineCss({
53
+ background: "var(--ds-background-accent-purple-subtler-pressed, #D8A0F7)",
54
+ padding: `1px 0 2px`
55
+ });
56
+ export const editingContentStyleInBlockExtendedNoUnderline = convertToInlineCss({
57
+ padding: `1px 0 2px`
58
+ });
41
59
  export const deletedContentStyle = convertToInlineCss({
42
60
  color: "var(--ds-text-accent-gray, #505258)",
43
61
  textDecoration: 'line-through',
@@ -1,7 +1,7 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
3
  import { isExtendedEnabled } from '../isExtendedEnabled';
4
- import { editingStyle, editingStyleExtended, editingStyleActive, editingStyleActiveExtended, deletedContentStyle, deletedContentStyleActive, deletedInlineContentStyleExtended } from './colorSchemes/standard';
4
+ import { editingStyle, editingStyleExtended, editingStyleExtendedNoUnderline, editingStyleActive, editingStyleActiveExtended, editingStyleActiveExtendedNoUnderline, deletedContentStyle, deletedContentStyleActive, deletedInlineContentStyleExtended } from './colorSchemes/standard';
5
5
  import { traditionalInsertStyle, traditionalInsertStyleActive, getDeletedTraditionalInlineStyle } from './colorSchemes/traditional';
6
6
  import { createInlineIndicatorAnchorWidgets } from './createAnchorDecorationWidgets';
7
7
  import { buildDiffDecorationSpec } from './decorationKeys';
@@ -23,7 +23,8 @@ export const createInlineChangedDecoration = ({
23
23
  shouldHideDeleted = false,
24
24
  showIndicators = false,
25
25
  doc,
26
- diffType
26
+ diffType,
27
+ hideAddedDiffsUnderline = false
27
28
  }) => {
28
29
  const diffId = crypto.randomUUID();
29
30
  if (shouldHideDeleted) {
@@ -41,7 +42,7 @@ export const createInlineChangedDecoration = ({
41
42
  if (colorScheme === 'traditional') {
42
43
  style = isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
43
44
  } else {
44
- style = isActive ? editingStyleActiveExtended : editingStyleExtended;
45
+ style = isActive ? hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended : hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
45
46
  }
46
47
  } else {
47
48
  if (colorScheme === 'traditional') {
@@ -25,7 +25,8 @@ export const createNodeChangedDecorationWidget = ({
25
25
  // before it. Used for `smart` node-level changes so the deleted node appears beneath
26
26
  // its replacement (gray + strikethrough).
27
27
  placeBelow = false,
28
- diffType
28
+ diffType,
29
+ hideAddedDiffsUnderline = false
29
30
  }) => {
30
31
  var _slice$content, _slice$content2, _slice$content2$first, _slice$content3, _slice$content3$first, _slice$content$firstC;
31
32
  const slice = doc.slice(change.fromA, change.toA);
@@ -164,7 +165,8 @@ export const createNodeChangedDecorationWidget = ({
164
165
  intl,
165
166
  isActive,
166
167
  isInserted,
167
- diffType
168
+ diffType,
169
+ hideAddedDiffsUnderline
168
170
  });
169
171
  }
170
172
  } else if (nodeViewSerializer.getFilteredNodeViewBlocklist(['paragraph', 'tableRow']).has(node.type.name)) {
@@ -3,7 +3,7 @@ import { trackChangesMessages } from '@atlaskit/editor-common/messages';
3
3
  import { getBaseNodeTypeName } from '@atlaskit/editor-common/utils/node-type-utils';
4
4
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
5
5
  import { isExtendedEnabled } from '../../isExtendedEnabled';
6
- import { deletedBlockOutline, deletedBlockOutlineActive, deletedBlockOutlineRounded, deletedBlockOutlineRoundedActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleUnbounded, deletedInlineContentStyleExtended, deletedStyleQuoteNodeWithLozenge, deletedStyleQuoteNodeWithLozengeActive, editingContentStyleInBlockExtended, editingStyleExtended, editingStyleActiveExtended, editingStyleNode, addedCellOverlayStyle, deletedCellOverlayStyle } from '../colorSchemes/standard';
6
+ import { deletedBlockOutline, deletedBlockOutlineActive, deletedBlockOutlineRounded, deletedBlockOutlineRoundedActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleUnbounded, deletedInlineContentStyleExtended, deletedStyleQuoteNodeWithLozenge, deletedStyleQuoteNodeWithLozengeActive, editingContentStyleInBlockExtended, editingContentStyleInBlockExtendedNoUnderline, editingStyleExtended, editingStyleExtendedNoUnderline, editingStyleActiveExtended, editingStyleActiveExtendedNoUnderline, editingStyleNode, addedCellOverlayStyle, deletedCellOverlayStyle } from '../colorSchemes/standard';
7
7
  import { deletedTraditionalBlockOutlineActive, deletedTraditionalBlockOutlineNew, deletedTraditionalBlockOutlineRoundedActive, deletedTraditionalBlockOutlineRoundedNew, deletedTraditionalContentStyleUnbounded, deletedTraditionalContentStyleUnboundedActive, getDeletedTraditionalInlineStyle, deletedTraditionalStyleQuoteNode, deletedTraditionalStyleQuoteNodeActive, traditionalInsertStyle, traditionalInsertStyleActive, traditionalStyleNodeActive, traditionalStyleNodeNew, traditionalAddedCellOverlayStyleNew, deletedTraditionalCellOverlayStyle } from '../colorSchemes/traditional';
8
8
  const lozengeStyle = convertToInlineCss({
9
9
  display: 'inline-flex',
@@ -53,12 +53,12 @@ const lozengeStyleActiveTraditional = convertToInlineCss({
53
53
  whiteSpace: 'nowrap',
54
54
  color: "var(--ds-text-warning-inverse, #292A2E)"
55
55
  });
56
- const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false, diffType) => {
56
+ const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false, diffType, hideAddedDiffsUnderline = false) => {
57
57
  if (isExtendedEnabled(diffType) && isInserted) {
58
58
  if (colorScheme === 'traditional') {
59
59
  return isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
60
60
  }
61
- return isActive ? editingStyleActiveExtended : editingStyleExtended;
61
+ return isActive ? hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended : hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
62
62
  }
63
63
  if (colorScheme === 'traditional') {
64
64
  return getDeletedTraditionalInlineStyle(isActive);
@@ -68,11 +68,11 @@ const getChangedContentStyle = (colorScheme, isActive = false, isInserted = fals
68
68
  }
69
69
  return expValEquals('platform_editor_enghealth_a11y_jan_fixes', 'isEnabled', true) ? deletedContentStyleNew : deletedContentStyle;
70
70
  };
71
- const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false, isActive = false, diffType) => {
71
+ const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false, isActive = false, diffType, hideAddedDiffsUnderline = false) => {
72
72
  const isTraditional = colorScheme === 'traditional';
73
73
  if (isExtendedEnabled(diffType) && isInserted) {
74
74
  if (isMultiContainerBlockNode(nodeName)) {
75
- return editingContentStyleInBlockExtended;
75
+ return hideAddedDiffsUnderline ? editingContentStyleInBlockExtendedNoUnderline : editingContentStyleInBlockExtended;
76
76
  }
77
77
  if (isTextLikeBlockNode(nodeName)) {
78
78
  return undefined;
@@ -219,12 +219,13 @@ const applyStylesToElement = ({
219
219
  colorScheme,
220
220
  isActive,
221
221
  isInserted,
222
- diffType
222
+ diffType,
223
+ hideAddedDiffsUnderline = false
223
224
  }) => {
224
225
  const currentStyle = element.getAttribute('style') || '';
225
- const contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
226
+ const contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
226
227
  const targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
227
- const nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType) || '';
228
+ const nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
228
229
  element.setAttribute('style', `${currentStyle}${contentStyle}${nodeSpecificStyle}`);
229
230
  };
230
231
  const applyMultiContainerLikeStyles = ({
@@ -233,11 +234,12 @@ const applyMultiContainerLikeStyles = ({
233
234
  colorScheme,
234
235
  isActive,
235
236
  isInserted,
236
- diffType
237
+ diffType,
238
+ hideAddedDiffsUnderline = false
237
239
  }) => {
238
240
  const currentStyle = element.getAttribute('style') || '';
239
241
  const targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
240
- const nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType) || '';
242
+ const nodeSpecificStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
241
243
  if (targetNode.type.name === 'decisionList') {
242
244
  element.querySelectorAll('li').forEach(listItem => {
243
245
  const currentListItemStyle = listItem.getAttribute('style') || '';
@@ -262,14 +264,15 @@ const applyTextLikeBlockNodeStyles = ({
262
264
  colorScheme,
263
265
  isActive,
264
266
  isInserted,
265
- diffType
267
+ diffType,
268
+ hideAddedDiffsUnderline = false
266
269
  }) => {
267
270
  const currentStyle = element.getAttribute('style') || '';
268
- const nodeSpecificStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted, isActive, diffType) || '';
271
+ const nodeSpecificStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline) || '';
269
272
  if (nodeSpecificStyle) {
270
273
  element.setAttribute('style', `${currentStyle}${nodeSpecificStyle}`);
271
274
  }
272
- const contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
275
+ const contentStyle = getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
273
276
  const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
274
277
  const textNodesToWrap = [];
275
278
  let currentNode = walker.nextNode();
@@ -296,17 +299,18 @@ const createBlockNodeContentWrapper = ({
296
299
  colorScheme,
297
300
  isActive,
298
301
  isInserted,
299
- diffType
302
+ diffType,
303
+ hideAddedDiffsUnderline = false
300
304
  }) => {
301
305
  const contentWrapper = document.createElement('div');
302
306
  const targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
303
- const nodeStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType);
307
+ const nodeStyle = getChangedNodeStyle(targetNodeName, colorScheme, isInserted, isActive, diffType, hideAddedDiffsUnderline);
304
308
 
305
309
  // When the extended experiment is enabled and the content is inserted,
306
310
  // block widget nodes that already have dedicated node-level styling (e.g. boxShadow outline)
307
311
  // should not also get the inline content style (borderBottom underline) on their container.
308
312
  const shouldSkipContentStyle = isExtendedEnabled(diffType) && isInserted && nodeStyle !== undefined;
309
- const contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, diffType);
313
+ const contentStyle = shouldSkipContentStyle ? '' : getChangedContentStyle(colorScheme, isActive, isInserted, diffType, hideAddedDiffsUnderline);
310
314
  contentWrapper.setAttribute('style', `${contentStyle}${nodeStyle || ''}`);
311
315
  contentWrapper.append(nodeView);
312
316
  return contentWrapper;
@@ -419,7 +423,8 @@ const wrapBlockNode = ({
419
423
  intl,
420
424
  isActive = false,
421
425
  isInserted = false,
422
- diffType
426
+ diffType,
427
+ hideAddedDiffsUnderline = false
423
428
  }) => {
424
429
  const blockWrapper = createBlockNodeWrapper();
425
430
  const targetNodeName = expValEquals('platform_editor_nest_table_in_panel', 'isEnabled', true) ? getBaseNodeTypeName(targetNode.type) : targetNode.type.name;
@@ -453,7 +458,8 @@ const wrapBlockNode = ({
453
458
  colorScheme,
454
459
  isActive,
455
460
  isInserted,
456
- diffType
461
+ diffType,
462
+ hideAddedDiffsUnderline
457
463
  });
458
464
  blockWrapper.append(contentWrapper);
459
465
  if (nodeView instanceof HTMLElement && shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
@@ -485,7 +491,8 @@ export const wrapBlockNodeView = ({
485
491
  intl,
486
492
  isActive = false,
487
493
  isInserted = false,
488
- diffType
494
+ diffType,
495
+ hideAddedDiffsUnderline = false
489
496
  }) => {
490
497
  if (isExtendedEnabled(diffType)) {
491
498
  if (nodeView instanceof HTMLElement) {
@@ -496,7 +503,8 @@ export const wrapBlockNodeView = ({
496
503
  colorScheme,
497
504
  isActive,
498
505
  isInserted,
499
- diffType
506
+ diffType,
507
+ hideAddedDiffsUnderline
500
508
  });
501
509
  dom.append(nodeView);
502
510
  return;
@@ -508,7 +516,8 @@ export const wrapBlockNodeView = ({
508
516
  colorScheme,
509
517
  isActive,
510
518
  isInserted,
511
- diffType
519
+ diffType,
520
+ hideAddedDiffsUnderline
512
521
  });
513
522
  dom.append(nodeView);
514
523
  return;
@@ -531,7 +540,8 @@ export const wrapBlockNodeView = ({
531
540
  intl,
532
541
  isActive,
533
542
  isInserted,
534
- diffType
543
+ diffType,
544
+ hideAddedDiffsUnderline
535
545
  });
536
546
  return;
537
547
  } else {
@@ -566,14 +576,14 @@ const getDeletedContentStyleUnbounded = (colorScheme, isActive = false) => {
566
576
  }
567
577
  return colorScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
568
578
  };
569
- const getInsertedContentStyle = (colorScheme, isActive = false) => {
579
+ const getInsertedContentStyle = (colorScheme, isActive = false, hideAddedDiffsUnderline = false) => {
570
580
  if (colorScheme === 'traditional') {
571
581
  return isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
572
582
  }
573
583
  if (isActive) {
574
- return editingStyleActiveExtended;
584
+ return hideAddedDiffsUnderline ? editingStyleActiveExtendedNoUnderline : editingStyleActiveExtended;
575
585
  }
576
- return editingStyleExtended;
586
+ return hideAddedDiffsUnderline ? editingStyleExtendedNoUnderline : editingStyleExtended;
577
587
  };
578
588
  const getDeletedContentStyle = (colorScheme, isActive = false, diffType) => {
579
589
  if (colorScheme === 'traditional') {
@@ -32,6 +32,7 @@ export const createPlugin = (config, getIntl, api) => {
32
32
  isInverted: false,
33
33
  diffType: 'inline',
34
34
  hideDeletedDiffs: false,
35
+ hideAddedDiffsUnderline: false,
35
36
  showIndicators: false,
36
37
  diffDescriptors: []
37
38
  } : {})
@@ -42,7 +43,7 @@ export const createPlugin = (config, getIntl, api) => {
42
43
  let newPluginState = currentPluginState;
43
44
  if (meta) {
44
45
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
45
- var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8;
46
+ var _newPluginState, _newPluginState2, _newPluginState3, _newPluginState4, _newPluginState5, _newPluginState6, _newPluginState7, _newPluginState8, _newPluginState9;
46
47
  // Update the plugin state with the new metadata
47
48
  newPluginState = {
48
49
  ...currentPluginState,
@@ -66,14 +67,15 @@ export const createPlugin = (config, getIntl, api) => {
66
67
  isInverted: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.isInverted,
67
68
  diffType: (_newPluginState3 = newPluginState) === null || _newPluginState3 === void 0 ? void 0 : _newPluginState3.diffType,
68
69
  hideDeletedDiffs: (_newPluginState4 = newPluginState) === null || _newPluginState4 === void 0 ? void 0 : _newPluginState4.hideDeletedDiffs,
69
- showIndicators: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.showIndicators,
70
- smartThresholds: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.smartThresholds,
71
- deletedDiffPlacement: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.deletedDiffPlacement
70
+ hideAddedDiffsUnderline: (_newPluginState5 = newPluginState) === null || _newPluginState5 === void 0 ? void 0 : _newPluginState5.hideAddedDiffsUnderline,
71
+ showIndicators: (_newPluginState6 = newPluginState) === null || _newPluginState6 === void 0 ? void 0 : _newPluginState6.showIndicators,
72
+ smartThresholds: (_newPluginState7 = newPluginState) === null || _newPluginState7 === void 0 ? void 0 : _newPluginState7.smartThresholds,
73
+ deletedDiffPlacement: (_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.deletedDiffPlacement
72
74
  } : {})
73
75
  });
74
76
  // Update the decorations and their ids
75
77
  newPluginState.decorations = decorations;
76
- if (isExtendedEnabled((_newPluginState8 = newPluginState) === null || _newPluginState8 === void 0 ? void 0 : _newPluginState8.diffType)) {
78
+ if (isExtendedEnabled((_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.diffType)) {
77
79
  newPluginState.diffDescriptors = diffDescriptors;
78
80
  }
79
81
  } else if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'HIDE_DIFF') {
@@ -91,13 +93,14 @@ export const createPlugin = (config, getIntl, api) => {
91
93
  isInverted: false,
92
94
  diffType: 'inline',
93
95
  hideDeletedDiffs: false,
96
+ hideAddedDiffsUnderline: false,
94
97
  diffDescriptors: []
95
98
  } : {})
96
99
  };
97
100
  } 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') {
98
- var _newPluginState9;
101
+ var _newPluginState0;
99
102
  // Update the active index in plugin state and recalculate decorations
100
- const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState9 = newPluginState) === null || _newPluginState9 === void 0 ? void 0 : _newPluginState9.diffType);
103
+ const decorations = getScrollableDecorations(currentPluginState.decorations, newState.doc, (_newPluginState0 = newPluginState) === null || _newPluginState0 === void 0 ? void 0 : _newPluginState0.diffType);
101
104
  if (decorations.length > 0) {
102
105
  var _currentPluginState$a;
103
106
  // Initialize to -1 if undefined so that the first "next" scroll takes us to index 0 (first change).
@@ -139,6 +142,7 @@ export const createPlugin = (config, getIntl, api) => {
139
142
  isInverted: newPluginState.isInverted,
140
143
  diffType: newPluginState.diffType,
141
144
  hideDeletedDiffs: newPluginState.hideDeletedDiffs,
145
+ hideAddedDiffsUnderline: newPluginState.hideAddedDiffsUnderline,
142
146
  showIndicators: newPluginState.showIndicators,
143
147
  smartThresholds: newPluginState.smartThresholds,
144
148
  deletedDiffPlacement: newPluginState.deletedDiffPlacement
@@ -0,0 +1,2 @@
1
+ /* eslint-disable @atlaskit/editor/no-re-export */
2
+ export { computeDiffChanges } from '../pm-plugins/calculateDiff/computeDiffChanges';
@@ -139,6 +139,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
139
139
  diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType,
140
140
  _ref3$hideDeletedDiff = _ref3.hideDeletedDiffs,
141
141
  hideDeletedDiffs = _ref3$hideDeletedDiff === void 0 ? false : _ref3$hideDeletedDiff,
142
+ _ref3$hideAddedDiffsU = _ref3.hideAddedDiffsUnderline,
143
+ hideAddedDiffsUnderlineParam = _ref3$hideAddedDiffsU === void 0 ? false : _ref3$hideAddedDiffsU,
142
144
  _ref3$showIndicators = _ref3.showIndicators,
143
145
  showIndicators = _ref3$showIndicators === void 0 ? false : _ref3$showIndicators,
144
146
  smartThresholds = _ref3.smartThresholds,
@@ -153,6 +155,10 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
153
155
  diffDescriptors: []
154
156
  };
155
157
  }
158
+
159
+ // Resolve the option against its gate once here, so every downstream inline/block builder
160
+ // receives the same value. When the gate is off the option is a no-op.
161
+ var hideAddedDiffsUnderline = hideAddedDiffsUnderlineParam && fg('platform_editor_ai_smart_diff');
156
162
  var tr = state.tr;
157
163
  var steppedDoc = originalDoc;
158
164
  var attrSteps = [];
@@ -261,7 +267,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
261
267
  }, isExtendedEnabled(diffType) && {
262
268
  isInserted: isInserted,
263
269
  shouldHideDeleted: shouldHideDeleted,
264
- showIndicators: showIndicators
270
+ showIndicators: showIndicators,
271
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
265
272
  }))));
266
273
  }
267
274
  } catch (err) {
@@ -279,7 +286,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
279
286
  }, isExtendedEnabled(diffType) && {
280
287
  isInserted: isInserted,
281
288
  shouldHideDeleted: shouldHideDeleted,
282
- showIndicators: showIndicators
289
+ showIndicators: showIndicators,
290
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline
283
291
  }))));
284
292
  }
285
293
  decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration(_objectSpread(_objectSpread({
@@ -311,6 +319,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3
311
319
  }, isExtendedEnabled(diffType) && {
312
320
  isInserted: !isInserted,
313
321
  diffType: diffType,
322
+ hideAddedDiffsUnderline: hideAddedDiffsUnderline,
314
323
  // For `smart` node- and paragraph-level changes, optionally render the
315
324
  // deleted content below the new content (gray + strikethrough) instead
316
325
  // of above it. Controlled by `deletedDiffPlacement` (default `'top'`).
@@ -455,6 +464,7 @@ function (_ref5, _ref6) {
455
464
  isInverted = _ref7$.isInverted,
456
465
  diffType = _ref7$.diffType,
457
466
  hideDeletedDiffs = _ref7$.hideDeletedDiffs,
467
+ hideAddedDiffsUnderline = _ref7$.hideAddedDiffsUnderline,
458
468
  showIndicators = _ref7$.showIndicators,
459
469
  smartThresholds = _ref7$.smartThresholds,
460
470
  deletedDiffPlacement = _ref7$.deletedDiffPlacement;
@@ -468,13 +478,14 @@ function (_ref5, _ref6) {
468
478
  lastIsInverted = _ref8$.isInverted,
469
479
  lastDiffType = _ref8$.diffType,
470
480
  lastHideDeletedDiffs = _ref8$.hideDeletedDiffs,
481
+ lastHideAddedDiffsUnderline = _ref8$.hideAddedDiffsUnderline,
471
482
  lastShowIndicators = _ref8$.showIndicators,
472
483
  lastSmartThresholds = _ref8$.smartThresholds,
473
484
  lastDeletedDiffPlacement = _ref8$.deletedDiffPlacement;
474
485
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
475
486
  if (isExtendedEnabled(diffType)) {
476
487
  var _ref9;
477
- return (_ref9 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement) !== null && _ref9 !== void 0 ? _ref9 : false;
488
+ return (_ref9 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && hideDeletedDiffs === lastHideDeletedDiffs && hideAddedDiffsUnderline === lastHideAddedDiffsUnderline && showIndicators === lastShowIndicators && isEqual(smartThresholds, lastSmartThresholds) && deletedDiffPlacement === lastDeletedDiffPlacement) !== null && _ref9 !== void 0 ? _ref9 : false;
478
489
  }
479
490
  return (_ref0 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos) && hideDeletedDiffs === lastHideDeletedDiffs) !== null && _ref0 !== void 0 ? _ref0 : false;
480
491
  });