@atlaskit/editor-plugin-show-diff 6.0.1 → 6.1.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 (50) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/pm-plugins/calculateDiffDecorations.js +37 -16
  3. package/dist/cjs/pm-plugins/decorations/colorSchemes/standard.js +23 -1
  4. package/dist/cjs/pm-plugins/decorations/colorSchemes/traditional.js +23 -1
  5. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +60 -8
  6. package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +19 -4
  7. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +24 -4
  8. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +92 -21
  9. package/dist/cjs/pm-plugins/decorations/utils/getMarkChangeRanges.js +0 -15
  10. package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeView.js +87 -45
  11. package/dist/cjs/pm-plugins/main.js +17 -7
  12. package/dist/es2019/pm-plugins/calculateDiffDecorations.js +35 -13
  13. package/dist/es2019/pm-plugins/decorations/colorSchemes/standard.js +22 -0
  14. package/dist/es2019/pm-plugins/decorations/colorSchemes/traditional.js +22 -0
  15. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +59 -8
  16. package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +20 -6
  17. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +25 -6
  18. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +84 -16
  19. package/dist/es2019/pm-plugins/decorations/utils/getMarkChangeRanges.js +0 -13
  20. package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeView.js +58 -19
  21. package/dist/es2019/pm-plugins/main.js +22 -4
  22. package/dist/esm/pm-plugins/calculateDiffDecorations.js +37 -16
  23. package/dist/esm/pm-plugins/decorations/colorSchemes/standard.js +22 -0
  24. package/dist/esm/pm-plugins/decorations/colorSchemes/traditional.js +22 -0
  25. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +62 -10
  26. package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +21 -6
  27. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +26 -6
  28. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +93 -23
  29. package/dist/esm/pm-plugins/decorations/utils/getMarkChangeRanges.js +0 -15
  30. package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeView.js +89 -47
  31. package/dist/esm/pm-plugins/main.js +17 -7
  32. package/dist/types/pm-plugins/decorations/colorSchemes/standard.d.ts +2 -0
  33. package/dist/types/pm-plugins/decorations/colorSchemes/traditional.d.ts +2 -0
  34. package/dist/types/pm-plugins/decorations/createBlockChangedDecoration.d.ts +2 -1
  35. package/dist/types/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +2 -1
  36. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  37. package/dist/types/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +6 -1
  38. package/dist/types/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
  39. package/dist/types/pm-plugins/main.d.ts +1 -0
  40. package/dist/types/showDiffPluginType.d.ts +1 -0
  41. package/dist/types-ts4.5/pm-plugins/decorations/colorSchemes/standard.d.ts +2 -0
  42. package/dist/types-ts4.5/pm-plugins/decorations/colorSchemes/traditional.d.ts +2 -0
  43. package/dist/types-ts4.5/pm-plugins/decorations/createBlockChangedDecoration.d.ts +2 -1
  44. package/dist/types-ts4.5/pm-plugins/decorations/createChangedRowDecorationWidgets.d.ts +2 -1
  45. package/dist/types-ts4.5/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  46. package/dist/types-ts4.5/pm-plugins/decorations/createNodeChangedDecorationWidget.d.ts +6 -1
  47. package/dist/types-ts4.5/pm-plugins/decorations/utils/wrapBlockNodeView.d.ts +2 -1
  48. package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -0
  49. package/dist/types-ts4.5/showDiffPluginType.d.ts +1 -0
  50. package/package.json +4 -3
@@ -2,8 +2,9 @@ import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document
2
2
  import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
3
3
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
4
  import { TableMap } from '@atlaskit/editor-tables/table-map';
5
- import { deletedRowStyle } from './colorSchemes/standard';
6
- import { deletedTraditionalRowStyle } from './colorSchemes/traditional';
5
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
+ import { addedCellOverlayStyle, deletedRowStyle, deletedCellOverlayStyle } from './colorSchemes/standard';
7
+ import { deletedTraditionalRowStyle, deletedTraditionalCellOverlayStyle, traditionalAddedCellOverlayStyle } from './colorSchemes/traditional';
7
8
  import { findSafeInsertPos } from './utils/findSafeInsertPos';
8
9
  /**
9
10
  * Extracts information about deleted table rows from a change
@@ -96,9 +97,15 @@ const isEmptyRow = rowNode => {
96
97
  /**
97
98
  * Creates a DOM representation of a deleted table row
98
99
  */
99
- const createChangedRowDOM = (rowNode, nodeViewSerializer, colorScheme) => {
100
+ const createChangedRowDOM = (rowNode, nodeViewSerializer, colorScheme, isInserted) => {
100
101
  const tr = document.createElement('tr');
101
- tr.setAttribute('style', colorScheme === 'traditional' ? deletedTraditionalRowStyle : deletedRowStyle);
102
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
103
+ if (!isInserted) {
104
+ tr.setAttribute('style', colorScheme === 'traditional' ? deletedTraditionalRowStyle : deletedRowStyle);
105
+ }
106
+ } else {
107
+ tr.setAttribute('style', colorScheme === 'traditional' ? deletedTraditionalRowStyle : deletedRowStyle);
108
+ }
102
109
  tr.setAttribute('data-testid', 'show-diff-deleted-row');
103
110
 
104
111
  // Serialize each cell in the row
@@ -106,6 +113,12 @@ const createChangedRowDOM = (rowNode, nodeViewSerializer, colorScheme) => {
106
113
  if (cellNode.type.name === 'tableCell' || cellNode.type.name === 'tableHeader') {
107
114
  const nodeView = nodeViewSerializer.tryCreateNodeView(cellNode);
108
115
  if (nodeView) {
116
+ if (isInserted && nodeView instanceof HTMLElement && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
117
+ const overlay = document.createElement('span');
118
+ const overlayStyle = colorScheme === 'traditional' ? isInserted ? traditionalAddedCellOverlayStyle : deletedTraditionalCellOverlayStyle : isInserted ? addedCellOverlayStyle : deletedCellOverlayStyle;
119
+ overlay.setAttribute('style', overlayStyle);
120
+ nodeView.appendChild(overlay);
121
+ }
109
122
  tr.appendChild(nodeView);
110
123
  } else {
111
124
  // Fallback to fragment serialization
@@ -142,12 +155,13 @@ export const createChangedRowDecorationWidgets = ({
142
155
  originalDoc,
143
156
  newDoc,
144
157
  nodeViewSerializer,
145
- colorScheme
158
+ colorScheme,
159
+ isInserted = false
146
160
  }) => {
147
161
  // First, expand the changes to include complete deleted rows
148
162
  const changedRows = expandDiffForChangedRows(changes.filter(change => change.deleted.length > 0), originalDoc, newDoc);
149
163
  return changedRows.map(changedRow => {
150
- const rowDOM = createChangedRowDOM(changedRow.rowNode, nodeViewSerializer, colorScheme);
164
+ const rowDOM = createChangedRowDOM(changedRow.rowNode, nodeViewSerializer, colorScheme, isInserted);
151
165
 
152
166
  // Find safe insertion position for the deleted row
153
167
  const safeInsertPos = findSafeInsertPos(newDoc, changedRow.fromB - 1,
@@ -1,6 +1,7 @@
1
1
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
2
- import { editingStyle, editingStyleActive } from './colorSchemes/standard';
3
- import { traditionalInsertStyle, traditionalInsertStyleActive } from './colorSchemes/traditional';
2
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
+ import { editingStyle, editingStyleActive, deletedContentStyle, deletedContentStyleActive } from './colorSchemes/standard';
4
+ import { traditionalInsertStyle, traditionalInsertStyleActive, deletedTraditionalContentStyle } from './colorSchemes/traditional';
4
5
 
5
6
  /**
6
7
  * Inline decoration used for insertions as the content already exists in the document
@@ -8,16 +9,34 @@ import { traditionalInsertStyle, traditionalInsertStyleActive } from './colorSch
8
9
  * @param change Changeset "change" containing information about the change content + range
9
10
  * @returns Prosemirror inline decoration
10
11
  */
12
+
11
13
  export const createInlineChangedDecoration = ({
12
14
  change,
13
15
  colorScheme,
14
- isActive = false
16
+ isActive = false,
17
+ isInserted = true
15
18
  }) => {
16
19
  let style;
17
- if (colorScheme === 'traditional') {
18
- style = isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
20
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
21
+ if (isInserted) {
22
+ if (colorScheme === 'traditional') {
23
+ style = isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
24
+ } else {
25
+ style = isActive ? editingStyleActive : editingStyle;
26
+ }
27
+ } else {
28
+ if (colorScheme === 'traditional') {
29
+ style = deletedTraditionalContentStyle;
30
+ } else {
31
+ style = isActive ? deletedContentStyleActive : deletedContentStyle;
32
+ }
33
+ }
19
34
  } else {
20
- style = isActive ? editingStyleActive : editingStyle;
35
+ if (colorScheme === 'traditional') {
36
+ style = isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
37
+ } else {
38
+ style = isActive ? editingStyleActive : editingStyle;
39
+ }
21
40
  }
22
41
  return Decoration.inline(change.fromB, change.toB, {
23
42
  style,
@@ -1,12 +1,24 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
3
3
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
- import { deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleNewActive, deletedContentStyleUnbounded } from './colorSchemes/standard';
5
- import { deletedTraditionalContentStyle, deletedTraditionalContentStyleUnbounded } from './colorSchemes/traditional';
4
+ import { editingStyle, editingStyleActive, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleNewActive, deletedContentStyleUnbounded } from './colorSchemes/standard';
5
+ import { traditionalInsertStyle, traditionalInsertStyleActive, deletedTraditionalContentStyle, deletedTraditionalContentStyleUnbounded } from './colorSchemes/traditional';
6
6
  import { createChangedRowDecorationWidgets } from './createChangedRowDecorationWidgets';
7
7
  import { findSafeInsertPos } from './utils/findSafeInsertPos';
8
8
  import { wrapBlockNodeView } from './utils/wrapBlockNodeView';
9
9
  const getDeletedContentStyleUnbounded = colorScheme => colorScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
10
+ const getInsertedContentStyle = (colorScheme, isActive = false) => {
11
+ if (colorScheme === 'traditional') {
12
+ if (isActive) {
13
+ return traditionalInsertStyleActive;
14
+ }
15
+ return traditionalInsertStyle;
16
+ }
17
+ if (isActive) {
18
+ return editingStyleActive;
19
+ }
20
+ return editingStyle;
21
+ };
10
22
  const getDeletedContentStyle = (colorScheme, isActive = false) => {
11
23
  if (colorScheme === 'traditional') {
12
24
  return deletedTraditionalContentStyle;
@@ -25,18 +37,54 @@ const createDeletedStyleWrapperWithoutOpacity = (colorScheme, isActive) => {
25
37
  wrapper.setAttribute('style', getDeletedContentStyle(colorScheme, isActive));
26
38
  return wrapper;
27
39
  };
28
- const createContentWrapper = (colorScheme, isActive = false) => {
40
+
41
+ /**
42
+ * CSS backgrounds don't work when applied to a wrapper around a paragraph, so
43
+ * the wrapper needs to be injected inside the node around the child content
44
+ */
45
+ const injectInnerWrapper = ({
46
+ node,
47
+ colorScheme,
48
+ isActive,
49
+ isInserted
50
+ }) => {
51
+ const wrapper = document.createElement('span');
52
+ wrapper.setAttribute('style', isInserted ? getInsertedContentStyle(colorScheme, isActive) : getDeletedContentStyle(colorScheme, isActive));
53
+ [...node.childNodes].forEach(child => {
54
+ const removedChild = node.removeChild(child);
55
+ wrapper.append(removedChild);
56
+ });
57
+ node.appendChild(wrapper);
58
+ return node;
59
+ };
60
+ const createContentWrapper = (colorScheme, isActive = false, isInserted = false) => {
29
61
  const wrapper = document.createElement('span');
30
62
  const baseStyle = convertToInlineCss({
31
63
  position: 'relative',
32
64
  width: 'fit-content'
33
65
  });
34
- wrapper.setAttribute('style', `${baseStyle}${getDeletedContentStyle(colorScheme, isActive)}`);
35
- const strikethrough = document.createElement('span');
36
- strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme));
37
- wrapper.append(strikethrough);
66
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
67
+ if (isInserted) {
68
+ wrapper.setAttribute('style', `${baseStyle}${getInsertedContentStyle(colorScheme, isActive)}`);
69
+ } else {
70
+ wrapper.setAttribute('style', `${baseStyle}${getDeletedContentStyle(colorScheme, isActive)}`);
71
+ const strikethrough = document.createElement('span');
72
+ strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme));
73
+ wrapper.append(strikethrough);
74
+ }
75
+ } else {
76
+ wrapper.setAttribute('style', `${baseStyle}${getDeletedContentStyle(colorScheme, isActive)}`);
77
+ const strikethrough = document.createElement('span');
78
+ strikethrough.setAttribute('style', getDeletedContentStyleUnbounded(colorScheme));
79
+ wrapper.append(strikethrough);
80
+ }
38
81
  return wrapper;
39
82
  };
83
+
84
+ /**
85
+ * This function is used to create a decoration widget to show content
86
+ * that is not in the current document.
87
+ */
40
88
  export const createNodeChangedDecorationWidget = ({
41
89
  change,
42
90
  doc,
@@ -44,7 +92,9 @@ export const createNodeChangedDecorationWidget = ({
44
92
  colorScheme,
45
93
  newDoc,
46
94
  intl,
47
- isActive = false
95
+ isActive = false,
96
+ // This is false by default as this is generally used to show deleted content
97
+ isInserted = false
48
98
  }) => {
49
99
  const slice = doc.slice(change.fromA, change.toA);
50
100
  if (slice.content.content.length === 0) {
@@ -61,7 +111,8 @@ export const createNodeChangedDecorationWidget = ({
61
111
  originalDoc: doc,
62
112
  newDoc,
63
113
  nodeViewSerializer,
64
- colorScheme
114
+ colorScheme,
115
+ isInserted
65
116
  });
66
117
  }
67
118
  const serializer = nodeViewSerializer;
@@ -83,14 +134,14 @@ export const createNodeChangedDecorationWidget = ({
83
134
  if (childNodeView) {
84
135
  const lineBreak = document.createElement('br');
85
136
  dom.append(lineBreak);
86
- const wrapper = createContentWrapper(colorScheme, isActive);
137
+ const wrapper = createContentWrapper(colorScheme, isActive, isInserted);
87
138
  wrapper.append(childNodeView);
88
139
  dom.append(wrapper);
89
140
  } else {
90
141
  // Fallback to serializing the individual child node
91
142
  const serializedChild = serializer.serializeNode(childNode);
92
143
  if (serializedChild) {
93
- const wrapper = createContentWrapper(colorScheme, isActive);
144
+ const wrapper = createContentWrapper(colorScheme, isActive, isInserted);
94
145
  wrapper.append(serializedChild);
95
146
  dom.append(wrapper);
96
147
  }
@@ -131,7 +182,7 @@ export const createNodeChangedDecorationWidget = ({
131
182
  const nodeView = serializer.tryCreateNodeView(node);
132
183
  if (nodeView) {
133
184
  if (node.isInline) {
134
- const wrapper = createContentWrapper(colorScheme, isActive);
185
+ const wrapper = createContentWrapper(colorScheme, isActive, isInserted);
135
186
  wrapper.append(nodeView);
136
187
  dom.append(wrapper);
137
188
  } else {
@@ -141,7 +192,8 @@ export const createNodeChangedDecorationWidget = ({
141
192
  nodeView,
142
193
  targetNode: node,
143
194
  colorScheme,
144
- intl
195
+ intl,
196
+ isInserted
145
197
  });
146
198
  }
147
199
  } else if (nodeViewSerializer.getFilteredNodeViewBlocklist(['paragraph', 'tableRow']).has(node.type.name)) {
@@ -150,9 +202,25 @@ export const createNodeChangedDecorationWidget = ({
150
202
  } else {
151
203
  const fallbackNode = fallbackSerialization();
152
204
  if (fallbackNode) {
153
- const wrapper = createDeletedStyleWrapperWithoutOpacity(colorScheme, isActive);
154
- wrapper.append(fallbackNode);
155
- dom.append(wrapper);
205
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
206
+ if (fallbackNode instanceof HTMLElement) {
207
+ const injectedNode = injectInnerWrapper({
208
+ node: fallbackNode,
209
+ colorScheme,
210
+ isActive,
211
+ isInserted
212
+ });
213
+ dom.append(injectedNode);
214
+ } else {
215
+ const wrapper = createContentWrapper(colorScheme, isActive, isInserted);
216
+ wrapper.append(fallbackNode);
217
+ dom.append(wrapper);
218
+ }
219
+ } else {
220
+ const wrapper = createDeletedStyleWrapperWithoutOpacity(colorScheme, isActive);
221
+ wrapper.append(fallbackNode);
222
+ dom.append(wrapper);
223
+ }
156
224
  }
157
225
  }
158
226
  });
@@ -1,6 +1,4 @@
1
1
  import { AddMarkStep, RemoveMarkStep } from '@atlaskit/editor-prosemirror/transform';
2
- import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
3
- const filterUndefined = x => !!x;
4
2
  const extractMarkStep = step => {
5
3
  if (step instanceof AddMarkStep) {
6
4
  return {
@@ -21,17 +19,6 @@ const extractMarkStep = step => {
21
19
  return undefined;
22
20
  };
23
21
  export const getMarkChangeRanges = steps => {
24
- if (!expValEquals('platform_editor_deduplicate_mark_diff', 'isEnabled', true)) {
25
- return steps.map(step => {
26
- if (step instanceof AddMarkStep || step instanceof RemoveMarkStep) {
27
- return {
28
- fromB: step.from,
29
- toB: step.to
30
- };
31
- }
32
- return undefined;
33
- }).filter(filterUndefined);
34
- }
35
22
  const resultRanges = [];
36
23
  let lastOp;
37
24
  for (const step of steps) {
@@ -1,8 +1,8 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
2
  import { trackChangesMessages } from '@atlaskit/editor-common/messages';
3
3
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
4
- import { deletedBlockOutline, deletedBlockOutlineRounded, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleNewActive, deletedStyleQuoteNodeWithLozenge } from '../colorSchemes/standard';
5
- import { deletedTraditionalBlockOutline, deletedTraditionalBlockOutlineRounded, deletedTraditionalContentStyle, deletedTraditionalStyleQuoteNode } from '../colorSchemes/traditional';
4
+ import { deletedBlockOutline, deletedBlockOutlineRounded, deletedContentStyle, deletedContentStyleActive, deletedContentStyleNew, deletedContentStyleNewActive, deletedStyleQuoteNodeWithLozenge, editingStyle, editingStyleActive, editingStyleNode, addedCellOverlayStyle, deletedCellOverlayStyle } from '../colorSchemes/standard';
5
+ import { deletedTraditionalBlockOutline, deletedTraditionalBlockOutlineRounded, deletedTraditionalContentStyle, deletedTraditionalStyleQuoteNode, traditionalInsertStyle, traditionalInsertStyleActive, traditionalStyleNode, traditionalAddedCellOverlayStyle, deletedTraditionalCellOverlayStyle } from '../colorSchemes/traditional';
6
6
  const lozengeStyle = convertToInlineCss({
7
7
  display: 'inline-flex',
8
8
  boxSizing: 'border-box',
@@ -19,7 +19,13 @@ const lozengeStyle = convertToInlineCss({
19
19
  whiteSpace: 'nowrap',
20
20
  color: "var(--ds-text-warning-inverse, #292A2E)"
21
21
  });
22
- const getDeletedContentStyle = (colorScheme, isActive = false) => {
22
+ const getChangedContentStyle = (colorScheme, isActive = false, isInserted = false) => {
23
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && isInserted) {
24
+ if (colorScheme === 'traditional') {
25
+ return isActive ? traditionalInsertStyleActive : traditionalInsertStyle;
26
+ }
27
+ return isActive ? editingStyleActive : editingStyle;
28
+ }
23
29
  if (colorScheme === 'traditional') {
24
30
  return deletedTraditionalContentStyle;
25
31
  }
@@ -28,8 +34,17 @@ const getDeletedContentStyle = (colorScheme, isActive = false) => {
28
34
  }
29
35
  return expValEquals('platform_editor_enghealth_a11y_jan_fixes', 'isEnabled', true) ? deletedContentStyleNew : deletedContentStyle;
30
36
  };
31
- const getDeletedStyleNode = (nodeName, colorScheme) => {
37
+ const getChangedNodeStyle = (nodeName, colorScheme, isInserted = false) => {
32
38
  const isTraditional = colorScheme === 'traditional';
39
+ if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) && isInserted) {
40
+ if (shouldApplyStylesDirectly(nodeName)) {
41
+ return undefined;
42
+ }
43
+ if (isTraditional) {
44
+ return traditionalStyleNode;
45
+ }
46
+ return editingStyleNode;
47
+ }
33
48
  switch (nodeName) {
34
49
  case 'blockquote':
35
50
  return isTraditional ? deletedTraditionalStyleQuoteNode : deletedStyleQuoteNodeWithLozenge;
@@ -50,7 +65,6 @@ const shouldShowRemovedLozenge = nodeName => {
50
65
  case 'mediaSingle':
51
66
  case 'panel':
52
67
  case 'decisionList':
53
- return true;
54
68
  case 'embedCard':
55
69
  case 'blockquote':
56
70
  return true;
@@ -62,7 +76,6 @@ const shouldAddShowDiffDeletedNodeClass = nodeName => {
62
76
  switch (nodeName) {
63
77
  case 'mediaSingle':
64
78
  case 'embedCard':
65
- return true;
66
79
  case 'blockquote':
67
80
  return true;
68
81
  default:
@@ -77,6 +90,18 @@ const shouldAddShowDiffDeletedNodeClass = nodeName => {
77
90
  const shouldApplyStylesDirectly = nodeName => {
78
91
  return nodeName === 'heading';
79
92
  };
93
+ const applyCellOverlayStyles = ({
94
+ element,
95
+ colorScheme,
96
+ isInserted
97
+ }) => {
98
+ element.querySelectorAll('td, th').forEach(cell => {
99
+ const overlay = document.createElement('span');
100
+ const overlayStyle = colorScheme === 'traditional' ? isInserted ? traditionalAddedCellOverlayStyle : deletedTraditionalCellOverlayStyle : isInserted ? addedCellOverlayStyle : deletedCellOverlayStyle;
101
+ overlay.setAttribute('style', overlayStyle);
102
+ cell.appendChild(overlay);
103
+ });
104
+ };
80
105
 
81
106
  /**
82
107
  * Creates a "Removed" lozenge to be displayed at the top right corner of deleted block nodes
@@ -122,12 +147,13 @@ const createBlockNodeWrapper = () => {
122
147
  const applyStylesToElement = ({
123
148
  element,
124
149
  targetNode,
125
- colorScheme
150
+ colorScheme,
151
+ isInserted
126
152
  }) => {
127
153
  const currentStyle = element.getAttribute('style') || '';
128
- const deletedContentStyle = getDeletedContentStyle(colorScheme);
129
- const nodeSpecificStyle = getDeletedStyleNode(targetNode.type.name, colorScheme) || '';
130
- element.setAttribute('style', `${currentStyle}${deletedContentStyle}${nodeSpecificStyle}`);
154
+ const contentStyle = getChangedContentStyle(colorScheme, false, isInserted);
155
+ const nodeSpecificStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted) || '';
156
+ element.setAttribute('style', `${currentStyle}${contentStyle}${nodeSpecificStyle}`);
131
157
  };
132
158
 
133
159
  /**
@@ -136,11 +162,12 @@ const applyStylesToElement = ({
136
162
  const createBlockNodeContentWrapper = ({
137
163
  nodeView,
138
164
  targetNode,
139
- colorScheme
165
+ colorScheme,
166
+ isInserted
140
167
  }) => {
141
168
  const contentWrapper = document.createElement('div');
142
- const nodeStyle = getDeletedStyleNode(targetNode.type.name, colorScheme);
143
- contentWrapper.setAttribute('style', `${getDeletedContentStyle(colorScheme)}${nodeStyle || ''}`);
169
+ const nodeStyle = getChangedNodeStyle(targetNode.type.name, colorScheme, isInserted);
170
+ contentWrapper.setAttribute('style', `${getChangedContentStyle(colorScheme, false, isInserted)}${nodeStyle || ''}`);
144
171
  contentWrapper.append(nodeView);
145
172
  return contentWrapper;
146
173
  };
@@ -229,10 +256,11 @@ const wrapBlockNode = ({
229
256
  nodeView,
230
257
  targetNode,
231
258
  colorScheme,
232
- intl
259
+ intl,
260
+ isInserted = false
233
261
  }) => {
234
262
  const blockWrapper = createBlockNodeWrapper();
235
- if (shouldShowRemovedLozenge(targetNode.type.name)) {
263
+ if (shouldShowRemovedLozenge(targetNode.type.name) && (!expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) || !isInserted)) {
236
264
  const lozenge = createRemovedLozenge(intl);
237
265
  if (handleEmbedCardWithLozenge({
238
266
  dom,
@@ -257,7 +285,8 @@ const wrapBlockNode = ({
257
285
  const contentWrapper = createBlockNodeContentWrapper({
258
286
  nodeView,
259
287
  targetNode,
260
- colorScheme
288
+ colorScheme,
289
+ isInserted
261
290
  });
262
291
  blockWrapper.append(contentWrapper);
263
292
  if (nodeView instanceof HTMLElement && shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
@@ -277,14 +306,23 @@ export const wrapBlockNodeView = ({
277
306
  nodeView,
278
307
  targetNode,
279
308
  colorScheme,
280
- intl
309
+ intl,
310
+ isInserted = false
281
311
  }) => {
282
312
  if (shouldApplyStylesDirectly(targetNode.type.name) && nodeView instanceof HTMLElement) {
283
313
  // Apply deleted styles directly to preserve natural block-level margins
284
314
  applyStylesToElement({
285
315
  element: nodeView,
286
316
  targetNode,
287
- colorScheme
317
+ colorScheme,
318
+ isInserted
319
+ });
320
+ dom.append(nodeView);
321
+ } else if (targetNode.type.name === 'table' && nodeView instanceof HTMLElement && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
322
+ applyCellOverlayStyles({
323
+ element: nodeView,
324
+ colorScheme,
325
+ isInserted
288
326
  });
289
327
  dom.append(nodeView);
290
328
  } else {
@@ -294,7 +332,8 @@ export const wrapBlockNodeView = ({
294
332
  nodeView,
295
333
  targetNode,
296
334
  colorScheme,
297
- intl
335
+ intl,
336
+ isInserted
298
337
  });
299
338
  }
300
339
  };
@@ -4,6 +4,7 @@ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
4
4
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
5
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
6
  import { fg } from '@atlaskit/platform-feature-flags';
7
+ import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
8
  import { calculateDiffDecorations } from './calculateDiffDecorations';
8
9
  import { NodeViewSerializer } from './NodeViewSerializer';
9
10
  import { scrollToActiveDecoration } from './scrollToActiveDecoration';
@@ -28,7 +29,10 @@ export const createPlugin = (config, getIntl, api) => {
28
29
  steps: [],
29
30
  originalDoc: undefined,
30
31
  decorations: DecorationSet.empty,
31
- isDisplayingChanges: false
32
+ isDisplayingChanges: false,
33
+ ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
34
+ isInverted: false
35
+ } : {})
32
36
  };
33
37
  },
34
38
  apply: (tr, currentPluginState, oldState, newState) => {
@@ -36,6 +40,7 @@ export const createPlugin = (config, getIntl, api) => {
36
40
  let newPluginState = currentPluginState;
37
41
  if (meta) {
38
42
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
43
+ var _newPluginState;
39
44
  // Update the plugin state with the new metadata
40
45
  newPluginState = {
41
46
  ...currentPluginState,
@@ -51,7 +56,10 @@ export const createPlugin = (config, getIntl, api) => {
51
56
  colorScheme: config === null || config === void 0 ? void 0 : config.colorScheme,
52
57
  intl: getIntl(),
53
58
  activeIndexPos: fg('platform_editor_show_diff_scroll_navigation') ? newPluginState.activeIndexPos : undefined,
54
- api
59
+ api,
60
+ ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
61
+ isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted
62
+ } : {})
55
63
  });
56
64
  // Update the decorations
57
65
  newPluginState.decorations = decorations;
@@ -61,7 +69,14 @@ export const createPlugin = (config, getIntl, api) => {
61
69
  ...meta,
62
70
  decorations: DecorationSet.empty,
63
71
  isDisplayingChanges: false,
64
- activeIndex: undefined
72
+ activeIndex: undefined,
73
+ /**
74
+ * Reset isInverted state when hiding diffs
75
+ * Otherwise this should persist for the diff-showing session
76
+ */
77
+ ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
78
+ isInverted: false
79
+ } : {})
65
80
  };
66
81
  } 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') && fg('platform_editor_show_diff_scroll_navigation')) {
67
82
  // Update the active index in plugin state and recalculate decorations
@@ -99,7 +114,10 @@ export const createPlugin = (config, getIntl, api) => {
99
114
  colorScheme: config === null || config === void 0 ? void 0 : config.colorScheme,
100
115
  intl: getIntl(),
101
116
  activeIndexPos: newPluginState.activeIndexPos,
102
- api
117
+ api,
118
+ ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
119
+ isInverted: newPluginState.isInverted
120
+ } : {})
103
121
  });
104
122
  newPluginState.decorations = updatedDecorations;
105
123
  }