@atlaskit/editor-plugin-show-diff 3.2.4 → 3.2.6

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