@atlaskit/editor-plugin-show-diff 3.0.0 → 3.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 +14 -0
- package/dist/cjs/pm-plugins/calculateDiffDecorations.js +107 -7
- package/dist/cjs/pm-plugins/decorations.js +79 -1
- package/dist/es2019/pm-plugins/calculateDiffDecorations.js +101 -7
- package/dist/es2019/pm-plugins/decorations.js +76 -0
- package/dist/esm/pm-plugins/calculateDiffDecorations.js +106 -7
- package/dist/esm/pm-plugins/decorations.js +78 -0
- package/dist/types/pm-plugins/calculateDiffDecorations.d.ts +2 -2
- package/dist/types/pm-plugins/decorations.d.ts +11 -0
- package/dist/types-ts4.5/pm-plugins/calculateDiffDecorations.d.ts +2 -2
- package/dist/types-ts4.5/pm-plugins/decorations.d.ts +11 -0
- package/package.json +6 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 3.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
|
|
9
|
+
## 3.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- [`16d89ac68ca47`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/16d89ac68ca47) -
|
|
14
|
+
Improve how large number of small steps are grouped together in the diff.
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
3
17
|
## 3.0.0
|
|
4
18
|
|
|
5
19
|
### Patch Changes
|
|
@@ -1,30 +1,109 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
3
4
|
Object.defineProperty(exports, "__esModule", {
|
|
4
5
|
value: true
|
|
5
6
|
});
|
|
6
7
|
exports.calculateDiffDecorations = void 0;
|
|
8
|
+
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
9
|
+
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
10
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
11
|
+
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
12
|
+
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
|
|
7
13
|
var _prosemirrorChangeset = require("prosemirror-changeset");
|
|
14
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
8
15
|
var _document = require("@atlaskit/editor-common/utils/document");
|
|
16
|
+
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
9
17
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
10
18
|
var _decorations = require("./decorations");
|
|
11
19
|
var _markDecorations = require("./markDecorations");
|
|
12
20
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
13
21
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
14
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
15
|
-
var
|
|
22
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
23
|
+
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; }
|
|
24
|
+
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; } // eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
25
|
+
var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(doc, from, to, colourScheme) {
|
|
26
|
+
var decorations = [];
|
|
27
|
+
// Iterate over the document nodes within the range
|
|
28
|
+
doc.nodesBetween(from, to, function (node, pos) {
|
|
29
|
+
if (node.isBlock) {
|
|
30
|
+
decorations.push((0, _decorations.createBlockChangedDecoration)({
|
|
31
|
+
from: pos,
|
|
32
|
+
to: pos + node.nodeSize,
|
|
33
|
+
name: node.type.name
|
|
34
|
+
}, colourScheme));
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return decorations;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Groups adjacent changes to reduce visual fragmentation in diffs.
|
|
42
|
+
* Merges consecutive insertions and deletions that are close together.
|
|
43
|
+
*/
|
|
44
|
+
function optimizeChanges(changes) {
|
|
45
|
+
if (changes.length <= 1) {
|
|
46
|
+
return changes;
|
|
47
|
+
}
|
|
48
|
+
var optimized = [];
|
|
49
|
+
var current = _objectSpread({}, changes[0]);
|
|
50
|
+
for (var i = 1; i < changes.length; i++) {
|
|
51
|
+
var next = changes[i];
|
|
52
|
+
|
|
53
|
+
// Check if changes are adjacent or very close (within 2 positions)
|
|
54
|
+
var isAdjacent = next.fromB <= current.toB + 2;
|
|
55
|
+
if (isAdjacent) {
|
|
56
|
+
current = {
|
|
57
|
+
fromA: current.fromA,
|
|
58
|
+
toA: Math.max(current.toA, next.toA),
|
|
59
|
+
fromB: current.fromB,
|
|
60
|
+
toB: Math.max(current.toB, next.toB),
|
|
61
|
+
deleted: [].concat((0, _toConsumableArray2.default)(current.deleted), (0, _toConsumableArray2.default)(next.deleted)),
|
|
62
|
+
inserted: [].concat((0, _toConsumableArray2.default)(current.inserted), (0, _toConsumableArray2.default)(next.inserted))
|
|
63
|
+
};
|
|
64
|
+
} else {
|
|
65
|
+
optimized.push(current);
|
|
66
|
+
current = _objectSpread({}, next);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
optimized.push(current);
|
|
70
|
+
return optimized;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
74
|
+
function simplifySteps(steps) {
|
|
75
|
+
return steps
|
|
76
|
+
// Remove steps that don't affect document structure or content
|
|
77
|
+
.filter(function (step) {
|
|
78
|
+
return !(step instanceof _steps.AnalyticsStep || step instanceof _transform.AttrStep || step instanceof _steps.SetAttrsStep);
|
|
79
|
+
})
|
|
80
|
+
// Merge consecutive steps where possible
|
|
81
|
+
.reduce(function (acc, step) {
|
|
82
|
+
var _lastStep$merge;
|
|
83
|
+
var lastStep = acc[acc.length - 1];
|
|
84
|
+
var merged = lastStep === null || lastStep === void 0 || (_lastStep$merge = lastStep.merge) === null || _lastStep$merge === void 0 ? void 0 : _lastStep$merge.call(lastStep, step);
|
|
85
|
+
if (merged) {
|
|
86
|
+
acc[acc.length - 1] = merged;
|
|
87
|
+
} else {
|
|
88
|
+
acc.push(step);
|
|
89
|
+
}
|
|
90
|
+
return acc;
|
|
91
|
+
}, []);
|
|
92
|
+
}
|
|
93
|
+
var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref) {
|
|
16
94
|
var state = _ref.state,
|
|
17
95
|
pluginState = _ref.pluginState,
|
|
18
96
|
nodeViewSerializer = _ref.nodeViewSerializer,
|
|
19
97
|
colourScheme = _ref.colourScheme;
|
|
20
98
|
var originalDoc = pluginState.originalDoc,
|
|
21
|
-
|
|
99
|
+
rawSteps = pluginState.steps;
|
|
100
|
+
var steps = simplifySteps(rawSteps);
|
|
22
101
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
23
102
|
return _view.DecorationSet.empty;
|
|
24
103
|
}
|
|
25
104
|
var tr = state.tr;
|
|
26
105
|
var steppedDoc = originalDoc;
|
|
27
|
-
var
|
|
106
|
+
var stepMaps = [];
|
|
28
107
|
var _iterator = _createForOfIteratorHelper(steps),
|
|
29
108
|
_step;
|
|
30
109
|
try {
|
|
@@ -33,9 +112,10 @@ var calculateDiffDecorations = exports.calculateDiffDecorations = function calcu
|
|
|
33
112
|
var result = step.apply(steppedDoc);
|
|
34
113
|
if (result.failed === null && result.doc) {
|
|
35
114
|
steppedDoc = result.doc;
|
|
36
|
-
|
|
115
|
+
stepMaps.push(step.getMap());
|
|
37
116
|
}
|
|
38
117
|
}
|
|
118
|
+
|
|
39
119
|
// Rather than using .eq() we use a custom function that only checks for structural
|
|
40
120
|
// changes and ignores differences in attributes which don't affect decoration positions
|
|
41
121
|
} catch (err) {
|
|
@@ -46,11 +126,14 @@ var calculateDiffDecorations = exports.calculateDiffDecorations = function calcu
|
|
|
46
126
|
if (!(0, _document.areNodesEqualIgnoreAttrs)(steppedDoc, tr.doc)) {
|
|
47
127
|
return _view.DecorationSet.empty;
|
|
48
128
|
}
|
|
129
|
+
var changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
49
130
|
var changes = (0, _prosemirrorChangeset.simplifyChanges)(changeset.changes, tr.doc);
|
|
131
|
+
var optimizedChanges = optimizeChanges(changes);
|
|
50
132
|
var decorations = [];
|
|
51
|
-
|
|
133
|
+
optimizedChanges.forEach(function (change) {
|
|
52
134
|
if (change.inserted.length > 0) {
|
|
53
135
|
decorations.push((0, _decorations.createInlineChangedDecoration)(change, colourScheme));
|
|
136
|
+
decorations.push.apply(decorations, (0, _toConsumableArray2.default)(calculateNodesForBlockDecoration(tr.doc, change.fromB, change.toB, colourScheme)));
|
|
54
137
|
}
|
|
55
138
|
if (change.deleted.length > 0) {
|
|
56
139
|
var decoration = (0, _decorations.createDeletedContentDecoration)({
|
|
@@ -68,4 +151,21 @@ var calculateDiffDecorations = exports.calculateDiffDecorations = function calcu
|
|
|
68
151
|
decorations.push((0, _decorations.createInlineChangedDecoration)(change, colourScheme));
|
|
69
152
|
});
|
|
70
153
|
return _view.DecorationSet.empty.add(tr.doc, decorations);
|
|
71
|
-
};
|
|
154
|
+
};
|
|
155
|
+
var calculateDiffDecorations = exports.calculateDiffDecorations = (0, _memoizeOne.default)(calculateDiffDecorationsInner,
|
|
156
|
+
// Cache results unless relevant inputs change
|
|
157
|
+
function (_ref2, _ref3) {
|
|
158
|
+
var _ref6;
|
|
159
|
+
var _ref4 = (0, _slicedToArray2.default)(_ref2, 1),
|
|
160
|
+
_ref4$ = _ref4[0],
|
|
161
|
+
pluginState = _ref4$.pluginState,
|
|
162
|
+
state = _ref4$.state,
|
|
163
|
+
colourScheme = _ref4$.colourScheme;
|
|
164
|
+
var _ref5 = (0, _slicedToArray2.default)(_ref3, 1),
|
|
165
|
+
_ref5$ = _ref5[0],
|
|
166
|
+
lastPluginState = _ref5$.pluginState,
|
|
167
|
+
lastState = _ref5$.state,
|
|
168
|
+
lastColourScheme = _ref5$.colourScheme;
|
|
169
|
+
var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
|
|
170
|
+
return (_ref6 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colourScheme === lastColourScheme) !== null && _ref6 !== void 0 ? _ref6 : false;
|
|
171
|
+
});
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.createInlineChangedDecoration = exports.createDeletedContentDecoration = void 0;
|
|
6
|
+
exports.createInlineChangedDecoration = exports.createDeletedContentDecoration = exports.createBlockChangedDecoration = void 0;
|
|
7
7
|
var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
|
|
8
8
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
9
9
|
var editingStyle = (0, _lazyNodeView.convertToInlineCss)({
|
|
@@ -33,6 +33,84 @@ var createInlineChangedDecoration = exports.createInlineChangedDecoration = func
|
|
|
33
33
|
'data-testid': 'show-diff-changed-decoration'
|
|
34
34
|
}, {});
|
|
35
35
|
};
|
|
36
|
+
var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
37
|
+
switch (nodeName) {
|
|
38
|
+
case 'blockquote':
|
|
39
|
+
return colourScheme === 'traditional' ? traditionalStyleQuoteNode : editingStyleQuoteNode;
|
|
40
|
+
case 'mediaSingle':
|
|
41
|
+
case 'mediaGroup':
|
|
42
|
+
case 'embedCard':
|
|
43
|
+
case 'table':
|
|
44
|
+
case 'tableRow':
|
|
45
|
+
case 'tableCell':
|
|
46
|
+
case 'tableHeader':
|
|
47
|
+
return undefined;
|
|
48
|
+
// Handle table separately to avoid border issues
|
|
49
|
+
case 'paragraph':
|
|
50
|
+
case 'heading':
|
|
51
|
+
case 'hardBreak':
|
|
52
|
+
return undefined;
|
|
53
|
+
// Paragraph and heading nodes do not need special styling
|
|
54
|
+
case 'decisionList':
|
|
55
|
+
case 'taskList':
|
|
56
|
+
case 'taskItem':
|
|
57
|
+
case 'bulletList':
|
|
58
|
+
case 'orderedList':
|
|
59
|
+
case 'listItem':
|
|
60
|
+
return undefined;
|
|
61
|
+
// Lists do not need special styling
|
|
62
|
+
case 'layoutSection':
|
|
63
|
+
return undefined;
|
|
64
|
+
// Layout nodes do not need special styling
|
|
65
|
+
case 'rule':
|
|
66
|
+
return colourScheme === 'traditional' ? traditionalStyleRuleNode : editingStyleRuleNode;
|
|
67
|
+
case 'blockCard':
|
|
68
|
+
return colourScheme === 'traditional' ? traditionalStyleCardBlockNode : editingStyleCardBlockNode;
|
|
69
|
+
default:
|
|
70
|
+
return colourScheme === 'traditional' ? traditionalStyleNode : editingStyleNode;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
var editingStyleQuoteNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
74
|
+
borderLeft: "2px solid ".concat("var(--ds-border-accent-purple, #8270DB)")
|
|
75
|
+
});
|
|
76
|
+
var traditionalStyleQuoteNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
77
|
+
borderLeft: "2px solid ".concat("var(--ds-border-accent-green, #22A06B)")
|
|
78
|
+
});
|
|
79
|
+
var editingStyleRuleNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
80
|
+
backgroundColor: "var(--ds-border-accent-purple, #8270DB)"
|
|
81
|
+
});
|
|
82
|
+
var traditionalStyleRuleNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
83
|
+
backgroundColor: "var(--ds-border-accent-green, #22A06B)"
|
|
84
|
+
});
|
|
85
|
+
var editingStyleNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
86
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-purple, #8270DB)"),
|
|
87
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
88
|
+
});
|
|
89
|
+
var traditionalStyleNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
90
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-green, #22A06B)"),
|
|
91
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
92
|
+
});
|
|
93
|
+
var editingStyleCardBlockNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
94
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-purple, #8270DB)"),
|
|
95
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
96
|
+
});
|
|
97
|
+
var traditionalStyleCardBlockNode = (0, _lazyNodeView.convertToInlineCss)({
|
|
98
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-green, #22A06B)"),
|
|
99
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
100
|
+
});
|
|
101
|
+
/**
|
|
102
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
103
|
+
*
|
|
104
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
105
|
+
* @returns Prosemirror inline decoration
|
|
106
|
+
*/
|
|
107
|
+
var createBlockChangedDecoration = exports.createBlockChangedDecoration = function createBlockChangedDecoration(change, colourScheme) {
|
|
108
|
+
return _view.Decoration.node(change.from, change.to, {
|
|
109
|
+
style: getEditorStyleNode(change.name, colourScheme),
|
|
110
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
111
|
+
class: "show-diff-changed-decoration-node-".concat(colourScheme || 'standard')
|
|
112
|
+
}, {});
|
|
113
|
+
};
|
|
36
114
|
var deletedContentStyle = (0, _lazyNodeView.convertToInlineCss)({
|
|
37
115
|
color: "var(--ds-text-accent-gray, #44546F)",
|
|
38
116
|
textDecoration: 'line-through',
|
|
@@ -1,10 +1,84 @@
|
|
|
1
1
|
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
2
|
+
import isEqual from 'lodash/isEqual';
|
|
3
|
+
import memoizeOne from 'memoize-one';
|
|
2
4
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
5
|
+
import { AnalyticsStep, SetAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
3
6
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
7
|
+
import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
8
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
5
|
-
import { createInlineChangedDecoration, createDeletedContentDecoration } from './decorations';
|
|
9
|
+
import { createInlineChangedDecoration, createDeletedContentDecoration, createBlockChangedDecoration } from './decorations';
|
|
6
10
|
import { getMarkChangeRanges } from './markDecorations';
|
|
7
|
-
|
|
11
|
+
const calculateNodesForBlockDecoration = (doc, from, to, colourScheme) => {
|
|
12
|
+
const decorations = [];
|
|
13
|
+
// Iterate over the document nodes within the range
|
|
14
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
|
15
|
+
if (node.isBlock) {
|
|
16
|
+
decorations.push(createBlockChangedDecoration({
|
|
17
|
+
from: pos,
|
|
18
|
+
to: pos + node.nodeSize,
|
|
19
|
+
name: node.type.name
|
|
20
|
+
}, colourScheme));
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
return decorations;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Groups adjacent changes to reduce visual fragmentation in diffs.
|
|
28
|
+
* Merges consecutive insertions and deletions that are close together.
|
|
29
|
+
*/
|
|
30
|
+
function optimizeChanges(changes) {
|
|
31
|
+
if (changes.length <= 1) {
|
|
32
|
+
return changes;
|
|
33
|
+
}
|
|
34
|
+
const optimized = [];
|
|
35
|
+
let current = {
|
|
36
|
+
...changes[0]
|
|
37
|
+
};
|
|
38
|
+
for (let i = 1; i < changes.length; i++) {
|
|
39
|
+
const next = changes[i];
|
|
40
|
+
|
|
41
|
+
// Check if changes are adjacent or very close (within 2 positions)
|
|
42
|
+
const isAdjacent = next.fromB <= current.toB + 2;
|
|
43
|
+
if (isAdjacent) {
|
|
44
|
+
current = {
|
|
45
|
+
fromA: current.fromA,
|
|
46
|
+
toA: Math.max(current.toA, next.toA),
|
|
47
|
+
fromB: current.fromB,
|
|
48
|
+
toB: Math.max(current.toB, next.toB),
|
|
49
|
+
deleted: [...current.deleted, ...next.deleted],
|
|
50
|
+
inserted: [...current.inserted, ...next.inserted]
|
|
51
|
+
};
|
|
52
|
+
} else {
|
|
53
|
+
optimized.push(current);
|
|
54
|
+
current = {
|
|
55
|
+
...next
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
optimized.push(current);
|
|
60
|
+
return optimized;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
64
|
+
function simplifySteps(steps) {
|
|
65
|
+
return steps
|
|
66
|
+
// Remove steps that don't affect document structure or content
|
|
67
|
+
.filter(step => !(step instanceof AnalyticsStep || step instanceof AttrStep || step instanceof SetAttrsStep))
|
|
68
|
+
// Merge consecutive steps where possible
|
|
69
|
+
.reduce((acc, step) => {
|
|
70
|
+
var _lastStep$merge;
|
|
71
|
+
const lastStep = acc[acc.length - 1];
|
|
72
|
+
const merged = lastStep === null || lastStep === void 0 ? void 0 : (_lastStep$merge = lastStep.merge) === null || _lastStep$merge === void 0 ? void 0 : _lastStep$merge.call(lastStep, step);
|
|
73
|
+
if (merged) {
|
|
74
|
+
acc[acc.length - 1] = merged;
|
|
75
|
+
} else {
|
|
76
|
+
acc.push(step);
|
|
77
|
+
}
|
|
78
|
+
return acc;
|
|
79
|
+
}, []);
|
|
80
|
+
}
|
|
81
|
+
const calculateDiffDecorationsInner = ({
|
|
8
82
|
state,
|
|
9
83
|
pluginState,
|
|
10
84
|
nodeViewSerializer,
|
|
@@ -12,8 +86,9 @@ export const calculateDiffDecorations = ({
|
|
|
12
86
|
}) => {
|
|
13
87
|
const {
|
|
14
88
|
originalDoc,
|
|
15
|
-
steps
|
|
89
|
+
steps: rawSteps
|
|
16
90
|
} = pluginState;
|
|
91
|
+
const steps = simplifySteps(rawSteps);
|
|
17
92
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
18
93
|
return DecorationSet.empty;
|
|
19
94
|
}
|
|
@@ -21,24 +96,28 @@ export const calculateDiffDecorations = ({
|
|
|
21
96
|
tr
|
|
22
97
|
} = state;
|
|
23
98
|
let steppedDoc = originalDoc;
|
|
24
|
-
|
|
99
|
+
const stepMaps = [];
|
|
25
100
|
for (const step of steps) {
|
|
26
101
|
const result = step.apply(steppedDoc);
|
|
27
102
|
if (result.failed === null && result.doc) {
|
|
28
103
|
steppedDoc = result.doc;
|
|
29
|
-
|
|
104
|
+
stepMaps.push(step.getMap());
|
|
30
105
|
}
|
|
31
106
|
}
|
|
107
|
+
|
|
32
108
|
// Rather than using .eq() we use a custom function that only checks for structural
|
|
33
109
|
// changes and ignores differences in attributes which don't affect decoration positions
|
|
34
110
|
if (!areNodesEqualIgnoreAttrs(steppedDoc, tr.doc)) {
|
|
35
111
|
return DecorationSet.empty;
|
|
36
112
|
}
|
|
113
|
+
const changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
37
114
|
const changes = simplifyChanges(changeset.changes, tr.doc);
|
|
115
|
+
const optimizedChanges = optimizeChanges(changes);
|
|
38
116
|
const decorations = [];
|
|
39
|
-
|
|
117
|
+
optimizedChanges.forEach(change => {
|
|
40
118
|
if (change.inserted.length > 0) {
|
|
41
119
|
decorations.push(createInlineChangedDecoration(change, colourScheme));
|
|
120
|
+
decorations.push(...calculateNodesForBlockDecoration(tr.doc, change.fromB, change.toB, colourScheme));
|
|
42
121
|
}
|
|
43
122
|
if (change.deleted.length > 0) {
|
|
44
123
|
const decoration = createDeletedContentDecoration({
|
|
@@ -56,4 +135,19 @@ export const calculateDiffDecorations = ({
|
|
|
56
135
|
decorations.push(createInlineChangedDecoration(change, colourScheme));
|
|
57
136
|
});
|
|
58
137
|
return DecorationSet.empty.add(tr.doc, decorations);
|
|
59
|
-
};
|
|
138
|
+
};
|
|
139
|
+
export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
|
|
140
|
+
// Cache results unless relevant inputs change
|
|
141
|
+
([{
|
|
142
|
+
pluginState,
|
|
143
|
+
state,
|
|
144
|
+
colourScheme
|
|
145
|
+
}], [{
|
|
146
|
+
pluginState: lastPluginState,
|
|
147
|
+
state: lastState,
|
|
148
|
+
colourScheme: lastColourScheme
|
|
149
|
+
}]) => {
|
|
150
|
+
var _ref;
|
|
151
|
+
const originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
|
|
152
|
+
return (_ref = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colourScheme === lastColourScheme) !== null && _ref !== void 0 ? _ref : false;
|
|
153
|
+
});
|
|
@@ -25,6 +25,82 @@ export const createInlineChangedDecoration = (change, colourScheme) => Decoratio
|
|
|
25
25
|
style: colourScheme === 'traditional' ? traditionalInsertStyle : editingStyle,
|
|
26
26
|
'data-testid': 'show-diff-changed-decoration'
|
|
27
27
|
}, {});
|
|
28
|
+
const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
29
|
+
switch (nodeName) {
|
|
30
|
+
case 'blockquote':
|
|
31
|
+
return colourScheme === 'traditional' ? traditionalStyleQuoteNode : editingStyleQuoteNode;
|
|
32
|
+
case 'mediaSingle':
|
|
33
|
+
case 'mediaGroup':
|
|
34
|
+
case 'embedCard':
|
|
35
|
+
case 'table':
|
|
36
|
+
case 'tableRow':
|
|
37
|
+
case 'tableCell':
|
|
38
|
+
case 'tableHeader':
|
|
39
|
+
return undefined;
|
|
40
|
+
// Handle table separately to avoid border issues
|
|
41
|
+
case 'paragraph':
|
|
42
|
+
case 'heading':
|
|
43
|
+
case 'hardBreak':
|
|
44
|
+
return undefined;
|
|
45
|
+
// Paragraph and heading nodes do not need special styling
|
|
46
|
+
case 'decisionList':
|
|
47
|
+
case 'taskList':
|
|
48
|
+
case 'taskItem':
|
|
49
|
+
case 'bulletList':
|
|
50
|
+
case 'orderedList':
|
|
51
|
+
case 'listItem':
|
|
52
|
+
return undefined;
|
|
53
|
+
// Lists do not need special styling
|
|
54
|
+
case 'layoutSection':
|
|
55
|
+
return undefined;
|
|
56
|
+
// Layout nodes do not need special styling
|
|
57
|
+
case 'rule':
|
|
58
|
+
return colourScheme === 'traditional' ? traditionalStyleRuleNode : editingStyleRuleNode;
|
|
59
|
+
case 'blockCard':
|
|
60
|
+
return colourScheme === 'traditional' ? traditionalStyleCardBlockNode : editingStyleCardBlockNode;
|
|
61
|
+
default:
|
|
62
|
+
return colourScheme === 'traditional' ? traditionalStyleNode : editingStyleNode;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const editingStyleQuoteNode = convertToInlineCss({
|
|
66
|
+
borderLeft: `2px solid ${"var(--ds-border-accent-purple, #8270DB)"}`
|
|
67
|
+
});
|
|
68
|
+
const traditionalStyleQuoteNode = convertToInlineCss({
|
|
69
|
+
borderLeft: `2px solid ${"var(--ds-border-accent-green, #22A06B)"}`
|
|
70
|
+
});
|
|
71
|
+
const editingStyleRuleNode = convertToInlineCss({
|
|
72
|
+
backgroundColor: "var(--ds-border-accent-purple, #8270DB)"
|
|
73
|
+
});
|
|
74
|
+
const traditionalStyleRuleNode = convertToInlineCss({
|
|
75
|
+
backgroundColor: "var(--ds-border-accent-green, #22A06B)"
|
|
76
|
+
});
|
|
77
|
+
const editingStyleNode = convertToInlineCss({
|
|
78
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #8270DB)"}`,
|
|
79
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
80
|
+
});
|
|
81
|
+
const traditionalStyleNode = convertToInlineCss({
|
|
82
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-green, #22A06B)"}`,
|
|
83
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
84
|
+
});
|
|
85
|
+
const editingStyleCardBlockNode = convertToInlineCss({
|
|
86
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-purple, #8270DB)"}`,
|
|
87
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
88
|
+
});
|
|
89
|
+
const traditionalStyleCardBlockNode = convertToInlineCss({
|
|
90
|
+
boxShadow: `0 0 0 1px ${"var(--ds-border-accent-green, #22A06B)"}`,
|
|
91
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
92
|
+
});
|
|
93
|
+
/**
|
|
94
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
95
|
+
*
|
|
96
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
97
|
+
* @returns Prosemirror inline decoration
|
|
98
|
+
*/
|
|
99
|
+
export const createBlockChangedDecoration = (change, colourScheme) => Decoration.node(change.from, change.to, {
|
|
100
|
+
style: getEditorStyleNode(change.name, colourScheme),
|
|
101
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
102
|
+
class: `show-diff-changed-decoration-node-${colourScheme || 'standard'}`
|
|
103
|
+
}, {});
|
|
28
104
|
const deletedContentStyle = convertToInlineCss({
|
|
29
105
|
color: "var(--ds-text-accent-gray, #44546F)",
|
|
30
106
|
textDecoration: 'line-through',
|
|
@@ -1,25 +1,103 @@
|
|
|
1
|
+
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
2
|
+
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
3
|
+
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
1
4
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
2
5
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
3
6
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
+
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; }
|
|
8
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
4
9
|
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
10
|
+
import isEqual from 'lodash/isEqual';
|
|
11
|
+
import memoizeOne from 'memoize-one';
|
|
5
12
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
13
|
+
import { AnalyticsStep, SetAttrsStep } from '@atlaskit/adf-schema/steps';
|
|
6
14
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
15
|
+
import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
|
|
7
16
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
|
-
import { createInlineChangedDecoration, createDeletedContentDecoration } from './decorations';
|
|
17
|
+
import { createInlineChangedDecoration, createDeletedContentDecoration, createBlockChangedDecoration } from './decorations';
|
|
9
18
|
import { getMarkChangeRanges } from './markDecorations';
|
|
10
|
-
|
|
19
|
+
var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(doc, from, to, colourScheme) {
|
|
20
|
+
var decorations = [];
|
|
21
|
+
// Iterate over the document nodes within the range
|
|
22
|
+
doc.nodesBetween(from, to, function (node, pos) {
|
|
23
|
+
if (node.isBlock) {
|
|
24
|
+
decorations.push(createBlockChangedDecoration({
|
|
25
|
+
from: pos,
|
|
26
|
+
to: pos + node.nodeSize,
|
|
27
|
+
name: node.type.name
|
|
28
|
+
}, colourScheme));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return decorations;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Groups adjacent changes to reduce visual fragmentation in diffs.
|
|
36
|
+
* Merges consecutive insertions and deletions that are close together.
|
|
37
|
+
*/
|
|
38
|
+
function optimizeChanges(changes) {
|
|
39
|
+
if (changes.length <= 1) {
|
|
40
|
+
return changes;
|
|
41
|
+
}
|
|
42
|
+
var optimized = [];
|
|
43
|
+
var current = _objectSpread({}, changes[0]);
|
|
44
|
+
for (var i = 1; i < changes.length; i++) {
|
|
45
|
+
var next = changes[i];
|
|
46
|
+
|
|
47
|
+
// Check if changes are adjacent or very close (within 2 positions)
|
|
48
|
+
var isAdjacent = next.fromB <= current.toB + 2;
|
|
49
|
+
if (isAdjacent) {
|
|
50
|
+
current = {
|
|
51
|
+
fromA: current.fromA,
|
|
52
|
+
toA: Math.max(current.toA, next.toA),
|
|
53
|
+
fromB: current.fromB,
|
|
54
|
+
toB: Math.max(current.toB, next.toB),
|
|
55
|
+
deleted: [].concat(_toConsumableArray(current.deleted), _toConsumableArray(next.deleted)),
|
|
56
|
+
inserted: [].concat(_toConsumableArray(current.inserted), _toConsumableArray(next.inserted))
|
|
57
|
+
};
|
|
58
|
+
} else {
|
|
59
|
+
optimized.push(current);
|
|
60
|
+
current = _objectSpread({}, next);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
optimized.push(current);
|
|
64
|
+
return optimized;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
68
|
+
function simplifySteps(steps) {
|
|
69
|
+
return steps
|
|
70
|
+
// Remove steps that don't affect document structure or content
|
|
71
|
+
.filter(function (step) {
|
|
72
|
+
return !(step instanceof AnalyticsStep || step instanceof AttrStep || step instanceof SetAttrsStep);
|
|
73
|
+
})
|
|
74
|
+
// Merge consecutive steps where possible
|
|
75
|
+
.reduce(function (acc, step) {
|
|
76
|
+
var _lastStep$merge;
|
|
77
|
+
var lastStep = acc[acc.length - 1];
|
|
78
|
+
var merged = lastStep === null || lastStep === void 0 || (_lastStep$merge = lastStep.merge) === null || _lastStep$merge === void 0 ? void 0 : _lastStep$merge.call(lastStep, step);
|
|
79
|
+
if (merged) {
|
|
80
|
+
acc[acc.length - 1] = merged;
|
|
81
|
+
} else {
|
|
82
|
+
acc.push(step);
|
|
83
|
+
}
|
|
84
|
+
return acc;
|
|
85
|
+
}, []);
|
|
86
|
+
}
|
|
87
|
+
var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref) {
|
|
11
88
|
var state = _ref.state,
|
|
12
89
|
pluginState = _ref.pluginState,
|
|
13
90
|
nodeViewSerializer = _ref.nodeViewSerializer,
|
|
14
91
|
colourScheme = _ref.colourScheme;
|
|
15
92
|
var originalDoc = pluginState.originalDoc,
|
|
16
|
-
|
|
93
|
+
rawSteps = pluginState.steps;
|
|
94
|
+
var steps = simplifySteps(rawSteps);
|
|
17
95
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
18
96
|
return DecorationSet.empty;
|
|
19
97
|
}
|
|
20
98
|
var tr = state.tr;
|
|
21
99
|
var steppedDoc = originalDoc;
|
|
22
|
-
var
|
|
100
|
+
var stepMaps = [];
|
|
23
101
|
var _iterator = _createForOfIteratorHelper(steps),
|
|
24
102
|
_step;
|
|
25
103
|
try {
|
|
@@ -28,9 +106,10 @@ export var calculateDiffDecorations = function calculateDiffDecorations(_ref) {
|
|
|
28
106
|
var result = step.apply(steppedDoc);
|
|
29
107
|
if (result.failed === null && result.doc) {
|
|
30
108
|
steppedDoc = result.doc;
|
|
31
|
-
|
|
109
|
+
stepMaps.push(step.getMap());
|
|
32
110
|
}
|
|
33
111
|
}
|
|
112
|
+
|
|
34
113
|
// Rather than using .eq() we use a custom function that only checks for structural
|
|
35
114
|
// changes and ignores differences in attributes which don't affect decoration positions
|
|
36
115
|
} catch (err) {
|
|
@@ -41,11 +120,14 @@ export var calculateDiffDecorations = function calculateDiffDecorations(_ref) {
|
|
|
41
120
|
if (!areNodesEqualIgnoreAttrs(steppedDoc, tr.doc)) {
|
|
42
121
|
return DecorationSet.empty;
|
|
43
122
|
}
|
|
123
|
+
var changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
|
|
44
124
|
var changes = simplifyChanges(changeset.changes, tr.doc);
|
|
125
|
+
var optimizedChanges = optimizeChanges(changes);
|
|
45
126
|
var decorations = [];
|
|
46
|
-
|
|
127
|
+
optimizedChanges.forEach(function (change) {
|
|
47
128
|
if (change.inserted.length > 0) {
|
|
48
129
|
decorations.push(createInlineChangedDecoration(change, colourScheme));
|
|
130
|
+
decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration(tr.doc, change.fromB, change.toB, colourScheme)));
|
|
49
131
|
}
|
|
50
132
|
if (change.deleted.length > 0) {
|
|
51
133
|
var decoration = createDeletedContentDecoration({
|
|
@@ -63,4 +145,21 @@ export var calculateDiffDecorations = function calculateDiffDecorations(_ref) {
|
|
|
63
145
|
decorations.push(createInlineChangedDecoration(change, colourScheme));
|
|
64
146
|
});
|
|
65
147
|
return DecorationSet.empty.add(tr.doc, decorations);
|
|
66
|
-
};
|
|
148
|
+
};
|
|
149
|
+
export var calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
|
|
150
|
+
// Cache results unless relevant inputs change
|
|
151
|
+
function (_ref2, _ref3) {
|
|
152
|
+
var _ref6;
|
|
153
|
+
var _ref4 = _slicedToArray(_ref2, 1),
|
|
154
|
+
_ref4$ = _ref4[0],
|
|
155
|
+
pluginState = _ref4$.pluginState,
|
|
156
|
+
state = _ref4$.state,
|
|
157
|
+
colourScheme = _ref4$.colourScheme;
|
|
158
|
+
var _ref5 = _slicedToArray(_ref3, 1),
|
|
159
|
+
_ref5$ = _ref5[0],
|
|
160
|
+
lastPluginState = _ref5$.pluginState,
|
|
161
|
+
lastState = _ref5$.state,
|
|
162
|
+
lastColourScheme = _ref5$.colourScheme;
|
|
163
|
+
var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
|
|
164
|
+
return (_ref6 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colourScheme === lastColourScheme) !== null && _ref6 !== void 0 ? _ref6 : false;
|
|
165
|
+
});
|
|
@@ -27,6 +27,84 @@ export var createInlineChangedDecoration = function createInlineChangedDecoratio
|
|
|
27
27
|
'data-testid': 'show-diff-changed-decoration'
|
|
28
28
|
}, {});
|
|
29
29
|
};
|
|
30
|
+
var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
31
|
+
switch (nodeName) {
|
|
32
|
+
case 'blockquote':
|
|
33
|
+
return colourScheme === 'traditional' ? traditionalStyleQuoteNode : editingStyleQuoteNode;
|
|
34
|
+
case 'mediaSingle':
|
|
35
|
+
case 'mediaGroup':
|
|
36
|
+
case 'embedCard':
|
|
37
|
+
case 'table':
|
|
38
|
+
case 'tableRow':
|
|
39
|
+
case 'tableCell':
|
|
40
|
+
case 'tableHeader':
|
|
41
|
+
return undefined;
|
|
42
|
+
// Handle table separately to avoid border issues
|
|
43
|
+
case 'paragraph':
|
|
44
|
+
case 'heading':
|
|
45
|
+
case 'hardBreak':
|
|
46
|
+
return undefined;
|
|
47
|
+
// Paragraph and heading nodes do not need special styling
|
|
48
|
+
case 'decisionList':
|
|
49
|
+
case 'taskList':
|
|
50
|
+
case 'taskItem':
|
|
51
|
+
case 'bulletList':
|
|
52
|
+
case 'orderedList':
|
|
53
|
+
case 'listItem':
|
|
54
|
+
return undefined;
|
|
55
|
+
// Lists do not need special styling
|
|
56
|
+
case 'layoutSection':
|
|
57
|
+
return undefined;
|
|
58
|
+
// Layout nodes do not need special styling
|
|
59
|
+
case 'rule':
|
|
60
|
+
return colourScheme === 'traditional' ? traditionalStyleRuleNode : editingStyleRuleNode;
|
|
61
|
+
case 'blockCard':
|
|
62
|
+
return colourScheme === 'traditional' ? traditionalStyleCardBlockNode : editingStyleCardBlockNode;
|
|
63
|
+
default:
|
|
64
|
+
return colourScheme === 'traditional' ? traditionalStyleNode : editingStyleNode;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
var editingStyleQuoteNode = convertToInlineCss({
|
|
68
|
+
borderLeft: "2px solid ".concat("var(--ds-border-accent-purple, #8270DB)")
|
|
69
|
+
});
|
|
70
|
+
var traditionalStyleQuoteNode = convertToInlineCss({
|
|
71
|
+
borderLeft: "2px solid ".concat("var(--ds-border-accent-green, #22A06B)")
|
|
72
|
+
});
|
|
73
|
+
var editingStyleRuleNode = convertToInlineCss({
|
|
74
|
+
backgroundColor: "var(--ds-border-accent-purple, #8270DB)"
|
|
75
|
+
});
|
|
76
|
+
var traditionalStyleRuleNode = convertToInlineCss({
|
|
77
|
+
backgroundColor: "var(--ds-border-accent-green, #22A06B)"
|
|
78
|
+
});
|
|
79
|
+
var editingStyleNode = convertToInlineCss({
|
|
80
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-purple, #8270DB)"),
|
|
81
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
82
|
+
});
|
|
83
|
+
var traditionalStyleNode = convertToInlineCss({
|
|
84
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-green, #22A06B)"),
|
|
85
|
+
borderRadius: "var(--ds-radius-small, 4px)"
|
|
86
|
+
});
|
|
87
|
+
var editingStyleCardBlockNode = convertToInlineCss({
|
|
88
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-purple, #8270DB)"),
|
|
89
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
90
|
+
});
|
|
91
|
+
var traditionalStyleCardBlockNode = convertToInlineCss({
|
|
92
|
+
boxShadow: "0 0 0 1px ".concat("var(--ds-border-accent-green, #22A06B)"),
|
|
93
|
+
borderRadius: "var(--ds-radius-medium, 6px)"
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
97
|
+
*
|
|
98
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
99
|
+
* @returns Prosemirror inline decoration
|
|
100
|
+
*/
|
|
101
|
+
export var createBlockChangedDecoration = function createBlockChangedDecoration(change, colourScheme) {
|
|
102
|
+
return Decoration.node(change.from, change.to, {
|
|
103
|
+
style: getEditorStyleNode(change.name, colourScheme),
|
|
104
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
105
|
+
class: "show-diff-changed-decoration-node-".concat(colourScheme || 'standard')
|
|
106
|
+
}, {});
|
|
107
|
+
};
|
|
30
108
|
var deletedContentStyle = convertToInlineCss({
|
|
31
109
|
color: "var(--ds-text-accent-gray, #44546F)",
|
|
32
110
|
textDecoration: 'line-through',
|
|
@@ -2,9 +2,9 @@ import { type EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
|
2
2
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
3
|
import type { ShowDiffPluginState } from './main';
|
|
4
4
|
import type { NodeViewSerializer } from './NodeViewSerializer';
|
|
5
|
-
export declare const calculateDiffDecorations: ({ state, pluginState, nodeViewSerializer, colourScheme, }: {
|
|
5
|
+
export declare const calculateDiffDecorations: import("memoize-one").MemoizedFn<({ state, pluginState, nodeViewSerializer, colourScheme, }: {
|
|
6
6
|
colourScheme?: "standard" | "traditional";
|
|
7
7
|
nodeViewSerializer: NodeViewSerializer;
|
|
8
8
|
pluginState: Omit<ShowDiffPluginState, "decorations">;
|
|
9
9
|
state: EditorState;
|
|
10
|
-
}) => DecorationSet
|
|
10
|
+
}) => DecorationSet>;
|
|
@@ -12,6 +12,17 @@ export declare const createInlineChangedDecoration: (change: {
|
|
|
12
12
|
fromB: number;
|
|
13
13
|
toB: number;
|
|
14
14
|
}, colourScheme?: "standard" | "traditional") => Decoration;
|
|
15
|
+
/**
|
|
16
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
17
|
+
*
|
|
18
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
19
|
+
* @returns Prosemirror inline decoration
|
|
20
|
+
*/
|
|
21
|
+
export declare const createBlockChangedDecoration: (change: {
|
|
22
|
+
from: number;
|
|
23
|
+
name: string;
|
|
24
|
+
to: number;
|
|
25
|
+
}, colourScheme?: "standard" | "traditional") => Decoration;
|
|
15
26
|
interface DeletedContentDecorationProps {
|
|
16
27
|
change: Change;
|
|
17
28
|
colourScheme?: 'standard' | 'traditional';
|
|
@@ -2,9 +2,9 @@ import { type EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
|
2
2
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
3
3
|
import type { ShowDiffPluginState } from './main';
|
|
4
4
|
import type { NodeViewSerializer } from './NodeViewSerializer';
|
|
5
|
-
export declare const calculateDiffDecorations: ({ state, pluginState, nodeViewSerializer, colourScheme, }: {
|
|
5
|
+
export declare const calculateDiffDecorations: import("memoize-one").MemoizedFn<({ state, pluginState, nodeViewSerializer, colourScheme, }: {
|
|
6
6
|
colourScheme?: "standard" | "traditional";
|
|
7
7
|
nodeViewSerializer: NodeViewSerializer;
|
|
8
8
|
pluginState: Omit<ShowDiffPluginState, "decorations">;
|
|
9
9
|
state: EditorState;
|
|
10
|
-
}) => DecorationSet
|
|
10
|
+
}) => DecorationSet>;
|
|
@@ -12,6 +12,17 @@ export declare const createInlineChangedDecoration: (change: {
|
|
|
12
12
|
fromB: number;
|
|
13
13
|
toB: number;
|
|
14
14
|
}, colourScheme?: "standard" | "traditional") => Decoration;
|
|
15
|
+
/**
|
|
16
|
+
* Inline decoration used for insertions as the content already exists in the document
|
|
17
|
+
*
|
|
18
|
+
* @param change Changeset "change" containing information about the change content + range
|
|
19
|
+
* @returns Prosemirror inline decoration
|
|
20
|
+
*/
|
|
21
|
+
export declare const createBlockChangedDecoration: (change: {
|
|
22
|
+
from: number;
|
|
23
|
+
name: string;
|
|
24
|
+
to: number;
|
|
25
|
+
}, colourScheme?: "standard" | "traditional") => Decoration;
|
|
15
26
|
interface DeletedContentDecorationProps {
|
|
16
27
|
change: Change;
|
|
17
28
|
colourScheme?: 'standard' | 'traditional';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,13 +28,16 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"atlaskit:src": "src/index.ts",
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@atlaskit/adf-schema": "^51.2.0",
|
|
31
32
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
32
|
-
"@atlaskit/tokens": "^
|
|
33
|
+
"@atlaskit/tokens": "^7.0.0",
|
|
33
34
|
"@babel/runtime": "^7.0.0",
|
|
35
|
+
"lodash": "^4.17.21",
|
|
36
|
+
"memoize-one": "^6.0.0",
|
|
34
37
|
"prosemirror-changeset": "^2.2.1"
|
|
35
38
|
},
|
|
36
39
|
"peerDependencies": {
|
|
37
|
-
"@atlaskit/editor-common": "^110.
|
|
40
|
+
"@atlaskit/editor-common": "^110.13.0",
|
|
38
41
|
"react": "^18.2.0"
|
|
39
42
|
},
|
|
40
43
|
"techstack": {
|