@atlaskit/editor-plugin-show-diff 21.0.2 → 21.0.3
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 +18 -0
- package/dist/cjs/pm-plugins/NodeViewSerializer.js +33 -4
- package/dist/cjs/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -1
- package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -3
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +4 -0
- package/dist/cjs/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -0
- package/dist/es2019/pm-plugins/NodeViewSerializer.js +31 -7
- package/dist/es2019/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -1
- package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -3
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +4 -0
- package/dist/es2019/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -0
- package/dist/esm/pm-plugins/NodeViewSerializer.js +33 -4
- package/dist/esm/pm-plugins/decorations/createChangedRowDecorationWidgets.js +1 -1
- package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +3 -3
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.js +4 -0
- package/dist/esm/pm-plugins/decorations/utils/wrapBlockNodeViewStyles.legacy.js +6 -0
- package/dist/types/pm-plugins/NodeViewSerializer.d.ts +2 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 21.0.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`bb99ff596a192`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/bb99ff596a192) -
|
|
8
|
+
Fix show-diff rendering a bordered box around fully-replaced paragraphs, a
|
|
9
|
+
platform_editor_ai_show_diff_patch_2 regression caused by paragraph falling through to the generic
|
|
10
|
+
block-container border treatment intended for real block containers (panels, blockquotes). Gated
|
|
11
|
+
behind platform_editor_ai_show_diff_patch_2, the same gate that caused the regression.
|
|
12
|
+
|
|
13
|
+
Also give an inserted atomic inline leaf (date/emoji/mention/status) the same box-shadow highlight
|
|
14
|
+
an in-place attribute change already gets, when it renders through `NodeViewSerializer`'s
|
|
15
|
+
blocklisted-container recursion under platform_editor_show_diff_deleted_nodeview_content — that
|
|
16
|
+
recursion gives the node its real node view instead of a lossy `toDOM()`, but previously carried
|
|
17
|
+
no diff styling of its own.
|
|
18
|
+
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
|
|
3
21
|
## 21.0.2
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
|
@@ -14,6 +14,8 @@ var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
|
14
14
|
var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
|
|
15
15
|
var _fg = require("@atlaskit/platform-feature-flags/fg");
|
|
16
16
|
var _createEditorProxy = require("./createEditorProxy");
|
|
17
|
+
var _createInlineChangedDecoration = require("./decorations/createInlineChangedDecoration");
|
|
18
|
+
var _getAttrChangeRanges = require("./decorations/utils/getAttrChangeRanges");
|
|
17
19
|
var _markViews = require("./markViews");
|
|
18
20
|
/**
|
|
19
21
|
* Utilities for working with ProseMirror node views and DOM serialization within the
|
|
@@ -45,6 +47,14 @@ function isEditorViewWithNodeViews(view) {
|
|
|
45
47
|
/** Expand-family nodes whose expanded state lives in a node-keyed WeakMap. */
|
|
46
48
|
var EXPAND_TYPES = new Set(['expand', 'nestedExpand']);
|
|
47
49
|
|
|
50
|
+
/** Merges an inline style string onto an element's existing `style` attribute. */
|
|
51
|
+
var appendInlineStyle = function appendInlineStyle(element, style) {
|
|
52
|
+
var _element$getAttribute;
|
|
53
|
+
var currentStyle = (_element$getAttribute = element.getAttribute('style')) !== null && _element$getAttribute !== void 0 ? _element$getAttribute : '';
|
|
54
|
+
var separator = currentStyle && style && !currentStyle.trimEnd().endsWith(';') ? '; ' : '';
|
|
55
|
+
element.setAttribute('style', "".concat(currentStyle).concat(separator).concat(style));
|
|
56
|
+
};
|
|
57
|
+
|
|
48
58
|
/** Tables are the only node views that read and write positions, so only they need a preview. */
|
|
49
59
|
var containsTable = function containsTable(node) {
|
|
50
60
|
var table = node.type.schema.nodes.table;
|
|
@@ -99,13 +109,28 @@ var NodeViewSerializer = exports.NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
99
109
|
var _this = this;
|
|
100
110
|
var basePos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
101
111
|
var editorProxy = arguments.length > 3 ? arguments[3] : undefined;
|
|
112
|
+
var isInserted = arguments.length > 4 ? arguments[4] : undefined;
|
|
113
|
+
var colorScheme = arguments.length > 5 ? arguments[5] : undefined;
|
|
102
114
|
// A node's first child sits one position inside it, and each subsequent
|
|
103
115
|
// child is offset by the previous child's `nodeSize`. Tracking this lets nested node
|
|
104
116
|
// views resolve to their real depth instead of every one of them seeing depth 0.
|
|
105
117
|
var childPos = basePos + 1;
|
|
106
118
|
children.forEach(function (child) {
|
|
107
|
-
var childNode = _this.tryCreateNodeViewInner(child, childPos, editorProxy) || _this.serializeNode(child);
|
|
119
|
+
var childNode = _this.tryCreateNodeViewInner(child, childPos, editorProxy, isInserted, colorScheme) || _this.serializeNode(child);
|
|
108
120
|
if (childNode) {
|
|
121
|
+
// Give inserted atomic children the same box-shadow
|
|
122
|
+
// highlight an in-place attribute change already gets (`getAtomicInlineChangedAttrs`).
|
|
123
|
+
if (isInserted && (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_show_diff_deleted_nodeview_content') && (0, _getAttrChangeRanges.isInlineAttrChangeNodeName)(child.type.name) && childNode instanceof HTMLElement) {
|
|
124
|
+
var _childNode$getAttribu;
|
|
125
|
+
var _getAtomicInlineChang = (0, _createInlineChangedDecoration.getAtomicInlineChangedAttrs)(child.type.name, colorScheme),
|
|
126
|
+
className = _getAtomicInlineChang.className,
|
|
127
|
+
styleSuffix = _getAtomicInlineChang.styleSuffix;
|
|
128
|
+
var existingClassName = (_childNode$getAttribu = childNode.getAttribute('class')) !== null && _childNode$getAttribu !== void 0 ? _childNode$getAttribu : '';
|
|
129
|
+
childNode.setAttribute('class', existingClassName ? "".concat(existingClassName, " ").concat(className) : className);
|
|
130
|
+
if (styleSuffix) {
|
|
131
|
+
appendInlineStyle(childNode, styleSuffix);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
109
134
|
contentDOM === null || contentDOM === void 0 || contentDOM.append(childNode);
|
|
110
135
|
}
|
|
111
136
|
childPos += child.nodeSize;
|
|
@@ -126,13 +151,15 @@ var NodeViewSerializer = exports.NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
126
151
|
var _preview$rootPos;
|
|
127
152
|
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
128
153
|
var $sourcePos = arguments.length > 2 ? arguments[2] : undefined;
|
|
154
|
+
var isInserted = arguments.length > 3 ? arguments[3] : undefined;
|
|
155
|
+
var colorScheme = arguments.length > 4 ? arguments[4] : undefined;
|
|
129
156
|
if (!this.editorView) {
|
|
130
157
|
return null;
|
|
131
158
|
}
|
|
132
159
|
// The preview becomes the document every nested node view resolves its position against,
|
|
133
160
|
// so positions stay internally consistent.
|
|
134
161
|
var preview = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && containsTable(targetNode) ? (0, _createEditorProxy.createEditorProxy)(this.editorView, targetNode, $sourcePos) : null;
|
|
135
|
-
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy);
|
|
162
|
+
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy, isInserted, colorScheme);
|
|
136
163
|
}
|
|
137
164
|
}, {
|
|
138
165
|
key: "tryCreateNodeViewInner",
|
|
@@ -140,6 +167,8 @@ var NodeViewSerializer = exports.NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
140
167
|
var _this$nodeViews;
|
|
141
168
|
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
142
169
|
var editorProxy = arguments.length > 2 ? arguments[2] : undefined;
|
|
170
|
+
var isInserted = arguments.length > 3 ? arguments[3] : undefined;
|
|
171
|
+
var colorScheme = arguments.length > 4 ? arguments[4] : undefined;
|
|
143
172
|
if (!this.editorView) {
|
|
144
173
|
return null;
|
|
145
174
|
}
|
|
@@ -185,7 +214,7 @@ var NodeViewSerializer = exports.NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
185
214
|
if (!(0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_show_diff_deleted_nodeview_content') && targetNode.type.name === 'paragraph' && targetNode.children.length === 1) {
|
|
186
215
|
return this.serializeFragment(targetNode.content);
|
|
187
216
|
}
|
|
188
|
-
this.appendChildNodes(targetNode.children, _contentDOM, basePos, editorProxy);
|
|
217
|
+
this.appendChildNodes(targetNode.children, _contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
189
218
|
}
|
|
190
219
|
return this.withMarkViews(targetNode, _dom, editorProxy);
|
|
191
220
|
}
|
|
@@ -209,7 +238,7 @@ var NodeViewSerializer = exports.NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
209
238
|
dom = _constructor.dom,
|
|
210
239
|
contentDOM = _constructor.contentDOM;
|
|
211
240
|
// Iteratively populate children
|
|
212
|
-
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy);
|
|
241
|
+
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
213
242
|
return this.withMarkViews(targetNode, dom, editorProxy);
|
|
214
243
|
} catch (_unused) {
|
|
215
244
|
return null;
|
|
@@ -182,7 +182,7 @@ var createChangedRowDOM = function createChangedRowDOM(_ref3) {
|
|
|
182
182
|
var cellIndex = 0;
|
|
183
183
|
rowNode.content.forEach(function (cellNode) {
|
|
184
184
|
if (cellNode.type.name === 'tableCell' || cellNode.type.name === 'tableHeader') {
|
|
185
|
-
var nodeView = nodeViewSerializer.tryCreateNodeView(cellNode);
|
|
185
|
+
var nodeView = nodeViewSerializer.tryCreateNodeView(cellNode, 0, undefined, isInserted, colorScheme);
|
|
186
186
|
if (nodeView) {
|
|
187
187
|
if (nodeView instanceof HTMLElement) {
|
|
188
188
|
(0, _tableCellEdgeAttrs.applyCellEdgeAttrs)(nodeView, cellEdgeAttrs === null || cellEdgeAttrs === void 0 ? void 0 : cellEdgeAttrs[cellIndex]);
|
|
@@ -82,7 +82,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
|
|
|
82
82
|
// A cell contains block content (paragraphs); serialize the cell's content
|
|
83
83
|
// so every block inside the cell is rendered.
|
|
84
84
|
cellNode.content.forEach(function (blockNode) {
|
|
85
|
-
var nodeView = nodeViewSerializer.tryCreateNodeView(blockNode);
|
|
85
|
+
var nodeView = nodeViewSerializer.tryCreateNodeView(blockNode, 0, undefined, isInserted, colorScheme);
|
|
86
86
|
var wrapper = (0, _wrapBlockNodeView.createContentWrapper)(colorScheme, false, isInserted);
|
|
87
87
|
if (nodeView) {
|
|
88
88
|
wrapper.append(nodeView);
|
|
@@ -322,7 +322,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
322
322
|
var handleMultipleChildNodes = function handleMultipleChildNodes(node) {
|
|
323
323
|
if (!shouldPreserveCompleteMultiInlineBlock && !shouldRenderAsBlockNode && node.content.childCount > 1 && node.type.inlineContent) {
|
|
324
324
|
node.content.forEach(function (childNode) {
|
|
325
|
-
var childNodeView = serializer.tryCreateNodeView(childNode);
|
|
325
|
+
var childNodeView = serializer.tryCreateNodeView(childNode, 0, undefined, isInserted, colorScheme);
|
|
326
326
|
if (childNodeView) {
|
|
327
327
|
var lineBreak = document.createElement('br');
|
|
328
328
|
dom.append(lineBreak);
|
|
@@ -378,7 +378,7 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
|
|
|
378
378
|
|
|
379
379
|
// Try to create node view, fallback to serialization
|
|
380
380
|
var $sourcePos = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
|
|
381
|
-
var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined);
|
|
381
|
+
var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
|
|
382
382
|
if (nodeView) {
|
|
383
383
|
if (node.isInline) {
|
|
384
384
|
var wrapper = (0, _wrapBlockNodeView.createContentWrapper)(colorScheme, isActive, isInserted, reveal);
|
|
@@ -41,6 +41,10 @@ var isMultiContainerBlockNode = exports.isMultiContainerBlockNode = function isM
|
|
|
41
41
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
42
42
|
};
|
|
43
43
|
var isTextLikeBlockNode = exports.isTextLikeBlockNode = function isTextLikeBlockNode(nodeName) {
|
|
44
|
+
// When cleaning up platform_editor_ai_show_diff_patch_2 just put paragraph into the list
|
|
45
|
+
if (nodeName === 'paragraph') {
|
|
46
|
+
return (0, _fg.fg)('platform_editor_ai_show_diff_patch_2');
|
|
47
|
+
}
|
|
44
48
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
45
49
|
};
|
|
46
50
|
var getChangedContentStyleNext = function getChangedContentStyleNext(colorScheme) {
|
|
@@ -78,6 +78,12 @@ var isMultiContainerBlockNode = function isMultiContainerBlockNode(nodeName) {
|
|
|
78
78
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
79
79
|
};
|
|
80
80
|
var isTextLikeBlockNode = function isTextLikeBlockNode(nodeName) {
|
|
81
|
+
// `paragraph` only reaches this classification via patch_2's `shouldRenderAsBlockNode` routing
|
|
82
|
+
// (createNodeChangedDecorationWidget.ts), which fully replaced paragraphs never hit otherwise —
|
|
83
|
+
// gating it here keeps that dependency explicit rather than implicit.
|
|
84
|
+
if (nodeName === 'paragraph') {
|
|
85
|
+
return (0, _fg.fg)('platform_editor_ai_show_diff_patch_2');
|
|
86
|
+
}
|
|
81
87
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
82
88
|
};
|
|
83
89
|
|
|
@@ -4,6 +4,8 @@ import { contains } from '@atlaskit/editor-prosemirror/utils';
|
|
|
4
4
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
6
6
|
import { createEditorProxy } from './createEditorProxy';
|
|
7
|
+
import { getAtomicInlineChangedAttrs } from './decorations/createInlineChangedDecoration';
|
|
8
|
+
import { isInlineAttrChangeNodeName } from './decorations/utils/getAttrChangeRanges';
|
|
7
9
|
import { wrapInMarkViews } from './markViews';
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -36,6 +38,14 @@ export function isEditorViewWithNodeViews(view) {
|
|
|
36
38
|
/** Expand-family nodes whose expanded state lives in a node-keyed WeakMap. */
|
|
37
39
|
const EXPAND_TYPES = new Set(['expand', 'nestedExpand']);
|
|
38
40
|
|
|
41
|
+
/** Merges an inline style string onto an element's existing `style` attribute. */
|
|
42
|
+
const appendInlineStyle = (element, style) => {
|
|
43
|
+
var _element$getAttribute;
|
|
44
|
+
const currentStyle = (_element$getAttribute = element.getAttribute('style')) !== null && _element$getAttribute !== void 0 ? _element$getAttribute : '';
|
|
45
|
+
const separator = currentStyle && style && !currentStyle.trimEnd().endsWith(';') ? '; ' : '';
|
|
46
|
+
element.setAttribute('style', `${currentStyle}${separator}${style}`);
|
|
47
|
+
};
|
|
48
|
+
|
|
39
49
|
/** Tables are the only node views that read and write positions, so only they need a preview. */
|
|
40
50
|
const containsTable = node => {
|
|
41
51
|
const {
|
|
@@ -83,14 +93,28 @@ export class NodeViewSerializer {
|
|
|
83
93
|
/**
|
|
84
94
|
* Appends serialized child nodes to the given contentDOM element.
|
|
85
95
|
*/
|
|
86
|
-
appendChildNodes(children, contentDOM, basePos = 0, editorProxy) {
|
|
96
|
+
appendChildNodes(children, contentDOM, basePos = 0, editorProxy, isInserted, colorScheme) {
|
|
87
97
|
// A node's first child sits one position inside it, and each subsequent
|
|
88
98
|
// child is offset by the previous child's `nodeSize`. Tracking this lets nested node
|
|
89
99
|
// views resolve to their real depth instead of every one of them seeing depth 0.
|
|
90
100
|
let childPos = basePos + 1;
|
|
91
101
|
children.forEach(child => {
|
|
92
|
-
const childNode = this.tryCreateNodeViewInner(child, childPos, editorProxy) || this.serializeNode(child);
|
|
102
|
+
const childNode = this.tryCreateNodeViewInner(child, childPos, editorProxy, isInserted, colorScheme) || this.serializeNode(child);
|
|
93
103
|
if (childNode) {
|
|
104
|
+
// Give inserted atomic children the same box-shadow
|
|
105
|
+
// highlight an in-place attribute change already gets (`getAtomicInlineChangedAttrs`).
|
|
106
|
+
if (isInserted && isExperimentEnabled('platform_editor_show_diff_deleted_nodeview_content') && isInlineAttrChangeNodeName(child.type.name) && childNode instanceof HTMLElement) {
|
|
107
|
+
var _childNode$getAttribu;
|
|
108
|
+
const {
|
|
109
|
+
className,
|
|
110
|
+
styleSuffix
|
|
111
|
+
} = getAtomicInlineChangedAttrs(child.type.name, colorScheme);
|
|
112
|
+
const existingClassName = (_childNode$getAttribu = childNode.getAttribute('class')) !== null && _childNode$getAttribu !== void 0 ? _childNode$getAttribu : '';
|
|
113
|
+
childNode.setAttribute('class', existingClassName ? `${existingClassName} ${className}` : className);
|
|
114
|
+
if (styleSuffix) {
|
|
115
|
+
appendInlineStyle(childNode, styleSuffix);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
94
118
|
contentDOM === null || contentDOM === void 0 ? void 0 : contentDOM.append(childNode);
|
|
95
119
|
}
|
|
96
120
|
childPos += child.nodeSize;
|
|
@@ -105,7 +129,7 @@ export class NodeViewSerializer {
|
|
|
105
129
|
*
|
|
106
130
|
* `$sourcePos` is where the node sits in the doc it came from, so nested tables keep their depth.
|
|
107
131
|
*/
|
|
108
|
-
tryCreateNodeView(targetNode, basePos = 0, $sourcePos) {
|
|
132
|
+
tryCreateNodeView(targetNode, basePos = 0, $sourcePos, isInserted, colorScheme) {
|
|
109
133
|
var _preview$rootPos;
|
|
110
134
|
if (!this.editorView) {
|
|
111
135
|
return null;
|
|
@@ -113,9 +137,9 @@ export class NodeViewSerializer {
|
|
|
113
137
|
// The preview becomes the document every nested node view resolves its position against,
|
|
114
138
|
// so positions stay internally consistent.
|
|
115
139
|
const preview = fg('platform_editor_ai_show_diff_patch_2') && containsTable(targetNode) ? createEditorProxy(this.editorView, targetNode, $sourcePos) : null;
|
|
116
|
-
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy);
|
|
140
|
+
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy, isInserted, colorScheme);
|
|
117
141
|
}
|
|
118
|
-
tryCreateNodeViewInner(targetNode, basePos = 0, editorProxy) {
|
|
142
|
+
tryCreateNodeViewInner(targetNode, basePos = 0, editorProxy, isInserted, colorScheme) {
|
|
119
143
|
var _this$nodeViews;
|
|
120
144
|
if (!this.editorView) {
|
|
121
145
|
return null;
|
|
@@ -163,7 +187,7 @@ export class NodeViewSerializer {
|
|
|
163
187
|
if (!isExperimentEnabled('platform_editor_show_diff_deleted_nodeview_content') && targetNode.type.name === 'paragraph' && targetNode.children.length === 1) {
|
|
164
188
|
return this.serializeFragment(targetNode.content);
|
|
165
189
|
}
|
|
166
|
-
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy);
|
|
190
|
+
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
167
191
|
}
|
|
168
192
|
return this.withMarkViews(targetNode, dom, editorProxy);
|
|
169
193
|
}
|
|
@@ -186,7 +210,7 @@ export class NodeViewSerializer {
|
|
|
186
210
|
contentDOM
|
|
187
211
|
} = constructor(targetNode, view, () => resolvedPos, [], {});
|
|
188
212
|
// Iteratively populate children
|
|
189
|
-
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy);
|
|
213
|
+
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
190
214
|
return this.withMarkViews(targetNode, dom, editorProxy);
|
|
191
215
|
} catch {
|
|
192
216
|
return null;
|
|
@@ -157,7 +157,7 @@ const createChangedRowDOM = ({
|
|
|
157
157
|
let cellIndex = 0;
|
|
158
158
|
rowNode.content.forEach(cellNode => {
|
|
159
159
|
if (cellNode.type.name === 'tableCell' || cellNode.type.name === 'tableHeader') {
|
|
160
|
-
const nodeView = nodeViewSerializer.tryCreateNodeView(cellNode);
|
|
160
|
+
const nodeView = nodeViewSerializer.tryCreateNodeView(cellNode, 0, undefined, isInserted, colorScheme);
|
|
161
161
|
if (nodeView) {
|
|
162
162
|
if (nodeView instanceof HTMLElement) {
|
|
163
163
|
applyCellEdgeAttrs(nodeView, cellEdgeAttrs === null || cellEdgeAttrs === void 0 ? void 0 : cellEdgeAttrs[cellIndex]);
|
|
@@ -72,7 +72,7 @@ const createTableCellContentWidgets = ({
|
|
|
72
72
|
// A cell contains block content (paragraphs); serialize the cell's content
|
|
73
73
|
// so every block inside the cell is rendered.
|
|
74
74
|
cellNode.content.forEach(blockNode => {
|
|
75
|
-
const nodeView = nodeViewSerializer.tryCreateNodeView(blockNode);
|
|
75
|
+
const nodeView = nodeViewSerializer.tryCreateNodeView(blockNode, 0, undefined, isInserted, colorScheme);
|
|
76
76
|
const wrapper = createContentWrapper(colorScheme, false, isInserted);
|
|
77
77
|
if (nodeView) {
|
|
78
78
|
wrapper.append(nodeView);
|
|
@@ -314,7 +314,7 @@ export const createNodeChangedDecorationWidget = ({
|
|
|
314
314
|
const handleMultipleChildNodes = node => {
|
|
315
315
|
if (!shouldPreserveCompleteMultiInlineBlock && !shouldRenderAsBlockNode && node.content.childCount > 1 && node.type.inlineContent) {
|
|
316
316
|
node.content.forEach(childNode => {
|
|
317
|
-
const childNodeView = serializer.tryCreateNodeView(childNode);
|
|
317
|
+
const childNodeView = serializer.tryCreateNodeView(childNode, 0, undefined, isInserted, colorScheme);
|
|
318
318
|
if (childNodeView) {
|
|
319
319
|
const lineBreak = document.createElement('br');
|
|
320
320
|
dom.append(lineBreak);
|
|
@@ -364,7 +364,7 @@ export const createNodeChangedDecorationWidget = ({
|
|
|
364
364
|
|
|
365
365
|
// Try to create node view, fallback to serialization
|
|
366
366
|
const $sourcePos = fg('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
|
|
367
|
-
const nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined);
|
|
367
|
+
const nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
|
|
368
368
|
if (nodeView) {
|
|
369
369
|
if (node.isInline) {
|
|
370
370
|
const wrapper = createContentWrapper(colorScheme, isActive, isInserted, reveal);
|
|
@@ -30,6 +30,10 @@ export const isMultiContainerBlockNode = nodeName => {
|
|
|
30
30
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
31
31
|
};
|
|
32
32
|
export const isTextLikeBlockNode = nodeName => {
|
|
33
|
+
// When cleaning up platform_editor_ai_show_diff_patch_2 just put paragraph into the list
|
|
34
|
+
if (nodeName === 'paragraph') {
|
|
35
|
+
return fg('platform_editor_ai_show_diff_patch_2');
|
|
36
|
+
}
|
|
33
37
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
34
38
|
};
|
|
35
39
|
const getChangedContentStyleNext = (colorScheme, isActive = false, isInserted = false, hideAddedDiffsUnderline = false) => {
|
|
@@ -71,6 +71,12 @@ const isMultiContainerBlockNode = nodeName => {
|
|
|
71
71
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
72
72
|
};
|
|
73
73
|
const isTextLikeBlockNode = nodeName => {
|
|
74
|
+
// `paragraph` only reaches this classification via patch_2's `shouldRenderAsBlockNode` routing
|
|
75
|
+
// (createNodeChangedDecorationWidget.ts), which fully replaced paragraphs never hit otherwise —
|
|
76
|
+
// gating it here keeps that dependency explicit rather than implicit.
|
|
77
|
+
if (nodeName === 'paragraph') {
|
|
78
|
+
return fg('platform_editor_ai_show_diff_patch_2');
|
|
79
|
+
}
|
|
74
80
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
75
81
|
};
|
|
76
82
|
|
|
@@ -6,6 +6,8 @@ import { contains } from '@atlaskit/editor-prosemirror/utils';
|
|
|
6
6
|
import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
|
|
7
7
|
import { fg } from '@atlaskit/platform-feature-flags/fg';
|
|
8
8
|
import { createEditorProxy } from './createEditorProxy';
|
|
9
|
+
import { getAtomicInlineChangedAttrs } from './decorations/createInlineChangedDecoration';
|
|
10
|
+
import { isInlineAttrChangeNodeName } from './decorations/utils/getAttrChangeRanges';
|
|
9
11
|
import { wrapInMarkViews } from './markViews';
|
|
10
12
|
|
|
11
13
|
/**
|
|
@@ -38,6 +40,14 @@ export function isEditorViewWithNodeViews(view) {
|
|
|
38
40
|
/** Expand-family nodes whose expanded state lives in a node-keyed WeakMap. */
|
|
39
41
|
var EXPAND_TYPES = new Set(['expand', 'nestedExpand']);
|
|
40
42
|
|
|
43
|
+
/** Merges an inline style string onto an element's existing `style` attribute. */
|
|
44
|
+
var appendInlineStyle = function appendInlineStyle(element, style) {
|
|
45
|
+
var _element$getAttribute;
|
|
46
|
+
var currentStyle = (_element$getAttribute = element.getAttribute('style')) !== null && _element$getAttribute !== void 0 ? _element$getAttribute : '';
|
|
47
|
+
var separator = currentStyle && style && !currentStyle.trimEnd().endsWith(';') ? '; ' : '';
|
|
48
|
+
element.setAttribute('style', "".concat(currentStyle).concat(separator).concat(style));
|
|
49
|
+
};
|
|
50
|
+
|
|
41
51
|
/** Tables are the only node views that read and write positions, so only they need a preview. */
|
|
42
52
|
var containsTable = function containsTable(node) {
|
|
43
53
|
var table = node.type.schema.nodes.table;
|
|
@@ -92,13 +102,28 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
92
102
|
var _this = this;
|
|
93
103
|
var basePos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
|
|
94
104
|
var editorProxy = arguments.length > 3 ? arguments[3] : undefined;
|
|
105
|
+
var isInserted = arguments.length > 4 ? arguments[4] : undefined;
|
|
106
|
+
var colorScheme = arguments.length > 5 ? arguments[5] : undefined;
|
|
95
107
|
// A node's first child sits one position inside it, and each subsequent
|
|
96
108
|
// child is offset by the previous child's `nodeSize`. Tracking this lets nested node
|
|
97
109
|
// views resolve to their real depth instead of every one of them seeing depth 0.
|
|
98
110
|
var childPos = basePos + 1;
|
|
99
111
|
children.forEach(function (child) {
|
|
100
|
-
var childNode = _this.tryCreateNodeViewInner(child, childPos, editorProxy) || _this.serializeNode(child);
|
|
112
|
+
var childNode = _this.tryCreateNodeViewInner(child, childPos, editorProxy, isInserted, colorScheme) || _this.serializeNode(child);
|
|
101
113
|
if (childNode) {
|
|
114
|
+
// Give inserted atomic children the same box-shadow
|
|
115
|
+
// highlight an in-place attribute change already gets (`getAtomicInlineChangedAttrs`).
|
|
116
|
+
if (isInserted && isExperimentEnabled('platform_editor_show_diff_deleted_nodeview_content') && isInlineAttrChangeNodeName(child.type.name) && childNode instanceof HTMLElement) {
|
|
117
|
+
var _childNode$getAttribu;
|
|
118
|
+
var _getAtomicInlineChang = getAtomicInlineChangedAttrs(child.type.name, colorScheme),
|
|
119
|
+
className = _getAtomicInlineChang.className,
|
|
120
|
+
styleSuffix = _getAtomicInlineChang.styleSuffix;
|
|
121
|
+
var existingClassName = (_childNode$getAttribu = childNode.getAttribute('class')) !== null && _childNode$getAttribu !== void 0 ? _childNode$getAttribu : '';
|
|
122
|
+
childNode.setAttribute('class', existingClassName ? "".concat(existingClassName, " ").concat(className) : className);
|
|
123
|
+
if (styleSuffix) {
|
|
124
|
+
appendInlineStyle(childNode, styleSuffix);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
102
127
|
contentDOM === null || contentDOM === void 0 || contentDOM.append(childNode);
|
|
103
128
|
}
|
|
104
129
|
childPos += child.nodeSize;
|
|
@@ -119,13 +144,15 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
119
144
|
var _preview$rootPos;
|
|
120
145
|
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
121
146
|
var $sourcePos = arguments.length > 2 ? arguments[2] : undefined;
|
|
147
|
+
var isInserted = arguments.length > 3 ? arguments[3] : undefined;
|
|
148
|
+
var colorScheme = arguments.length > 4 ? arguments[4] : undefined;
|
|
122
149
|
if (!this.editorView) {
|
|
123
150
|
return null;
|
|
124
151
|
}
|
|
125
152
|
// The preview becomes the document every nested node view resolves its position against,
|
|
126
153
|
// so positions stay internally consistent.
|
|
127
154
|
var preview = fg('platform_editor_ai_show_diff_patch_2') && containsTable(targetNode) ? createEditorProxy(this.editorView, targetNode, $sourcePos) : null;
|
|
128
|
-
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy);
|
|
155
|
+
return this.tryCreateNodeViewInner(targetNode, (_preview$rootPos = preview === null || preview === void 0 ? void 0 : preview.rootPos) !== null && _preview$rootPos !== void 0 ? _preview$rootPos : basePos, preview === null || preview === void 0 ? void 0 : preview.editorProxy, isInserted, colorScheme);
|
|
129
156
|
}
|
|
130
157
|
}, {
|
|
131
158
|
key: "tryCreateNodeViewInner",
|
|
@@ -133,6 +160,8 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
133
160
|
var _this$nodeViews;
|
|
134
161
|
var basePos = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
135
162
|
var editorProxy = arguments.length > 2 ? arguments[2] : undefined;
|
|
163
|
+
var isInserted = arguments.length > 3 ? arguments[3] : undefined;
|
|
164
|
+
var colorScheme = arguments.length > 4 ? arguments[4] : undefined;
|
|
136
165
|
if (!this.editorView) {
|
|
137
166
|
return null;
|
|
138
167
|
}
|
|
@@ -178,7 +207,7 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
178
207
|
if (!isExperimentEnabled('platform_editor_show_diff_deleted_nodeview_content') && targetNode.type.name === 'paragraph' && targetNode.children.length === 1) {
|
|
179
208
|
return this.serializeFragment(targetNode.content);
|
|
180
209
|
}
|
|
181
|
-
this.appendChildNodes(targetNode.children, _contentDOM, basePos, editorProxy);
|
|
210
|
+
this.appendChildNodes(targetNode.children, _contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
182
211
|
}
|
|
183
212
|
return this.withMarkViews(targetNode, _dom, editorProxy);
|
|
184
213
|
}
|
|
@@ -202,7 +231,7 @@ export var NodeViewSerializer = /*#__PURE__*/function () {
|
|
|
202
231
|
dom = _constructor.dom,
|
|
203
232
|
contentDOM = _constructor.contentDOM;
|
|
204
233
|
// Iteratively populate children
|
|
205
|
-
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy);
|
|
234
|
+
this.appendChildNodes(targetNode.children, contentDOM, basePos, editorProxy, isInserted, colorScheme);
|
|
206
235
|
return this.withMarkViews(targetNode, dom, editorProxy);
|
|
207
236
|
} catch (_unused) {
|
|
208
237
|
return null;
|
|
@@ -175,7 +175,7 @@ var createChangedRowDOM = function createChangedRowDOM(_ref3) {
|
|
|
175
175
|
var cellIndex = 0;
|
|
176
176
|
rowNode.content.forEach(function (cellNode) {
|
|
177
177
|
if (cellNode.type.name === 'tableCell' || cellNode.type.name === 'tableHeader') {
|
|
178
|
-
var nodeView = nodeViewSerializer.tryCreateNodeView(cellNode);
|
|
178
|
+
var nodeView = nodeViewSerializer.tryCreateNodeView(cellNode, 0, undefined, isInserted, colorScheme);
|
|
179
179
|
if (nodeView) {
|
|
180
180
|
if (nodeView instanceof HTMLElement) {
|
|
181
181
|
applyCellEdgeAttrs(nodeView, cellEdgeAttrs === null || cellEdgeAttrs === void 0 ? void 0 : cellEdgeAttrs[cellIndex]);
|
|
@@ -76,7 +76,7 @@ var createTableCellContentWidgets = function createTableCellContentWidgets(_ref)
|
|
|
76
76
|
// A cell contains block content (paragraphs); serialize the cell's content
|
|
77
77
|
// so every block inside the cell is rendered.
|
|
78
78
|
cellNode.content.forEach(function (blockNode) {
|
|
79
|
-
var nodeView = nodeViewSerializer.tryCreateNodeView(blockNode);
|
|
79
|
+
var nodeView = nodeViewSerializer.tryCreateNodeView(blockNode, 0, undefined, isInserted, colorScheme);
|
|
80
80
|
var wrapper = createContentWrapper(colorScheme, false, isInserted);
|
|
81
81
|
if (nodeView) {
|
|
82
82
|
wrapper.append(nodeView);
|
|
@@ -316,7 +316,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
316
316
|
var handleMultipleChildNodes = function handleMultipleChildNodes(node) {
|
|
317
317
|
if (!shouldPreserveCompleteMultiInlineBlock && !shouldRenderAsBlockNode && node.content.childCount > 1 && node.type.inlineContent) {
|
|
318
318
|
node.content.forEach(function (childNode) {
|
|
319
|
-
var childNodeView = serializer.tryCreateNodeView(childNode);
|
|
319
|
+
var childNodeView = serializer.tryCreateNodeView(childNode, 0, undefined, isInserted, colorScheme);
|
|
320
320
|
if (childNodeView) {
|
|
321
321
|
var lineBreak = document.createElement('br');
|
|
322
322
|
dom.append(lineBreak);
|
|
@@ -372,7 +372,7 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
|
|
|
372
372
|
|
|
373
373
|
// Try to create node view, fallback to serialization
|
|
374
374
|
var $sourcePos = fg('platform_editor_ai_show_diff_patch_2') ? getSourcePos(doc, $changeFromA, slice.openStart, index) : null;
|
|
375
|
-
var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined);
|
|
375
|
+
var nodeView = serializer.tryCreateNodeView(node, 0, $sourcePos !== null && $sourcePos !== void 0 ? $sourcePos : undefined, isInserted, colorScheme);
|
|
376
376
|
if (nodeView) {
|
|
377
377
|
if (node.isInline) {
|
|
378
378
|
var wrapper = createContentWrapper(colorScheme, isActive, isInserted, reveal);
|
|
@@ -35,6 +35,10 @@ export var isMultiContainerBlockNode = function isMultiContainerBlockNode(nodeNa
|
|
|
35
35
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
36
36
|
};
|
|
37
37
|
export var isTextLikeBlockNode = function isTextLikeBlockNode(nodeName) {
|
|
38
|
+
// When cleaning up platform_editor_ai_show_diff_patch_2 just put paragraph into the list
|
|
39
|
+
if (nodeName === 'paragraph') {
|
|
40
|
+
return fg('platform_editor_ai_show_diff_patch_2');
|
|
41
|
+
}
|
|
38
42
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
39
43
|
};
|
|
40
44
|
var getChangedContentStyleNext = function getChangedContentStyleNext(colorScheme) {
|
|
@@ -71,6 +71,12 @@ var isMultiContainerBlockNode = function isMultiContainerBlockNode(nodeName) {
|
|
|
71
71
|
return ['decisionList', 'layoutSection'].includes(nodeName);
|
|
72
72
|
};
|
|
73
73
|
var isTextLikeBlockNode = function isTextLikeBlockNode(nodeName) {
|
|
74
|
+
// `paragraph` only reaches this classification via patch_2's `shouldRenderAsBlockNode` routing
|
|
75
|
+
// (createNodeChangedDecorationWidget.ts), which fully replaced paragraphs never hit otherwise —
|
|
76
|
+
// gating it here keeps that dependency explicit rather than implicit.
|
|
77
|
+
if (nodeName === 'paragraph') {
|
|
78
|
+
return fg('platform_editor_ai_show_diff_patch_2');
|
|
79
|
+
}
|
|
74
80
|
return ['heading', 'bulletList', 'orderedList', 'listItem', 'taskList', 'blockquote'].includes(nodeName);
|
|
75
81
|
};
|
|
76
82
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { NodeViewConstructor } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
2
|
import type { Node as PMNode, Fragment, ResolvedPos } from '@atlaskit/editor-prosemirror/model';
|
|
3
3
|
import type { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import type { ColorScheme } from './decorations/colorSchemes/types';
|
|
4
5
|
/**
|
|
5
6
|
* Utilities for working with ProseMirror node views and DOM serialization within the
|
|
6
7
|
* Show Diff editor plugin.
|
|
@@ -61,7 +62,7 @@ export declare class NodeViewSerializer {
|
|
|
61
62
|
*
|
|
62
63
|
* `$sourcePos` is where the node sits in the doc it came from, so nested tables keep their depth.
|
|
63
64
|
*/
|
|
64
|
-
tryCreateNodeView(targetNode: PMNode, basePos?: number, $sourcePos?: ResolvedPos): Node | null;
|
|
65
|
+
tryCreateNodeView(targetNode: PMNode, basePos?: number, $sourcePos?: ResolvedPos, isInserted?: boolean, colorScheme?: ColorScheme): Node | null;
|
|
65
66
|
private tryCreateNodeViewInner;
|
|
66
67
|
/** Wraps rendered DOM in its marks, rendered against the editor proxy when there is one. */
|
|
67
68
|
private withMarkViews;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "21.0.
|
|
3
|
+
"version": "21.0.3",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"@atlaskit/platform-feature-experiments": "^0.3.0",
|
|
40
40
|
"@atlaskit/platform-feature-flags": "^2.2.0",
|
|
41
41
|
"@atlaskit/primitives": "^22.5.0",
|
|
42
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
42
|
+
"@atlaskit/tmp-editor-statsig": "^220.0.0",
|
|
43
43
|
"@atlaskit/tokens": "^20.1.0",
|
|
44
44
|
"@babel/runtime": "^7.0.0",
|
|
45
45
|
"@compiled/react": "^1.0.2",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"react-intl": "^7.0.0"
|
|
72
72
|
},
|
|
73
73
|
"peerDependencies": {
|
|
74
|
-
"@atlaskit/editor-common": "^127.
|
|
74
|
+
"@atlaskit/editor-common": "^127.2.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"
|