@atlaskit/editor-plugin-show-diff 1.0.0 → 1.0.1
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 +8 -0
- package/dist/cjs/pm-plugins/calculateDiffDecorations.js +100 -0
- package/dist/cjs/pm-plugins/main.js +2 -60
- package/dist/es2019/pm-plugins/calculateDiffDecorations.js +87 -0
- package/dist/es2019/pm-plugins/main.js +2 -54
- package/dist/esm/pm-plugins/calculateDiffDecorations.js +94 -0
- package/dist/esm/pm-plugins/main.js +2 -61
- package/dist/types/pm-plugins/calculateDiffDecorations.d.ts +21 -0
- package/dist/types/pm-plugins/main.d.ts +1 -2
- package/dist/types-ts4.5/pm-plugins/calculateDiffDecorations.d.ts +21 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-show-diff
|
|
2
2
|
|
|
3
|
+
## 1.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`4144b576f0bf8`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/4144b576f0bf8) -
|
|
8
|
+
Ignore attribute changes when ensuring the steps match the final document
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
3
11
|
## 1.0.0
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.areNodesEqual = areNodesEqual;
|
|
7
|
+
exports.calculateDiffDecorations = void 0;
|
|
8
|
+
var _prosemirrorChangeset = require("prosemirror-changeset");
|
|
9
|
+
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
10
|
+
var _decorations = require("./decorations");
|
|
11
|
+
var _markDecorations = require("./markDecorations");
|
|
12
|
+
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
|
+
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; } // eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
15
|
+
var calculateDiffDecorations = exports.calculateDiffDecorations = function calculateDiffDecorations(_ref) {
|
|
16
|
+
var state = _ref.state,
|
|
17
|
+
pluginState = _ref.pluginState,
|
|
18
|
+
nodeViewSerializer = _ref.nodeViewSerializer;
|
|
19
|
+
var originalDoc = pluginState.originalDoc,
|
|
20
|
+
steps = pluginState.steps;
|
|
21
|
+
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
22
|
+
return _view.DecorationSet.empty;
|
|
23
|
+
}
|
|
24
|
+
var tr = state.tr;
|
|
25
|
+
var steppedDoc = originalDoc;
|
|
26
|
+
var changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc);
|
|
27
|
+
var _iterator = _createForOfIteratorHelper(steps),
|
|
28
|
+
_step;
|
|
29
|
+
try {
|
|
30
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
31
|
+
var step = _step.value;
|
|
32
|
+
var result = step.apply(steppedDoc);
|
|
33
|
+
if (result.failed === null && result.doc) {
|
|
34
|
+
steppedDoc = result.doc;
|
|
35
|
+
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Rather than using .eq() we use a custom function that only checks for structural
|
|
39
|
+
// changes and ignores differences in attributes which don't affect decoration positions
|
|
40
|
+
} catch (err) {
|
|
41
|
+
_iterator.e(err);
|
|
42
|
+
} finally {
|
|
43
|
+
_iterator.f();
|
|
44
|
+
}
|
|
45
|
+
if (!areNodesEqual(steppedDoc, tr.doc)) {
|
|
46
|
+
return _view.DecorationSet.empty;
|
|
47
|
+
}
|
|
48
|
+
var changes = (0, _prosemirrorChangeset.simplifyChanges)(changeset.changes, tr.doc);
|
|
49
|
+
var decorations = [];
|
|
50
|
+
changes.forEach(function (change) {
|
|
51
|
+
if (change.inserted.length > 0) {
|
|
52
|
+
decorations.push((0, _decorations.createInlineChangedDecoration)(change));
|
|
53
|
+
}
|
|
54
|
+
if (change.deleted.length > 0) {
|
|
55
|
+
var decoration = (0, _decorations.createDeletedContentDecoration)({
|
|
56
|
+
change: change,
|
|
57
|
+
doc: originalDoc,
|
|
58
|
+
nodeViewSerializer: nodeViewSerializer
|
|
59
|
+
});
|
|
60
|
+
if (decoration) {
|
|
61
|
+
decorations.push(decoration);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
(0, _markDecorations.getMarkChangeRanges)(steps).forEach(function (change) {
|
|
66
|
+
decorations.push((0, _decorations.createInlineChangedDecoration)(change));
|
|
67
|
+
});
|
|
68
|
+
return _view.DecorationSet.empty.add(tr.doc, decorations);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Compares two ProseMirror documents for equality, ignoring attributes
|
|
73
|
+
* which don't affect the document structure.
|
|
74
|
+
*
|
|
75
|
+
* This is almost a copy of the .eq() PM function - tweaked to ignore attrs
|
|
76
|
+
*
|
|
77
|
+
* @param doc1 PMNode
|
|
78
|
+
* @param doc2 PMNode
|
|
79
|
+
* @returns boolean
|
|
80
|
+
*/
|
|
81
|
+
function areNodesEqual(node1, node2) {
|
|
82
|
+
if (node1.isText) {
|
|
83
|
+
return node1.eq(node2);
|
|
84
|
+
}
|
|
85
|
+
return node1 === node2 || node1.hasMarkup(node2.type, node1.attrs, node2.marks) && areFragmentsEqual(node1.content, node2.content);
|
|
86
|
+
}
|
|
87
|
+
function areFragmentsEqual(frag1, frag2) {
|
|
88
|
+
if (frag1.content.length !== frag2.content.length) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
var childrenEqual = true;
|
|
92
|
+
frag1.content.forEach(function (child, i) {
|
|
93
|
+
var otherChild = frag2.child(i);
|
|
94
|
+
if (child === otherChild || otherChild && areNodesEqual(child, otherChild)) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
childrenEqual = false;
|
|
98
|
+
});
|
|
99
|
+
return childrenEqual;
|
|
100
|
+
}
|
|
@@ -6,73 +6,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.showDiffPluginKey = exports.createPlugin = void 0;
|
|
8
8
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
|
-
var _prosemirrorChangeset = require("prosemirror-changeset");
|
|
10
9
|
var _processRawValue = require("@atlaskit/editor-common/process-raw-value");
|
|
11
10
|
var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
|
|
12
11
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
13
12
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
14
13
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
15
|
-
var
|
|
16
|
-
var _markDecorations = require("./markDecorations");
|
|
14
|
+
var _calculateDiffDecorations = require("./calculateDiffDecorations");
|
|
17
15
|
var _NodeViewSerializer = require("./NodeViewSerializer");
|
|
18
16
|
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; }
|
|
19
17
|
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; }
|
|
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
|
-
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
|
-
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; } // eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
23
|
-
var calculateDecorations = function calculateDecorations(_ref) {
|
|
24
|
-
var state = _ref.state,
|
|
25
|
-
pluginState = _ref.pluginState,
|
|
26
|
-
nodeViewSerializer = _ref.nodeViewSerializer;
|
|
27
|
-
var originalDoc = pluginState.originalDoc,
|
|
28
|
-
steps = pluginState.steps;
|
|
29
|
-
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
30
|
-
return _view.DecorationSet.empty;
|
|
31
|
-
}
|
|
32
|
-
var tr = state.tr;
|
|
33
|
-
var steppedDoc = originalDoc;
|
|
34
|
-
var changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc);
|
|
35
|
-
var _iterator = _createForOfIteratorHelper(steps),
|
|
36
|
-
_step;
|
|
37
|
-
try {
|
|
38
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
39
|
-
var step = _step.value;
|
|
40
|
-
var result = step.apply(steppedDoc);
|
|
41
|
-
if (result.failed === null && result.doc) {
|
|
42
|
-
steppedDoc = result.doc;
|
|
43
|
-
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
} catch (err) {
|
|
47
|
-
_iterator.e(err);
|
|
48
|
-
} finally {
|
|
49
|
-
_iterator.f();
|
|
50
|
-
}
|
|
51
|
-
if (!steppedDoc.eq(tr.doc)) {
|
|
52
|
-
return _view.DecorationSet.empty;
|
|
53
|
-
}
|
|
54
|
-
var changes = (0, _prosemirrorChangeset.simplifyChanges)(changeset.changes, tr.doc);
|
|
55
|
-
var decorations = [];
|
|
56
|
-
changes.forEach(function (change) {
|
|
57
|
-
if (change.inserted.length > 0) {
|
|
58
|
-
decorations.push((0, _decorations.createInlineChangedDecoration)(change));
|
|
59
|
-
}
|
|
60
|
-
if (change.deleted.length > 0) {
|
|
61
|
-
var decoration = (0, _decorations.createDeletedContentDecoration)({
|
|
62
|
-
change: change,
|
|
63
|
-
doc: originalDoc,
|
|
64
|
-
nodeViewSerializer: nodeViewSerializer
|
|
65
|
-
});
|
|
66
|
-
if (decoration) {
|
|
67
|
-
decorations.push(decoration);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
(0, _markDecorations.getMarkChangeRanges)(steps).forEach(function (change) {
|
|
72
|
-
decorations.push((0, _decorations.createInlineChangedDecoration)(change));
|
|
73
|
-
});
|
|
74
|
-
return _view.DecorationSet.empty.add(tr.doc, decorations);
|
|
75
|
-
};
|
|
76
18
|
var showDiffPluginKey = exports.showDiffPluginKey = new _state.PluginKey('showDiffPlugin');
|
|
77
19
|
var createPlugin = exports.createPlugin = function createPlugin(config) {
|
|
78
20
|
var nodeViewSerializer = new _NodeViewSerializer.NodeViewSerializer({});
|
|
@@ -103,7 +45,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config) {
|
|
|
103
45
|
isDisplayingChanges: true
|
|
104
46
|
});
|
|
105
47
|
// Calculate and store decorations in state
|
|
106
|
-
var decorations =
|
|
48
|
+
var decorations = (0, _calculateDiffDecorations.calculateDiffDecorations)({
|
|
107
49
|
state: newState,
|
|
108
50
|
pluginState: newPluginState,
|
|
109
51
|
nodeViewSerializer: nodeViewSerializer
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
2
|
+
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
3
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import { createInlineChangedDecoration, createDeletedContentDecoration } from './decorations';
|
|
5
|
+
import { getMarkChangeRanges } from './markDecorations';
|
|
6
|
+
export const calculateDiffDecorations = ({
|
|
7
|
+
state,
|
|
8
|
+
pluginState,
|
|
9
|
+
nodeViewSerializer
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
originalDoc,
|
|
13
|
+
steps
|
|
14
|
+
} = pluginState;
|
|
15
|
+
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
16
|
+
return DecorationSet.empty;
|
|
17
|
+
}
|
|
18
|
+
const {
|
|
19
|
+
tr
|
|
20
|
+
} = state;
|
|
21
|
+
let steppedDoc = originalDoc;
|
|
22
|
+
let changeset = ChangeSet.create(originalDoc);
|
|
23
|
+
for (const step of steps) {
|
|
24
|
+
const result = step.apply(steppedDoc);
|
|
25
|
+
if (result.failed === null && result.doc) {
|
|
26
|
+
steppedDoc = result.doc;
|
|
27
|
+
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
// Rather than using .eq() we use a custom function that only checks for structural
|
|
31
|
+
// changes and ignores differences in attributes which don't affect decoration positions
|
|
32
|
+
if (!areNodesEqual(steppedDoc, tr.doc)) {
|
|
33
|
+
return DecorationSet.empty;
|
|
34
|
+
}
|
|
35
|
+
const changes = simplifyChanges(changeset.changes, tr.doc);
|
|
36
|
+
const decorations = [];
|
|
37
|
+
changes.forEach(change => {
|
|
38
|
+
if (change.inserted.length > 0) {
|
|
39
|
+
decorations.push(createInlineChangedDecoration(change));
|
|
40
|
+
}
|
|
41
|
+
if (change.deleted.length > 0) {
|
|
42
|
+
const decoration = createDeletedContentDecoration({
|
|
43
|
+
change,
|
|
44
|
+
doc: originalDoc,
|
|
45
|
+
nodeViewSerializer
|
|
46
|
+
});
|
|
47
|
+
if (decoration) {
|
|
48
|
+
decorations.push(decoration);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
getMarkChangeRanges(steps).forEach(change => {
|
|
53
|
+
decorations.push(createInlineChangedDecoration(change));
|
|
54
|
+
});
|
|
55
|
+
return DecorationSet.empty.add(tr.doc, decorations);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Compares two ProseMirror documents for equality, ignoring attributes
|
|
60
|
+
* which don't affect the document structure.
|
|
61
|
+
*
|
|
62
|
+
* This is almost a copy of the .eq() PM function - tweaked to ignore attrs
|
|
63
|
+
*
|
|
64
|
+
* @param doc1 PMNode
|
|
65
|
+
* @param doc2 PMNode
|
|
66
|
+
* @returns boolean
|
|
67
|
+
*/
|
|
68
|
+
export function areNodesEqual(node1, node2) {
|
|
69
|
+
if (node1.isText) {
|
|
70
|
+
return node1.eq(node2);
|
|
71
|
+
}
|
|
72
|
+
return node1 === node2 || node1.hasMarkup(node2.type, node1.attrs, node2.marks) && areFragmentsEqual(node1.content, node2.content);
|
|
73
|
+
}
|
|
74
|
+
function areFragmentsEqual(frag1, frag2) {
|
|
75
|
+
if (frag1.content.length !== frag2.content.length) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
let childrenEqual = true;
|
|
79
|
+
frag1.content.forEach((child, i) => {
|
|
80
|
+
const otherChild = frag2.child(i);
|
|
81
|
+
if (child === otherChild || otherChild && areNodesEqual(child, otherChild)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
childrenEqual = false;
|
|
85
|
+
});
|
|
86
|
+
return childrenEqual;
|
|
87
|
+
}
|
|
@@ -1,62 +1,10 @@
|
|
|
1
|
-
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
2
|
-
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
3
1
|
import { processRawValue } from '@atlaskit/editor-common/process-raw-value';
|
|
4
2
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
5
3
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
6
4
|
import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
|
|
7
5
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
8
|
-
import {
|
|
9
|
-
import { getMarkChangeRanges } from './markDecorations';
|
|
6
|
+
import { calculateDiffDecorations } from './calculateDiffDecorations';
|
|
10
7
|
import { NodeViewSerializer } from './NodeViewSerializer';
|
|
11
|
-
const calculateDecorations = ({
|
|
12
|
-
state,
|
|
13
|
-
pluginState,
|
|
14
|
-
nodeViewSerializer
|
|
15
|
-
}) => {
|
|
16
|
-
const {
|
|
17
|
-
originalDoc,
|
|
18
|
-
steps
|
|
19
|
-
} = pluginState;
|
|
20
|
-
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
21
|
-
return DecorationSet.empty;
|
|
22
|
-
}
|
|
23
|
-
const {
|
|
24
|
-
tr
|
|
25
|
-
} = state;
|
|
26
|
-
let steppedDoc = originalDoc;
|
|
27
|
-
let changeset = ChangeSet.create(originalDoc);
|
|
28
|
-
for (const step of steps) {
|
|
29
|
-
const result = step.apply(steppedDoc);
|
|
30
|
-
if (result.failed === null && result.doc) {
|
|
31
|
-
steppedDoc = result.doc;
|
|
32
|
-
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
if (!steppedDoc.eq(tr.doc)) {
|
|
36
|
-
return DecorationSet.empty;
|
|
37
|
-
}
|
|
38
|
-
const changes = simplifyChanges(changeset.changes, tr.doc);
|
|
39
|
-
const decorations = [];
|
|
40
|
-
changes.forEach(change => {
|
|
41
|
-
if (change.inserted.length > 0) {
|
|
42
|
-
decorations.push(createInlineChangedDecoration(change));
|
|
43
|
-
}
|
|
44
|
-
if (change.deleted.length > 0) {
|
|
45
|
-
const decoration = createDeletedContentDecoration({
|
|
46
|
-
change,
|
|
47
|
-
doc: originalDoc,
|
|
48
|
-
nodeViewSerializer
|
|
49
|
-
});
|
|
50
|
-
if (decoration) {
|
|
51
|
-
decorations.push(decoration);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
getMarkChangeRanges(steps).forEach(change => {
|
|
56
|
-
decorations.push(createInlineChangedDecoration(change));
|
|
57
|
-
});
|
|
58
|
-
return DecorationSet.empty.add(tr.doc, decorations);
|
|
59
|
-
};
|
|
60
8
|
export const showDiffPluginKey = new PluginKey('showDiffPlugin');
|
|
61
9
|
export const createPlugin = config => {
|
|
62
10
|
const nodeViewSerializer = new NodeViewSerializer({});
|
|
@@ -89,7 +37,7 @@ export const createPlugin = config => {
|
|
|
89
37
|
isDisplayingChanges: true
|
|
90
38
|
};
|
|
91
39
|
// Calculate and store decorations in state
|
|
92
|
-
const decorations =
|
|
40
|
+
const decorations = calculateDiffDecorations({
|
|
93
41
|
state: newState,
|
|
94
42
|
pluginState: newPluginState,
|
|
95
43
|
nodeViewSerializer
|
|
@@ -0,0 +1,94 @@
|
|
|
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
|
+
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
5
|
+
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
6
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
7
|
+
import { createInlineChangedDecoration, createDeletedContentDecoration } from './decorations';
|
|
8
|
+
import { getMarkChangeRanges } from './markDecorations';
|
|
9
|
+
export var calculateDiffDecorations = function calculateDiffDecorations(_ref) {
|
|
10
|
+
var state = _ref.state,
|
|
11
|
+
pluginState = _ref.pluginState,
|
|
12
|
+
nodeViewSerializer = _ref.nodeViewSerializer;
|
|
13
|
+
var originalDoc = pluginState.originalDoc,
|
|
14
|
+
steps = pluginState.steps;
|
|
15
|
+
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
16
|
+
return DecorationSet.empty;
|
|
17
|
+
}
|
|
18
|
+
var tr = state.tr;
|
|
19
|
+
var steppedDoc = originalDoc;
|
|
20
|
+
var changeset = ChangeSet.create(originalDoc);
|
|
21
|
+
var _iterator = _createForOfIteratorHelper(steps),
|
|
22
|
+
_step;
|
|
23
|
+
try {
|
|
24
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
25
|
+
var step = _step.value;
|
|
26
|
+
var result = step.apply(steppedDoc);
|
|
27
|
+
if (result.failed === null && result.doc) {
|
|
28
|
+
steppedDoc = result.doc;
|
|
29
|
+
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
// Rather than using .eq() we use a custom function that only checks for structural
|
|
33
|
+
// changes and ignores differences in attributes which don't affect decoration positions
|
|
34
|
+
} catch (err) {
|
|
35
|
+
_iterator.e(err);
|
|
36
|
+
} finally {
|
|
37
|
+
_iterator.f();
|
|
38
|
+
}
|
|
39
|
+
if (!areNodesEqual(steppedDoc, tr.doc)) {
|
|
40
|
+
return DecorationSet.empty;
|
|
41
|
+
}
|
|
42
|
+
var changes = simplifyChanges(changeset.changes, tr.doc);
|
|
43
|
+
var decorations = [];
|
|
44
|
+
changes.forEach(function (change) {
|
|
45
|
+
if (change.inserted.length > 0) {
|
|
46
|
+
decorations.push(createInlineChangedDecoration(change));
|
|
47
|
+
}
|
|
48
|
+
if (change.deleted.length > 0) {
|
|
49
|
+
var decoration = createDeletedContentDecoration({
|
|
50
|
+
change: change,
|
|
51
|
+
doc: originalDoc,
|
|
52
|
+
nodeViewSerializer: nodeViewSerializer
|
|
53
|
+
});
|
|
54
|
+
if (decoration) {
|
|
55
|
+
decorations.push(decoration);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
getMarkChangeRanges(steps).forEach(function (change) {
|
|
60
|
+
decorations.push(createInlineChangedDecoration(change));
|
|
61
|
+
});
|
|
62
|
+
return DecorationSet.empty.add(tr.doc, decorations);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Compares two ProseMirror documents for equality, ignoring attributes
|
|
67
|
+
* which don't affect the document structure.
|
|
68
|
+
*
|
|
69
|
+
* This is almost a copy of the .eq() PM function - tweaked to ignore attrs
|
|
70
|
+
*
|
|
71
|
+
* @param doc1 PMNode
|
|
72
|
+
* @param doc2 PMNode
|
|
73
|
+
* @returns boolean
|
|
74
|
+
*/
|
|
75
|
+
export function areNodesEqual(node1, node2) {
|
|
76
|
+
if (node1.isText) {
|
|
77
|
+
return node1.eq(node2);
|
|
78
|
+
}
|
|
79
|
+
return node1 === node2 || node1.hasMarkup(node2.type, node1.attrs, node2.marks) && areFragmentsEqual(node1.content, node2.content);
|
|
80
|
+
}
|
|
81
|
+
function areFragmentsEqual(frag1, frag2) {
|
|
82
|
+
if (frag1.content.length !== frag2.content.length) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
var childrenEqual = true;
|
|
86
|
+
frag1.content.forEach(function (child, i) {
|
|
87
|
+
var otherChild = frag2.child(i);
|
|
88
|
+
if (child === otherChild || otherChild && areNodesEqual(child, otherChild)) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
childrenEqual = false;
|
|
92
|
+
});
|
|
93
|
+
return childrenEqual;
|
|
94
|
+
}
|
|
@@ -1,72 +1,13 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
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; }
|
|
3
3
|
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
|
-
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; } } }; }
|
|
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; } }
|
|
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
|
-
// eslint-disable-next-line @atlassian/tangerine/import/entry-points
|
|
8
|
-
import { ChangeSet, simplifyChanges } from 'prosemirror-changeset';
|
|
9
4
|
import { processRawValue } from '@atlaskit/editor-common/process-raw-value';
|
|
10
5
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
11
6
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
12
7
|
import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
|
|
13
8
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
14
|
-
import {
|
|
15
|
-
import { getMarkChangeRanges } from './markDecorations';
|
|
9
|
+
import { calculateDiffDecorations } from './calculateDiffDecorations';
|
|
16
10
|
import { NodeViewSerializer } from './NodeViewSerializer';
|
|
17
|
-
var calculateDecorations = function calculateDecorations(_ref) {
|
|
18
|
-
var state = _ref.state,
|
|
19
|
-
pluginState = _ref.pluginState,
|
|
20
|
-
nodeViewSerializer = _ref.nodeViewSerializer;
|
|
21
|
-
var originalDoc = pluginState.originalDoc,
|
|
22
|
-
steps = pluginState.steps;
|
|
23
|
-
if (!originalDoc || !pluginState.isDisplayingChanges) {
|
|
24
|
-
return DecorationSet.empty;
|
|
25
|
-
}
|
|
26
|
-
var tr = state.tr;
|
|
27
|
-
var steppedDoc = originalDoc;
|
|
28
|
-
var changeset = ChangeSet.create(originalDoc);
|
|
29
|
-
var _iterator = _createForOfIteratorHelper(steps),
|
|
30
|
-
_step;
|
|
31
|
-
try {
|
|
32
|
-
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
33
|
-
var step = _step.value;
|
|
34
|
-
var result = step.apply(steppedDoc);
|
|
35
|
-
if (result.failed === null && result.doc) {
|
|
36
|
-
steppedDoc = result.doc;
|
|
37
|
-
changeset = changeset.addSteps(steppedDoc, [step.getMap()], tr.doc);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
} catch (err) {
|
|
41
|
-
_iterator.e(err);
|
|
42
|
-
} finally {
|
|
43
|
-
_iterator.f();
|
|
44
|
-
}
|
|
45
|
-
if (!steppedDoc.eq(tr.doc)) {
|
|
46
|
-
return DecorationSet.empty;
|
|
47
|
-
}
|
|
48
|
-
var changes = simplifyChanges(changeset.changes, tr.doc);
|
|
49
|
-
var decorations = [];
|
|
50
|
-
changes.forEach(function (change) {
|
|
51
|
-
if (change.inserted.length > 0) {
|
|
52
|
-
decorations.push(createInlineChangedDecoration(change));
|
|
53
|
-
}
|
|
54
|
-
if (change.deleted.length > 0) {
|
|
55
|
-
var decoration = createDeletedContentDecoration({
|
|
56
|
-
change: change,
|
|
57
|
-
doc: originalDoc,
|
|
58
|
-
nodeViewSerializer: nodeViewSerializer
|
|
59
|
-
});
|
|
60
|
-
if (decoration) {
|
|
61
|
-
decorations.push(decoration);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
getMarkChangeRanges(steps).forEach(function (change) {
|
|
66
|
-
decorations.push(createInlineChangedDecoration(change));
|
|
67
|
-
});
|
|
68
|
-
return DecorationSet.empty.add(tr.doc, decorations);
|
|
69
|
-
};
|
|
70
11
|
export var showDiffPluginKey = new PluginKey('showDiffPlugin');
|
|
71
12
|
export var createPlugin = function createPlugin(config) {
|
|
72
13
|
var nodeViewSerializer = new NodeViewSerializer({});
|
|
@@ -97,7 +38,7 @@ export var createPlugin = function createPlugin(config) {
|
|
|
97
38
|
isDisplayingChanges: true
|
|
98
39
|
});
|
|
99
40
|
// Calculate and store decorations in state
|
|
100
|
-
var decorations =
|
|
41
|
+
var decorations = calculateDiffDecorations({
|
|
101
42
|
state: newState,
|
|
102
43
|
pluginState: newPluginState,
|
|
103
44
|
nodeViewSerializer: nodeViewSerializer
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { type EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import type { ShowDiffPluginState } from './main';
|
|
5
|
+
import type { NodeViewSerializer } from './NodeViewSerializer';
|
|
6
|
+
export declare const calculateDiffDecorations: ({ state, pluginState, nodeViewSerializer, }: {
|
|
7
|
+
nodeViewSerializer: NodeViewSerializer;
|
|
8
|
+
pluginState: Omit<ShowDiffPluginState, "decorations">;
|
|
9
|
+
state: EditorState;
|
|
10
|
+
}) => DecorationSet;
|
|
11
|
+
/**
|
|
12
|
+
* Compares two ProseMirror documents for equality, ignoring attributes
|
|
13
|
+
* which don't affect the document structure.
|
|
14
|
+
*
|
|
15
|
+
* This is almost a copy of the .eq() PM function - tweaked to ignore attrs
|
|
16
|
+
*
|
|
17
|
+
* @param doc1 PMNode
|
|
18
|
+
* @param doc2 PMNode
|
|
19
|
+
* @returns boolean
|
|
20
|
+
*/
|
|
21
|
+
export declare function areNodesEqual(node1: PMNode, node2: PMNode): boolean;
|
|
@@ -5,11 +5,10 @@ import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform'
|
|
|
5
5
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
6
6
|
import { type DiffParams } from '../showDiffPluginType';
|
|
7
7
|
export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
|
|
8
|
-
type ShowDiffPluginState = {
|
|
8
|
+
export type ShowDiffPluginState = {
|
|
9
9
|
decorations: DecorationSet;
|
|
10
10
|
isDisplayingChanges: boolean;
|
|
11
11
|
originalDoc: PMNode | undefined;
|
|
12
12
|
steps: ProseMirrorStep[];
|
|
13
13
|
};
|
|
14
14
|
export declare const createPlugin: (config: DiffParams | undefined) => SafePlugin<ShowDiffPluginState>;
|
|
15
|
-
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { type EditorState } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
4
|
+
import type { ShowDiffPluginState } from './main';
|
|
5
|
+
import type { NodeViewSerializer } from './NodeViewSerializer';
|
|
6
|
+
export declare const calculateDiffDecorations: ({ state, pluginState, nodeViewSerializer, }: {
|
|
7
|
+
nodeViewSerializer: NodeViewSerializer;
|
|
8
|
+
pluginState: Omit<ShowDiffPluginState, "decorations">;
|
|
9
|
+
state: EditorState;
|
|
10
|
+
}) => DecorationSet;
|
|
11
|
+
/**
|
|
12
|
+
* Compares two ProseMirror documents for equality, ignoring attributes
|
|
13
|
+
* which don't affect the document structure.
|
|
14
|
+
*
|
|
15
|
+
* This is almost a copy of the .eq() PM function - tweaked to ignore attrs
|
|
16
|
+
*
|
|
17
|
+
* @param doc1 PMNode
|
|
18
|
+
* @param doc2 PMNode
|
|
19
|
+
* @returns boolean
|
|
20
|
+
*/
|
|
21
|
+
export declare function areNodesEqual(node1: PMNode, node2: PMNode): boolean;
|
|
@@ -5,11 +5,10 @@ import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform'
|
|
|
5
5
|
import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
|
|
6
6
|
import { type DiffParams } from '../showDiffPluginType';
|
|
7
7
|
export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
|
|
8
|
-
type ShowDiffPluginState = {
|
|
8
|
+
export type ShowDiffPluginState = {
|
|
9
9
|
decorations: DecorationSet;
|
|
10
10
|
isDisplayingChanges: boolean;
|
|
11
11
|
originalDoc: PMNode | undefined;
|
|
12
12
|
steps: ProseMirrorStep[];
|
|
13
13
|
};
|
|
14
14
|
export declare const createPlugin: (config: DiffParams | undefined) => SafePlugin<ShowDiffPluginState>;
|
|
15
|
-
export {};
|