@atlaskit/editor-plugin-show-diff 6.1.9 → 6.2.0

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/cjs/pm-plugins/{calculateDiffDecorations.js → calculateDiff/calculateDiffDecorations.js} +74 -84
  3. package/dist/cjs/pm-plugins/calculateDiff/groupChangesByBlock.js +77 -0
  4. package/dist/cjs/pm-plugins/calculateDiff/optimizeChanges.js +43 -0
  5. package/dist/cjs/pm-plugins/main.js +8 -5
  6. package/dist/es2019/pm-plugins/{calculateDiffDecorations.js → calculateDiff/calculateDiffDecorations.js} +37 -51
  7. package/dist/es2019/pm-plugins/calculateDiff/groupChangesByBlock.js +54 -0
  8. package/dist/es2019/pm-plugins/calculateDiff/optimizeChanges.js +36 -0
  9. package/dist/es2019/pm-plugins/main.js +9 -6
  10. package/dist/esm/pm-plugins/{calculateDiffDecorations.js → calculateDiff/calculateDiffDecorations.js} +72 -82
  11. package/dist/esm/pm-plugins/calculateDiff/groupChangesByBlock.js +70 -0
  12. package/dist/esm/pm-plugins/calculateDiff/optimizeChanges.js +36 -0
  13. package/dist/esm/pm-plugins/main.js +8 -5
  14. package/dist/types/pm-plugins/{calculateDiffDecorations.d.ts → calculateDiff/calculateDiffDecorations.d.ts} +4 -4
  15. package/dist/types/pm-plugins/calculateDiff/groupChangesByBlock.d.ts +7 -0
  16. package/dist/types/pm-plugins/calculateDiff/optimizeChanges.d.ts +6 -0
  17. package/dist/types/pm-plugins/main.d.ts +2 -1
  18. package/dist/types/showDiffPluginType.d.ts +2 -0
  19. package/dist/types-ts4.5/pm-plugins/{calculateDiffDecorations.d.ts → calculateDiff/calculateDiffDecorations.d.ts} +4 -4
  20. package/dist/types-ts4.5/pm-plugins/calculateDiff/groupChangesByBlock.d.ts +7 -0
  21. package/dist/types-ts4.5/pm-plugins/calculateDiff/optimizeChanges.d.ts +6 -0
  22. package/dist/types-ts4.5/pm-plugins/main.d.ts +2 -1
  23. package/dist/types-ts4.5/showDiffPluginType.d.ts +2 -0
  24. package/package.json +4 -4
  25. /package/dist/cjs/pm-plugins/{simplifyChanges.js → calculateDiff/simplifySteps.js} +0 -0
  26. /package/dist/es2019/pm-plugins/{simplifyChanges.js → calculateDiff/simplifySteps.js} +0 -0
  27. /package/dist/esm/pm-plugins/{simplifyChanges.js → calculateDiff/simplifySteps.js} +0 -0
  28. /package/dist/types/pm-plugins/{simplifyChanges.d.ts → calculateDiff/simplifySteps.d.ts} +0 -0
  29. /package/dist/types-ts4.5/pm-plugins/{simplifyChanges.d.ts → calculateDiff/simplifySteps.d.ts} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 6.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`255e764f80182`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/255e764f80182) -
8
+ EDITOR-5830: Add support for showing inline vs. block diff types.
9
+
10
+ ### Patch Changes
11
+
12
+ - Updated dependencies
13
+
14
+ ## 6.1.10
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+
3
20
  ## 6.1.9
4
21
 
5
22
  ### Patch Changes
@@ -15,26 +15,40 @@ var _document = require("@atlaskit/editor-common/utils/document");
15
15
  var _view = require("@atlaskit/editor-prosemirror/view");
16
16
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
17
17
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
18
- var _areDocsEqualByBlockStructureAndText = require("./areDocsEqualByBlockStructureAndText");
19
- var _createBlockChangedDecoration = require("./decorations/createBlockChangedDecoration");
20
- var _createInlineChangedDecoration = require("./decorations/createInlineChangedDecoration");
21
- var _createNodeChangedDecorationWidget = require("./decorations/createNodeChangedDecorationWidget");
22
- var _getAttrChangeRanges = require("./decorations/utils/getAttrChangeRanges");
23
- var _getMarkChangeRanges = require("./decorations/utils/getMarkChangeRanges");
24
- var _simplifyChanges = require("./simplifyChanges");
18
+ var _areDocsEqualByBlockStructureAndText = require("../areDocsEqualByBlockStructureAndText");
19
+ var _createBlockChangedDecoration = require("../decorations/createBlockChangedDecoration");
20
+ var _createInlineChangedDecoration = require("../decorations/createInlineChangedDecoration");
21
+ var _createNodeChangedDecorationWidget = require("../decorations/createNodeChangedDecorationWidget");
22
+ var _getAttrChangeRanges = require("../decorations/utils/getAttrChangeRanges");
23
+ var _getMarkChangeRanges = require("../decorations/utils/getMarkChangeRanges");
24
+ var _groupChangesByBlock = require("./groupChangesByBlock");
25
+ var _optimizeChanges = require("./optimizeChanges");
26
+ var _simplifySteps = require("./simplifySteps");
27
+ 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; }
28
+ 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; }
25
29
  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; } } }; }
26
30
  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; } }
27
- 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; }
28
- 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; }
29
- 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
30
- var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref) {
31
- var doc = _ref.doc,
32
- from = _ref.from,
33
- to = _ref.to,
34
- colorScheme = _ref.colorScheme,
35
- _ref$isInserted = _ref.isInserted,
36
- isInserted = _ref$isInserted === void 0 ? true : _ref$isInserted,
37
- activeIndexPos = _ref.activeIndexPos;
31
+ 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
32
+ var getChanges = function getChanges(_ref) {
33
+ var changeset = _ref.changeset,
34
+ originalDoc = _ref.originalDoc,
35
+ steppedDoc = _ref.steppedDoc,
36
+ diffType = _ref.diffType,
37
+ tr = _ref.tr;
38
+ if (diffType === 'block' && (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
39
+ return (0, _groupChangesByBlock.groupChangesByBlock)(changeset.changes, originalDoc, steppedDoc);
40
+ }
41
+ var changes = (0, _prosemirrorChangeset.simplifyChanges)(changeset.changes, tr.doc);
42
+ return (0, _optimizeChanges.optimizeChanges)(changes);
43
+ };
44
+ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref2) {
45
+ var doc = _ref2.doc,
46
+ from = _ref2.from,
47
+ to = _ref2.to,
48
+ colorScheme = _ref2.colorScheme,
49
+ _ref2$isInserted = _ref2.isInserted,
50
+ isInserted = _ref2$isInserted === void 0 ? true : _ref2$isInserted,
51
+ activeIndexPos = _ref2.activeIndexPos;
38
52
  var decorations = [];
39
53
  // Iterate over the document nodes within the range
40
54
  doc.nodesBetween(from, to, function (node, pos) {
@@ -58,49 +72,18 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
58
72
  });
59
73
  return decorations;
60
74
  };
61
-
62
- /**
63
- * Groups adjacent changes to reduce visual fragmentation in diffs.
64
- * Merges consecutive insertions and deletions that are close together.
65
- */
66
- function optimizeChanges(changes) {
67
- if (changes.length <= 1) {
68
- return changes;
69
- }
70
- var optimized = [];
71
- var current = _objectSpread({}, changes[0]);
72
- for (var i = 1; i < changes.length; i++) {
73
- var next = changes[i];
74
-
75
- // Check if changes are adjacent or very close (within 2 positions)
76
- var isAdjacent = next.fromB <= current.toB + 2;
77
- if (isAdjacent) {
78
- current = {
79
- fromA: current.fromA,
80
- toA: Math.max(current.toA, next.toA),
81
- fromB: current.fromB,
82
- toB: Math.max(current.toB, next.toB),
83
- deleted: [].concat((0, _toConsumableArray2.default)(current.deleted), (0, _toConsumableArray2.default)(next.deleted)),
84
- inserted: [].concat((0, _toConsumableArray2.default)(current.inserted), (0, _toConsumableArray2.default)(next.inserted))
85
- };
86
- } else {
87
- optimized.push(current);
88
- current = _objectSpread({}, next);
89
- }
90
- }
91
- optimized.push(current);
92
- return optimized;
93
- }
94
- var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2) {
95
- var state = _ref2.state,
96
- pluginState = _ref2.pluginState,
97
- nodeViewSerializer = _ref2.nodeViewSerializer,
98
- colorScheme = _ref2.colorScheme,
99
- intl = _ref2.intl,
100
- activeIndexPos = _ref2.activeIndexPos,
101
- api = _ref2.api,
102
- _ref2$isInverted = _ref2.isInverted,
103
- isInverted = _ref2$isInverted === void 0 ? false : _ref2$isInverted;
75
+ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3) {
76
+ var state = _ref3.state,
77
+ pluginState = _ref3.pluginState,
78
+ nodeViewSerializer = _ref3.nodeViewSerializer,
79
+ colorScheme = _ref3.colorScheme,
80
+ intl = _ref3.intl,
81
+ activeIndexPos = _ref3.activeIndexPos,
82
+ api = _ref3.api,
83
+ _ref3$isInverted = _ref3.isInverted,
84
+ isInverted = _ref3$isInverted === void 0 ? false : _ref3$isInverted,
85
+ _ref3$diffType = _ref3.diffType,
86
+ diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType;
104
87
  var originalDoc = pluginState.originalDoc,
105
88
  steps = pluginState.steps;
106
89
  if (!originalDoc || !pluginState.isDisplayingChanges) {
@@ -109,7 +92,7 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2
109
92
  var tr = state.tr;
110
93
  var steppedDoc = originalDoc;
111
94
  var attrSteps = [];
112
- var simplifiedSteps = (0, _simplifyChanges.simplifySteps)(steps, originalDoc);
95
+ var simplifiedSteps = (0, _simplifySteps.simplifySteps)(steps, originalDoc);
113
96
  var stepMaps = [];
114
97
  var _iterator = _createForOfIteratorHelper(simplifiedSteps),
115
98
  _step;
@@ -157,10 +140,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2
157
140
  }
158
141
  }
159
142
  var changeset = _prosemirrorChangeset.ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
160
- var changes = (0, _prosemirrorChangeset.simplifyChanges)(changeset.changes, tr.doc);
161
- var optimizedChanges = optimizeChanges(changes);
143
+ var changes = getChanges({
144
+ changeset: changeset,
145
+ originalDoc: originalDoc,
146
+ steppedDoc: steppedDoc,
147
+ diffType: diffType,
148
+ tr: tr
149
+ });
162
150
  var decorations = [];
163
- optimizedChanges.forEach(function (change) {
151
+ changes.forEach(function (change) {
164
152
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
165
153
  // Our default operations are insertions, so it should match the opposite of isInverted.
166
154
  var isInserted = !isInverted;
@@ -226,28 +214,30 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2
226
214
  };
227
215
  var calculateDiffDecorations = exports.calculateDiffDecorations = (0, _memoizeOne.default)(calculateDiffDecorationsInner,
228
216
  // Cache results unless relevant inputs change
229
- function (_ref3, _ref4) {
230
- var _ref8;
231
- var _ref5 = (0, _slicedToArray2.default)(_ref3, 1),
232
- _ref5$ = _ref5[0],
233
- pluginState = _ref5$.pluginState,
234
- state = _ref5$.state,
235
- colorScheme = _ref5$.colorScheme,
236
- intl = _ref5$.intl,
237
- activeIndexPos = _ref5$.activeIndexPos,
238
- isInverted = _ref5$.isInverted;
217
+ function (_ref4, _ref5) {
218
+ var _ref9;
239
219
  var _ref6 = (0, _slicedToArray2.default)(_ref4, 1),
240
220
  _ref6$ = _ref6[0],
241
- lastPluginState = _ref6$.pluginState,
242
- lastState = _ref6$.state,
243
- lastColorScheme = _ref6$.colorScheme,
244
- lastIntl = _ref6$.intl,
245
- lastActiveIndexPos = _ref6$.activeIndexPos,
246
- lastIsInverted = _ref6$.isInverted;
221
+ pluginState = _ref6$.pluginState,
222
+ state = _ref6$.state,
223
+ colorScheme = _ref6$.colorScheme,
224
+ intl = _ref6$.intl,
225
+ activeIndexPos = _ref6$.activeIndexPos,
226
+ isInverted = _ref6$.isInverted,
227
+ diffType = _ref6$.diffType;
228
+ var _ref7 = (0, _slicedToArray2.default)(_ref5, 1),
229
+ _ref7$ = _ref7[0],
230
+ lastPluginState = _ref7$.pluginState,
231
+ lastState = _ref7$.state,
232
+ lastColorScheme = _ref7$.colorScheme,
233
+ lastIntl = _ref7$.intl,
234
+ lastActiveIndexPos = _ref7$.activeIndexPos,
235
+ lastIsInverted = _ref7$.isInverted,
236
+ lastDiffType = _ref7$.diffType;
247
237
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
248
238
  if ((0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
249
- var _ref7;
250
- return (_ref7 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref7 !== void 0 ? _ref7 : false;
239
+ var _ref8;
240
+ return (_ref8 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref8 !== void 0 ? _ref8 : false;
251
241
  }
252
- return (_ref8 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos)) !== null && _ref8 !== void 0 ? _ref8 : false;
242
+ return (_ref9 = originalDocIsSame && (0, _isEqual.default)(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && (0, _isEqual.default)(activeIndexPos, lastActiveIndexPos)) !== null && _ref9 !== void 0 ? _ref9 : false;
253
243
  });
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.groupChangesByBlock = groupChangesByBlock;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ 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; } } }; }
10
+ 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; } }
11
+ 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; }
12
+ /**
13
+ * Finds the position range of the top-level block (direct child of doc) that contains `pos`.
14
+ * Returns null if `pos` is at the doc boundary or outside the doc content.
15
+ */
16
+ function getTopLevelBlockAt(doc, from, to) {
17
+ return {
18
+ from: doc.resolve(from).before(1),
19
+ to: doc.resolve(to).after(1)
20
+ };
21
+ }
22
+
23
+ /**
24
+ * Groups all changes that fall within the same top-level block (direct child of doc)
25
+ * and merges them into a single change spanning the full block in both old and new doc.
26
+ */
27
+ function groupChangesByBlock(changes, docA, docB) {
28
+ var groups = new Map();
29
+ var _iterator = _createForOfIteratorHelper(changes),
30
+ _step;
31
+ try {
32
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
33
+ var change = _step.value;
34
+ var blockA = getTopLevelBlockAt(docA, change.fromA, change.toA);
35
+ var blockB = getTopLevelBlockAt(docB, change.fromB, change.toB);
36
+ if (!groups.has(blockB.from)) {
37
+ groups.set(blockB.from, {
38
+ fromB: blockB.from,
39
+ toB: blockB.to,
40
+ fromA: blockA ? blockA.from : change.fromA,
41
+ toA: blockA ? blockA.to : change.toA,
42
+ changed: []
43
+ });
44
+ }
45
+ var group = groups.get(blockB.from);
46
+ if (group) {
47
+ group.changed = [].concat((0, _toConsumableArray2.default)(group.changed), (0, _toConsumableArray2.default)(change.inserted), (0, _toConsumableArray2.default)(change.deleted));
48
+ }
49
+ }
50
+ } catch (err) {
51
+ _iterator.e(err);
52
+ } finally {
53
+ _iterator.f();
54
+ }
55
+ return Array.from(groups.values()).sort(function (a, b) {
56
+ return a.fromB - b.fromB;
57
+ }).map(function (_ref) {
58
+ var fromA = _ref.fromA,
59
+ toA = _ref.toA,
60
+ fromB = _ref.fromB,
61
+ toB = _ref.toB,
62
+ changed = _ref.changed;
63
+ return {
64
+ fromA: fromA,
65
+ toA: toA,
66
+ fromB: fromB,
67
+ toB: toB,
68
+ /**
69
+ * We add all changes (both deleted and inserted) as that will
70
+ * inform the calculateDiffDecorations function that changes should be rendered
71
+ * (even if the change is only one of the two).
72
+ */
73
+ deleted: changed,
74
+ inserted: changed
75
+ };
76
+ });
77
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.optimizeChanges = optimizeChanges;
8
+ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ 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; }
11
+ 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; }
12
+ /**
13
+ * Groups adjacent changes to reduce visual fragmentation in diffs.
14
+ * Merges consecutive insertions and deletions that are close together.
15
+ */
16
+ function optimizeChanges(changes) {
17
+ if (changes.length <= 1) {
18
+ return changes;
19
+ }
20
+ var optimized = [];
21
+ var current = _objectSpread({}, changes[0]);
22
+ for (var i = 1; i < changes.length; i++) {
23
+ var next = changes[i];
24
+
25
+ // Check if changes are adjacent or very close (within 2 positions)
26
+ var isAdjacent = next.fromB <= current.toB + 2;
27
+ if (isAdjacent) {
28
+ current = {
29
+ fromA: current.fromA,
30
+ toA: Math.max(current.toA, next.toA),
31
+ fromB: current.fromB,
32
+ toB: Math.max(current.toB, next.toB),
33
+ deleted: [].concat((0, _toConsumableArray2.default)(current.deleted), (0, _toConsumableArray2.default)(next.deleted)),
34
+ inserted: [].concat((0, _toConsumableArray2.default)(current.inserted), (0, _toConsumableArray2.default)(next.inserted))
35
+ };
36
+ } else {
37
+ optimized.push(current);
38
+ current = _objectSpread({}, next);
39
+ }
40
+ }
41
+ optimized.push(current);
42
+ return optimized;
43
+ }
@@ -13,7 +13,7 @@ var _transform = require("@atlaskit/editor-prosemirror/transform");
13
13
  var _view = require("@atlaskit/editor-prosemirror/view");
14
14
  var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
15
15
  var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
16
- var _calculateDiffDecorations = require("./calculateDiffDecorations");
16
+ var _calculateDiffDecorations = require("./calculateDiff/calculateDiffDecorations");
17
17
  var _NodeViewSerializer = require("./NodeViewSerializer");
18
18
  var _scrollToActiveDecoration = require("./scrollToActiveDecoration");
19
19
  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; }
@@ -59,7 +59,8 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
59
59
  decorations: _view.DecorationSet.empty,
60
60
  isDisplayingChanges: false
61
61
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
62
- isInverted: false
62
+ isInverted: false,
63
+ diffType: 'inline'
63
64
  } : {});
64
65
  },
65
66
  apply: function apply(tr, currentPluginState, oldState, newState) {
@@ -67,7 +68,7 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
67
68
  var newPluginState = currentPluginState;
68
69
  if (meta) {
69
70
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
70
- var _newPluginState;
71
+ var _newPluginState, _newPluginState2;
71
72
  // Update the plugin state with the new metadata
72
73
  newPluginState = _objectSpread(_objectSpread(_objectSpread({}, currentPluginState), meta), {}, {
73
74
  isDisplayingChanges: true,
@@ -83,7 +84,8 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
83
84
  activeIndexPos: (0, _platformFeatureFlags.fg)('platform_editor_show_diff_scroll_navigation') ? newPluginState.activeIndexPos : undefined,
84
85
  api: api
85
86
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
86
- isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted
87
+ isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted,
88
+ diffType: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType
87
89
  } : {}));
88
90
  // Update the decorations
89
91
  newPluginState.decorations = decorations;
@@ -93,7 +95,8 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
93
95
  isDisplayingChanges: false,
94
96
  activeIndex: undefined
95
97
  }, (0, _expValEquals.expValEquals)('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
96
- isInverted: false
98
+ isInverted: false,
99
+ diffType: 'inline'
97
100
  } : {});
98
101
  } else if (((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') && (0, _platformFeatureFlags.fg)('platform_editor_show_diff_scroll_navigation')) {
99
102
  // Update the active index in plugin state and recalculate decorations
@@ -6,13 +6,28 @@ import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document
6
6
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
7
7
  import { fg } from '@atlaskit/platform-feature-flags';
8
8
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
9
- import { areDocsEqualByBlockStructureAndText } from './areDocsEqualByBlockStructureAndText';
10
- import { createBlockChangedDecoration } from './decorations/createBlockChangedDecoration';
11
- import { createInlineChangedDecoration } from './decorations/createInlineChangedDecoration';
12
- import { createNodeChangedDecorationWidget } from './decorations/createNodeChangedDecorationWidget';
13
- import { getAttrChangeRanges, stepIsValidAttrChange } from './decorations/utils/getAttrChangeRanges';
14
- import { getMarkChangeRanges } from './decorations/utils/getMarkChangeRanges';
15
- import { simplifySteps } from './simplifyChanges';
9
+ import { areDocsEqualByBlockStructureAndText } from '../areDocsEqualByBlockStructureAndText';
10
+ import { createBlockChangedDecoration } from '../decorations/createBlockChangedDecoration';
11
+ import { createInlineChangedDecoration } from '../decorations/createInlineChangedDecoration';
12
+ import { createNodeChangedDecorationWidget } from '../decorations/createNodeChangedDecorationWidget';
13
+ import { getAttrChangeRanges, stepIsValidAttrChange } from '../decorations/utils/getAttrChangeRanges';
14
+ import { getMarkChangeRanges } from '../decorations/utils/getMarkChangeRanges';
15
+ import { groupChangesByBlock } from './groupChangesByBlock';
16
+ import { optimizeChanges } from './optimizeChanges';
17
+ import { simplifySteps } from './simplifySteps';
18
+ const getChanges = ({
19
+ changeset,
20
+ originalDoc,
21
+ steppedDoc,
22
+ diffType,
23
+ tr
24
+ }) => {
25
+ if (diffType === 'block' && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
26
+ return groupChangesByBlock(changeset.changes, originalDoc, steppedDoc);
27
+ }
28
+ const changes = simplifyChanges(changeset.changes, tr.doc);
29
+ return optimizeChanges(changes);
30
+ };
16
31
  const calculateNodesForBlockDecoration = ({
17
32
  doc,
18
33
  from,
@@ -44,43 +59,6 @@ const calculateNodesForBlockDecoration = ({
44
59
  });
45
60
  return decorations;
46
61
  };
47
-
48
- /**
49
- * Groups adjacent changes to reduce visual fragmentation in diffs.
50
- * Merges consecutive insertions and deletions that are close together.
51
- */
52
- function optimizeChanges(changes) {
53
- if (changes.length <= 1) {
54
- return changes;
55
- }
56
- const optimized = [];
57
- let current = {
58
- ...changes[0]
59
- };
60
- for (let i = 1; i < changes.length; i++) {
61
- const next = changes[i];
62
-
63
- // Check if changes are adjacent or very close (within 2 positions)
64
- const isAdjacent = next.fromB <= current.toB + 2;
65
- if (isAdjacent) {
66
- current = {
67
- fromA: current.fromA,
68
- toA: Math.max(current.toA, next.toA),
69
- fromB: current.fromB,
70
- toB: Math.max(current.toB, next.toB),
71
- deleted: [...current.deleted, ...next.deleted],
72
- inserted: [...current.inserted, ...next.inserted]
73
- };
74
- } else {
75
- optimized.push(current);
76
- current = {
77
- ...next
78
- };
79
- }
80
- }
81
- optimized.push(current);
82
- return optimized;
83
- }
84
62
  const calculateDiffDecorationsInner = ({
85
63
  state,
86
64
  pluginState,
@@ -89,7 +67,8 @@ const calculateDiffDecorationsInner = ({
89
67
  intl,
90
68
  activeIndexPos,
91
69
  api,
92
- isInverted = false
70
+ isInverted = false,
71
+ diffType = 'inline'
93
72
  }) => {
94
73
  const {
95
74
  originalDoc,
@@ -142,10 +121,15 @@ const calculateDiffDecorationsInner = ({
142
121
  }
143
122
  }
144
123
  const changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
145
- const changes = simplifyChanges(changeset.changes, tr.doc);
146
- const optimizedChanges = optimizeChanges(changes);
124
+ const changes = getChanges({
125
+ changeset,
126
+ originalDoc,
127
+ steppedDoc,
128
+ diffType,
129
+ tr
130
+ });
147
131
  const decorations = [];
148
- optimizedChanges.forEach(change => {
132
+ changes.forEach(change => {
149
133
  const isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
150
134
  // Our default operations are insertions, so it should match the opposite of isInverted.
151
135
  const isInserted = !isInverted;
@@ -219,20 +203,22 @@ export const calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner
219
203
  colorScheme,
220
204
  intl,
221
205
  activeIndexPos,
222
- isInverted
206
+ isInverted,
207
+ diffType
223
208
  }], [{
224
209
  pluginState: lastPluginState,
225
210
  state: lastState,
226
211
  colorScheme: lastColorScheme,
227
212
  intl: lastIntl,
228
213
  activeIndexPos: lastActiveIndexPos,
229
- isInverted: lastIsInverted
214
+ isInverted: lastIsInverted,
215
+ diffType: lastDiffType
230
216
  }]) => {
231
217
  var _ref2;
232
218
  const originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
233
219
  if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
234
220
  var _ref;
235
- return (_ref = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref !== void 0 ? _ref : false;
221
+ return (_ref = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref !== void 0 ? _ref : false;
236
222
  }
237
223
  return (_ref2 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos)) !== null && _ref2 !== void 0 ? _ref2 : false;
238
224
  });
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Finds the position range of the top-level block (direct child of doc) that contains `pos`.
3
+ * Returns null if `pos` is at the doc boundary or outside the doc content.
4
+ */
5
+ function getTopLevelBlockAt(doc, from, to) {
6
+ return {
7
+ from: doc.resolve(from).before(1),
8
+ to: doc.resolve(to).after(1)
9
+ };
10
+ }
11
+
12
+ /**
13
+ * Groups all changes that fall within the same top-level block (direct child of doc)
14
+ * and merges them into a single change spanning the full block in both old and new doc.
15
+ */
16
+ export function groupChangesByBlock(changes, docA, docB) {
17
+ const groups = new Map();
18
+ for (const change of changes) {
19
+ const blockA = getTopLevelBlockAt(docA, change.fromA, change.toA);
20
+ const blockB = getTopLevelBlockAt(docB, change.fromB, change.toB);
21
+ if (!groups.has(blockB.from)) {
22
+ groups.set(blockB.from, {
23
+ fromB: blockB.from,
24
+ toB: blockB.to,
25
+ fromA: blockA ? blockA.from : change.fromA,
26
+ toA: blockA ? blockA.to : change.toA,
27
+ changed: []
28
+ });
29
+ }
30
+ const group = groups.get(blockB.from);
31
+ if (group) {
32
+ group.changed = [...group.changed, ...change.inserted, ...change.deleted];
33
+ }
34
+ }
35
+ return Array.from(groups.values()).sort((a, b) => a.fromB - b.fromB).map(({
36
+ fromA,
37
+ toA,
38
+ fromB,
39
+ toB,
40
+ changed
41
+ }) => ({
42
+ fromA,
43
+ toA,
44
+ fromB,
45
+ toB,
46
+ /**
47
+ * We add all changes (both deleted and inserted) as that will
48
+ * inform the calculateDiffDecorations function that changes should be rendered
49
+ * (even if the change is only one of the two).
50
+ */
51
+ deleted: changed,
52
+ inserted: changed
53
+ }));
54
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Groups adjacent changes to reduce visual fragmentation in diffs.
3
+ * Merges consecutive insertions and deletions that are close together.
4
+ */
5
+ export function optimizeChanges(changes) {
6
+ if (changes.length <= 1) {
7
+ return changes;
8
+ }
9
+ const optimized = [];
10
+ let current = {
11
+ ...changes[0]
12
+ };
13
+ for (let i = 1; i < changes.length; i++) {
14
+ const next = changes[i];
15
+
16
+ // Check if changes are adjacent or very close (within 2 positions)
17
+ const isAdjacent = next.fromB <= current.toB + 2;
18
+ if (isAdjacent) {
19
+ current = {
20
+ fromA: current.fromA,
21
+ toA: Math.max(current.toA, next.toA),
22
+ fromB: current.fromB,
23
+ toB: Math.max(current.toB, next.toB),
24
+ deleted: [...current.deleted, ...next.deleted],
25
+ inserted: [...current.inserted, ...next.inserted]
26
+ };
27
+ } else {
28
+ optimized.push(current);
29
+ current = {
30
+ ...next
31
+ };
32
+ }
33
+ }
34
+ optimized.push(current);
35
+ return optimized;
36
+ }
@@ -5,7 +5,7 @@ import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform'
5
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
6
  import { fg } from '@atlaskit/platform-feature-flags';
7
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
8
- import { calculateDiffDecorations } from './calculateDiffDecorations';
8
+ import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
9
9
  import { NodeViewSerializer } from './NodeViewSerializer';
10
10
  import { scrollToActiveDecoration } from './scrollToActiveDecoration';
11
11
  export const showDiffPluginKey = new PluginKey('showDiffPlugin');
@@ -47,7 +47,8 @@ export const createPlugin = (config, getIntl, api) => {
47
47
  decorations: DecorationSet.empty,
48
48
  isDisplayingChanges: false,
49
49
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
50
- isInverted: false
50
+ isInverted: false,
51
+ diffType: 'inline'
51
52
  } : {})
52
53
  };
53
54
  },
@@ -56,7 +57,7 @@ export const createPlugin = (config, getIntl, api) => {
56
57
  let newPluginState = currentPluginState;
57
58
  if (meta) {
58
59
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
59
- var _newPluginState;
60
+ var _newPluginState, _newPluginState2;
60
61
  // Update the plugin state with the new metadata
61
62
  newPluginState = {
62
63
  ...currentPluginState,
@@ -74,7 +75,8 @@ export const createPlugin = (config, getIntl, api) => {
74
75
  activeIndexPos: fg('platform_editor_show_diff_scroll_navigation') ? newPluginState.activeIndexPos : undefined,
75
76
  api,
76
77
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
77
- isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted
78
+ isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted,
79
+ diffType: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType
78
80
  } : {})
79
81
  });
80
82
  // Update the decorations
@@ -87,11 +89,12 @@ export const createPlugin = (config, getIntl, api) => {
87
89
  isDisplayingChanges: false,
88
90
  activeIndex: undefined,
89
91
  /**
90
- * Reset isInverted state when hiding diffs
92
+ * Reset isInverted & diffType state when hiding diffs
91
93
  * Otherwise this should persist for the diff-showing session
92
94
  */
93
95
  ...(expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
94
- isInverted: false
96
+ isInverted: false,
97
+ diffType: 'inline'
95
98
  } : {})
96
99
  };
97
100
  } else if (((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') && fg('platform_editor_show_diff_scroll_navigation')) {
@@ -1,11 +1,11 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
3
3
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
4
+ 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; }
5
+ 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
6
  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
7
  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
8
  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; }
9
9
  // eslint-disable-next-line @atlassian/tangerine/import/entry-points
10
10
  import isEqual from 'lodash/isEqual';
11
11
  import memoizeOne from 'memoize-one';
@@ -14,21 +14,35 @@ import { areNodesEqualIgnoreAttrs } from '@atlaskit/editor-common/utils/document
14
14
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
15
15
  import { fg } from '@atlaskit/platform-feature-flags';
16
16
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
17
- import { areDocsEqualByBlockStructureAndText } from './areDocsEqualByBlockStructureAndText';
18
- import { createBlockChangedDecoration } from './decorations/createBlockChangedDecoration';
19
- import { createInlineChangedDecoration } from './decorations/createInlineChangedDecoration';
20
- import { createNodeChangedDecorationWidget } from './decorations/createNodeChangedDecorationWidget';
21
- import { getAttrChangeRanges, stepIsValidAttrChange } from './decorations/utils/getAttrChangeRanges';
22
- import { getMarkChangeRanges } from './decorations/utils/getMarkChangeRanges';
23
- import { simplifySteps } from './simplifyChanges';
24
- var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref) {
25
- var doc = _ref.doc,
26
- from = _ref.from,
27
- to = _ref.to,
28
- colorScheme = _ref.colorScheme,
29
- _ref$isInserted = _ref.isInserted,
30
- isInserted = _ref$isInserted === void 0 ? true : _ref$isInserted,
31
- activeIndexPos = _ref.activeIndexPos;
17
+ import { areDocsEqualByBlockStructureAndText } from '../areDocsEqualByBlockStructureAndText';
18
+ import { createBlockChangedDecoration } from '../decorations/createBlockChangedDecoration';
19
+ import { createInlineChangedDecoration } from '../decorations/createInlineChangedDecoration';
20
+ import { createNodeChangedDecorationWidget } from '../decorations/createNodeChangedDecorationWidget';
21
+ import { getAttrChangeRanges, stepIsValidAttrChange } from '../decorations/utils/getAttrChangeRanges';
22
+ import { getMarkChangeRanges } from '../decorations/utils/getMarkChangeRanges';
23
+ import { groupChangesByBlock } from './groupChangesByBlock';
24
+ import { optimizeChanges } from './optimizeChanges';
25
+ import { simplifySteps } from './simplifySteps';
26
+ var getChanges = function getChanges(_ref) {
27
+ var changeset = _ref.changeset,
28
+ originalDoc = _ref.originalDoc,
29
+ steppedDoc = _ref.steppedDoc,
30
+ diffType = _ref.diffType,
31
+ tr = _ref.tr;
32
+ if (diffType === 'block' && expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
33
+ return groupChangesByBlock(changeset.changes, originalDoc, steppedDoc);
34
+ }
35
+ var changes = simplifyChanges(changeset.changes, tr.doc);
36
+ return optimizeChanges(changes);
37
+ };
38
+ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref2) {
39
+ var doc = _ref2.doc,
40
+ from = _ref2.from,
41
+ to = _ref2.to,
42
+ colorScheme = _ref2.colorScheme,
43
+ _ref2$isInserted = _ref2.isInserted,
44
+ isInserted = _ref2$isInserted === void 0 ? true : _ref2$isInserted,
45
+ activeIndexPos = _ref2.activeIndexPos;
32
46
  var decorations = [];
33
47
  // Iterate over the document nodes within the range
34
48
  doc.nodesBetween(from, to, function (node, pos) {
@@ -52,49 +66,18 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
52
66
  });
53
67
  return decorations;
54
68
  };
55
-
56
- /**
57
- * Groups adjacent changes to reduce visual fragmentation in diffs.
58
- * Merges consecutive insertions and deletions that are close together.
59
- */
60
- function optimizeChanges(changes) {
61
- if (changes.length <= 1) {
62
- return changes;
63
- }
64
- var optimized = [];
65
- var current = _objectSpread({}, changes[0]);
66
- for (var i = 1; i < changes.length; i++) {
67
- var next = changes[i];
68
-
69
- // Check if changes are adjacent or very close (within 2 positions)
70
- var isAdjacent = next.fromB <= current.toB + 2;
71
- if (isAdjacent) {
72
- current = {
73
- fromA: current.fromA,
74
- toA: Math.max(current.toA, next.toA),
75
- fromB: current.fromB,
76
- toB: Math.max(current.toB, next.toB),
77
- deleted: [].concat(_toConsumableArray(current.deleted), _toConsumableArray(next.deleted)),
78
- inserted: [].concat(_toConsumableArray(current.inserted), _toConsumableArray(next.inserted))
79
- };
80
- } else {
81
- optimized.push(current);
82
- current = _objectSpread({}, next);
83
- }
84
- }
85
- optimized.push(current);
86
- return optimized;
87
- }
88
- var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2) {
89
- var state = _ref2.state,
90
- pluginState = _ref2.pluginState,
91
- nodeViewSerializer = _ref2.nodeViewSerializer,
92
- colorScheme = _ref2.colorScheme,
93
- intl = _ref2.intl,
94
- activeIndexPos = _ref2.activeIndexPos,
95
- api = _ref2.api,
96
- _ref2$isInverted = _ref2.isInverted,
97
- isInverted = _ref2$isInverted === void 0 ? false : _ref2$isInverted;
69
+ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref3) {
70
+ var state = _ref3.state,
71
+ pluginState = _ref3.pluginState,
72
+ nodeViewSerializer = _ref3.nodeViewSerializer,
73
+ colorScheme = _ref3.colorScheme,
74
+ intl = _ref3.intl,
75
+ activeIndexPos = _ref3.activeIndexPos,
76
+ api = _ref3.api,
77
+ _ref3$isInverted = _ref3.isInverted,
78
+ isInverted = _ref3$isInverted === void 0 ? false : _ref3$isInverted,
79
+ _ref3$diffType = _ref3.diffType,
80
+ diffType = _ref3$diffType === void 0 ? 'inline' : _ref3$diffType;
98
81
  var originalDoc = pluginState.originalDoc,
99
82
  steps = pluginState.steps;
100
83
  if (!originalDoc || !pluginState.isDisplayingChanges) {
@@ -151,10 +134,15 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2
151
134
  }
152
135
  }
153
136
  var changeset = ChangeSet.create(originalDoc).addSteps(steppedDoc, stepMaps, tr.doc);
154
- var changes = simplifyChanges(changeset.changes, tr.doc);
155
- var optimizedChanges = optimizeChanges(changes);
137
+ var changes = getChanges({
138
+ changeset: changeset,
139
+ originalDoc: originalDoc,
140
+ steppedDoc: steppedDoc,
141
+ diffType: diffType,
142
+ tr: tr
143
+ });
156
144
  var decorations = [];
157
- optimizedChanges.forEach(function (change) {
145
+ changes.forEach(function (change) {
158
146
  var isActive = activeIndexPos && change.fromB === activeIndexPos.from && change.toB === activeIndexPos.to;
159
147
  // Our default operations are insertions, so it should match the opposite of isInverted.
160
148
  var isInserted = !isInverted;
@@ -220,28 +208,30 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref2
220
208
  };
221
209
  export var calculateDiffDecorations = memoizeOne(calculateDiffDecorationsInner,
222
210
  // Cache results unless relevant inputs change
223
- function (_ref3, _ref4) {
224
- var _ref8;
225
- var _ref5 = _slicedToArray(_ref3, 1),
226
- _ref5$ = _ref5[0],
227
- pluginState = _ref5$.pluginState,
228
- state = _ref5$.state,
229
- colorScheme = _ref5$.colorScheme,
230
- intl = _ref5$.intl,
231
- activeIndexPos = _ref5$.activeIndexPos,
232
- isInverted = _ref5$.isInverted;
211
+ function (_ref4, _ref5) {
212
+ var _ref9;
233
213
  var _ref6 = _slicedToArray(_ref4, 1),
234
214
  _ref6$ = _ref6[0],
235
- lastPluginState = _ref6$.pluginState,
236
- lastState = _ref6$.state,
237
- lastColorScheme = _ref6$.colorScheme,
238
- lastIntl = _ref6$.intl,
239
- lastActiveIndexPos = _ref6$.activeIndexPos,
240
- lastIsInverted = _ref6$.isInverted;
215
+ pluginState = _ref6$.pluginState,
216
+ state = _ref6$.state,
217
+ colorScheme = _ref6$.colorScheme,
218
+ intl = _ref6$.intl,
219
+ activeIndexPos = _ref6$.activeIndexPos,
220
+ isInverted = _ref6$.isInverted,
221
+ diffType = _ref6$.diffType;
222
+ var _ref7 = _slicedToArray(_ref5, 1),
223
+ _ref7$ = _ref7[0],
224
+ lastPluginState = _ref7$.pluginState,
225
+ lastState = _ref7$.state,
226
+ lastColorScheme = _ref7$.colorScheme,
227
+ lastIntl = _ref7$.intl,
228
+ lastActiveIndexPos = _ref7$.activeIndexPos,
229
+ lastIsInverted = _ref7$.isInverted,
230
+ lastDiffType = _ref7$.diffType;
241
231
  var originalDocIsSame = lastPluginState.originalDoc && pluginState.originalDoc && pluginState.originalDoc.eq(lastPluginState.originalDoc);
242
232
  if (expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true)) {
243
- var _ref7;
244
- return (_ref7 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref7 !== void 0 ? _ref7 : false;
233
+ var _ref8;
234
+ return (_ref8 = colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isInverted === lastIsInverted && diffType === lastDiffType && isEqual(activeIndexPos, lastActiveIndexPos) && originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc)) !== null && _ref8 !== void 0 ? _ref8 : false;
245
235
  }
246
- return (_ref8 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos)) !== null && _ref8 !== void 0 ? _ref8 : false;
236
+ return (_ref9 = originalDocIsSame && isEqual(pluginState.steps, lastPluginState.steps) && state.doc.eq(lastState.doc) && colorScheme === lastColorScheme && intl.locale === lastIntl.locale && isEqual(activeIndexPos, lastActiveIndexPos)) !== null && _ref9 !== void 0 ? _ref9 : false;
247
237
  });
@@ -0,0 +1,70 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ 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; } } }; }
3
+ 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; } }
4
+ 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; }
5
+ /**
6
+ * Finds the position range of the top-level block (direct child of doc) that contains `pos`.
7
+ * Returns null if `pos` is at the doc boundary or outside the doc content.
8
+ */
9
+ function getTopLevelBlockAt(doc, from, to) {
10
+ return {
11
+ from: doc.resolve(from).before(1),
12
+ to: doc.resolve(to).after(1)
13
+ };
14
+ }
15
+
16
+ /**
17
+ * Groups all changes that fall within the same top-level block (direct child of doc)
18
+ * and merges them into a single change spanning the full block in both old and new doc.
19
+ */
20
+ export function groupChangesByBlock(changes, docA, docB) {
21
+ var groups = new Map();
22
+ var _iterator = _createForOfIteratorHelper(changes),
23
+ _step;
24
+ try {
25
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
26
+ var change = _step.value;
27
+ var blockA = getTopLevelBlockAt(docA, change.fromA, change.toA);
28
+ var blockB = getTopLevelBlockAt(docB, change.fromB, change.toB);
29
+ if (!groups.has(blockB.from)) {
30
+ groups.set(blockB.from, {
31
+ fromB: blockB.from,
32
+ toB: blockB.to,
33
+ fromA: blockA ? blockA.from : change.fromA,
34
+ toA: blockA ? blockA.to : change.toA,
35
+ changed: []
36
+ });
37
+ }
38
+ var group = groups.get(blockB.from);
39
+ if (group) {
40
+ group.changed = [].concat(_toConsumableArray(group.changed), _toConsumableArray(change.inserted), _toConsumableArray(change.deleted));
41
+ }
42
+ }
43
+ } catch (err) {
44
+ _iterator.e(err);
45
+ } finally {
46
+ _iterator.f();
47
+ }
48
+ return Array.from(groups.values()).sort(function (a, b) {
49
+ return a.fromB - b.fromB;
50
+ }).map(function (_ref) {
51
+ var fromA = _ref.fromA,
52
+ toA = _ref.toA,
53
+ fromB = _ref.fromB,
54
+ toB = _ref.toB,
55
+ changed = _ref.changed;
56
+ return {
57
+ fromA: fromA,
58
+ toA: toA,
59
+ fromB: fromB,
60
+ toB: toB,
61
+ /**
62
+ * We add all changes (both deleted and inserted) as that will
63
+ * inform the calculateDiffDecorations function that changes should be rendered
64
+ * (even if the change is only one of the two).
65
+ */
66
+ deleted: changed,
67
+ inserted: changed
68
+ };
69
+ });
70
+ }
@@ -0,0 +1,36 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ 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; }
4
+ 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; }
5
+ /**
6
+ * Groups adjacent changes to reduce visual fragmentation in diffs.
7
+ * Merges consecutive insertions and deletions that are close together.
8
+ */
9
+ export function optimizeChanges(changes) {
10
+ if (changes.length <= 1) {
11
+ return changes;
12
+ }
13
+ var optimized = [];
14
+ var current = _objectSpread({}, changes[0]);
15
+ for (var i = 1; i < changes.length; i++) {
16
+ var next = changes[i];
17
+
18
+ // Check if changes are adjacent or very close (within 2 positions)
19
+ var isAdjacent = next.fromB <= current.toB + 2;
20
+ if (isAdjacent) {
21
+ current = {
22
+ fromA: current.fromA,
23
+ toA: Math.max(current.toA, next.toA),
24
+ fromB: current.fromB,
25
+ toB: Math.max(current.toB, next.toB),
26
+ deleted: [].concat(_toConsumableArray(current.deleted), _toConsumableArray(next.deleted)),
27
+ inserted: [].concat(_toConsumableArray(current.inserted), _toConsumableArray(next.inserted))
28
+ };
29
+ } else {
30
+ optimized.push(current);
31
+ current = _objectSpread({}, next);
32
+ }
33
+ }
34
+ optimized.push(current);
35
+ return optimized;
36
+ }
@@ -8,7 +8,7 @@ import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform'
8
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
9
  import { fg } from '@atlaskit/platform-feature-flags';
10
10
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
11
- import { calculateDiffDecorations } from './calculateDiffDecorations';
11
+ import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
12
12
  import { NodeViewSerializer } from './NodeViewSerializer';
13
13
  import { scrollToActiveDecoration } from './scrollToActiveDecoration';
14
14
  export var showDiffPluginKey = new PluginKey('showDiffPlugin');
@@ -52,7 +52,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
52
52
  decorations: DecorationSet.empty,
53
53
  isDisplayingChanges: false
54
54
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
55
- isInverted: false
55
+ isInverted: false,
56
+ diffType: 'inline'
56
57
  } : {});
57
58
  },
58
59
  apply: function apply(tr, currentPluginState, oldState, newState) {
@@ -60,7 +61,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
60
61
  var newPluginState = currentPluginState;
61
62
  if (meta) {
62
63
  if ((meta === null || meta === void 0 ? void 0 : meta.action) === 'SHOW_DIFF') {
63
- var _newPluginState;
64
+ var _newPluginState, _newPluginState2;
64
65
  // Update the plugin state with the new metadata
65
66
  newPluginState = _objectSpread(_objectSpread(_objectSpread({}, currentPluginState), meta), {}, {
66
67
  isDisplayingChanges: true,
@@ -76,7 +77,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
76
77
  activeIndexPos: fg('platform_editor_show_diff_scroll_navigation') ? newPluginState.activeIndexPos : undefined,
77
78
  api: api
78
79
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
79
- isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted
80
+ isInverted: (_newPluginState = newPluginState) === null || _newPluginState === void 0 ? void 0 : _newPluginState.isInverted,
81
+ diffType: (_newPluginState2 = newPluginState) === null || _newPluginState2 === void 0 ? void 0 : _newPluginState2.diffType
80
82
  } : {}));
81
83
  // Update the decorations
82
84
  newPluginState.decorations = decorations;
@@ -86,7 +88,8 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
86
88
  isDisplayingChanges: false,
87
89
  activeIndex: undefined
88
90
  }, expValEquals('platform_editor_diff_plugin_extended', 'isEnabled', true) ? {
89
- isInverted: false
91
+ isInverted: false,
92
+ diffType: 'inline'
90
93
  } : {});
91
94
  } else if (((meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_NEXT' || (meta === null || meta === void 0 ? void 0 : meta.action) === 'SCROLL_TO_PREVIOUS') && fg('platform_editor_show_diff_scroll_navigation')) {
92
95
  // Update the active index in plugin state and recalculate decorations
@@ -1,11 +1,11 @@
1
1
  import { type MemoizedFn } from 'memoize-one';
2
2
  import type { IntlShape } from 'react-intl-next';
3
3
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
- import { type EditorState } from '@atlaskit/editor-prosemirror/state';
4
+ import type { EditorState } from '@atlaskit/editor-prosemirror/state';
5
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
- import type { ColorScheme, ShowDiffPlugin } from '../showDiffPluginType';
7
- import type { ShowDiffPluginState } from './main';
8
- import type { NodeViewSerializer } from './NodeViewSerializer';
6
+ import type { ColorScheme, ShowDiffPlugin } from '../../showDiffPluginType';
7
+ import type { ShowDiffPluginState } from '../main';
8
+ import type { NodeViewSerializer } from '../NodeViewSerializer';
9
9
  export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, }: {
10
10
  activeIndexPos?: {
11
11
  from: number;
@@ -0,0 +1,7 @@
1
+ import { type Change } from 'prosemirror-changeset';
2
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ /**
4
+ * Groups all changes that fall within the same top-level block (direct child of doc)
5
+ * and merges them into a single change spanning the full block in both old and new doc.
6
+ */
7
+ export declare function groupChangesByBlock(changes: readonly Change[], docA: PMNode, docB: PMNode): Change[];
@@ -0,0 +1,6 @@
1
+ import type { Change } from 'prosemirror-changeset';
2
+ /**
3
+ * Groups adjacent changes to reduce visual fragmentation in diffs.
4
+ * Merges consecutive insertions and deletions that are close together.
5
+ */
6
+ export declare function optimizeChanges(changes: Change[]): Change[];
@@ -6,7 +6,7 @@ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
7
7
  import type { Decoration } from '@atlaskit/editor-prosemirror/view';
8
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
- import { type DiffParams, type ShowDiffPlugin } from '../showDiffPluginType';
9
+ import { type DiffParams, type DiffType, type ShowDiffPlugin } from '../showDiffPluginType';
10
10
  export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
11
11
  export type ShowDiffPluginState = {
12
12
  activeIndex?: number;
@@ -15,6 +15,7 @@ export type ShowDiffPluginState = {
15
15
  to: number;
16
16
  };
17
17
  decorations: DecorationSet;
18
+ diffType?: DiffType;
18
19
  isDisplayingChanges: boolean;
19
20
  isInverted?: boolean;
20
21
  originalDoc: PMNode | undefined;
@@ -5,6 +5,7 @@ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
5
5
  import type { Node } from '@atlaskit/editor-prosemirror/model';
6
6
  import type { Step } from '@atlaskit/editor-prosemirror/transform';
7
7
  export type ColorScheme = 'standard' | 'traditional';
8
+ export type DiffType = 'inline' | 'block';
8
9
  export type DiffParams = {
9
10
  /**
10
11
  * Color scheme to use for displaying diffs.
@@ -19,6 +20,7 @@ export type DiffParams = {
19
20
  steps: StepJson[];
20
21
  };
21
22
  export type PMDiffParams = {
23
+ diffType?: DiffType;
22
24
  isInverted?: boolean;
23
25
  originalDoc: Node;
24
26
  /**
@@ -1,11 +1,11 @@
1
1
  import { type MemoizedFn } from 'memoize-one';
2
2
  import type { IntlShape } from 'react-intl-next';
3
3
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
- import { type EditorState } from '@atlaskit/editor-prosemirror/state';
4
+ import type { EditorState } from '@atlaskit/editor-prosemirror/state';
5
5
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
6
- import type { ColorScheme, ShowDiffPlugin } from '../showDiffPluginType';
7
- import type { ShowDiffPluginState } from './main';
8
- import type { NodeViewSerializer } from './NodeViewSerializer';
6
+ import type { ColorScheme, ShowDiffPlugin } from '../../showDiffPluginType';
7
+ import type { ShowDiffPluginState } from '../main';
8
+ import type { NodeViewSerializer } from '../NodeViewSerializer';
9
9
  export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, }: {
10
10
  activeIndexPos?: {
11
11
  from: number;
@@ -0,0 +1,7 @@
1
+ import { type Change } from 'prosemirror-changeset';
2
+ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
3
+ /**
4
+ * Groups all changes that fall within the same top-level block (direct child of doc)
5
+ * and merges them into a single change spanning the full block in both old and new doc.
6
+ */
7
+ export declare function groupChangesByBlock(changes: readonly Change[], docA: PMNode, docB: PMNode): Change[];
@@ -0,0 +1,6 @@
1
+ import type { Change } from 'prosemirror-changeset';
2
+ /**
3
+ * Groups adjacent changes to reduce visual fragmentation in diffs.
4
+ * Merges consecutive insertions and deletions that are close together.
5
+ */
6
+ export declare function optimizeChanges(changes: Change[]): Change[];
@@ -6,7 +6,7 @@ import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
7
7
  import type { Decoration } from '@atlaskit/editor-prosemirror/view';
8
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
9
- import { type DiffParams, type ShowDiffPlugin } from '../showDiffPluginType';
9
+ import { type DiffParams, type DiffType, type ShowDiffPlugin } from '../showDiffPluginType';
10
10
  export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
11
11
  export type ShowDiffPluginState = {
12
12
  activeIndex?: number;
@@ -15,6 +15,7 @@ export type ShowDiffPluginState = {
15
15
  to: number;
16
16
  };
17
17
  decorations: DecorationSet;
18
+ diffType?: DiffType;
18
19
  isDisplayingChanges: boolean;
19
20
  isInverted?: boolean;
20
21
  originalDoc: PMNode | undefined;
@@ -5,6 +5,7 @@ import type { AnalyticsPlugin } from '@atlaskit/editor-plugin-analytics';
5
5
  import type { Node } from '@atlaskit/editor-prosemirror/model';
6
6
  import type { Step } from '@atlaskit/editor-prosemirror/transform';
7
7
  export type ColorScheme = 'standard' | 'traditional';
8
+ export type DiffType = 'inline' | 'block';
8
9
  export type DiffParams = {
9
10
  /**
10
11
  * Color scheme to use for displaying diffs.
@@ -19,6 +20,7 @@ export type DiffParams = {
19
20
  steps: StepJson[];
20
21
  };
21
22
  export type PMDiffParams = {
23
+ diffType?: DiffType;
22
24
  isInverted?: boolean;
23
25
  originalDoc: Node;
24
26
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "6.1.9",
3
+ "version": "6.2.0",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -33,8 +33,8 @@
33
33
  "@atlaskit/editor-prosemirror": "^7.3.0",
34
34
  "@atlaskit/editor-tables": "^2.9.0",
35
35
  "@atlaskit/platform-feature-flags": "^1.1.0",
36
- "@atlaskit/tmp-editor-statsig": "^44.0.0",
37
- "@atlaskit/tokens": "^11.1.0",
36
+ "@atlaskit/tmp-editor-statsig": "^45.1.0",
37
+ "@atlaskit/tokens": "^11.2.0",
38
38
  "@babel/runtime": "^7.0.0",
39
39
  "lodash": "^4.17.21",
40
40
  "memoize-one": "^6.0.0",
@@ -45,7 +45,7 @@
45
45
  "@atlassian/content-reconciliation": "^0.1.3506"
46
46
  },
47
47
  "peerDependencies": {
48
- "@atlaskit/editor-common": "^112.7.0",
48
+ "@atlaskit/editor-common": "^112.9.0",
49
49
  "react": "^18.2.0"
50
50
  },
51
51
  "techstack": {