@atlaskit/editor-plugin-show-diff 26.0.0 → 26.0.2
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 +20 -0
- package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +36 -3
- package/dist/cjs/pm-plugins/calculateDiff/diffBySteps.js +14 -2
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -0
- package/dist/cjs/pm-plugins/decorations/createReplacedCellDecorations.js +350 -0
- package/dist/cjs/pm-plugins/decorations/utils/cellAttrs.js +30 -0
- package/dist/cjs/pm-plugins/scrollToDiff.js +41 -32
- package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +37 -4
- package/dist/es2019/pm-plugins/calculateDiff/diffBySteps.js +12 -2
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -0
- package/dist/es2019/pm-plugins/decorations/createReplacedCellDecorations.js +338 -0
- package/dist/es2019/pm-plugins/decorations/utils/cellAttrs.js +19 -0
- package/dist/es2019/pm-plugins/scrollToDiff.js +39 -30
- package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +36 -3
- package/dist/esm/pm-plugins/calculateDiff/diffBySteps.js +14 -2
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +14 -0
- package/dist/esm/pm-plugins/decorations/createReplacedCellDecorations.js +343 -0
- package/dist/esm/pm-plugins/decorations/utils/cellAttrs.js +25 -0
- package/dist/esm/pm-plugins/scrollToDiff.js +41 -32
- package/dist/types/pm-plugins/decorations/createReplacedCellDecorations.d.ts +67 -0
- package/dist/types/pm-plugins/decorations/utils/cellAttrs.d.ts +13 -0
- package/dist/types/pm-plugins/markViews.d.ts +1 -1
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 26.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`fa1e60dbfa6e5`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fa1e60dbfa6e5) -
|
|
8
|
+
Keep rendered diffs visible when navigating inside horizontally overflowing tables, behind
|
|
9
|
+
`platform_editor_ai_suggestion_table_scroll_fix`.
|
|
10
|
+
- Updated dependencies
|
|
11
|
+
|
|
12
|
+
## 26.0.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- [`00d7be6e38362`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/00d7be6e38362) -
|
|
17
|
+
Render a whole-cell table replacement inside the live cell behind
|
|
18
|
+
`platform_editor_ai_show_diff_patch_2`, showing the new cell background when it changed, and hide
|
|
19
|
+
only the cell's content rather than the cell when deleted diffs are hidden, so the table keeps its
|
|
20
|
+
shape. Neither the diff nor the suggestion hover highlight overrides a cell's own background any
|
|
21
|
+
more, so removing them leaves it in place.
|
|
22
|
+
|
|
3
23
|
## 26.0.0
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -24,6 +24,7 @@ var _createAnchorDecorationWidgets = require("../decorations/createAnchorDecorat
|
|
|
24
24
|
var _createBlockChangedDecoration = require("../decorations/createBlockChangedDecoration");
|
|
25
25
|
var _createInlineChangedDecoration = require("../decorations/createInlineChangedDecoration");
|
|
26
26
|
var _createNodeChangedDecorationWidget = require("../decorations/createNodeChangedDecorationWidget");
|
|
27
|
+
var _createReplacedCellDecorations = require("../decorations/createReplacedCellDecorations");
|
|
27
28
|
var _decorationKeys = require("../decorations/decorationKeys");
|
|
28
29
|
var _extractContributorTags = require("../decorations/extractContributorTags");
|
|
29
30
|
var _createDeletedLineBreakWidget = require("../decorations/utils/createDeletedLineBreakWidget");
|
|
@@ -603,7 +604,11 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
603
604
|
// suppressed in the clean view. `hideDeletedDiffs` is load-bearing: when false the reviewer
|
|
604
605
|
// asked to compare against the original, and the deleted side is the only place the
|
|
605
606
|
// previous formatting is visible.
|
|
606
|
-
|
|
607
|
+
//
|
|
608
|
+
// Not on an inverted diff: there the widget's side is the suggested content, which the clean
|
|
609
|
+
// view keeps. Suppressing it hides the suggestion along with the displayed side it replaces,
|
|
610
|
+
// e.g. a cell whose only change is its background, as the signature ignores attrs.
|
|
611
|
+
var isMarkOnly = shouldHideMarkOnlyDeletions && hideDeletedDiffs && !(isInverted && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2')) && change.deleted.length > 0 && (0, _isMarkOnlyChange.isMarkOnlyChange)({
|
|
607
612
|
change: change,
|
|
608
613
|
originalDoc: originalDoc,
|
|
609
614
|
newDoc: tr.doc
|
|
@@ -689,7 +694,35 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
689
694
|
hideDeletedDiffs: hideDeletedDiffs,
|
|
690
695
|
isInverted: isInverted
|
|
691
696
|
});
|
|
692
|
-
|
|
697
|
+
|
|
698
|
+
// A whole-cell replacement keeps its cells in place, so it takes its own decorations
|
|
699
|
+
// instead of the generic inline and block ones.
|
|
700
|
+
var replacedCells = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? (0, _createReplacedCellDecorations.getReplacedCells)({
|
|
701
|
+
slice: originalDoc.slice(change.fromA, change.toA),
|
|
702
|
+
doc: tr.doc,
|
|
703
|
+
fromB: change.fromB,
|
|
704
|
+
toB: change.toB
|
|
705
|
+
}) : [];
|
|
706
|
+
if (replacedCells.length > 0) {
|
|
707
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createReplacedCellDecorations.createReplacedCellDecorations)({
|
|
708
|
+
replacedCells: replacedCells,
|
|
709
|
+
change: change,
|
|
710
|
+
doc: tr.doc,
|
|
711
|
+
attributionKey: attributionKey,
|
|
712
|
+
colorScheme: changeColorScheme,
|
|
713
|
+
hasDeletedWidget: willRenderDeletedWidget,
|
|
714
|
+
hideAddedDiffsUnderline: hideAddedDiffsUnderline,
|
|
715
|
+
isActive: isActive,
|
|
716
|
+
isDeletedWidgetBelow: isDeletedWidgetBelow,
|
|
717
|
+
isInserted: isInserted,
|
|
718
|
+
leftAnchorId: leftAnchorId,
|
|
719
|
+
reveal: reveal,
|
|
720
|
+
shouldHideDeleted: shouldHideDeleted,
|
|
721
|
+
showContributorTags: showContributorTags,
|
|
722
|
+
showIndicators: showIndicators,
|
|
723
|
+
tagMountContext: tagMountContext
|
|
724
|
+
})));
|
|
725
|
+
} else if (isSmartNodeLevel) {
|
|
693
726
|
// For a large inserted table, skip the O(cells) inline decorations inside the
|
|
694
727
|
// table (the cell overlays added below provide the highlight without the
|
|
695
728
|
// expensive content re-render); leaf blocks outside the table still get theirs.
|
|
@@ -749,7 +782,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
|
|
|
749
782
|
tagMountContext: tagMountContext
|
|
750
783
|
})));
|
|
751
784
|
}
|
|
752
|
-
decorations.push.apply(decorations, (0, _toConsumableArray2.default)(calculateNodesForBlockDecoration({
|
|
785
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)(replacedCells.length > 0 ? [] : calculateNodesForBlockDecoration({
|
|
753
786
|
// A deleted widget placed below anchors at the change's end, inside the very block
|
|
754
787
|
// this would let the decoration claim.
|
|
755
788
|
allowTrailingCloseTokens: !isDeletedWidgetBelow,
|
|
@@ -13,6 +13,7 @@ var _model = require("@atlaskit/editor-prosemirror/model");
|
|
|
13
13
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
14
14
|
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
15
15
|
var _attributions = require("../decorations/colorSchemes/attributions");
|
|
16
|
+
var _cellAttrs = require("../decorations/utils/cellAttrs");
|
|
16
17
|
var _charsByOffset = require("../utils/charsByOffset");
|
|
17
18
|
var _attrAwareTokenEncoder = require("./attrAwareTokenEncoder");
|
|
18
19
|
var _optimizeChanges = require("./optimizeChanges");
|
|
@@ -34,6 +35,16 @@ var WHITESPACE_REGEX = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u
|
|
|
34
35
|
var isGranularIsolatingNode = function isGranularIsolatingNode(node) {
|
|
35
36
|
return !!node.type.spec.isolating && node.type.spec.tableRole !== 'table';
|
|
36
37
|
};
|
|
38
|
+
var CELL_TYPE_NAMES = ['tableCell', 'tableHeader'];
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Whether a table cell's replacement changes one of its diffable attributes, such as its background.
|
|
42
|
+
* Such a cell is diffed whole: it renders as a cell style plus a copy of its row, which already shows
|
|
43
|
+
* the cell's new content, so inline marks inside it would only repeat that.
|
|
44
|
+
*/
|
|
45
|
+
var isCellAttrChange = function isCellAttrChange(replacedNode, replacingNode) {
|
|
46
|
+
return CELL_TYPE_NAMES.includes(replacedNode.type.name) && (0, _cellAttrs.isCellAttrChanged)(replacedNode, replacingNode);
|
|
47
|
+
};
|
|
37
48
|
var mapPosition = function mapPosition(mapping, pos) {
|
|
38
49
|
return mapping.map(pos);
|
|
39
50
|
};
|
|
@@ -237,7 +248,8 @@ var mergeOverlappingByNewDocRange = function mergeOverlappingByNewDocRange(chang
|
|
|
237
248
|
* - The replaced slice has only one child
|
|
238
249
|
* - The replacing slice has only one child
|
|
239
250
|
* - Both children are the same textblock type, or (behind `platform_editor_ai_show_diff_patch_2`)
|
|
240
|
-
* the same isolating, non-table node type whose text content differs
|
|
251
|
+
* the same isolating, non-table node type whose text content differs (for a table cell, only when
|
|
252
|
+
* its diffable attributes are unchanged)
|
|
241
253
|
* - The replaced slice and replacing slice have the same text content
|
|
242
254
|
* - The replaced slice and replacing slice have the same child marks (if text content is equal)
|
|
243
255
|
*/
|
|
@@ -275,7 +287,7 @@ var shouldCheckGranularDiff = function shouldCheckGranularDiff(step, before, fro
|
|
|
275
287
|
// `hasSameChildMarks` only compares an isolating node's direct (block) children, so it cannot
|
|
276
288
|
// vouch for one with unchanged text. Keep the existing whole-node fallback for that case.
|
|
277
289
|
if (isIsolatingNode) {
|
|
278
|
-
return !isTextContentEqual;
|
|
290
|
+
return !isTextContentEqual && !(replacingNode && isCellAttrChange(replacedNode, replacingNode));
|
|
279
291
|
}
|
|
280
292
|
return !isTextContentEqual || isTextContentEqual && hasSameChildMarks(replacedNode, replacingNode);
|
|
281
293
|
};
|
|
@@ -18,6 +18,7 @@ var _createAnchorDecorationWidgets = require("./createAnchorDecorationWidgets");
|
|
|
18
18
|
var _createChangedRowDecorationWidgets = require("./createChangedRowDecorationWidgets");
|
|
19
19
|
var _createContributorTagWidget = require("./createContributorTagWidget");
|
|
20
20
|
var _createInlineChangedDecoration = require("./createInlineChangedDecoration");
|
|
21
|
+
var _createReplacedCellDecorations = require("./createReplacedCellDecorations");
|
|
21
22
|
var _decorationKeys = require("./decorationKeys");
|
|
22
23
|
var _absorbFirstChildMarginReset = require("./utils/absorbFirstChildMarginReset");
|
|
23
24
|
var _createDeletedLineBreakWidget = require("./utils/createDeletedLineBreakWidget");
|
|
@@ -222,6 +223,19 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
222
223
|
isInserted: isInserted
|
|
223
224
|
});
|
|
224
225
|
if (tableDiffMode.kind === 'cells') {
|
|
226
|
+
if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_2')) {
|
|
227
|
+
return (0, _createReplacedCellDecorations.createReplacedCellWidgets)({
|
|
228
|
+
slice: slice,
|
|
229
|
+
newDoc: newDoc,
|
|
230
|
+
change: change,
|
|
231
|
+
nodeViewSerializer: nodeViewSerializer,
|
|
232
|
+
colorScheme: colorScheme,
|
|
233
|
+
intl: intl,
|
|
234
|
+
isActive: isActive,
|
|
235
|
+
isInserted: isInserted,
|
|
236
|
+
leftAnchorId: leftAnchorId
|
|
237
|
+
});
|
|
238
|
+
}
|
|
225
239
|
return createTableCellContentWidgets({
|
|
226
240
|
slice: slice,
|
|
227
241
|
newDoc: newDoc,
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.getReplacedCells = exports.createReplacedCellWidgets = exports.createReplacedCellDecorations = void 0;
|
|
8
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
10
|
+
var _getDarkModeLchColor = require("@atlaskit/adf-schema/get-dark-mode-lch-color");
|
|
11
|
+
var _isRgb = require("@atlaskit/adf-schema/is-rgb");
|
|
12
|
+
var _rgbToHex = require("@atlaskit/adf-schema/rgb-to-hex");
|
|
13
|
+
var _tableNodes = require("@atlaskit/adf-schema/tableNodes");
|
|
14
|
+
var _cssHelper = require("@atlaskit/editor-common/css-helper");
|
|
15
|
+
var _document = require("@atlaskit/editor-common/utils/document");
|
|
16
|
+
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
17
|
+
var _createBlockChangedDecoration = require("./createBlockChangedDecoration");
|
|
18
|
+
var _createInlineChangedDecoration = require("./createInlineChangedDecoration");
|
|
19
|
+
var _decorationKeys = require("./decorationKeys");
|
|
20
|
+
var _cellAttrs = require("./utils/cellAttrs");
|
|
21
|
+
var _wrapBlockNodeView = require("./utils/wrapBlockNodeView");
|
|
22
|
+
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
|
+
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
|
+
var CELL_TYPE_NAMES = ['tableCell', 'tableHeader'];
|
|
25
|
+
/**
|
|
26
|
+
* Pairs each cell of a whole-cell replacement with the live cell it replaces, or `[]` when the slice
|
|
27
|
+
* is not a run of whole cells matching the live ones. Whole-cell replacement preserves cell count and
|
|
28
|
+
* order, so the nth live cell in the range matches the nth cell in the slice.
|
|
29
|
+
*/
|
|
30
|
+
var getReplacedCells = exports.getReplacedCells = function getReplacedCells(_ref) {
|
|
31
|
+
var slice = _ref.slice,
|
|
32
|
+
doc = _ref.doc,
|
|
33
|
+
fromB = _ref.fromB,
|
|
34
|
+
toB = _ref.toB;
|
|
35
|
+
var otherCells = slice.content.content;
|
|
36
|
+
if (slice.openStart !== 0 || slice.openEnd !== 0 || otherCells.length === 0 || !otherCells.every(function (node) {
|
|
37
|
+
return CELL_TYPE_NAMES.includes(node.type.name);
|
|
38
|
+
})) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
var liveCells = [];
|
|
42
|
+
doc.nodesBetween(fromB, toB, function (node, pos) {
|
|
43
|
+
if (CELL_TYPE_NAMES.includes(node.type.name)) {
|
|
44
|
+
liveCells.push({
|
|
45
|
+
node: node,
|
|
46
|
+
pos: pos
|
|
47
|
+
});
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
return true;
|
|
51
|
+
});
|
|
52
|
+
if (liveCells.length !== otherCells.length) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
return otherCells.map(function (otherCell, index) {
|
|
56
|
+
return {
|
|
57
|
+
otherCell: otherCell,
|
|
58
|
+
liveCell: liveCells[index].node,
|
|
59
|
+
liveCellPos: liveCells[index].pos
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether two cells hold the same content, ignoring the cells' own attributes and `localId`s, which
|
|
66
|
+
* a suggestion can regenerate. Such a replacement only changed the cell (e.g. its background), so
|
|
67
|
+
* there is no content to diff.
|
|
68
|
+
*/
|
|
69
|
+
var isCellContentEqual = function isCellContentEqual(left, right) {
|
|
70
|
+
if (left.childCount !== right.childCount) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
for (var index = 0; index < left.childCount; index++) {
|
|
74
|
+
if (!(0, _document.areNodesEqualIgnoreAttrs)(left.child(index), right.child(index), ['localId'])) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return true;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Whether the cell itself changed — its type, or an attribute that represents a change such as its
|
|
83
|
+
* background or span — as opposed to only its content.
|
|
84
|
+
*/
|
|
85
|
+
var isCellChanged = function isCellChanged(left, right) {
|
|
86
|
+
return left.type !== right.type || (0, _cellAttrs.isCellAttrChanged)(left, right);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A custom (non-palette) cell colour as the schema renders it: inverted in dark mode so text stays
|
|
91
|
+
* readable, except for design tokens, which are already themed.
|
|
92
|
+
*/
|
|
93
|
+
var getCustomCellColor = function getCustomCellColor(background) {
|
|
94
|
+
var color = (0, _isRgb.isRgb)(background) && (0, _rgbToHex.rgbToHex)(background) || background;
|
|
95
|
+
if (color.startsWith('var(') || document.documentElement.getAttribute('data-color-mode') !== 'dark') {
|
|
96
|
+
return background;
|
|
97
|
+
}
|
|
98
|
+
return (0, _getDarkModeLchColor.getDarkModeLCHColor)(color);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The colour `cell` renders with. A palette colour is the editor's own themed variable for its colour
|
|
103
|
+
* name (e.g. for dark mode), the one `td[colorname]` cells use; a custom colour is the schema's own
|
|
104
|
+
* treatment of it; no colour is the editor's default.
|
|
105
|
+
*/
|
|
106
|
+
var getCellBackgroundColor = function getCellBackgroundColor(cell) {
|
|
107
|
+
var background = (0, _cellAttrs.normalizeCellBackground)(cell.attrs.background);
|
|
108
|
+
if (!background) {
|
|
109
|
+
return cell.type.name === 'tableHeader' ? "var(--ds-background-accent-gray-subtlest, #F0F1F2)" : "var(--ds-surface, #FFFFFF)";
|
|
110
|
+
}
|
|
111
|
+
var _getCellDomAttrs = (0, _tableNodes.getCellDomAttrs)(cell),
|
|
112
|
+
colorname = _getCellDomAttrs.colorname;
|
|
113
|
+
return colorname ? "var(--ak-editor-table-cell-background-".concat(colorname.toLowerCase().split(' ').join('-'), ")") : getCustomCellColor(background);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* A layer painting `color` over the cell's own background and under its content, so the cell reads
|
|
118
|
+
* as having the new background without any of the cell's own attributes being overridden: removing
|
|
119
|
+
* a decoration removes the attributes it set rather than restoring the ones they replaced.
|
|
120
|
+
*/
|
|
121
|
+
var createCellBackgroundLayer = function createCellBackgroundLayer(color) {
|
|
122
|
+
var layer = document.createElement('div');
|
|
123
|
+
layer.setAttribute('aria-hidden', 'true');
|
|
124
|
+
layer.contentEditable = 'false';
|
|
125
|
+
layer.dataset.testid = 'show-diff-new-cell-background';
|
|
126
|
+
layer.setAttribute('style', (0, _cssHelper.convertToInlineCss)({
|
|
127
|
+
position: 'absolute',
|
|
128
|
+
inset: 0,
|
|
129
|
+
zIndex: -1,
|
|
130
|
+
borderRadius: 'inherit',
|
|
131
|
+
pointerEvents: 'none',
|
|
132
|
+
backgroundColor: color
|
|
133
|
+
}));
|
|
134
|
+
return layer;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/** The other side's cell content, as blocks, for the top of the live cell. */
|
|
138
|
+
var createCellContentWidget = function createCellContentWidget(_ref2) {
|
|
139
|
+
var cell = _ref2.cell,
|
|
140
|
+
pos = _ref2.pos,
|
|
141
|
+
nodeViewSerializer = _ref2.nodeViewSerializer,
|
|
142
|
+
colorScheme = _ref2.colorScheme,
|
|
143
|
+
intl = _ref2.intl,
|
|
144
|
+
isActive = _ref2.isActive,
|
|
145
|
+
isInserted = _ref2.isInserted,
|
|
146
|
+
leftAnchorId = _ref2.leftAnchorId;
|
|
147
|
+
var dom = document.createElement('div');
|
|
148
|
+
cell.content.forEach(function (block) {
|
|
149
|
+
var nodeView = nodeViewSerializer.tryCreateNodeView(block, 0, undefined, isInserted, colorScheme);
|
|
150
|
+
if (nodeView) {
|
|
151
|
+
(0, _wrapBlockNodeView.wrapBlockNodeView)({
|
|
152
|
+
dom: dom,
|
|
153
|
+
nodeView: nodeView,
|
|
154
|
+
targetNode: block,
|
|
155
|
+
colorScheme: colorScheme,
|
|
156
|
+
intl: intl,
|
|
157
|
+
isActive: isActive,
|
|
158
|
+
isInserted: isInserted
|
|
159
|
+
});
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
var serialized = nodeViewSerializer.serializeNode(block);
|
|
163
|
+
if (serialized instanceof HTMLElement) {
|
|
164
|
+
dom.append((0, _wrapBlockNodeView.injectInnerWrapper)({
|
|
165
|
+
node: serialized,
|
|
166
|
+
colorScheme: colorScheme,
|
|
167
|
+
isActive: isActive,
|
|
168
|
+
isInserted: isInserted
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
if (dom.childNodes.length === 0) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
dom.setAttribute('data-testid', isInserted ? 'show-diff-changed-decoration' : 'show-diff-deleted-decoration');
|
|
176
|
+
|
|
177
|
+
// Before the cell's own blocks, as a block of its own, so it never lands inside a paragraph the
|
|
178
|
+
// displayed side may hide.
|
|
179
|
+
return _view.Decoration.widget(pos + 1, dom, _objectSpread(_objectSpread({}, (0, _decorationKeys.buildDiffDecorationSpec)({
|
|
180
|
+
colorScheme: colorScheme,
|
|
181
|
+
decorationType: 'widget',
|
|
182
|
+
diffId: crypto.randomUUID(),
|
|
183
|
+
leftAnchorId: leftAnchorId,
|
|
184
|
+
isActive: isActive,
|
|
185
|
+
isInserted: isInserted,
|
|
186
|
+
side: -1
|
|
187
|
+
})), {}, {
|
|
188
|
+
marks: []
|
|
189
|
+
}));
|
|
190
|
+
};
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* The other side of a whole-cell replacement, drawn inside the live cells so the table keeps its
|
|
194
|
+
* shape: each live cell takes the other cell's background when it differs, and its content when that
|
|
195
|
+
* differs. A cell whose content did not change has nothing to diff.
|
|
196
|
+
*/
|
|
197
|
+
var createReplacedCellWidgets = exports.createReplacedCellWidgets = function createReplacedCellWidgets(_ref3) {
|
|
198
|
+
var slice = _ref3.slice,
|
|
199
|
+
newDoc = _ref3.newDoc,
|
|
200
|
+
change = _ref3.change,
|
|
201
|
+
nodeViewSerializer = _ref3.nodeViewSerializer,
|
|
202
|
+
colorScheme = _ref3.colorScheme,
|
|
203
|
+
intl = _ref3.intl,
|
|
204
|
+
isActive = _ref3.isActive,
|
|
205
|
+
isInserted = _ref3.isInserted,
|
|
206
|
+
leftAnchorId = _ref3.leftAnchorId;
|
|
207
|
+
return getReplacedCells({
|
|
208
|
+
slice: slice,
|
|
209
|
+
doc: newDoc,
|
|
210
|
+
fromB: change.fromB,
|
|
211
|
+
toB: change.toB
|
|
212
|
+
}).flatMap(function (_ref4) {
|
|
213
|
+
var otherCell = _ref4.otherCell,
|
|
214
|
+
liveCell = _ref4.liveCell,
|
|
215
|
+
liveCellPos = _ref4.liveCellPos;
|
|
216
|
+
var decorations = [];
|
|
217
|
+
if (isInserted && (0, _cellAttrs.isCellBackgroundChanged)(otherCell, liveCell)) {
|
|
218
|
+
var cellEnd = liveCellPos + liveCell.nodeSize;
|
|
219
|
+
decorations.push(
|
|
220
|
+
// The cell becomes the layer's stacking context, so the layer sits above the cell's own
|
|
221
|
+
// background rather than behind it. Through `z-index` at the cell overlay's own level, not
|
|
222
|
+
// `isolation`: an isolated cell would trap its overlay below later cells, which then cover
|
|
223
|
+
// the overlay's outline where it overlaps their border. Properties the cell never sets, so
|
|
224
|
+
// removing them takes nothing of its own.
|
|
225
|
+
_view.Decoration.node(liveCellPos, cellEnd, {
|
|
226
|
+
style: (0, _cssHelper.convertToInlineCss)({
|
|
227
|
+
position: 'relative',
|
|
228
|
+
// The highest z-index a cell diff overlay takes (the rounded-corner variant).
|
|
229
|
+
zIndex: 2
|
|
230
|
+
})
|
|
231
|
+
}, {
|
|
232
|
+
key: "show-diff-new-cell-background-host-".concat(liveCellPos)
|
|
233
|
+
}),
|
|
234
|
+
// At the cell's end, beside its diff overlay, so the cell's first block stays its first child.
|
|
235
|
+
_view.Decoration.widget(cellEnd - 1, createCellBackgroundLayer(getCellBackgroundColor(otherCell)), {
|
|
236
|
+
key: "show-diff-new-cell-background-".concat(liveCellPos),
|
|
237
|
+
side: -1,
|
|
238
|
+
marks: [],
|
|
239
|
+
ignoreSelection: true
|
|
240
|
+
}));
|
|
241
|
+
}
|
|
242
|
+
if (!isCellContentEqual(otherCell, liveCell)) {
|
|
243
|
+
var contentWidget = createCellContentWidget({
|
|
244
|
+
cell: otherCell,
|
|
245
|
+
pos: liveCellPos,
|
|
246
|
+
nodeViewSerializer: nodeViewSerializer,
|
|
247
|
+
colorScheme: colorScheme,
|
|
248
|
+
intl: intl,
|
|
249
|
+
isActive: isActive,
|
|
250
|
+
isInserted: isInserted,
|
|
251
|
+
leftAnchorId: leftAnchorId
|
|
252
|
+
});
|
|
253
|
+
if (contentWidget) {
|
|
254
|
+
decorations.push(contentWidget);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return decorations;
|
|
258
|
+
});
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* The displayed side of a whole-cell replacement. A table cell is never removed on its own, only
|
|
263
|
+
* replaced in place, so a live cell is never hidden — hiding it would leave the row a cell short. It
|
|
264
|
+
* takes the changed-cell treatment only when the cell itself changed; its content is diffed, and
|
|
265
|
+
* hidden in the clean view, only when that changed. A cell whose content stayed the same keeps
|
|
266
|
+
* showing it.
|
|
267
|
+
*/
|
|
268
|
+
var createReplacedCellDecorations = exports.createReplacedCellDecorations = function createReplacedCellDecorations(_ref5) {
|
|
269
|
+
var replacedCells = _ref5.replacedCells,
|
|
270
|
+
change = _ref5.change,
|
|
271
|
+
doc = _ref5.doc,
|
|
272
|
+
attributionKey = _ref5.attributionKey,
|
|
273
|
+
colorScheme = _ref5.colorScheme,
|
|
274
|
+
hasDeletedWidget = _ref5.hasDeletedWidget,
|
|
275
|
+
hideAddedDiffsUnderline = _ref5.hideAddedDiffsUnderline,
|
|
276
|
+
isActive = _ref5.isActive,
|
|
277
|
+
isDeletedWidgetBelow = _ref5.isDeletedWidgetBelow,
|
|
278
|
+
isInserted = _ref5.isInserted,
|
|
279
|
+
leftAnchorId = _ref5.leftAnchorId,
|
|
280
|
+
reveal = _ref5.reveal,
|
|
281
|
+
shouldHideDeleted = _ref5.shouldHideDeleted,
|
|
282
|
+
showContributorTags = _ref5.showContributorTags,
|
|
283
|
+
showIndicators = _ref5.showIndicators,
|
|
284
|
+
tagMountContext = _ref5.tagMountContext;
|
|
285
|
+
return replacedCells.flatMap(function (_ref6) {
|
|
286
|
+
var otherCell = _ref6.otherCell,
|
|
287
|
+
liveCell = _ref6.liveCell,
|
|
288
|
+
liveCellPos = _ref6.liveCellPos;
|
|
289
|
+
var cellEnd = liveCellPos + liveCell.nodeSize;
|
|
290
|
+
var decorations = isCellChanged(otherCell, liveCell) ? (0, _createBlockChangedDecoration.createBlockChangedDecoration)({
|
|
291
|
+
attributionKey: attributionKey,
|
|
292
|
+
change: {
|
|
293
|
+
from: liveCellPos,
|
|
294
|
+
to: cellEnd,
|
|
295
|
+
name: liveCell.type.name
|
|
296
|
+
},
|
|
297
|
+
colorScheme: colorScheme,
|
|
298
|
+
doc: doc,
|
|
299
|
+
isActive: isActive,
|
|
300
|
+
// The cell stays either way, so it reads as changed, not removed.
|
|
301
|
+
isInserted: true,
|
|
302
|
+
leftAnchorId: leftAnchorId,
|
|
303
|
+
showContributorTags: showContributorTags,
|
|
304
|
+
showIndicators: showIndicators,
|
|
305
|
+
tagMountContext: tagMountContext
|
|
306
|
+
}) : [];
|
|
307
|
+
if (isCellContentEqual(otherCell, liveCell)) {
|
|
308
|
+
return decorations;
|
|
309
|
+
}
|
|
310
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createInlineChangedDecoration.createInlineChangedDecoration)({
|
|
311
|
+
attributionKey: attributionKey,
|
|
312
|
+
change: _objectSpread(_objectSpread({}, change), {}, {
|
|
313
|
+
fromB: liveCellPos,
|
|
314
|
+
toB: cellEnd
|
|
315
|
+
}),
|
|
316
|
+
colorScheme: colorScheme,
|
|
317
|
+
doc: doc,
|
|
318
|
+
hasDeletedWidget: hasDeletedWidget,
|
|
319
|
+
hideAddedDiffsUnderline: hideAddedDiffsUnderline,
|
|
320
|
+
isActive: isActive,
|
|
321
|
+
isDeletedWidgetBelow: isDeletedWidgetBelow,
|
|
322
|
+
isInserted: isInserted,
|
|
323
|
+
leftAnchorId: leftAnchorId,
|
|
324
|
+
reveal: reveal,
|
|
325
|
+
shouldHideDeleted: shouldHideDeleted,
|
|
326
|
+
showContributorTags: showContributorTags,
|
|
327
|
+
showIndicators: showIndicators,
|
|
328
|
+
tagMountContext: tagMountContext
|
|
329
|
+
})));
|
|
330
|
+
if (shouldHideDeleted) {
|
|
331
|
+
liveCell.forEach(function (block, offset) {
|
|
332
|
+
var blockPos = liveCellPos + 1 + offset;
|
|
333
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createBlockChangedDecoration.createBlockChangedDecoration)({
|
|
334
|
+
change: {
|
|
335
|
+
from: blockPos,
|
|
336
|
+
to: blockPos + block.nodeSize,
|
|
337
|
+
name: block.type.name
|
|
338
|
+
},
|
|
339
|
+
colorScheme: colorScheme,
|
|
340
|
+
doc: doc,
|
|
341
|
+
isActive: isActive,
|
|
342
|
+
isInserted: isInserted,
|
|
343
|
+
leftAnchorId: leftAnchorId,
|
|
344
|
+
shouldHideDeleted: shouldHideDeleted
|
|
345
|
+
})));
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
return decorations;
|
|
349
|
+
});
|
|
350
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.normalizeCellBackground = exports.isCellBackgroundChanged = exports.isCellAttrChanged = void 0;
|
|
7
|
+
var _diffableAttrs = require("./diffableAttrs");
|
|
8
|
+
/**
|
|
9
|
+
* A cell background as it renders: absent, empty and `"null"` — the string agent payloads send for
|
|
10
|
+
* no background — all mean the cell has none.
|
|
11
|
+
*/
|
|
12
|
+
var normalizeCellBackground = exports.normalizeCellBackground = function normalizeCellBackground(background) {
|
|
13
|
+
return typeof background === 'string' && background !== '' && background !== 'null' ? background : null;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/** Whether two cells render different backgrounds. */
|
|
17
|
+
var isCellBackgroundChanged = exports.isCellBackgroundChanged = function isCellBackgroundChanged(left, right) {
|
|
18
|
+
return normalizeCellBackground(left.attrs.background) !== normalizeCellBackground(right.attrs.background);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Whether two cells differ by an attribute that represents a change, such as their background or
|
|
23
|
+
* span, as opposed to only their content.
|
|
24
|
+
*/
|
|
25
|
+
var isCellAttrChanged = exports.isCellAttrChanged = function isCellAttrChanged(left, right) {
|
|
26
|
+
var _getDiffableAttrNames;
|
|
27
|
+
return ((_getDiffableAttrNames = (0, _diffableAttrs.getDiffableAttrNames)(left.type.name, left.attrs)) !== null && _getDiffableAttrNames !== void 0 ? _getDiffableAttrNames : []).some(function (name) {
|
|
28
|
+
return name === 'background' ? isCellBackgroundChanged(left, right) : left.attrs[name] !== right.attrs[name];
|
|
29
|
+
});
|
|
30
|
+
};
|
|
@@ -8,6 +8,7 @@ var _table = require("@atlaskit/editor-common/styles/table");
|
|
|
8
8
|
var _getStickyHeaderHeight = require("@atlaskit/editor-common/table/get-sticky-header-height");
|
|
9
9
|
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
10
10
|
var _decorationKeys = require("./decorations/decorationKeys");
|
|
11
|
+
var _getWidgetElement = require("./decorations/utils/getWidgetElement");
|
|
11
12
|
/**
|
|
12
13
|
* Extra space above the scrolled-to element so it does not sit flush under the
|
|
13
14
|
* viewport edge (helps with sticky table headers, toolbars, etc.).
|
|
@@ -24,21 +25,21 @@ function updateScrollTargetMargin(view, targetPos, api) {
|
|
|
24
25
|
var tableHeaderHeight = isLimitedModeEnabled ? undefined : (0, _getStickyHeaderHeight.getStickyHeaderHeight)(view, targetPos);
|
|
25
26
|
view.dom.style.setProperty(_decorationKeys.SCROLL_TARGET_MARGIN_CSS_PROPERTY, "".concat(tableHeaderHeight ? tableHeaderHeight + _table.tableMarginTop : 0, "px"));
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Returns the resolved HTMLElement for a given DOM node, walking up to the
|
|
30
|
-
* parent element if the node itself is not an Element (e.g. a text node).
|
|
31
|
-
*/
|
|
32
28
|
function scrollToSelection(node) {
|
|
33
|
-
|
|
29
|
+
// ProseMirror may return a text node; scroll its parent element instead.
|
|
30
|
+
var element = node instanceof Element ? node : node === null || node === void 0 ? void 0 : node.parentElement;
|
|
34
31
|
if (!(element instanceof HTMLElement)) {
|
|
35
32
|
return;
|
|
36
33
|
}
|
|
34
|
+
var scrollOptions = {
|
|
35
|
+
behavior: 'smooth',
|
|
36
|
+
block: 'start'
|
|
37
|
+
};
|
|
38
|
+
if ((0, _fg.fg)('platform_editor_ai_suggestion_table_scroll_fix')) {
|
|
39
|
+
scrollOptions.inline = 'center';
|
|
40
|
+
}
|
|
37
41
|
if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_1')) {
|
|
38
|
-
element.scrollIntoView(
|
|
39
|
-
behavior: 'smooth',
|
|
40
|
-
block: 'start'
|
|
41
|
-
});
|
|
42
|
+
element.scrollIntoView(scrollOptions);
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -46,14 +47,25 @@ function scrollToSelection(node) {
|
|
|
46
47
|
var previousScrollMarginTop = element.style.scrollMarginTop;
|
|
47
48
|
element.style.scrollMarginTop = "".concat(SCROLL_TOP_MARGIN_PX, "px");
|
|
48
49
|
try {
|
|
49
|
-
element.scrollIntoView(
|
|
50
|
-
behavior: 'smooth',
|
|
51
|
-
block: 'start'
|
|
52
|
-
});
|
|
50
|
+
element.scrollIntoView(scrollOptions);
|
|
53
51
|
} finally {
|
|
54
52
|
element.style.scrollMarginTop = previousScrollMarginTop;
|
|
55
53
|
}
|
|
56
54
|
}
|
|
55
|
+
function resolveScrollTarget(view, target) {
|
|
56
|
+
var _view$domAtPos;
|
|
57
|
+
if ((0, _decorationKeys.isDiffDecoration)(target) && target.spec.decorationType === 'widget') {
|
|
58
|
+
return (0, _getWidgetElement.getWidgetElement)(target);
|
|
59
|
+
}
|
|
60
|
+
if ((0, _decorationKeys.isDiffDecoration)(target) && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2')) {
|
|
61
|
+
var _Array$from$find;
|
|
62
|
+
return (_Array$from$find = Array.from(view.dom.querySelectorAll('[data-diff-id]')).find(function (element) {
|
|
63
|
+
return element.dataset.diffId === target.spec.diffId;
|
|
64
|
+
})) !== null && _Array$from$find !== void 0 ? _Array$from$find : view.nodeDOM(target.from);
|
|
65
|
+
}
|
|
66
|
+
var targetNode = view.nodeDOM(target.from);
|
|
67
|
+
return targetNode instanceof Element ? targetNode : (_view$domAtPos = view.domAtPos(target.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
68
|
+
}
|
|
57
69
|
|
|
58
70
|
/**
|
|
59
71
|
* Schedules scrolling to the decoration at the given index after the next frame. Defaults to the
|
|
@@ -73,30 +85,27 @@ var scrollToDecoration = exports.scrollToDecoration = function scrollToDecoratio
|
|
|
73
85
|
// deleted-content widget rather than at the group's `from` position — see `scrollTarget` in
|
|
74
86
|
// `getScrollableDecorations`. Only set under `platform_editor_ai_show_diff_patch_1`.
|
|
75
87
|
var target = (0, _decorationKeys.isDiffDecoration)(decoration) && decoration.spec.scrollTarget || decoration;
|
|
76
|
-
var rafId =
|
|
77
|
-
|
|
88
|
+
var rafId = null;
|
|
89
|
+
var cancelled = false;
|
|
90
|
+
var scrollToTarget = function scrollToTarget() {
|
|
91
|
+
if (view.isDestroyed) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
78
94
|
if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_1')) {
|
|
79
95
|
updateScrollTargetMargin(view, target.from, api);
|
|
80
96
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return element.dataset.diffId === target.spec.diffId;
|
|
90
|
-
})) !== null && _Array$from$find !== void 0 ? _Array$from$find : view.nodeDOM(target === null || target === void 0 ? void 0 : target.from);
|
|
91
|
-
scrollToSelection(targetNode);
|
|
92
|
-
} else {
|
|
93
|
-
var _view$domAtPos;
|
|
94
|
-
var _targetNode = view.nodeDOM(target === null || target === void 0 ? void 0 : target.from);
|
|
95
|
-
var node = _targetNode instanceof Element ? _targetNode : (_view$domAtPos = view.domAtPos(target === null || target === void 0 ? void 0 : target.from)) === null || _view$domAtPos === void 0 ? void 0 : _view$domAtPos.node;
|
|
96
|
-
scrollToSelection(node);
|
|
97
|
+
scrollToSelection(resolveScrollTarget(view, target));
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Called from the plugin's post-DOM update hook; defer measurement until layout can settle.
|
|
101
|
+
rafId = requestAnimationFrame(function () {
|
|
102
|
+
rafId = null;
|
|
103
|
+
if (!cancelled) {
|
|
104
|
+
scrollToTarget();
|
|
97
105
|
}
|
|
98
106
|
});
|
|
99
107
|
return function () {
|
|
108
|
+
cancelled = true;
|
|
100
109
|
if (rafId !== null) {
|
|
101
110
|
cancelAnimationFrame(rafId);
|
|
102
111
|
rafId = null;
|