@atlaskit/editor-plugin-show-diff 3.2.4 → 3.2.6
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/afm-jira/tsconfig.json +1 -1
- package/dist/cjs/pm-plugins/calculateDiffDecorations.js +4 -25
- package/dist/cjs/pm-plugins/decorations.js +12 -5
- package/dist/cjs/pm-plugins/simplifyChanges.js +77 -0
- package/dist/es2019/pm-plugins/calculateDiffDecorations.js +4 -23
- package/dist/es2019/pm-plugins/decorations.js +12 -5
- package/dist/es2019/pm-plugins/simplifyChanges.js +58 -0
- package/dist/esm/pm-plugins/calculateDiffDecorations.js +4 -25
- package/dist/esm/pm-plugins/decorations.js +12 -5
- package/dist/esm/pm-plugins/simplifyChanges.js +72 -0
- package/dist/types/pm-plugins/simplifyChanges.d.ts +3 -0
- package/dist/types-ts4.5/pm-plugins/simplifyChanges.d.ts +3 -0
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 3.2.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`05ee61c6ace09`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/05ee61c6ace09) -
|
|
8
|
+
Improve performance of show diff by increasing merge of steps
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 3.2.5
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`a05464ea42678`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/a05464ea42678) -
|
|
16
|
+
EDITOR-2791 bump adf-schema
|
|
17
|
+
- [`657693883946f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/657693883946f) -
|
|
18
|
+
Fix diffs for extension nodes
|
|
19
|
+
- Updated dependencies
|
|
20
|
+
|
|
3
21
|
## 3.2.4
|
|
4
22
|
|
|
5
23
|
### Patch Changes
|
package/afm-jira/tsconfig.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"extends": "../../../../tsconfig.entry-points.jira.json",
|
|
3
3
|
"compilerOptions": {
|
|
4
4
|
"target": "es5",
|
|
5
|
-
"outDir": "../../../../../tsDist/@atlaskit__editor-plugin-show-diff/app",
|
|
5
|
+
"outDir": "../../../../../jira/tsDist/@atlaskit__editor-plugin-show-diff/app",
|
|
6
6
|
"rootDir": "../",
|
|
7
7
|
"composite": true
|
|
8
8
|
},
|
|
@@ -11,12 +11,12 @@ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/de
|
|
|
11
11
|
var _isEqual = _interopRequireDefault(require("lodash/isEqual"));
|
|
12
12
|
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
|
|
13
13
|
var _prosemirrorChangeset = require("prosemirror-changeset");
|
|
14
|
-
var _steps = require("@atlaskit/adf-schema/steps");
|
|
15
14
|
var _document = require("@atlaskit/editor-common/utils/document");
|
|
16
15
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
17
16
|
var _attributeDecorations = require("./attributeDecorations");
|
|
18
17
|
var _decorations = require("./decorations");
|
|
19
18
|
var _markDecorations = require("./markDecorations");
|
|
19
|
+
var _simplifyChanges = require("./simplifyChanges");
|
|
20
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; } } }; }
|
|
21
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; } }
|
|
22
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; }
|
|
@@ -69,27 +69,6 @@ function optimizeChanges(changes) {
|
|
|
69
69
|
optimized.push(current);
|
|
70
70
|
return optimized;
|
|
71
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);
|
|
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
72
|
var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref) {
|
|
94
73
|
var state = _ref.state,
|
|
95
74
|
pluginState = _ref.pluginState,
|
|
@@ -97,8 +76,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
|
|
|
97
76
|
colourScheme = _ref.colourScheme,
|
|
98
77
|
intl = _ref.intl;
|
|
99
78
|
var originalDoc = pluginState.originalDoc,
|
|
100
|
-
|
|
101
|
-
var steps = simplifySteps(rawSteps);
|
|
79
|
+
steps = pluginState.steps;
|
|
102
80
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
103
81
|
return _view.DecorationSet.empty;
|
|
104
82
|
}
|
|
@@ -106,7 +84,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
|
|
|
106
84
|
var steppedDoc = originalDoc;
|
|
107
85
|
var attrSteps = [];
|
|
108
86
|
var changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc);
|
|
109
|
-
var
|
|
87
|
+
var simplifiedSteps = (0, _simplifyChanges.simplifySteps)(steps, originalDoc);
|
|
88
|
+
var _iterator = _createForOfIteratorHelper(simplifiedSteps),
|
|
110
89
|
_step;
|
|
111
90
|
try {
|
|
112
91
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -49,10 +49,6 @@ var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
|
49
49
|
case 'tableHeader':
|
|
50
50
|
return undefined;
|
|
51
51
|
// Handle table separately to avoid border issues
|
|
52
|
-
case 'embedCard':
|
|
53
|
-
return (0, _lazyNodeView.convertToInlineCss)({
|
|
54
|
-
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
55
|
-
});
|
|
56
52
|
case 'paragraph':
|
|
57
53
|
case 'heading':
|
|
58
54
|
case 'hardBreak':
|
|
@@ -64,6 +60,8 @@ var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
|
64
60
|
case 'bulletList':
|
|
65
61
|
case 'orderedList':
|
|
66
62
|
return undefined;
|
|
63
|
+
case 'extension':
|
|
64
|
+
case 'embedCard':
|
|
67
65
|
case 'listItem':
|
|
68
66
|
return (0, _lazyNodeView.convertToInlineCss)({
|
|
69
67
|
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
@@ -143,6 +141,14 @@ var getDeletedContentStyleUnbounded = exports.getDeletedContentStyleUnbounded =
|
|
|
143
141
|
var getDeletedContentStyle = exports.getDeletedContentStyle = function getDeletedContentStyle(colourScheme) {
|
|
144
142
|
return colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
|
|
145
143
|
};
|
|
144
|
+
var getNodeClass = function getNodeClass(name) {
|
|
145
|
+
switch (name) {
|
|
146
|
+
case 'extension':
|
|
147
|
+
return 'show-diff-changed-decoration-node';
|
|
148
|
+
default:
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
};
|
|
146
152
|
|
|
147
153
|
/**
|
|
148
154
|
* Inline decoration used for insertions as the content already exists in the document
|
|
@@ -153,7 +159,8 @@ var getDeletedContentStyle = exports.getDeletedContentStyle = function getDelete
|
|
|
153
159
|
var createBlockChangedDecoration = exports.createBlockChangedDecoration = function createBlockChangedDecoration(change, colourScheme) {
|
|
154
160
|
return _view.Decoration.node(change.from, change.to, {
|
|
155
161
|
style: getEditorStyleNode(change.name, colourScheme),
|
|
156
|
-
'data-testid': 'show-diff-changed-decoration-node'
|
|
162
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
163
|
+
class: getNodeClass(change.name)
|
|
157
164
|
}, {});
|
|
158
165
|
};
|
|
159
166
|
var createDeletedContentDecoration = exports.createDeletedContentDecoration = function createDeletedContentDecoration(_ref) {
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.simplifySteps = simplifySteps;
|
|
7
|
+
var _steps = require("@atlaskit/adf-schema/steps");
|
|
8
|
+
var _document = require("@atlaskit/editor-common/utils/document");
|
|
9
|
+
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
10
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
11
|
+
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; } } }; }
|
|
12
|
+
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; } }
|
|
13
|
+
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; }
|
|
14
|
+
/**
|
|
15
|
+
* Attempts to merge two consecutive ReplaceStep operations.
|
|
16
|
+
* This merges steps where:
|
|
17
|
+
* - Both steps replace content at the same starting position
|
|
18
|
+
* - The second step's range encompasses the first step's range
|
|
19
|
+
* - The second step has content to insert
|
|
20
|
+
* Returns null if steps cannot be merged.
|
|
21
|
+
*/
|
|
22
|
+
function mergeReplaceSteps(step1, step2) {
|
|
23
|
+
if (!(step1 instanceof _transform.ReplaceStep) || !(step2 instanceof _transform.ReplaceStep)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (step1.from === step2.from && step2.to >= step1.to && step2.slice.size >= step1.slice.size) {
|
|
27
|
+
return new _transform.ReplaceStep(step1.from, step1.to, step2.slice);
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
33
|
+
function simplifySteps(steps, originalDoc) {
|
|
34
|
+
var stepsToFilter = (0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga') ? removeUnusedSteps(steps, originalDoc) : steps;
|
|
35
|
+
return stepsToFilter
|
|
36
|
+
// Remove steps that don't affect document structure or content
|
|
37
|
+
.filter(function (step) {
|
|
38
|
+
return !(step instanceof _steps.AnalyticsStep);
|
|
39
|
+
})
|
|
40
|
+
// Merge consecutive steps where possible
|
|
41
|
+
.reduce(function (acc, step) {
|
|
42
|
+
var _lastStep$merge, _lastStep$merge2, _lastStep$merge3;
|
|
43
|
+
var lastStep = acc[acc.length - 1];
|
|
44
|
+
var merged = (0, _platformFeatureFlags.fg)('platform_editor_ai_aifc_patch_ga') ? (_lastStep$merge = lastStep === null || lastStep === void 0 || (_lastStep$merge2 = lastStep.merge) === null || _lastStep$merge2 === void 0 ? void 0 : _lastStep$merge2.call(lastStep, step)) !== null && _lastStep$merge !== void 0 ? _lastStep$merge : mergeReplaceSteps(lastStep, step) : lastStep === null || lastStep === void 0 || (_lastStep$merge3 = lastStep.merge) === null || _lastStep$merge3 === void 0 ? void 0 : _lastStep$merge3.call(lastStep, step);
|
|
45
|
+
if (merged) {
|
|
46
|
+
acc[acc.length - 1] = merged;
|
|
47
|
+
} else {
|
|
48
|
+
acc.push(step);
|
|
49
|
+
}
|
|
50
|
+
return acc;
|
|
51
|
+
}, []);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Does a first pass to remove steps that don't impact the document
|
|
56
|
+
*/
|
|
57
|
+
function removeUnusedSteps(steps, originalDoc) {
|
|
58
|
+
var finalSteps = [];
|
|
59
|
+
var firstPassDoc = originalDoc;
|
|
60
|
+
var _iterator = _createForOfIteratorHelper(steps),
|
|
61
|
+
_step;
|
|
62
|
+
try {
|
|
63
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
64
|
+
var step = _step.value;
|
|
65
|
+
var result = step.apply(firstPassDoc);
|
|
66
|
+
if (result.failed === null && result.doc && !(0, _document.areNodesEqualIgnoreAttrs)(firstPassDoc, result.doc, ['localId'])) {
|
|
67
|
+
finalSteps.push(step);
|
|
68
|
+
firstPassDoc = result.doc;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
} catch (err) {
|
|
72
|
+
_iterator.e(err);
|
|
73
|
+
} finally {
|
|
74
|
+
_iterator.f();
|
|
75
|
+
}
|
|
76
|
+
return finalSteps;
|
|
77
|
+
}
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
import isEqual from 'lodash/isEqual';
|
|
3
3
|
import memoizeOne from 'memoize-one';
|
|
4
4
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
5
|
-
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
6
5
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
7
6
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
7
|
import { getAttrChangeRanges, stepIsValidAttrChange } from './attributeDecorations';
|
|
9
8
|
import { createInlineChangedDecoration, createDeletedContentDecoration, createBlockChangedDecoration } from './decorations';
|
|
10
9
|
import { getMarkChangeRanges } from './markDecorations';
|
|
10
|
+
import { simplifySteps } from './simplifyChanges';
|
|
11
11
|
const calculateNodesForBlockDecoration = (doc, from, to, colourScheme) => {
|
|
12
12
|
const decorations = [];
|
|
13
13
|
// Iterate over the document nodes within the range
|
|
@@ -59,25 +59,6 @@ function optimizeChanges(changes) {
|
|
|
59
59
|
optimized.push(current);
|
|
60
60
|
return optimized;
|
|
61
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))
|
|
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
62
|
const calculateDiffDecorationsInner = ({
|
|
82
63
|
state,
|
|
83
64
|
pluginState,
|
|
@@ -87,9 +68,8 @@ const calculateDiffDecorationsInner = ({
|
|
|
87
68
|
}) => {
|
|
88
69
|
const {
|
|
89
70
|
originalDoc,
|
|
90
|
-
steps
|
|
71
|
+
steps
|
|
91
72
|
} = pluginState;
|
|
92
|
-
const steps = simplifySteps(rawSteps);
|
|
93
73
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
94
74
|
return DecorationSet.empty;
|
|
95
75
|
}
|
|
@@ -99,7 +79,8 @@ const calculateDiffDecorationsInner = ({
|
|
|
99
79
|
let steppedDoc = originalDoc;
|
|
100
80
|
const attrSteps = [];
|
|
101
81
|
let changeset = ChangeSet.create(originalDoc);
|
|
102
|
-
|
|
82
|
+
const simplifiedSteps = simplifySteps(steps, originalDoc);
|
|
83
|
+
for (const step of simplifiedSteps) {
|
|
103
84
|
const result = step.apply(steppedDoc);
|
|
104
85
|
if (result.failed === null && result.doc) {
|
|
105
86
|
if (stepIsValidAttrChange(step, steppedDoc, result.doc)) {
|
|
@@ -41,10 +41,6 @@ const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
|
41
41
|
case 'tableHeader':
|
|
42
42
|
return undefined;
|
|
43
43
|
// Handle table separately to avoid border issues
|
|
44
|
-
case 'embedCard':
|
|
45
|
-
return convertToInlineCss({
|
|
46
|
-
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
47
|
-
});
|
|
48
44
|
case 'paragraph':
|
|
49
45
|
case 'heading':
|
|
50
46
|
case 'hardBreak':
|
|
@@ -56,6 +52,8 @@ const getEditorStyleNode = (nodeName, colourScheme) => {
|
|
|
56
52
|
case 'bulletList':
|
|
57
53
|
case 'orderedList':
|
|
58
54
|
return undefined;
|
|
55
|
+
case 'extension':
|
|
56
|
+
case 'embedCard':
|
|
59
57
|
case 'listItem':
|
|
60
58
|
return convertToInlineCss({
|
|
61
59
|
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
@@ -131,6 +129,14 @@ const deletedTraditionalContentStyleUnbounded = convertToInlineCss({
|
|
|
131
129
|
});
|
|
132
130
|
export const getDeletedContentStyleUnbounded = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyleUnbounded : deletedContentStyleUnbounded;
|
|
133
131
|
export const getDeletedContentStyle = colourScheme => colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
|
|
132
|
+
const getNodeClass = name => {
|
|
133
|
+
switch (name) {
|
|
134
|
+
case 'extension':
|
|
135
|
+
return 'show-diff-changed-decoration-node';
|
|
136
|
+
default:
|
|
137
|
+
return undefined;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
134
140
|
|
|
135
141
|
/**
|
|
136
142
|
* Inline decoration used for insertions as the content already exists in the document
|
|
@@ -140,7 +146,8 @@ export const getDeletedContentStyle = colourScheme => colourScheme === 'traditio
|
|
|
140
146
|
*/
|
|
141
147
|
export const createBlockChangedDecoration = (change, colourScheme) => Decoration.node(change.from, change.to, {
|
|
142
148
|
style: getEditorStyleNode(change.name, colourScheme),
|
|
143
|
-
'data-testid': 'show-diff-changed-decoration-node'
|
|
149
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
150
|
+
class: getNodeClass(change.name)
|
|
144
151
|
}, {});
|
|
145
152
|
export const createDeletedContentDecoration = ({
|
|
146
153
|
change,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
2
|
+
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
3
|
+
import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
4
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Attempts to merge two consecutive ReplaceStep operations.
|
|
8
|
+
* This merges steps where:
|
|
9
|
+
* - Both steps replace content at the same starting position
|
|
10
|
+
* - The second step's range encompasses the first step's range
|
|
11
|
+
* - The second step has content to insert
|
|
12
|
+
* Returns null if steps cannot be merged.
|
|
13
|
+
*/
|
|
14
|
+
function mergeReplaceSteps(step1, step2) {
|
|
15
|
+
if (!(step1 instanceof ReplaceStep) || !(step2 instanceof ReplaceStep)) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
if (step1.from === step2.from && step2.to >= step1.to && step2.slice.size >= step1.slice.size) {
|
|
19
|
+
return new ReplaceStep(step1.from, step1.to, step2.slice);
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
25
|
+
export function simplifySteps(steps, originalDoc) {
|
|
26
|
+
const stepsToFilter = fg('platform_editor_ai_aifc_patch_ga') ? removeUnusedSteps(steps, originalDoc) : steps;
|
|
27
|
+
return stepsToFilter
|
|
28
|
+
// Remove steps that don't affect document structure or content
|
|
29
|
+
.filter(step => !(step instanceof AnalyticsStep))
|
|
30
|
+
// Merge consecutive steps where possible
|
|
31
|
+
.reduce((acc, step) => {
|
|
32
|
+
var _lastStep$merge, _lastStep$merge2, _lastStep$merge3;
|
|
33
|
+
const lastStep = acc[acc.length - 1];
|
|
34
|
+
const merged = fg('platform_editor_ai_aifc_patch_ga') ? (_lastStep$merge = lastStep === null || lastStep === void 0 ? void 0 : (_lastStep$merge2 = lastStep.merge) === null || _lastStep$merge2 === void 0 ? void 0 : _lastStep$merge2.call(lastStep, step)) !== null && _lastStep$merge !== void 0 ? _lastStep$merge : mergeReplaceSteps(lastStep, step) : lastStep === null || lastStep === void 0 ? void 0 : (_lastStep$merge3 = lastStep.merge) === null || _lastStep$merge3 === void 0 ? void 0 : _lastStep$merge3.call(lastStep, step);
|
|
35
|
+
if (merged) {
|
|
36
|
+
acc[acc.length - 1] = merged;
|
|
37
|
+
} else {
|
|
38
|
+
acc.push(step);
|
|
39
|
+
}
|
|
40
|
+
return acc;
|
|
41
|
+
}, []);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Does a first pass to remove steps that don't impact the document
|
|
46
|
+
*/
|
|
47
|
+
function removeUnusedSteps(steps, originalDoc) {
|
|
48
|
+
const finalSteps = [];
|
|
49
|
+
let firstPassDoc = originalDoc;
|
|
50
|
+
for (const step of steps) {
|
|
51
|
+
const result = step.apply(firstPassDoc);
|
|
52
|
+
if (result.failed === null && result.doc && !areNodesEqualIgnoreAttrs(firstPassDoc, result.doc, ['localId'])) {
|
|
53
|
+
finalSteps.push(step);
|
|
54
|
+
firstPassDoc = result.doc;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return finalSteps;
|
|
58
|
+
}
|
|
@@ -10,12 +10,12 @@ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t =
|
|
|
10
10
|
import isEqual from 'lodash/isEqual';
|
|
11
11
|
import memoizeOne from 'memoize-one';
|
|
12
12
|
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
13
|
-
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
14
13
|
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
15
14
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
16
15
|
import { getAttrChangeRanges, stepIsValidAttrChange } from './attributeDecorations';
|
|
17
16
|
import { createInlineChangedDecoration, createDeletedContentDecoration, createBlockChangedDecoration } from './decorations';
|
|
18
17
|
import { getMarkChangeRanges } from './markDecorations';
|
|
18
|
+
import { simplifySteps } from './simplifyChanges';
|
|
19
19
|
var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(doc, from, to, colourScheme) {
|
|
20
20
|
var decorations = [];
|
|
21
21
|
// Iterate over the document nodes within the range
|
|
@@ -63,27 +63,6 @@ function optimizeChanges(changes) {
|
|
|
63
63
|
optimized.push(current);
|
|
64
64
|
return optimized;
|
|
65
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);
|
|
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
66
|
var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref) {
|
|
88
67
|
var state = _ref.state,
|
|
89
68
|
pluginState = _ref.pluginState,
|
|
@@ -91,8 +70,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
|
|
|
91
70
|
colourScheme = _ref.colourScheme,
|
|
92
71
|
intl = _ref.intl;
|
|
93
72
|
var originalDoc = pluginState.originalDoc,
|
|
94
|
-
|
|
95
|
-
var steps = simplifySteps(rawSteps);
|
|
73
|
+
steps = pluginState.steps;
|
|
96
74
|
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
97
75
|
return DecorationSet.empty;
|
|
98
76
|
}
|
|
@@ -100,7 +78,8 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref)
|
|
|
100
78
|
var steppedDoc = originalDoc;
|
|
101
79
|
var attrSteps = [];
|
|
102
80
|
var changeset = ChangeSet.create(originalDoc);
|
|
103
|
-
var
|
|
81
|
+
var simplifiedSteps = simplifySteps(steps, originalDoc);
|
|
82
|
+
var _iterator = _createForOfIteratorHelper(simplifiedSteps),
|
|
104
83
|
_step;
|
|
105
84
|
try {
|
|
106
85
|
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
@@ -43,10 +43,6 @@ var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
|
43
43
|
case 'tableHeader':
|
|
44
44
|
return undefined;
|
|
45
45
|
// Handle table separately to avoid border issues
|
|
46
|
-
case 'embedCard':
|
|
47
|
-
return convertToInlineCss({
|
|
48
|
-
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
49
|
-
});
|
|
50
46
|
case 'paragraph':
|
|
51
47
|
case 'heading':
|
|
52
48
|
case 'hardBreak':
|
|
@@ -58,6 +54,8 @@ var getEditorStyleNode = function getEditorStyleNode(nodeName, colourScheme) {
|
|
|
58
54
|
case 'bulletList':
|
|
59
55
|
case 'orderedList':
|
|
60
56
|
return undefined;
|
|
57
|
+
case 'extension':
|
|
58
|
+
case 'embedCard':
|
|
61
59
|
case 'listItem':
|
|
62
60
|
return convertToInlineCss({
|
|
63
61
|
'--diff-decoration-marker-color': colourScheme === 'traditional' ? "var(--ds-border-accent-green, #22A06B)" : "var(--ds-border-accent-purple, #AF59E1)"
|
|
@@ -137,6 +135,14 @@ export var getDeletedContentStyleUnbounded = function getDeletedContentStyleUnbo
|
|
|
137
135
|
export var getDeletedContentStyle = function getDeletedContentStyle(colourScheme) {
|
|
138
136
|
return colourScheme === 'traditional' ? deletedTraditionalContentStyle : deletedContentStyle;
|
|
139
137
|
};
|
|
138
|
+
var getNodeClass = function getNodeClass(name) {
|
|
139
|
+
switch (name) {
|
|
140
|
+
case 'extension':
|
|
141
|
+
return 'show-diff-changed-decoration-node';
|
|
142
|
+
default:
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
140
146
|
|
|
141
147
|
/**
|
|
142
148
|
* Inline decoration used for insertions as the content already exists in the document
|
|
@@ -147,7 +153,8 @@ export var getDeletedContentStyle = function getDeletedContentStyle(colourScheme
|
|
|
147
153
|
export var createBlockChangedDecoration = function createBlockChangedDecoration(change, colourScheme) {
|
|
148
154
|
return Decoration.node(change.from, change.to, {
|
|
149
155
|
style: getEditorStyleNode(change.name, colourScheme),
|
|
150
|
-
'data-testid': 'show-diff-changed-decoration-node'
|
|
156
|
+
'data-testid': 'show-diff-changed-decoration-node',
|
|
157
|
+
class: getNodeClass(change.name)
|
|
151
158
|
}, {});
|
|
152
159
|
};
|
|
153
160
|
export var createDeletedContentDecoration = function createDeletedContentDecoration(_ref) {
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
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
|
+
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
|
+
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; }
|
|
4
|
+
import { AnalyticsStep } from '@atlaskit/adf-schema/steps';
|
|
5
|
+
import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document';
|
|
6
|
+
import { ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
7
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Attempts to merge two consecutive ReplaceStep operations.
|
|
11
|
+
* This merges steps where:
|
|
12
|
+
* - Both steps replace content at the same starting position
|
|
13
|
+
* - The second step's range encompasses the first step's range
|
|
14
|
+
* - The second step has content to insert
|
|
15
|
+
* Returns null if steps cannot be merged.
|
|
16
|
+
*/
|
|
17
|
+
function mergeReplaceSteps(step1, step2) {
|
|
18
|
+
if (!(step1 instanceof ReplaceStep) || !(step2 instanceof ReplaceStep)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
if (step1.from === step2.from && step2.to >= step1.to && step2.slice.size >= step1.slice.size) {
|
|
22
|
+
return new ReplaceStep(step1.from, step1.to, step2.slice);
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Simplifies the steps to improve performance and reduce fragmentation in diffs
|
|
28
|
+
export function simplifySteps(steps, originalDoc) {
|
|
29
|
+
var stepsToFilter = fg('platform_editor_ai_aifc_patch_ga') ? removeUnusedSteps(steps, originalDoc) : steps;
|
|
30
|
+
return stepsToFilter
|
|
31
|
+
// Remove steps that don't affect document structure or content
|
|
32
|
+
.filter(function (step) {
|
|
33
|
+
return !(step instanceof AnalyticsStep);
|
|
34
|
+
})
|
|
35
|
+
// Merge consecutive steps where possible
|
|
36
|
+
.reduce(function (acc, step) {
|
|
37
|
+
var _lastStep$merge, _lastStep$merge2, _lastStep$merge3;
|
|
38
|
+
var lastStep = acc[acc.length - 1];
|
|
39
|
+
var merged = fg('platform_editor_ai_aifc_patch_ga') ? (_lastStep$merge = lastStep === null || lastStep === void 0 || (_lastStep$merge2 = lastStep.merge) === null || _lastStep$merge2 === void 0 ? void 0 : _lastStep$merge2.call(lastStep, step)) !== null && _lastStep$merge !== void 0 ? _lastStep$merge : mergeReplaceSteps(lastStep, step) : lastStep === null || lastStep === void 0 || (_lastStep$merge3 = lastStep.merge) === null || _lastStep$merge3 === void 0 ? void 0 : _lastStep$merge3.call(lastStep, step);
|
|
40
|
+
if (merged) {
|
|
41
|
+
acc[acc.length - 1] = merged;
|
|
42
|
+
} else {
|
|
43
|
+
acc.push(step);
|
|
44
|
+
}
|
|
45
|
+
return acc;
|
|
46
|
+
}, []);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Does a first pass to remove steps that don't impact the document
|
|
51
|
+
*/
|
|
52
|
+
function removeUnusedSteps(steps, originalDoc) {
|
|
53
|
+
var finalSteps = [];
|
|
54
|
+
var firstPassDoc = originalDoc;
|
|
55
|
+
var _iterator = _createForOfIteratorHelper(steps),
|
|
56
|
+
_step;
|
|
57
|
+
try {
|
|
58
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
59
|
+
var step = _step.value;
|
|
60
|
+
var result = step.apply(firstPassDoc);
|
|
61
|
+
if (result.failed === null && result.doc && !areNodesEqualIgnoreAttrs(firstPassDoc, result.doc, ['localId'])) {
|
|
62
|
+
finalSteps.push(step);
|
|
63
|
+
firstPassDoc = result.doc;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} catch (err) {
|
|
67
|
+
_iterator.e(err);
|
|
68
|
+
} finally {
|
|
69
|
+
_iterator.f();
|
|
70
|
+
}
|
|
71
|
+
return finalSteps;
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-show-diff",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.6",
|
|
4
4
|
"description": "ShowDiff plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -28,18 +28,18 @@
|
|
|
28
28
|
"sideEffects": false,
|
|
29
29
|
"atlaskit:src": "src/index.ts",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@atlaskit/adf-schema": "^51.
|
|
31
|
+
"@atlaskit/adf-schema": "^51.4.0",
|
|
32
32
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
33
33
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
34
34
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
35
|
-
"@atlaskit/tokens": "^8.
|
|
35
|
+
"@atlaskit/tokens": "^8.1.0",
|
|
36
36
|
"@babel/runtime": "^7.0.0",
|
|
37
37
|
"lodash": "^4.17.21",
|
|
38
38
|
"memoize-one": "^6.0.0",
|
|
39
39
|
"prosemirror-changeset": "^2.2.1"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@atlaskit/editor-common": "^110.
|
|
42
|
+
"@atlaskit/editor-common": "^110.33.0",
|
|
43
43
|
"react": "^18.2.0"
|
|
44
44
|
},
|
|
45
45
|
"techstack": {
|