@atlaskit/editor-plugin-show-diff 27.1.3 → 28.0.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.
- package/CHANGELOG.md +15 -0
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +2 -1
- package/dist/cjs/pm-plugins/decorations/createReplacedCellDecorations.js +70 -16
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +2 -1
- package/dist/es2019/pm-plugins/decorations/createReplacedCellDecorations.js +67 -17
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +2 -1
- package/dist/esm/pm-plugins/decorations/createReplacedCellDecorations.js +71 -17
- package/dist/types/pm-plugins/decorations/createReplacedCellDecorations.d.ts +2 -1
- package/package.json +13 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 28.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 27.1.4
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`a13cf337bdc67`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a13cf337bdc67) -
|
|
14
|
+
Fix a suggested table cell change showing a blank cell when the changeset trims it to the cell's
|
|
15
|
+
open tokens, and keep its indicator bar on the suggested content. Behind
|
|
16
|
+
`platform_editor_ai_show_diff_patch_2_fix`.
|
|
17
|
+
|
|
3
18
|
## 27.1.3
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -234,7 +234,8 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
234
234
|
intl: intl,
|
|
235
235
|
isActive: isActive,
|
|
236
236
|
isInserted: isInserted,
|
|
237
|
-
leftAnchorId: leftAnchorId
|
|
237
|
+
leftAnchorId: leftAnchorId,
|
|
238
|
+
showIndicators: showIndicators
|
|
238
239
|
});
|
|
239
240
|
}
|
|
240
241
|
return createTableCellContentWidgets({
|
|
@@ -14,6 +14,8 @@ var _tableNodes = require("@atlaskit/adf-schema/tableNodes");
|
|
|
14
14
|
var _cssHelper = require("@atlaskit/editor-common/css-helper");
|
|
15
15
|
var _document = require("@atlaskit/editor-common/utils/document");
|
|
16
16
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
17
|
+
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
18
|
+
var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
|
|
17
19
|
var _createBlockChangedDecoration = require("./createBlockChangedDecoration");
|
|
18
20
|
var _createInlineChangedDecoration = require("./createInlineChangedDecoration");
|
|
19
21
|
var _decorationKeys = require("./decorationKeys");
|
|
@@ -22,6 +24,26 @@ var _wrapBlockNodeView = require("./utils/wrapBlockNodeView");
|
|
|
22
24
|
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
23
25
|
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) { (0, _defineProperty2.default)(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; }
|
|
24
26
|
var CELL_TYPE_NAMES = ['tableCell', 'tableHeader'];
|
|
27
|
+
/**
|
|
28
|
+
* Whether only close tokens follow `pos` in its cell: it is at the end of its parent, and so is each
|
|
29
|
+
* ancestor up to the cell.
|
|
30
|
+
*/
|
|
31
|
+
var isAtEndOfCell = function isAtEndOfCell(doc, pos) {
|
|
32
|
+
var $pos = doc.resolve(pos);
|
|
33
|
+
if ($pos.parentOffset !== $pos.parent.content.size) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
for (var depth = $pos.depth; depth > 0; depth--) {
|
|
37
|
+
if (CELL_TYPE_NAMES.includes($pos.node(depth).type.name)) {
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
if ($pos.indexAfter(depth - 1) !== $pos.node(depth - 1).childCount) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
};
|
|
46
|
+
|
|
25
47
|
/**
|
|
26
48
|
* Pairs each cell of a whole-cell replacement with the live cell it replaces, or `[]` when the slice
|
|
27
49
|
* is not a run of whole cells matching the live ones. Whole-cell replacement preserves cell count and
|
|
@@ -33,7 +55,7 @@ var getReplacedCells = exports.getReplacedCells = function getReplacedCells(_ref
|
|
|
33
55
|
fromB = _ref.fromB,
|
|
34
56
|
toB = _ref.toB;
|
|
35
57
|
var otherCells = slice.content.content;
|
|
36
|
-
if (slice.openStart !== 0 || slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(function (node) {
|
|
58
|
+
if (slice.openStart !== 0 || (!(0, _fg.fg)('platform_editor_ai_show_diff_patch_2_fix') || !isAtEndOfCell(doc, toB)) && slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(function (node) {
|
|
37
59
|
return CELL_TYPE_NAMES.includes(node.type.name);
|
|
38
60
|
})) {
|
|
39
61
|
return [];
|
|
@@ -134,16 +156,18 @@ var createCellBackgroundLayer = function createCellBackgroundLayer(color) {
|
|
|
134
156
|
return layer;
|
|
135
157
|
};
|
|
136
158
|
|
|
137
|
-
/** The other side's cell content, as blocks, for the top of the live cell. */
|
|
138
|
-
var
|
|
159
|
+
/** The other side's cell content, as blocks, for the top of the live cell, with its indicator anchor. */
|
|
160
|
+
var createCellContentWidgets = function createCellContentWidgets(_ref2) {
|
|
139
161
|
var cell = _ref2.cell,
|
|
162
|
+
doc = _ref2.doc,
|
|
140
163
|
pos = _ref2.pos,
|
|
141
164
|
nodeViewSerializer = _ref2.nodeViewSerializer,
|
|
142
165
|
colorScheme = _ref2.colorScheme,
|
|
143
166
|
intl = _ref2.intl,
|
|
144
167
|
isActive = _ref2.isActive,
|
|
145
168
|
isInserted = _ref2.isInserted,
|
|
146
|
-
leftAnchorId = _ref2.leftAnchorId
|
|
169
|
+
leftAnchorId = _ref2.leftAnchorId,
|
|
170
|
+
showIndicators = _ref2.showIndicators;
|
|
147
171
|
var dom = document.createElement('div');
|
|
148
172
|
cell.content.forEach(function (block) {
|
|
149
173
|
var nodeView = nodeViewSerializer.tryCreateNodeView(block, 0, undefined, isInserted, colorScheme);
|
|
@@ -170,16 +194,24 @@ var createCellContentWidget = function createCellContentWidget(_ref2) {
|
|
|
170
194
|
}
|
|
171
195
|
});
|
|
172
196
|
if (dom.childNodes.length === 0) {
|
|
173
|
-
return
|
|
197
|
+
return [];
|
|
174
198
|
}
|
|
175
199
|
dom.setAttribute('data-testid', isInserted ? 'show-diff-changed-decoration' : 'show-diff-deleted-decoration');
|
|
200
|
+
var diffId = crypto.randomUUID();
|
|
201
|
+
if (showIndicators && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2_fix')) {
|
|
202
|
+
// The indicator bar of a widget anchors its top and bottom to the widget itself. Without this
|
|
203
|
+
// only the live cell's own bar resolves, which starts below the suggested content.
|
|
204
|
+
dom.style.setProperty('anchor-name', "--".concat((0, _decorationKeys.buildAnchorDecorationKey)({
|
|
205
|
+
diffId: diffId
|
|
206
|
+
})));
|
|
207
|
+
}
|
|
176
208
|
|
|
177
209
|
// Before the cell's own blocks, as a block of its own, so it never lands inside a paragraph the
|
|
178
210
|
// displayed side may hide.
|
|
179
|
-
|
|
211
|
+
var widget = _view.Decoration.widget(pos + 1, dom, _objectSpread(_objectSpread({}, (0, _decorationKeys.buildDiffDecorationSpec)({
|
|
180
212
|
colorScheme: colorScheme,
|
|
181
213
|
decorationType: 'widget',
|
|
182
|
-
diffId:
|
|
214
|
+
diffId: diffId,
|
|
183
215
|
leftAnchorId: leftAnchorId,
|
|
184
216
|
isActive: isActive,
|
|
185
217
|
isInserted: isInserted,
|
|
@@ -187,6 +219,16 @@ var createCellContentWidget = function createCellContentWidget(_ref2) {
|
|
|
187
219
|
})), {}, {
|
|
188
220
|
marks: []
|
|
189
221
|
}));
|
|
222
|
+
|
|
223
|
+
// The bar aligns its left edge to this anchor. The live cell's inline decoration makes one too,
|
|
224
|
+
// but not when the clean view hides it, and the widget is still showing then.
|
|
225
|
+
var leftAnchor = showIndicators && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2_fix') ? (0, _createAnchorDecorationWidgets.createLeftAnchorWidget)({
|
|
226
|
+
doc: doc,
|
|
227
|
+
from: pos,
|
|
228
|
+
diffId: diffId,
|
|
229
|
+
leftAnchorId: leftAnchorId
|
|
230
|
+
}) : undefined;
|
|
231
|
+
return leftAnchor ? [widget, leftAnchor] : [widget];
|
|
190
232
|
};
|
|
191
233
|
|
|
192
234
|
/**
|
|
@@ -203,7 +245,8 @@ var createReplacedCellWidgets = exports.createReplacedCellWidgets = function cre
|
|
|
203
245
|
intl = _ref3.intl,
|
|
204
246
|
isActive = _ref3.isActive,
|
|
205
247
|
isInserted = _ref3.isInserted,
|
|
206
|
-
leftAnchorId = _ref3.leftAnchorId
|
|
248
|
+
leftAnchorId = _ref3.leftAnchorId,
|
|
249
|
+
showIndicators = _ref3.showIndicators;
|
|
207
250
|
return getReplacedCells({
|
|
208
251
|
slice: slice,
|
|
209
252
|
doc: newDoc,
|
|
@@ -240,24 +283,31 @@ var createReplacedCellWidgets = exports.createReplacedCellWidgets = function cre
|
|
|
240
283
|
}));
|
|
241
284
|
}
|
|
242
285
|
if (!isCellContentEqual(otherCell, liveCell)) {
|
|
243
|
-
var
|
|
286
|
+
var contentWidgets = createCellContentWidgets({
|
|
244
287
|
cell: otherCell,
|
|
288
|
+
doc: newDoc,
|
|
245
289
|
pos: liveCellPos,
|
|
246
290
|
nodeViewSerializer: nodeViewSerializer,
|
|
247
291
|
colorScheme: colorScheme,
|
|
248
292
|
intl: intl,
|
|
249
293
|
isActive: isActive,
|
|
250
294
|
isInserted: isInserted,
|
|
251
|
-
leftAnchorId: leftAnchorId
|
|
295
|
+
leftAnchorId: leftAnchorId,
|
|
296
|
+
showIndicators: showIndicators
|
|
252
297
|
});
|
|
253
|
-
|
|
254
|
-
decorations.push(contentWidget);
|
|
255
|
-
}
|
|
298
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)(contentWidgets));
|
|
256
299
|
}
|
|
257
300
|
return decorations;
|
|
258
301
|
});
|
|
259
302
|
};
|
|
260
303
|
|
|
304
|
+
/** Whether a cell holds only blank lines: empty paragraphs or headings, with nothing to show. */
|
|
305
|
+
var isBlankCell = function isBlankCell(cell) {
|
|
306
|
+
return cell.childCount > 0 && cell.children.every(function (block) {
|
|
307
|
+
return block.isTextblock && block.content.size === 0;
|
|
308
|
+
});
|
|
309
|
+
};
|
|
310
|
+
|
|
261
311
|
/**
|
|
262
312
|
* The displayed side of a whole-cell replacement. A table cell is never removed on its own, only
|
|
263
313
|
* replaced in place, so a live cell is never hidden — hiding it would leave the row a cell short. It
|
|
@@ -307,6 +357,10 @@ var createReplacedCellDecorations = exports.createReplacedCellDecorations = func
|
|
|
307
357
|
if (isCellContentEqual(otherCell, liveCell)) {
|
|
308
358
|
return decorations;
|
|
309
359
|
}
|
|
360
|
+
|
|
361
|
+
// A blank live cell has no content to strike through, so the suggestion takes its place, as
|
|
362
|
+
// in the clean view, rather than leaving a blank line below it.
|
|
363
|
+
var hidesLiveCell = shouldHideDeleted || !isInserted && isBlankCell(liveCell) && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2_fix');
|
|
310
364
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
|
|
311
365
|
attributionKey: attributionKey,
|
|
312
366
|
change: _objectSpread(_objectSpread({}, change), {}, {
|
|
@@ -322,12 +376,12 @@ var createReplacedCellDecorations = exports.createReplacedCellDecorations = func
|
|
|
322
376
|
isInserted: isInserted,
|
|
323
377
|
leftAnchorId: leftAnchorId,
|
|
324
378
|
reveal: reveal,
|
|
325
|
-
shouldHideDeleted:
|
|
379
|
+
shouldHideDeleted: hidesLiveCell,
|
|
326
380
|
showContributorTags: showContributorTags,
|
|
327
381
|
showIndicators: showIndicators,
|
|
328
382
|
tagMountContext: tagMountContext
|
|
329
383
|
})));
|
|
330
|
-
if (
|
|
384
|
+
if (hidesLiveCell) {
|
|
331
385
|
liveCell.forEach(function (block, offset) {
|
|
332
386
|
var blockPos = liveCellPos + 1 + offset;
|
|
333
387
|
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createBlockChangedDecoration.createBlockChangedDecoration)({
|
|
@@ -341,7 +395,7 @@ var createReplacedCellDecorations = exports.createReplacedCellDecorations = func
|
|
|
341
395
|
isActive: isActive,
|
|
342
396
|
isInserted: isInserted,
|
|
343
397
|
leftAnchorId: leftAnchorId,
|
|
344
|
-
shouldHideDeleted:
|
|
398
|
+
shouldHideDeleted: hidesLiveCell
|
|
345
399
|
})));
|
|
346
400
|
});
|
|
347
401
|
}
|
|
@@ -5,12 +5,34 @@ import { getCellDomAttrs } from '@atlaskit/adf-schema/tableNodes';
|
|
|
5
5
|
import { convertToInlineCss } from '@atlaskit/editor-common/css-helper';
|
|
6
6
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
7
7
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
8
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
9
|
+
import { createLeftAnchorWidget } from './createAnchorDecorationWidgets';
|
|
8
10
|
import { createBlockChangedDecoration } from './createBlockChangedDecoration';
|
|
9
11
|
import { createInlineChangedDecoration } from './createInlineChangedDecoration';
|
|
10
|
-
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
12
|
+
import { buildAnchorDecorationKey, buildDiffDecorationSpec } from './decorationKeys';
|
|
11
13
|
import { isCellAttrChanged, isCellBackgroundChanged, normalizeCellBackground } from './utils/cellAttrs';
|
|
12
14
|
import { injectInnerWrapper, wrapBlockNodeView } from './utils/wrapBlockNodeView';
|
|
13
15
|
const CELL_TYPE_NAMES = ['tableCell', 'tableHeader'];
|
|
16
|
+
/**
|
|
17
|
+
* Whether only close tokens follow `pos` in its cell: it is at the end of its parent, and so is each
|
|
18
|
+
* ancestor up to the cell.
|
|
19
|
+
*/
|
|
20
|
+
const isAtEndOfCell = (doc, pos) => {
|
|
21
|
+
const $pos = doc.resolve(pos);
|
|
22
|
+
if ($pos.parentOffset !== $pos.parent.content.size) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
for (let depth = $pos.depth; depth > 0; depth--) {
|
|
26
|
+
if (CELL_TYPE_NAMES.includes($pos.node(depth).type.name)) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
if ($pos.indexAfter(depth - 1) !== $pos.node(depth - 1).childCount) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
};
|
|
35
|
+
|
|
14
36
|
/**
|
|
15
37
|
* Pairs each cell of a whole-cell replacement with the live cell it replaces, or `[]` when the slice
|
|
16
38
|
* is not a run of whole cells matching the live ones. Whole-cell replacement preserves cell count and
|
|
@@ -23,7 +45,7 @@ export const getReplacedCells = ({
|
|
|
23
45
|
toB
|
|
24
46
|
}) => {
|
|
25
47
|
const otherCells = slice.content.content;
|
|
26
|
-
if (slice.openStart !== 0 || slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(node => CELL_TYPE_NAMES.includes(node.type.name))) {
|
|
48
|
+
if (slice.openStart !== 0 || (!fg('platform_editor_ai_show_diff_patch_2_fix') || !isAtEndOfCell(doc, toB)) && slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(node => CELL_TYPE_NAMES.includes(node.type.name))) {
|
|
27
49
|
return [];
|
|
28
50
|
}
|
|
29
51
|
const liveCells = [];
|
|
@@ -119,16 +141,18 @@ const createCellBackgroundLayer = color => {
|
|
|
119
141
|
return layer;
|
|
120
142
|
};
|
|
121
143
|
|
|
122
|
-
/** The other side's cell content, as blocks, for the top of the live cell. */
|
|
123
|
-
const
|
|
144
|
+
/** The other side's cell content, as blocks, for the top of the live cell, with its indicator anchor. */
|
|
145
|
+
const createCellContentWidgets = ({
|
|
124
146
|
cell,
|
|
147
|
+
doc,
|
|
125
148
|
pos,
|
|
126
149
|
nodeViewSerializer,
|
|
127
150
|
colorScheme,
|
|
128
151
|
intl,
|
|
129
152
|
isActive,
|
|
130
153
|
isInserted,
|
|
131
|
-
leftAnchorId
|
|
154
|
+
leftAnchorId,
|
|
155
|
+
showIndicators
|
|
132
156
|
}) => {
|
|
133
157
|
const dom = document.createElement('div');
|
|
134
158
|
cell.content.forEach(block => {
|
|
@@ -156,17 +180,25 @@ const createCellContentWidget = ({
|
|
|
156
180
|
}
|
|
157
181
|
});
|
|
158
182
|
if (dom.childNodes.length === 0) {
|
|
159
|
-
return
|
|
183
|
+
return [];
|
|
160
184
|
}
|
|
161
185
|
dom.setAttribute('data-testid', isInserted ? 'show-diff-changed-decoration' : 'show-diff-deleted-decoration');
|
|
186
|
+
const diffId = crypto.randomUUID();
|
|
187
|
+
if (showIndicators && fg('platform_editor_ai_show_diff_patch_2_fix')) {
|
|
188
|
+
// The indicator bar of a widget anchors its top and bottom to the widget itself. Without this
|
|
189
|
+
// only the live cell's own bar resolves, which starts below the suggested content.
|
|
190
|
+
dom.style.setProperty('anchor-name', `--${buildAnchorDecorationKey({
|
|
191
|
+
diffId
|
|
192
|
+
})}`);
|
|
193
|
+
}
|
|
162
194
|
|
|
163
195
|
// Before the cell's own blocks, as a block of its own, so it never lands inside a paragraph the
|
|
164
196
|
// displayed side may hide.
|
|
165
|
-
|
|
197
|
+
const widget = Decoration.widget(pos + 1, dom, {
|
|
166
198
|
...buildDiffDecorationSpec({
|
|
167
199
|
colorScheme,
|
|
168
200
|
decorationType: 'widget',
|
|
169
|
-
diffId
|
|
201
|
+
diffId,
|
|
170
202
|
leftAnchorId,
|
|
171
203
|
isActive,
|
|
172
204
|
isInserted,
|
|
@@ -174,6 +206,16 @@ const createCellContentWidget = ({
|
|
|
174
206
|
}),
|
|
175
207
|
marks: []
|
|
176
208
|
});
|
|
209
|
+
|
|
210
|
+
// The bar aligns its left edge to this anchor. The live cell's inline decoration makes one too,
|
|
211
|
+
// but not when the clean view hides it, and the widget is still showing then.
|
|
212
|
+
const leftAnchor = showIndicators && fg('platform_editor_ai_show_diff_patch_2_fix') ? createLeftAnchorWidget({
|
|
213
|
+
doc,
|
|
214
|
+
from: pos,
|
|
215
|
+
diffId,
|
|
216
|
+
leftAnchorId
|
|
217
|
+
}) : undefined;
|
|
218
|
+
return leftAnchor ? [widget, leftAnchor] : [widget];
|
|
177
219
|
};
|
|
178
220
|
|
|
179
221
|
/**
|
|
@@ -190,7 +232,8 @@ export const createReplacedCellWidgets = ({
|
|
|
190
232
|
intl,
|
|
191
233
|
isActive,
|
|
192
234
|
isInserted,
|
|
193
|
-
leftAnchorId
|
|
235
|
+
leftAnchorId,
|
|
236
|
+
showIndicators
|
|
194
237
|
}) => getReplacedCells({
|
|
195
238
|
slice,
|
|
196
239
|
doc: newDoc,
|
|
@@ -228,23 +271,26 @@ export const createReplacedCellWidgets = ({
|
|
|
228
271
|
}));
|
|
229
272
|
}
|
|
230
273
|
if (!isCellContentEqual(otherCell, liveCell)) {
|
|
231
|
-
const
|
|
274
|
+
const contentWidgets = createCellContentWidgets({
|
|
232
275
|
cell: otherCell,
|
|
276
|
+
doc: newDoc,
|
|
233
277
|
pos: liveCellPos,
|
|
234
278
|
nodeViewSerializer,
|
|
235
279
|
colorScheme,
|
|
236
280
|
intl,
|
|
237
281
|
isActive,
|
|
238
282
|
isInserted,
|
|
239
|
-
leftAnchorId
|
|
283
|
+
leftAnchorId,
|
|
284
|
+
showIndicators
|
|
240
285
|
});
|
|
241
|
-
|
|
242
|
-
decorations.push(contentWidget);
|
|
243
|
-
}
|
|
286
|
+
decorations.push(...contentWidgets);
|
|
244
287
|
}
|
|
245
288
|
return decorations;
|
|
246
289
|
});
|
|
247
290
|
|
|
291
|
+
/** Whether a cell holds only blank lines: empty paragraphs or headings, with nothing to show. */
|
|
292
|
+
const isBlankCell = cell => cell.childCount > 0 && cell.children.every(block => block.isTextblock && block.content.size === 0);
|
|
293
|
+
|
|
248
294
|
/**
|
|
249
295
|
* The displayed side of a whole-cell replacement. A table cell is never removed on its own, only
|
|
250
296
|
* replaced in place, so a live cell is never hidden — hiding it would leave the row a cell short. It
|
|
@@ -295,6 +341,10 @@ export const createReplacedCellDecorations = ({
|
|
|
295
341
|
if (isCellContentEqual(otherCell, liveCell)) {
|
|
296
342
|
return decorations;
|
|
297
343
|
}
|
|
344
|
+
|
|
345
|
+
// A blank live cell has no content to strike through, so the suggestion takes its place, as
|
|
346
|
+
// in the clean view, rather than leaving a blank line below it.
|
|
347
|
+
const hidesLiveCell = shouldHideDeleted || !isInserted && isBlankCell(liveCell) && fg('platform_editor_ai_show_diff_patch_2_fix');
|
|
298
348
|
decorations.push(...createInlineChangedDecoration({
|
|
299
349
|
attributionKey,
|
|
300
350
|
change: {
|
|
@@ -311,12 +361,12 @@ export const createReplacedCellDecorations = ({
|
|
|
311
361
|
isInserted,
|
|
312
362
|
leftAnchorId,
|
|
313
363
|
reveal,
|
|
314
|
-
shouldHideDeleted,
|
|
364
|
+
shouldHideDeleted: hidesLiveCell,
|
|
315
365
|
showContributorTags,
|
|
316
366
|
showIndicators,
|
|
317
367
|
tagMountContext
|
|
318
368
|
}));
|
|
319
|
-
if (
|
|
369
|
+
if (hidesLiveCell) {
|
|
320
370
|
liveCell.forEach((block, offset) => {
|
|
321
371
|
const blockPos = liveCellPos + 1 + offset;
|
|
322
372
|
decorations.push(...createBlockChangedDecoration({
|
|
@@ -330,7 +380,7 @@ export const createReplacedCellDecorations = ({
|
|
|
330
380
|
isActive,
|
|
331
381
|
isInserted,
|
|
332
382
|
leftAnchorId,
|
|
333
|
-
shouldHideDeleted
|
|
383
|
+
shouldHideDeleted: hidesLiveCell
|
|
334
384
|
}));
|
|
335
385
|
});
|
|
336
386
|
}
|
|
@@ -228,7 +228,8 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
228
228
|
intl: intl,
|
|
229
229
|
isActive: isActive,
|
|
230
230
|
isInserted: isInserted,
|
|
231
|
-
leftAnchorId: leftAnchorId
|
|
231
|
+
leftAnchorId: leftAnchorId,
|
|
232
|
+
showIndicators: showIndicators
|
|
232
233
|
});
|
|
233
234
|
}
|
|
234
235
|
return createTableCellContentWidgets({
|
|
@@ -9,12 +9,34 @@ import { getCellDomAttrs } from '@atlaskit/adf-schema/tableNodes';
|
|
|
9
9
|
import { convertToInlineCss } from '@atlaskit/editor-common/css-helper';
|
|
10
10
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
11
11
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
12
|
+
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
13
|
+
import { createLeftAnchorWidget } from './createAnchorDecorationWidgets';
|
|
12
14
|
import { createBlockChangedDecoration } from './createBlockChangedDecoration';
|
|
13
15
|
import { createInlineChangedDecoration } from './createInlineChangedDecoration';
|
|
14
|
-
import { buildDiffDecorationSpec } from './decorationKeys';
|
|
16
|
+
import { buildAnchorDecorationKey, buildDiffDecorationSpec } from './decorationKeys';
|
|
15
17
|
import { isCellAttrChanged, isCellBackgroundChanged, normalizeCellBackground } from './utils/cellAttrs';
|
|
16
18
|
import { injectInnerWrapper, wrapBlockNodeView } from './utils/wrapBlockNodeView';
|
|
17
19
|
var CELL_TYPE_NAMES = ['tableCell', 'tableHeader'];
|
|
20
|
+
/**
|
|
21
|
+
* Whether only close tokens follow `pos` in its cell: it is at the end of its parent, and so is each
|
|
22
|
+
* ancestor up to the cell.
|
|
23
|
+
*/
|
|
24
|
+
var isAtEndOfCell = function isAtEndOfCell(doc, pos) {
|
|
25
|
+
var $pos = doc.resolve(pos);
|
|
26
|
+
if ($pos.parentOffset !== $pos.parent.content.size) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
for (var depth = $pos.depth; depth > 0; depth--) {
|
|
30
|
+
if (CELL_TYPE_NAMES.includes($pos.node(depth).type.name)) {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
if ($pos.indexAfter(depth - 1) !== $pos.node(depth - 1).childCount) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
};
|
|
39
|
+
|
|
18
40
|
/**
|
|
19
41
|
* Pairs each cell of a whole-cell replacement with the live cell it replaces, or `[]` when the slice
|
|
20
42
|
* is not a run of whole cells matching the live ones. Whole-cell replacement preserves cell count and
|
|
@@ -26,7 +48,7 @@ export var getReplacedCells = function getReplacedCells(_ref) {
|
|
|
26
48
|
fromB = _ref.fromB,
|
|
27
49
|
toB = _ref.toB;
|
|
28
50
|
var otherCells = slice.content.content;
|
|
29
|
-
if (slice.openStart !== 0 || slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(function (node) {
|
|
51
|
+
if (slice.openStart !== 0 || (!fg('platform_editor_ai_show_diff_patch_2_fix') || !isAtEndOfCell(doc, toB)) && slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(function (node) {
|
|
30
52
|
return CELL_TYPE_NAMES.includes(node.type.name);
|
|
31
53
|
})) {
|
|
32
54
|
return [];
|
|
@@ -127,16 +149,18 @@ var createCellBackgroundLayer = function createCellBackgroundLayer(color) {
|
|
|
127
149
|
return layer;
|
|
128
150
|
};
|
|
129
151
|
|
|
130
|
-
/** The other side's cell content, as blocks, for the top of the live cell. */
|
|
131
|
-
var
|
|
152
|
+
/** The other side's cell content, as blocks, for the top of the live cell, with its indicator anchor. */
|
|
153
|
+
var createCellContentWidgets = function createCellContentWidgets(_ref2) {
|
|
132
154
|
var cell = _ref2.cell,
|
|
155
|
+
doc = _ref2.doc,
|
|
133
156
|
pos = _ref2.pos,
|
|
134
157
|
nodeViewSerializer = _ref2.nodeViewSerializer,
|
|
135
158
|
colorScheme = _ref2.colorScheme,
|
|
136
159
|
intl = _ref2.intl,
|
|
137
160
|
isActive = _ref2.isActive,
|
|
138
161
|
isInserted = _ref2.isInserted,
|
|
139
|
-
leftAnchorId = _ref2.leftAnchorId
|
|
162
|
+
leftAnchorId = _ref2.leftAnchorId,
|
|
163
|
+
showIndicators = _ref2.showIndicators;
|
|
140
164
|
var dom = document.createElement('div');
|
|
141
165
|
cell.content.forEach(function (block) {
|
|
142
166
|
var nodeView = nodeViewSerializer.tryCreateNodeView(block, 0, undefined, isInserted, colorScheme);
|
|
@@ -163,16 +187,24 @@ var createCellContentWidget = function createCellContentWidget(_ref2) {
|
|
|
163
187
|
}
|
|
164
188
|
});
|
|
165
189
|
if (dom.childNodes.length === 0) {
|
|
166
|
-
return
|
|
190
|
+
return [];
|
|
167
191
|
}
|
|
168
192
|
dom.setAttribute('data-testid', isInserted ? 'show-diff-changed-decoration' : 'show-diff-deleted-decoration');
|
|
193
|
+
var diffId = crypto.randomUUID();
|
|
194
|
+
if (showIndicators && fg('platform_editor_ai_show_diff_patch_2_fix')) {
|
|
195
|
+
// The indicator bar of a widget anchors its top and bottom to the widget itself. Without this
|
|
196
|
+
// only the live cell's own bar resolves, which starts below the suggested content.
|
|
197
|
+
dom.style.setProperty('anchor-name', "--".concat(buildAnchorDecorationKey({
|
|
198
|
+
diffId: diffId
|
|
199
|
+
})));
|
|
200
|
+
}
|
|
169
201
|
|
|
170
202
|
// Before the cell's own blocks, as a block of its own, so it never lands inside a paragraph the
|
|
171
203
|
// displayed side may hide.
|
|
172
|
-
|
|
204
|
+
var widget = Decoration.widget(pos + 1, dom, _objectSpread(_objectSpread({}, buildDiffDecorationSpec({
|
|
173
205
|
colorScheme: colorScheme,
|
|
174
206
|
decorationType: 'widget',
|
|
175
|
-
diffId:
|
|
207
|
+
diffId: diffId,
|
|
176
208
|
leftAnchorId: leftAnchorId,
|
|
177
209
|
isActive: isActive,
|
|
178
210
|
isInserted: isInserted,
|
|
@@ -180,6 +212,16 @@ var createCellContentWidget = function createCellContentWidget(_ref2) {
|
|
|
180
212
|
})), {}, {
|
|
181
213
|
marks: []
|
|
182
214
|
}));
|
|
215
|
+
|
|
216
|
+
// The bar aligns its left edge to this anchor. The live cell's inline decoration makes one too,
|
|
217
|
+
// but not when the clean view hides it, and the widget is still showing then.
|
|
218
|
+
var leftAnchor = showIndicators && fg('platform_editor_ai_show_diff_patch_2_fix') ? createLeftAnchorWidget({
|
|
219
|
+
doc: doc,
|
|
220
|
+
from: pos,
|
|
221
|
+
diffId: diffId,
|
|
222
|
+
leftAnchorId: leftAnchorId
|
|
223
|
+
}) : undefined;
|
|
224
|
+
return leftAnchor ? [widget, leftAnchor] : [widget];
|
|
183
225
|
};
|
|
184
226
|
|
|
185
227
|
/**
|
|
@@ -196,7 +238,8 @@ export var createReplacedCellWidgets = function createReplacedCellWidgets(_ref3)
|
|
|
196
238
|
intl = _ref3.intl,
|
|
197
239
|
isActive = _ref3.isActive,
|
|
198
240
|
isInserted = _ref3.isInserted,
|
|
199
|
-
leftAnchorId = _ref3.leftAnchorId
|
|
241
|
+
leftAnchorId = _ref3.leftAnchorId,
|
|
242
|
+
showIndicators = _ref3.showIndicators;
|
|
200
243
|
return getReplacedCells({
|
|
201
244
|
slice: slice,
|
|
202
245
|
doc: newDoc,
|
|
@@ -233,24 +276,31 @@ export var createReplacedCellWidgets = function createReplacedCellWidgets(_ref3)
|
|
|
233
276
|
}));
|
|
234
277
|
}
|
|
235
278
|
if (!isCellContentEqual(otherCell, liveCell)) {
|
|
236
|
-
var
|
|
279
|
+
var contentWidgets = createCellContentWidgets({
|
|
237
280
|
cell: otherCell,
|
|
281
|
+
doc: newDoc,
|
|
238
282
|
pos: liveCellPos,
|
|
239
283
|
nodeViewSerializer: nodeViewSerializer,
|
|
240
284
|
colorScheme: colorScheme,
|
|
241
285
|
intl: intl,
|
|
242
286
|
isActive: isActive,
|
|
243
287
|
isInserted: isInserted,
|
|
244
|
-
leftAnchorId: leftAnchorId
|
|
288
|
+
leftAnchorId: leftAnchorId,
|
|
289
|
+
showIndicators: showIndicators
|
|
245
290
|
});
|
|
246
|
-
|
|
247
|
-
decorations.push(contentWidget);
|
|
248
|
-
}
|
|
291
|
+
decorations.push.apply(decorations, _toConsumableArray(contentWidgets));
|
|
249
292
|
}
|
|
250
293
|
return decorations;
|
|
251
294
|
});
|
|
252
295
|
};
|
|
253
296
|
|
|
297
|
+
/** Whether a cell holds only blank lines: empty paragraphs or headings, with nothing to show. */
|
|
298
|
+
var isBlankCell = function isBlankCell(cell) {
|
|
299
|
+
return cell.childCount > 0 && cell.children.every(function (block) {
|
|
300
|
+
return block.isTextblock && block.content.size === 0;
|
|
301
|
+
});
|
|
302
|
+
};
|
|
303
|
+
|
|
254
304
|
/**
|
|
255
305
|
* The displayed side of a whole-cell replacement. A table cell is never removed on its own, only
|
|
256
306
|
* replaced in place, so a live cell is never hidden — hiding it would leave the row a cell short. It
|
|
@@ -300,6 +350,10 @@ export var createReplacedCellDecorations = function createReplacedCellDecoration
|
|
|
300
350
|
if (isCellContentEqual(otherCell, liveCell)) {
|
|
301
351
|
return decorations;
|
|
302
352
|
}
|
|
353
|
+
|
|
354
|
+
// A blank live cell has no content to strike through, so the suggestion takes its place, as
|
|
355
|
+
// in the clean view, rather than leaving a blank line below it.
|
|
356
|
+
var hidesLiveCell = shouldHideDeleted || !isInserted && isBlankCell(liveCell) && fg('platform_editor_ai_show_diff_patch_2_fix');
|
|
303
357
|
decorations.push.apply(decorations, _toConsumableArray(createInlineChangedDecoration({
|
|
304
358
|
attributionKey: attributionKey,
|
|
305
359
|
change: _objectSpread(_objectSpread({}, change), {}, {
|
|
@@ -315,12 +369,12 @@ export var createReplacedCellDecorations = function createReplacedCellDecoration
|
|
|
315
369
|
isInserted: isInserted,
|
|
316
370
|
leftAnchorId: leftAnchorId,
|
|
317
371
|
reveal: reveal,
|
|
318
|
-
shouldHideDeleted:
|
|
372
|
+
shouldHideDeleted: hidesLiveCell,
|
|
319
373
|
showContributorTags: showContributorTags,
|
|
320
374
|
showIndicators: showIndicators,
|
|
321
375
|
tagMountContext: tagMountContext
|
|
322
376
|
})));
|
|
323
|
-
if (
|
|
377
|
+
if (hidesLiveCell) {
|
|
324
378
|
liveCell.forEach(function (block, offset) {
|
|
325
379
|
var blockPos = liveCellPos + 1 + offset;
|
|
326
380
|
decorations.push.apply(decorations, _toConsumableArray(createBlockChangedDecoration({
|
|
@@ -334,7 +388,7 @@ export var createReplacedCellDecorations = function createReplacedCellDecoration
|
|
|
334
388
|
isActive: isActive,
|
|
335
389
|
isInserted: isInserted,
|
|
336
390
|
leftAnchorId: leftAnchorId,
|
|
337
|
-
shouldHideDeleted:
|
|
391
|
+
shouldHideDeleted: hidesLiveCell
|
|
338
392
|
})));
|
|
339
393
|
});
|
|
340
394
|
}
|
|
@@ -29,7 +29,7 @@ export declare const getReplacedCells: ({ slice, doc, fromB, toB, }: {
|
|
|
29
29
|
* shape: each live cell takes the other cell's background when it differs, and its content when that
|
|
30
30
|
* differs. A cell whose content did not change has nothing to diff.
|
|
31
31
|
*/
|
|
32
|
-
export declare const createReplacedCellWidgets: ({ slice, newDoc, change, nodeViewSerializer, colorScheme, intl, isActive, isInserted, leftAnchorId, }: {
|
|
32
|
+
export declare const createReplacedCellWidgets: ({ slice, newDoc, change, nodeViewSerializer, colorScheme, intl, isActive, isInserted, leftAnchorId, showIndicators, }: {
|
|
33
33
|
change: Pick<Change, 'fromB' | 'toB'>;
|
|
34
34
|
colorScheme?: ColorScheme;
|
|
35
35
|
intl: IntlShape;
|
|
@@ -38,6 +38,7 @@ export declare const createReplacedCellWidgets: ({ slice, newDoc, change, nodeVi
|
|
|
38
38
|
leftAnchorId?: string;
|
|
39
39
|
newDoc: PMNode;
|
|
40
40
|
nodeViewSerializer: NodeViewSerializer;
|
|
41
|
+
showIndicators?: boolean;
|
|
41
42
|
slice: Slice;
|
|
42
43
|
}) => Decoration[];
|
|
43
44
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "28.0.0",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"@atlaskit/agent-color": "^1.0.0",
|
|
30
30
|
"@atlaskit/avatar": "^30.0.0",
|
|
31
31
|
"@atlaskit/custom-steps": "^1.1.0",
|
|
32
|
-
"@atlaskit/editor-plugin-accessibility-utils": "^
|
|
33
|
-
"@atlaskit/editor-plugin-analytics": "^
|
|
34
|
-
"@atlaskit/editor-plugin-limited-mode": "^
|
|
35
|
-
"@atlaskit/editor-plugin-user-intent": "^
|
|
32
|
+
"@atlaskit/editor-plugin-accessibility-utils": "^30.0.0",
|
|
33
|
+
"@atlaskit/editor-plugin-analytics": "^30.0.0",
|
|
34
|
+
"@atlaskit/editor-plugin-limited-mode": "^27.0.0",
|
|
35
|
+
"@atlaskit/editor-plugin-user-intent": "^28.0.0",
|
|
36
36
|
"@atlaskit/editor-prosemirror": "^9.0.0",
|
|
37
37
|
"@atlaskit/editor-shared-styles": "^4.6.0",
|
|
38
38
|
"@atlaskit/editor-tables": "^3.2.0",
|
|
@@ -53,25 +53,25 @@
|
|
|
53
53
|
"@atlaskit/button": "^25.6.0",
|
|
54
54
|
"@atlaskit/css": "^1.1.0",
|
|
55
55
|
"@atlaskit/dropdown-menu": "^21.0.0",
|
|
56
|
-
"@atlaskit/editor-core": "^
|
|
56
|
+
"@atlaskit/editor-core": "^241.0.0",
|
|
57
57
|
"@atlaskit/editor-json-transformer": "^10.0.0",
|
|
58
58
|
"@atlaskit/editor-plugins": "^16.2.0",
|
|
59
|
-
"@atlaskit/form": "^18.
|
|
59
|
+
"@atlaskit/form": "^18.3.0",
|
|
60
60
|
"@atlaskit/section-message": "^10.2.0",
|
|
61
61
|
"@atlaskit/textarea": "^10.2.0",
|
|
62
62
|
"@atlaskit/textfield": "^10.2.0",
|
|
63
63
|
"@atlaskit/util-data-test": "^19.1.0",
|
|
64
64
|
"@atlassian/confluence-presets": "workspace:^",
|
|
65
65
|
"@atlassian/content-reconciliation": "^0.1.3506",
|
|
66
|
-
"@atlassian/editor-ai-injected-editors": "^
|
|
67
|
-
"@atlassian/editor-plugin-ai": "^
|
|
66
|
+
"@atlassian/editor-ai-injected-editors": "^45.0.0",
|
|
67
|
+
"@atlassian/editor-plugin-ai": "^84.0.0",
|
|
68
68
|
"@atlassian/structured-docs-types": "workspace:^",
|
|
69
69
|
"react": "^19.2.0",
|
|
70
70
|
"react-dom": "^19.2.0",
|
|
71
71
|
"react-intl": "^7.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@atlaskit/editor-common": "^
|
|
74
|
+
"@atlaskit/editor-common": "^134.0.0",
|
|
75
75
|
"react": "^18.2.0 || ^19.2.0",
|
|
76
76
|
"react-dom": "^18.2.0 || ^19.2.0",
|
|
77
77
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
@@ -93,6 +93,9 @@
|
|
|
93
93
|
"platform_editor_ai_show_diff_patch_2": {
|
|
94
94
|
"type": "boolean"
|
|
95
95
|
},
|
|
96
|
+
"platform_editor_ai_show_diff_patch_2_fix": {
|
|
97
|
+
"type": "boolean"
|
|
98
|
+
},
|
|
96
99
|
"platform_editor_ai_smart_diff": {
|
|
97
100
|
"type": "boolean"
|
|
98
101
|
},
|