@atlaskit/editor-plugin-show-diff 3.2.3 → 3.2.4
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.
- package/CHANGELOG.md +8 -0
- package/dist/cjs/pm-plugins/decorations.js +25 -219
- package/dist/cjs/pm-plugins/deletedBlocksHandler.js +220 -0
- package/dist/cjs/pm-plugins/deletedRowsHandler.js +1 -1
- package/dist/es2019/pm-plugins/decorations.js +21 -215
- package/dist/es2019/pm-plugins/deletedBlocksHandler.js +214 -0
- package/dist/es2019/pm-plugins/deletedRowsHandler.js +1 -1
- package/dist/esm/pm-plugins/decorations.js +22 -216
- package/dist/esm/pm-plugins/deletedBlocksHandler.js +214 -0
- package/dist/esm/pm-plugins/deletedRowsHandler.js +1 -1
- package/dist/types/pm-plugins/NodeViewSerializer.d.ts +1 -1
- package/dist/types/pm-plugins/decorations.d.ts +2 -0
- package/dist/types/pm-plugins/deletedBlocksHandler.d.ts +48 -0
- package/dist/types-ts4.5/pm-plugins/NodeViewSerializer.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +2 -0
- package/dist/types-ts4.5/pm-plugins/deletedBlocksHandler.d.ts +48 -0
- package/package.json +2 -2
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
-
import { trackChangesMessages } from '@atlaskit/editor-common/messages';
|
|
3
2
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
4
3
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
4
|
+
import { createDeletedStyleWrapperWithoutOpacity, handleBlockNodeView } from './deletedBlocksHandler';
|
|
5
5
|
import { handleDeletedRows } from './deletedRowsHandler';
|
|
6
6
|
import { findSafeInsertPos } from './findSafeInsertPos';
|
|
7
7
|
const editingStyle = convertToInlineCss({
|
|
8
|
-
background: "var(--ds-background-accent-purple-subtlest, #
|
|
8
|
+
background: "var(--ds-background-accent-purple-subtlest, #F8EEFE)",
|
|
9
9
|
textDecoration: 'underline',
|
|
10
10
|
textDecorationStyle: 'dotted',
|
|
11
11
|
textDecorationThickness: "var(--ds-space-025, 2px)",
|
|
12
|
-
textDecorationColor: "var(--ds-border-accent-purple, #
|
|
12
|
+
textDecorationColor: "var(--ds-border-accent-purple, #AF59E1)"
|
|
13
13
|
});
|
|
14
14
|
const traditionalInsertStyle = convertToInlineCss({
|
|
15
15
|
background: "var(--ds-background-accent-green-subtlest, #DCFFF1)",
|
|
@@ -43,7 +43,7 @@ const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
|
43
43
|
// Handle table separately to avoid border issues
|
|
44
44
|
case 'embedCard':
|
|
45
45
|
return convertToInlineCss({
|
|
46
|
-
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #
|
|
46
|
+
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
47
47
|
});
|
|
48
48
|
case 'paragraph':
|
|
49
49
|
case 'heading':
|
|
@@ -58,7 +58,7 @@ const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
|
58
58
|
return undefined;
|
|
59
59
|
case 'listItem':
|
|
60
60
|
return convertToInlineCss({
|
|
61
|
-
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #
|
|
61
|
+
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
62
62
|
});
|
|
63
63
|
case 'layoutSection':
|
|
64
64
|
return undefined;
|
|
@@ -71,73 +71,20 @@ const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
|
71
71
|
return colourScheme === 'traditional' ? traditionalStyleNode : editingStyleNode;
|
|
72
72
|
}
|
|
73
73
|
};
|
|
74
|
-
const getDeletedStyleNode = nodeName => {
|
|
75
|
-
switch (nodeName) {
|
|
76
|
-
case 'blockquote':
|
|
77
|
-
return deletedStyleQuoteNode;
|
|
78
|
-
case 'expand':
|
|
79
|
-
case 'decisionList':
|
|
80
|
-
return deletedBlockOutline;
|
|
81
|
-
case 'panel':
|
|
82
|
-
case 'codeBlock':
|
|
83
|
-
return deletedBlockOutlineRounded;
|
|
84
|
-
default:
|
|
85
|
-
return undefined;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
const shouldShowRemovedLozenge = nodeName => {
|
|
89
|
-
switch (nodeName) {
|
|
90
|
-
case 'expand':
|
|
91
|
-
case 'codeBlock':
|
|
92
|
-
case 'mediaSingle':
|
|
93
|
-
case 'panel':
|
|
94
|
-
case 'decisionList':
|
|
95
|
-
return true;
|
|
96
|
-
default:
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
const shouldFitContentWidth = nodeName => {
|
|
101
|
-
switch (nodeName) {
|
|
102
|
-
case 'mediaSingle':
|
|
103
|
-
case 'embedCard':
|
|
104
|
-
case 'blockCard':
|
|
105
|
-
return true;
|
|
106
|
-
default:
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
const shouldAddShowDiffDeletedNodeClass = nodeName => {
|
|
111
|
-
switch (nodeName) {
|
|
112
|
-
case 'mediaSingle':
|
|
113
|
-
case 'embedCard':
|
|
114
|
-
return true;
|
|
115
|
-
default:
|
|
116
|
-
return false;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Checks if a node should apply deleted styles directly without wrapper
|
|
122
|
-
* to preserve natural block-level margins
|
|
123
|
-
*/
|
|
124
|
-
const shouldApplyDeletedStylesDirectly = nodeName => {
|
|
125
|
-
return nodeName === 'blockquote' || nodeName === 'heading';
|
|
126
|
-
};
|
|
127
74
|
const editingStyleQuoteNode = convertToInlineCss({
|
|
128
|
-
borderLeft: `2px solid ${"var(--ds-border-accent-purple, #
|
|
75
|
+
borderLeft: `2px solid ${"var(--ds-border-accent-purple, #AF59E1)"}`
|
|
129
76
|
});
|
|
130
77
|
const traditionalStyleQuoteNode = convertToInlineCss({
|
|
131
78
|
borderLeft: `2px solid ${"var(--ds-border-accent-green, #22A06B)"}`
|
|
132
79
|
});
|
|
133
80
|
const editingStyleRuleNode = convertToInlineCss({
|
|
134
|
-
backgroundColor: "var(--ds-border-accent-purple, #
|
|
81
|
+
backgroundColor: "var(--ds-border-accent-purple, #AF59E1)"
|
|
135
82
|
});
|
|
136
83
|
const traditionalStyleRuleNode = convertToInlineCss({
|
|
137
84
|
backgroundColor: "var(--ds-border-accent-green, #22A06B)"
|
|
138
85
|
});
|
|
139
86
|
const editingStyleNode = convertToInlineCss({
|
|
140
|
-
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #
|
|
87
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #AF59E1)"}`,
|
|
141
88
|
borderRadius: "var(--ds-radius-small, 4px)"
|
|
142
89
|
});
|
|
143
90
|
const traditionalStyleNode = convertToInlineCss({
|
|
@@ -145,37 +92,15 @@ const traditionalStyleNode = convertToInlineCss({
|
|
|
145
92
|
borderRadius: "var(--ds-radius-small, 4px)"
|
|
146
93
|
});
|
|
147
94
|
const editingStyleCardBlockNode = convertToInlineCss({
|
|
148
|
-
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #
|
|
95
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #AF59E1)"}`,
|
|
149
96
|
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
150
97
|
});
|
|
151
98
|
const traditionalStyleCardBlockNode = convertToInlineCss({
|
|
152
99
|
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-green, #22A06B)"}`,
|
|
153
100
|
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
154
101
|
});
|
|
155
|
-
const deletedStyleQuoteNode = convertToInlineCss({
|
|
156
|
-
borderLeft: `2px solid ${"var(--ds-border-accent-gray, #758195)"}`
|
|
157
|
-
});
|
|
158
|
-
const deletedBlockOutline = convertToInlineCss({
|
|
159
|
-
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-gray, #758195)"}`,
|
|
160
|
-
borderRadius: "var(--ds-radius-small, 4px)"
|
|
161
|
-
});
|
|
162
|
-
const deletedBlockOutlineRounded = convertToInlineCss({
|
|
163
|
-
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-gray, #758195)"}`,
|
|
164
|
-
borderRadius: `calc(${"var(--ds-radius-xsmall, 2px)"} + 1px)`
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Inline decoration used for insertions as the content already exists in the document
|
|
169
|
-
*
|
|
170
|
-
* @param change Changeset "change" containing information about the change content + range
|
|
171
|
-
* @returns Prosemirror inline decoration
|
|
172
|
-
*/
|
|
173
|
-
export const createBlockChangedDecoration = (change, colourScheme) => Decoration.node(change.from, change.to, {
|
|
174
|
-
style: getEditorStyleNode(change.name, colourScheme),
|
|
175
|
-
'data-testid': 'show-diff-changed-decoration-node'
|
|
176
|
-
}, {});
|
|
177
102
|
const deletedContentStyle = convertToInlineCss({
|
|
178
|
-
color: "var(--ds-text-accent-gray, #
|
|
103
|
+
color: "var(--ds-text-accent-gray, #505258)",
|
|
179
104
|
textDecoration: 'line-through',
|
|
180
105
|
position: 'relative',
|
|
181
106
|
opacity: 0.6
|
|
@@ -185,7 +110,7 @@ const deletedContentStyleUnbounded = convertToInlineCss({
|
|
|
185
110
|
top: '50%',
|
|
186
111
|
width: '100%',
|
|
187
112
|
display: 'inline-block',
|
|
188
|
-
borderTop: `1px solid ${"var(--ds-text-accent-gray, #
|
|
113
|
+
borderTop: `1px solid ${"var(--ds-text-accent-gray, #505258)"}`,
|
|
189
114
|
pointerEvents: 'none',
|
|
190
115
|
zIndex: 1
|
|
191
116
|
});
|
|
@@ -204,138 +129,19 @@ const deletedTraditionalContentStyleUnbounded = convertToInlineCss({
|
|
|
204
129
|
pointerEvents: 'none',
|
|
205
130
|
zIndex: 1
|
|
206
131
|
});
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
boxSizing: 'border-box',
|
|
210
|
-
position: 'static',
|
|
211
|
-
blockSize: 'min-content',
|
|
212
|
-
borderRadius: "var(--ds-radius-small, 4px)",
|
|
213
|
-
overflow: 'hidden',
|
|
214
|
-
paddingInlineStart: "var(--ds-space-050, 4px)",
|
|
215
|
-
paddingInlineEnd: "var(--ds-space-050, 4px)",
|
|
216
|
-
backgroundColor: "var(--ds-background-accent-gray-subtler, #DCDFE4)",
|
|
217
|
-
font: "var(--ds-font-body-small, normal 400 11px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
|
|
218
|
-
fontWeight: "var(--ds-font-weight-bold, 700)",
|
|
219
|
-
textOverflow: 'ellipsis',
|
|
220
|
-
whiteSpace: 'nowrap',
|
|
221
|
-
color: "var(--ds-text-warning-inverse, #172B4D)"
|
|
222
|
-
});
|
|
223
|
-
const getDeletedContentStyleUnbounded = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
|
|
224
|
-
const getDeletedContentStyle = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Creates a "Removed" lozenge to be displayed at the top right corner of deleted block nodes
|
|
228
|
-
*/
|
|
229
|
-
const createRemovedLozenge = (intl, nodeName) => {
|
|
230
|
-
const container = document.createElement('span');
|
|
231
|
-
let borderTopRightRadius;
|
|
232
|
-
let borderTopLeftRadius;
|
|
233
|
-
if (['expand', 'decisionList'].includes(nodeName || '')) {
|
|
234
|
-
borderTopRightRadius = "var(--ds-radius-small, 4px)";
|
|
235
|
-
} else if (['panel', 'codeBlock'].includes(nodeName || '')) {
|
|
236
|
-
borderTopRightRadius = `calc(${"var(--ds-radius-xsmall, 2px)"} + 1px)`;
|
|
237
|
-
} else if (nodeName === 'mediaSingle') {
|
|
238
|
-
borderTopLeftRadius = "var(--ds-radius-small, 4px)";
|
|
239
|
-
}
|
|
240
|
-
const containerStyle = convertToInlineCss({
|
|
241
|
-
position: 'absolute',
|
|
242
|
-
top: nodeName === 'mediaSingle' ? "var(--ds-space-300, 24px)" : "var(--ds-space-0, 0px)",
|
|
243
|
-
right: nodeName === 'mediaSingle' ? undefined : "var(--ds-space-0, 0px)",
|
|
244
|
-
left: nodeName === 'mediaSingle' ? "var(--ds-space-0, 0px)" : undefined,
|
|
245
|
-
zIndex: 2,
|
|
246
|
-
pointerEvents: 'none',
|
|
247
|
-
display: 'flex',
|
|
248
|
-
overflow: 'hidden',
|
|
249
|
-
borderTopRightRadius,
|
|
250
|
-
borderTopLeftRadius
|
|
251
|
-
});
|
|
252
|
-
container.setAttribute('style', containerStyle);
|
|
253
|
-
container.setAttribute('data-testid', 'show-diff-removed-lozenge');
|
|
254
|
-
|
|
255
|
-
// Create vanilla HTML lozenge element with Atlaskit Lozenge styling (visual refresh)
|
|
256
|
-
const lozengeElement = document.createElement('span');
|
|
257
|
-
lozengeElement.setAttribute('style', lozengeStyle);
|
|
258
|
-
lozengeElement.textContent = intl.formatMessage(trackChangesMessages.removed).toUpperCase();
|
|
259
|
-
container.appendChild(lozengeElement);
|
|
260
|
-
return container;
|
|
261
|
-
};
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Wraps a block node in a container with relative positioning to support absolute positioned lozenge
|
|
265
|
-
*/
|
|
266
|
-
const createBlockNodeWrapper = nodeName => {
|
|
267
|
-
const wrapper = document.createElement('div');
|
|
268
|
-
const fitContent = shouldFitContentWidth(nodeName);
|
|
269
|
-
const baseStyle = convertToInlineCss({
|
|
270
|
-
position: 'relative',
|
|
271
|
-
display: fitContent ? 'inline-block' : 'block',
|
|
272
|
-
width: fitContent ? 'fit-content' : undefined,
|
|
273
|
-
height: fitContent ? 'fit-content' : undefined,
|
|
274
|
-
opacity: 1
|
|
275
|
-
});
|
|
276
|
-
wrapper.setAttribute('style', baseStyle);
|
|
277
|
-
return wrapper;
|
|
278
|
-
};
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Wraps content with deleted styling without opacity (for use when content is a direct child of dom)
|
|
282
|
-
*/
|
|
283
|
-
const createDeletedStyleWrapperWithoutOpacity = colourScheme => {
|
|
284
|
-
const wrapper = document.createElement('span');
|
|
285
|
-
wrapper.setAttribute('style', getDeletedContentStyle(colourScheme));
|
|
286
|
-
return wrapper;
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Applies deleted styles directly to an HTML element by merging with existing styles
|
|
291
|
-
*/
|
|
292
|
-
const applyDeletedStylesToElement = (element, targetNode, colourScheme) => {
|
|
293
|
-
const currentStyle = element.getAttribute('style') || '';
|
|
294
|
-
const deletedContentStyle = getDeletedContentStyle(colourScheme);
|
|
295
|
-
const nodeSpecificStyle = getDeletedStyleNode(targetNode.type.name) || '';
|
|
296
|
-
element.setAttribute('style', `${currentStyle}${deletedContentStyle}${nodeSpecificStyle}`);
|
|
297
|
-
};
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Appends a block node with wrapper, lozenge, and appropriate styling
|
|
301
|
-
*/
|
|
302
|
-
const appendBlockNodeWithWrapper = (dom, nodeView, targetNode, colourScheme, intl) => {
|
|
303
|
-
const blockWrapper = createBlockNodeWrapper(targetNode.type.name);
|
|
304
|
-
if (shouldShowRemovedLozenge(targetNode.type.name)) {
|
|
305
|
-
const lozenge = createRemovedLozenge(intl, targetNode.type.name);
|
|
306
|
-
blockWrapper.append(lozenge);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
// Wrap the nodeView in a content wrapper that has the opacity style AND the box-shadow
|
|
310
|
-
// This keeps the lozenge at full opacity while the content AND border are faded
|
|
311
|
-
const contentWrapper = document.createElement('div');
|
|
312
|
-
const nodeStyle = getDeletedStyleNode(targetNode.type.name);
|
|
313
|
-
contentWrapper.setAttribute('style', `${getDeletedContentStyle(colourScheme)}${nodeStyle || ''}`);
|
|
314
|
-
contentWrapper.append(nodeView);
|
|
315
|
-
blockWrapper.append(contentWrapper);
|
|
316
|
-
if (nodeView instanceof HTMLElement) {
|
|
317
|
-
if (shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
|
|
318
|
-
nodeView.classList.add('show-diff-deleted-node');
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
dom.append(blockWrapper);
|
|
322
|
-
};
|
|
132
|
+
export const getDeletedContentStyleUnbounded = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
|
|
133
|
+
export const getDeletedContentStyle = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
|
|
323
134
|
|
|
324
135
|
/**
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
136
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
137
|
+
*
|
|
138
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
139
|
+
* @returns Prosemirror inline decoration
|
|
328
140
|
*/
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
dom.append(nodeView);
|
|
334
|
-
} else {
|
|
335
|
-
// Use wrapper approach for other block nodes
|
|
336
|
-
appendBlockNodeWithWrapper(dom, nodeView, targetNode, colourScheme, intl);
|
|
337
|
-
}
|
|
338
|
-
};
|
|
141
|
+
export const createBlockChangedDecoration = (change, colourScheme) => Decoration.node(change.from, change.to, {
|
|
142
|
+
style: getEditorStyleNode(change.name, colourScheme),
|
|
143
|
+
'data-testid': 'show-diff-changed-decoration-node'
|
|
144
|
+
}, {});
|
|
339
145
|
export const createDeletedContentDecoration = ({
|
|
340
146
|
change,
|
|
341
147
|
doc,
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
+
import { trackChangesMessages } from '@atlaskit/editor-common/messages';
|
|
3
|
+
import { getDeletedContentStyle } from './decorations';
|
|
4
|
+
export const deletedStyleQuoteNode = convertToInlineCss({
|
|
5
|
+
borderLeft: `2px solid ${"var(--ds-border-accent-gray, #7D818A)"}`
|
|
6
|
+
});
|
|
7
|
+
export const deletedBlockOutline = convertToInlineCss({
|
|
8
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-gray, #7D818A)"}`,
|
|
9
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
10
|
+
});
|
|
11
|
+
export const deletedBlockOutlineRounded = convertToInlineCss({
|
|
12
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-gray, #7D818A)"}`,
|
|
13
|
+
borderRadius: `calc(${"var(--ds-radius-xsmall, 2px)"} + 1px)`
|
|
14
|
+
});
|
|
15
|
+
const lozengeStyle = convertToInlineCss({
|
|
16
|
+
display: 'inline-flex',
|
|
17
|
+
boxSizing: 'border-box',
|
|
18
|
+
position: 'static',
|
|
19
|
+
blockSize: 'min-content',
|
|
20
|
+
borderRadius: "var(--ds-radius-small, 4px)",
|
|
21
|
+
overflow: 'hidden',
|
|
22
|
+
paddingInlineStart: "var(--ds-space-050, 4px)",
|
|
23
|
+
paddingInlineEnd: "var(--ds-space-050, 4px)",
|
|
24
|
+
backgroundColor: "var(--ds-background-accent-gray-subtler, #DDDEE1)",
|
|
25
|
+
font: "var(--ds-font-body-small, normal 400 11px/16px ui-sans-serif, -apple-system, BlinkMacSystemFont, \"Segoe UI\", Ubuntu, \"Helvetica Neue\", sans-serif)",
|
|
26
|
+
fontWeight: "var(--ds-font-weight-bold, 700)",
|
|
27
|
+
textOverflow: 'ellipsis',
|
|
28
|
+
whiteSpace: 'nowrap',
|
|
29
|
+
color: "var(--ds-text-warning-inverse, #292A2E)"
|
|
30
|
+
});
|
|
31
|
+
export const getDeletedStyleNode = nodeName => {
|
|
32
|
+
switch (nodeName) {
|
|
33
|
+
case 'blockquote':
|
|
34
|
+
return deletedStyleQuoteNode;
|
|
35
|
+
case 'expand':
|
|
36
|
+
case 'decisionList':
|
|
37
|
+
return deletedBlockOutline;
|
|
38
|
+
case 'panel':
|
|
39
|
+
case 'codeBlock':
|
|
40
|
+
return deletedBlockOutlineRounded;
|
|
41
|
+
default:
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export const shouldShowRemovedLozenge = nodeName => {
|
|
46
|
+
switch (nodeName) {
|
|
47
|
+
case 'expand':
|
|
48
|
+
case 'codeBlock':
|
|
49
|
+
case 'mediaSingle':
|
|
50
|
+
case 'panel':
|
|
51
|
+
case 'decisionList':
|
|
52
|
+
return true;
|
|
53
|
+
default:
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
export const shouldAddShowDiffDeletedNodeClass = nodeName => {
|
|
58
|
+
switch (nodeName) {
|
|
59
|
+
case 'mediaSingle':
|
|
60
|
+
case 'embedCard':
|
|
61
|
+
return true;
|
|
62
|
+
default:
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a node should apply deleted styles directly without wrapper
|
|
69
|
+
* to preserve natural block-level margins
|
|
70
|
+
*/
|
|
71
|
+
export const shouldApplyDeletedStylesDirectly = nodeName => {
|
|
72
|
+
return nodeName === 'blockquote' || nodeName === 'heading';
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Creates a "Removed" lozenge to be displayed at the top right corner of deleted block nodes
|
|
77
|
+
*/
|
|
78
|
+
export const createRemovedLozenge = (intl, nodeName) => {
|
|
79
|
+
const container = document.createElement('span');
|
|
80
|
+
let borderTopRightRadius;
|
|
81
|
+
if (['expand', 'decisionList'].includes(nodeName || '')) {
|
|
82
|
+
borderTopRightRadius = "var(--ds-radius-small, 4px)";
|
|
83
|
+
} else if (['panel', 'codeBlock', 'mediaSingle'].includes(nodeName || '')) {
|
|
84
|
+
borderTopRightRadius = `calc(${"var(--ds-radius-xsmall, 2px)"} + 1px)`;
|
|
85
|
+
}
|
|
86
|
+
const containerStyle = convertToInlineCss({
|
|
87
|
+
position: 'absolute',
|
|
88
|
+
top: "var(--ds-space-0, 0px)",
|
|
89
|
+
right: "var(--ds-space-0, 0px)",
|
|
90
|
+
zIndex: 2,
|
|
91
|
+
pointerEvents: 'none',
|
|
92
|
+
display: 'flex',
|
|
93
|
+
overflow: 'hidden',
|
|
94
|
+
borderTopRightRadius
|
|
95
|
+
});
|
|
96
|
+
container.setAttribute('style', containerStyle);
|
|
97
|
+
container.setAttribute('data-testid', 'show-diff-removed-lozenge');
|
|
98
|
+
|
|
99
|
+
// Create vanilla HTML lozenge element with Atlaskit Lozenge styling (visual refresh)
|
|
100
|
+
const lozengeElement = document.createElement('span');
|
|
101
|
+
lozengeElement.setAttribute('style', lozengeStyle);
|
|
102
|
+
lozengeElement.textContent = intl.formatMessage(trackChangesMessages.removed).toUpperCase();
|
|
103
|
+
container.appendChild(lozengeElement);
|
|
104
|
+
return container;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Wraps a block node in a container with relative positioning to support absolute positioned lozenge
|
|
109
|
+
*/
|
|
110
|
+
export const createBlockNodeWrapper = nodeName => {
|
|
111
|
+
const wrapper = document.createElement('div');
|
|
112
|
+
const baseStyle = convertToInlineCss({
|
|
113
|
+
position: 'relative',
|
|
114
|
+
display: 'block',
|
|
115
|
+
opacity: 1
|
|
116
|
+
});
|
|
117
|
+
wrapper.setAttribute('style', baseStyle);
|
|
118
|
+
return wrapper;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Wraps content with deleted styling without opacity (for use when content is a direct child of dom)
|
|
123
|
+
*/
|
|
124
|
+
export const createDeletedStyleWrapperWithoutOpacity = colourScheme => {
|
|
125
|
+
const wrapper = document.createElement('span');
|
|
126
|
+
wrapper.setAttribute('style', getDeletedContentStyle(colourScheme));
|
|
127
|
+
return wrapper;
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Applies deleted styles directly to an HTML element by merging with existing styles
|
|
132
|
+
*/
|
|
133
|
+
export const applyDeletedStylesToElement = (element, targetNode, colourScheme) => {
|
|
134
|
+
const currentStyle = element.getAttribute('style') || '';
|
|
135
|
+
const deletedContentStyle = getDeletedContentStyle(colourScheme);
|
|
136
|
+
const nodeSpecificStyle = getDeletedStyleNode(targetNode.type.name) || '';
|
|
137
|
+
element.setAttribute('style', `${currentStyle}${deletedContentStyle}${nodeSpecificStyle}`);
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Creates a content wrapper with deleted styles for a block node
|
|
142
|
+
*/
|
|
143
|
+
export const createBlockNodeContentWrapper = (nodeView, targetNode, colourScheme) => {
|
|
144
|
+
const contentWrapper = document.createElement('div');
|
|
145
|
+
const nodeStyle = getDeletedStyleNode(targetNode.type.name);
|
|
146
|
+
contentWrapper.setAttribute('style', `${getDeletedContentStyle(colourScheme)}${nodeStyle || ''}`);
|
|
147
|
+
contentWrapper.append(nodeView);
|
|
148
|
+
return contentWrapper;
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Handles special mediaSingle node rendering with lozenge on child media element
|
|
153
|
+
* @returns true if mediaSingle was handled, false otherwise
|
|
154
|
+
*/
|
|
155
|
+
export const handleMediaSingleWithLozenge = (dom, nodeView, targetNode, lozenge) => {
|
|
156
|
+
if (targetNode.type.name !== 'mediaSingle' || !(nodeView instanceof HTMLElement)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
const mediaNode = nodeView.querySelector('[data-prosemirror-node-name="media"]');
|
|
160
|
+
if (!mediaNode || !(mediaNode instanceof HTMLElement)) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Add relative positioning to media node to anchor lozenge
|
|
165
|
+
const currentStyle = mediaNode.getAttribute('style') || '';
|
|
166
|
+
const relativePositionStyle = convertToInlineCss({
|
|
167
|
+
position: 'relative'
|
|
168
|
+
});
|
|
169
|
+
mediaNode.setAttribute('style', `${currentStyle}${relativePositionStyle}`);
|
|
170
|
+
mediaNode.append(lozenge);
|
|
171
|
+
|
|
172
|
+
// Add deleted node class if needed
|
|
173
|
+
if (shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
|
|
174
|
+
nodeView.classList.add('show-diff-deleted-node');
|
|
175
|
+
}
|
|
176
|
+
dom.append(nodeView);
|
|
177
|
+
return true;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Appends a block node with wrapper, lozenge, and appropriate styling
|
|
182
|
+
*/
|
|
183
|
+
export const appendBlockNodeWithWrapper = (dom, nodeView, targetNode, colourScheme, intl) => {
|
|
184
|
+
const blockWrapper = createBlockNodeWrapper(targetNode.type.name);
|
|
185
|
+
if (shouldShowRemovedLozenge(targetNode.type.name)) {
|
|
186
|
+
const lozenge = createRemovedLozenge(intl, targetNode.type.name);
|
|
187
|
+
if (handleMediaSingleWithLozenge(dom, nodeView, targetNode, lozenge)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
blockWrapper.append(lozenge);
|
|
191
|
+
}
|
|
192
|
+
const contentWrapper = createBlockNodeContentWrapper(nodeView, targetNode, colourScheme);
|
|
193
|
+
blockWrapper.append(contentWrapper);
|
|
194
|
+
if (nodeView instanceof HTMLElement && shouldAddShowDiffDeletedNodeClass(targetNode.type.name)) {
|
|
195
|
+
nodeView.classList.add('show-diff-deleted-node');
|
|
196
|
+
}
|
|
197
|
+
dom.append(blockWrapper);
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Handles all block node rendering with appropriate deleted styling.
|
|
202
|
+
* For blockquote and heading nodes, applies styles directly to preserve natural margins.
|
|
203
|
+
* For other block nodes, uses wrapper approach with optional lozenge.
|
|
204
|
+
*/
|
|
205
|
+
export const handleBlockNodeView = (dom, nodeView, targetNode, colourScheme, intl) => {
|
|
206
|
+
if (shouldApplyDeletedStylesDirectly(targetNode.type.name) && nodeView instanceof HTMLElement) {
|
|
207
|
+
// Apply deleted styles directly to preserve natural block-level margins
|
|
208
|
+
applyDeletedStylesToElement(nodeView, targetNode, colourScheme);
|
|
209
|
+
dom.append(nodeView);
|
|
210
|
+
} else {
|
|
211
|
+
// Use wrapper approach for other block nodes
|
|
212
|
+
appendBlockNodeWithWrapper(dom, nodeView, targetNode, colourScheme, intl);
|
|
213
|
+
}
|
|
214
|
+
};
|
|
@@ -5,7 +5,7 @@ import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
|
5
5
|
import { TableMap } from '@atlaskit/editor-tables/table-map';
|
|
6
6
|
import { findSafeInsertPos } from './findSafeInsertPos';
|
|
7
7
|
const deletedRowStyle = convertToInlineCss({
|
|
8
|
-
color: "var(--ds-text-accent-gray, #
|
|
8
|
+
color: "var(--ds-text-accent-gray, #505258)",
|
|
9
9
|
textDecoration: 'line-through',
|
|
10
10
|
opacity: 0.6,
|
|
11
11
|
display: 'table-row'
|