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