@atlaskit/editor-plugin-show-diff 23.0.0 → 23.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 23.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+
9
+ ## 23.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [`608de54a73de3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/608de54a73de3) -
14
+ Behind platform_editor_ai_show_diff_patch_2, the step diff now diffs a replaced isolating node
15
+ (table cell or header, layout column, expand, bodied extension, …; tables excluded) granularly
16
+ instead of marking the whole node as changed, so a replaceNode suggestion on a cell no longer
17
+ shows a cell overlay on top of its inline changes. Block decorations now only apply to blocks
18
+ fully inside a change, so hiding deleted diffs no longer hides a block the change only starts
19
+ inside (along with its unchanged text and the suggested content).
20
+ - Updated dependencies
21
+
3
22
  ## 23.0.0
4
23
 
5
24
  ### Patch Changes
@@ -177,8 +177,29 @@ var isInsideTable = function isInsideTable(tables, pos) {
177
177
  return pos >= tFrom && pos < tTo;
178
178
  });
179
179
  };
180
+
181
+ /**
182
+ * Where a block's content ends, excluding the run of close tokens that ends it: the block's own,
183
+ * then its last child's, and so on down to the last textblock. A change that keeps those trailing
184
+ * close tokens unchanged (because the other side ends in the same structure, e.g.
185
+ * `…</p></li></ul>`) still covers all of the block's content.
186
+ */
187
+ var endBeforeTrailingCloseTokens = function endBeforeTrailingCloseTokens(node, pos) {
188
+ var end = pos + node.nodeSize;
189
+ var current = node;
190
+ while (current && !current.isLeaf) {
191
+ end -= 1;
192
+ if (current.isTextblock) {
193
+ break;
194
+ }
195
+ current = current.lastChild;
196
+ }
197
+ return end;
198
+ };
180
199
  var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref5) {
181
- var attributionKey = _ref5.attributionKey,
200
+ var _ref5$allowTrailingCl = _ref5.allowTrailingCloseTokens,
201
+ allowTrailingCloseTokens = _ref5$allowTrailingCl === void 0 ? false : _ref5$allowTrailingCl,
202
+ attributionKey = _ref5.attributionKey,
182
203
  doc = _ref5.doc,
183
204
  from = _ref5.from,
184
205
  to = _ref5.to,
@@ -245,8 +266,23 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
245
266
  // re-render. Blocks outside the table keep their normal decorations.
246
267
  var coarseTables = coarseTableCellsOnly ? tableRanges(doc, from, to) : [];
247
268
  // nodesBetween visits ancestors that start before the changed range.
248
- // Only fully contained blocks should mark existing list bullets as new.
249
- var requireContainedBlocks = (0, _unsafeExpValNoExposure.UNSAFE_expValNoExposure)('platform_editor_ai_review_moment', 'isEnabled', false) === true;
269
+ // Only fully contained blocks should mark existing list bullets as new. Under patch 2 this also
270
+ // keeps the clean view from hiding a block the change only starts inside: that block holds
271
+ // unchanged text and the deleted-content widget, so `display: none` on it hid the whole diff.
272
+ var requireContainedBlocks = (0, _unsafeExpValNoExposure.UNSAFE_expValNoExposure)('platform_editor_ai_review_moment', 'isEnabled', false) === true || (0, _fg.fg)('platform_editor_ai_show_diff_patch_2');
273
+ // Under patch 2, a block whose content the change covers but whose trailing close tokens it does
274
+ // not (e.g. the last list item when both sides end in a list) is decorated like its siblings.
275
+ // Otherwise the clean view hides its text but leaves the block, e.g. an empty bullet.
276
+ var relaxTrailingCloseTokens = allowTrailingCloseTokens && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2');
277
+ var isContained = function isContained(node, pos) {
278
+ if (requireContainedBlocks && pos < from) {
279
+ return false;
280
+ }
281
+ if (pos + node.nodeSize <= to) {
282
+ return true;
283
+ }
284
+ return relaxTrailingCloseTokens && pos >= from && endBeforeTrailingCloseTokens(node, pos) <= to;
285
+ };
250
286
  // Iterate over the document nodes within the range
251
287
  doc.nodesBetween(from, to, function (node, pos) {
252
288
  if (coarseTableCellsOnly && isInsideTable(coarseTables, pos)) {
@@ -255,7 +291,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
255
291
  return;
256
292
  }
257
293
  }
258
- if (node.isBlock && (!requireContainedBlocks || pos >= from) && pos + node.nodeSize <= to) {
294
+ if (node.isBlock && isContained(node, pos)) {
259
295
  var _nodeEnd = pos + node.nodeSize;
260
296
  var _isActive = isRangeActive(activeIndexPos, pos, _nodeEnd, attributionKey);
261
297
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)((0, _createBlockChangedDecoration.createBlockChangedDecoration)({
@@ -714,6 +750,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
714
750
  })));
715
751
  }
716
752
  decorations.push.apply(decorations, (0, _toConsumableArray2.default)(calculateNodesForBlockDecoration({
753
+ // A deleted widget placed below anchors at the change's end, inside the very block
754
+ // this would let the decoration claim.
755
+ allowTrailingCloseTokens: !isDeletedWidgetBelow,
717
756
  attributionKey: attributionKey,
718
757
  doc: tr.doc,
719
758
  from: change.fromB,
@@ -11,6 +11,7 @@ var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers
11
11
  var _prosemirrorChangeset = require("prosemirror-changeset");
12
12
  var _model = require("@atlaskit/editor-prosemirror/model");
13
13
  var _transform = require("@atlaskit/editor-prosemirror/transform");
14
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
14
15
  var _attributions = require("../decorations/colorSchemes/attributions");
15
16
  var _charsByOffset = require("../utils/charsByOffset");
16
17
  var _attrAwareTokenEncoder = require("./attrAwareTokenEncoder");
@@ -23,6 +24,16 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
23
24
  var WORD_CHAR_REGEX = /(?:[0-9A-Z_a-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDDC0-\uDDF3\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD40-\uDD59\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDD40-\uDD65\uDD6F-\uDD85\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDEC2-\uDEC7\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE3F\uDE40\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61\uDF80-\uDF89\uDF8B\uDF8E\uDF90-\uDFB5\uDFB7\uDFD1\uDFD3]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDED0-\uDEE3\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8\uDFC0-\uDFE0\uDFF0-\uDFF9]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDDB0-\uDDDB\uDDE0-\uDDE9\uDEE0-\uDEF2\uDF02\uDF04-\uDF10\uDF12-\uDF33\uDF50-\uDF59\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD80E\uD80F\uD81C-\uD822\uD840-\uD868\uD86A-\uD86D\uD86F-\uD872\uD874-\uD879\uD880-\uD883\uD885-\uD88C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F\uDC41-\uDC46\uDC60-\uDFFF]|\uD810[\uDC00-\uDFFA]|\uD811[\uDC00-\uDE46]|\uD818[\uDD00-\uDD1D\uDD30-\uDD39]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDD40-\uDD6C\uDD70-\uDD79\uDE40-\uDE96\uDEA0-\uDEB8\uDEBB-\uDED3\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3\uDFF2-\uDFF6]|\uD823[\uDC00-\uDCD5\uDCFF-\uDD1E\uDD80-\uDDF2]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD32\uDD50-\uDD52\uDD55\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD833[\uDCF0-\uDCF9]|\uD834[\uDEC0-\uDED3\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E\uDF25-\uDF2A]|\uD838[\uDC30-\uDC6D\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDCD0-\uDCEB\uDCF0-\uDCF9\uDDD0-\uDDED\uDDF0-\uDDFA\uDEC0-\uDEDE\uDEE0-\uDEE2\uDEE4\uDEE5\uDEE7-\uDEED\uDEF0-\uDEF4\uDEFE\uDEFF\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEAD\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0\uDFF0-\uDFFF]|\uD87B[\uDC00-\uDE5D]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A\uDF50-\uDFFF]|\uD88D[\uDC00-\uDC79])/;
24
25
  var PUNCTUATION_REGEX = /(?:[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B4E\u1B4F\u1B5A-\u1B60\u1B7D-\u1B7F\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDD6E\uDEAD\uDED0\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9\uDFD4\uDFD5\uDFD7\uDFD8]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09\uDFE1]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDD6D-\uDD6F\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD839\uDDFF|\uD83A[\uDD5E\uDD5F])/;
25
26
  var WHITESPACE_REGEX = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/;
27
+
28
+ /**
29
+ * Whether a same-type replacement of `node` is diffed granularly rather than as a whole node.
30
+ * `isolating` nodes (table cells, layout columns, expands, bodied extensions, …) keep edits inside
31
+ * their boundary, so replacing one wholesale is an edit of its content, not a new node. Tables are
32
+ * excluded: `groupDeletedColumnChanges` relies on a replaced table being one whole-table change.
33
+ */
34
+ var isGranularIsolatingNode = function isGranularIsolatingNode(node) {
35
+ return !!node.type.spec.isolating && node.type.spec.tableRole !== 'table';
36
+ };
26
37
  var mapPosition = function mapPosition(mapping, pos) {
27
38
  return mapping.map(pos);
28
39
  };
@@ -225,6 +236,8 @@ var mergeOverlappingByNewDocRange = function mergeOverlappingByNewDocRange(chang
225
236
  * - The replaced slice is not open
226
237
  * - The replaced slice has only one child
227
238
  * - The replacing slice has only one child
239
+ * - Both children are the same textblock type, or (behind `platform_editor_ai_show_diff_patch_2`)
240
+ * the same isolating, non-table node type whose text content differs
228
241
  * - The replaced slice and replacing slice have the same text content
229
242
  * - The replaced slice and replacing slice have the same child marks (if text content is equal)
230
243
  */
@@ -243,13 +256,27 @@ var shouldCheckGranularDiff = function shouldCheckGranularDiff(step, before, fro
243
256
  }
244
257
  var replacedNode = replacedSlice.content.firstChild;
245
258
  var replacingNode = replacingSlice.content.firstChild;
246
- if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name) || !(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock)) {
259
+ if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name)) {
260
+ return false;
261
+ }
262
+
263
+ // Replacing a whole isolating node (e.g. an AI `replaceNode` on a table cell) would otherwise
264
+ // report the entire node as changed, painting a cell overlay over content that was only
265
+ // edited inside it. Diff its content granularly instead, so only the inner edits are decorated.
266
+ var isIsolatingNode = (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') && replacedNode !== null && isGranularIsolatingNode(replacedNode);
267
+ if (!(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock) && !isIsolatingNode) {
247
268
  return false;
248
269
  }
249
270
  if (!_model.Mark.sameSet((_replacedNode$marks = replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.marks) !== null && _replacedNode$marks !== void 0 ? _replacedNode$marks : [], (_replacingNode$marks = replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.marks) !== null && _replacingNode$marks !== void 0 ? _replacingNode$marks : [])) {
250
271
  return false;
251
272
  }
252
273
  var isTextContentEqual = (replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.textContent) === (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.textContent);
274
+
275
+ // `hasSameChildMarks` only compares an isolating node's direct (block) children, so it cannot
276
+ // vouch for one with unchanged text. Keep the existing whole-node fallback for that case.
277
+ if (isIsolatingNode) {
278
+ return !isTextContentEqual;
279
+ }
253
280
  return !isTextContentEqual || isTextContentEqual && hasSameChildMarks(replacedNode, replacingNode);
254
281
  };
255
282
  var diffBySteps = exports.diffBySteps = function diffBySteps(originalDoc, steps, stepAttributions) {
@@ -157,7 +157,27 @@ const tableRanges = (doc, from, to) => {
157
157
  return ranges;
158
158
  };
159
159
  const isInsideTable = (tables, pos) => tables.some(([tFrom, tTo]) => pos >= tFrom && pos < tTo);
160
+
161
+ /**
162
+ * Where a block's content ends, excluding the run of close tokens that ends it: the block's own,
163
+ * then its last child's, and so on down to the last textblock. A change that keeps those trailing
164
+ * close tokens unchanged (because the other side ends in the same structure, e.g.
165
+ * `…</p></li></ul>`) still covers all of the block's content.
166
+ */
167
+ const endBeforeTrailingCloseTokens = (node, pos) => {
168
+ let end = pos + node.nodeSize;
169
+ let current = node;
170
+ while (current && !current.isLeaf) {
171
+ end -= 1;
172
+ if (current.isTextblock) {
173
+ break;
174
+ }
175
+ current = current.lastChild;
176
+ }
177
+ return end;
178
+ };
160
179
  const calculateNodesForBlockDecoration = ({
180
+ allowTrailingCloseTokens = false,
161
181
  attributionKey,
162
182
  doc,
163
183
  from,
@@ -213,8 +233,23 @@ const calculateNodesForBlockDecoration = ({
213
233
  // re-render. Blocks outside the table keep their normal decorations.
214
234
  const coarseTables = coarseTableCellsOnly ? tableRanges(doc, from, to) : [];
215
235
  // nodesBetween visits ancestors that start before the changed range.
216
- // Only fully contained blocks should mark existing list bullets as new.
217
- const requireContainedBlocks = UNSAFE_expValNoExposure('platform_editor_ai_review_moment', 'isEnabled', false) === true;
236
+ // Only fully contained blocks should mark existing list bullets as new. Under patch 2 this also
237
+ // keeps the clean view from hiding a block the change only starts inside: that block holds
238
+ // unchanged text and the deleted-content widget, so `display: none` on it hid the whole diff.
239
+ const requireContainedBlocks = UNSAFE_expValNoExposure('platform_editor_ai_review_moment', 'isEnabled', false) === true || fg('platform_editor_ai_show_diff_patch_2');
240
+ // Under patch 2, a block whose content the change covers but whose trailing close tokens it does
241
+ // not (e.g. the last list item when both sides end in a list) is decorated like its siblings.
242
+ // Otherwise the clean view hides its text but leaves the block, e.g. an empty bullet.
243
+ const relaxTrailingCloseTokens = allowTrailingCloseTokens && fg('platform_editor_ai_show_diff_patch_2');
244
+ const isContained = (node, pos) => {
245
+ if (requireContainedBlocks && pos < from) {
246
+ return false;
247
+ }
248
+ if (pos + node.nodeSize <= to) {
249
+ return true;
250
+ }
251
+ return relaxTrailingCloseTokens && pos >= from && endBeforeTrailingCloseTokens(node, pos) <= to;
252
+ };
218
253
  // Iterate over the document nodes within the range
219
254
  doc.nodesBetween(from, to, (node, pos) => {
220
255
  if (coarseTableCellsOnly && isInsideTable(coarseTables, pos)) {
@@ -223,7 +258,7 @@ const calculateNodesForBlockDecoration = ({
223
258
  return;
224
259
  }
225
260
  }
226
- if (node.isBlock && (!requireContainedBlocks || pos >= from) && pos + node.nodeSize <= to) {
261
+ if (node.isBlock && isContained(node, pos)) {
227
262
  const nodeEnd = pos + node.nodeSize;
228
263
  const isActive = isRangeActive(activeIndexPos, pos, nodeEnd, attributionKey);
229
264
  decorations.push(...createBlockChangedDecoration({
@@ -640,6 +675,9 @@ const calculateDiffDecorationsInner = ({
640
675
  }));
641
676
  }
642
677
  decorations.push(...calculateNodesForBlockDecoration({
678
+ // A deleted widget placed below anchors at the change's end, inside the very block
679
+ // this would let the decoration claim.
680
+ allowTrailingCloseTokens: !isDeletedWidgetBelow,
643
681
  attributionKey,
644
682
  doc: tr.doc,
645
683
  from: change.fromB,
@@ -1,6 +1,7 @@
1
1
  import { simplifyChanges, ChangeSet } from 'prosemirror-changeset';
2
2
  import { Mark } from '@atlaskit/editor-prosemirror/model';
3
3
  import { Mapping, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
4
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
4
5
  import { getAttributionKey } from '../decorations/colorSchemes/attributions';
5
6
  import { buildCharsByOffset } from '../utils/charsByOffset';
6
7
  import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
@@ -8,6 +9,14 @@ import { optimizeChanges } from './optimizeChanges';
8
9
  const WORD_CHAR_REGEX = /[\p{L}\p{N}_]/u;
9
10
  const PUNCTUATION_REGEX = /\p{P}/u;
10
11
  const WHITESPACE_REGEX = /\s/u;
12
+
13
+ /**
14
+ * Whether a same-type replacement of `node` is diffed granularly rather than as a whole node.
15
+ * `isolating` nodes (table cells, layout columns, expands, bodied extensions, …) keep edits inside
16
+ * their boundary, so replacing one wholesale is an edit of its content, not a new node. Tables are
17
+ * excluded: `groupDeletedColumnChanges` relies on a replaced table being one whole-table change.
18
+ */
19
+ const isGranularIsolatingNode = node => !!node.type.spec.isolating && node.type.spec.tableRole !== 'table';
11
20
  const mapPosition = (mapping, pos) => mapping.map(pos);
12
21
 
13
22
  /**
@@ -196,6 +205,8 @@ const mergeOverlappingByNewDocRange = changes => {
196
205
  * - The replaced slice is not open
197
206
  * - The replaced slice has only one child
198
207
  * - The replacing slice has only one child
208
+ * - Both children are the same textblock type, or (behind `platform_editor_ai_show_diff_patch_2`)
209
+ * the same isolating, non-table node type whose text content differs
199
210
  * - The replaced slice and replacing slice have the same text content
200
211
  * - The replaced slice and replacing slice have the same child marks (if text content is equal)
201
212
  */
@@ -214,13 +225,27 @@ const shouldCheckGranularDiff = (step, before, from, to) => {
214
225
  }
215
226
  const replacedNode = replacedSlice.content.firstChild;
216
227
  const replacingNode = replacingSlice.content.firstChild;
217
- if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name) || !(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock)) {
228
+ if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name)) {
229
+ return false;
230
+ }
231
+
232
+ // Replacing a whole isolating node (e.g. an AI `replaceNode` on a table cell) would otherwise
233
+ // report the entire node as changed, painting a cell overlay over content that was only
234
+ // edited inside it. Diff its content granularly instead, so only the inner edits are decorated.
235
+ const isIsolatingNode = fg('platform_editor_ai_show_diff_patch_2') && replacedNode !== null && isGranularIsolatingNode(replacedNode);
236
+ if (!(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock) && !isIsolatingNode) {
218
237
  return false;
219
238
  }
220
239
  if (!Mark.sameSet((_replacedNode$marks = replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.marks) !== null && _replacedNode$marks !== void 0 ? _replacedNode$marks : [], (_replacingNode$marks = replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.marks) !== null && _replacingNode$marks !== void 0 ? _replacingNode$marks : [])) {
221
240
  return false;
222
241
  }
223
242
  const isTextContentEqual = (replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.textContent) === (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.textContent);
243
+
244
+ // `hasSameChildMarks` only compares an isolating node's direct (block) children, so it cannot
245
+ // vouch for one with unchanged text. Keep the existing whole-node fallback for that case.
246
+ if (isIsolatingNode) {
247
+ return !isTextContentEqual;
248
+ }
224
249
  return !isTextContentEqual || isTextContentEqual && hasSameChildMarks(replacedNode, replacingNode);
225
250
  };
226
251
  export const diffBySteps = (originalDoc, steps, stepAttributions) => {
@@ -170,8 +170,29 @@ var isInsideTable = function isInsideTable(tables, pos) {
170
170
  return pos >= tFrom && pos < tTo;
171
171
  });
172
172
  };
173
+
174
+ /**
175
+ * Where a block's content ends, excluding the run of close tokens that ends it: the block's own,
176
+ * then its last child's, and so on down to the last textblock. A change that keeps those trailing
177
+ * close tokens unchanged (because the other side ends in the same structure, e.g.
178
+ * `…</p></li></ul>`) still covers all of the block's content.
179
+ */
180
+ var endBeforeTrailingCloseTokens = function endBeforeTrailingCloseTokens(node, pos) {
181
+ var end = pos + node.nodeSize;
182
+ var current = node;
183
+ while (current && !current.isLeaf) {
184
+ end -= 1;
185
+ if (current.isTextblock) {
186
+ break;
187
+ }
188
+ current = current.lastChild;
189
+ }
190
+ return end;
191
+ };
173
192
  var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration(_ref5) {
174
- var attributionKey = _ref5.attributionKey,
193
+ var _ref5$allowTrailingCl = _ref5.allowTrailingCloseTokens,
194
+ allowTrailingCloseTokens = _ref5$allowTrailingCl === void 0 ? false : _ref5$allowTrailingCl,
195
+ attributionKey = _ref5.attributionKey,
175
196
  doc = _ref5.doc,
176
197
  from = _ref5.from,
177
198
  to = _ref5.to,
@@ -238,8 +259,23 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
238
259
  // re-render. Blocks outside the table keep their normal decorations.
239
260
  var coarseTables = coarseTableCellsOnly ? tableRanges(doc, from, to) : [];
240
261
  // nodesBetween visits ancestors that start before the changed range.
241
- // Only fully contained blocks should mark existing list bullets as new.
242
- var requireContainedBlocks = UNSAFE_expValNoExposure('platform_editor_ai_review_moment', 'isEnabled', false) === true;
262
+ // Only fully contained blocks should mark existing list bullets as new. Under patch 2 this also
263
+ // keeps the clean view from hiding a block the change only starts inside: that block holds
264
+ // unchanged text and the deleted-content widget, so `display: none` on it hid the whole diff.
265
+ var requireContainedBlocks = UNSAFE_expValNoExposure('platform_editor_ai_review_moment', 'isEnabled', false) === true || fg('platform_editor_ai_show_diff_patch_2');
266
+ // Under patch 2, a block whose content the change covers but whose trailing close tokens it does
267
+ // not (e.g. the last list item when both sides end in a list) is decorated like its siblings.
268
+ // Otherwise the clean view hides its text but leaves the block, e.g. an empty bullet.
269
+ var relaxTrailingCloseTokens = allowTrailingCloseTokens && fg('platform_editor_ai_show_diff_patch_2');
270
+ var isContained = function isContained(node, pos) {
271
+ if (requireContainedBlocks && pos < from) {
272
+ return false;
273
+ }
274
+ if (pos + node.nodeSize <= to) {
275
+ return true;
276
+ }
277
+ return relaxTrailingCloseTokens && pos >= from && endBeforeTrailingCloseTokens(node, pos) <= to;
278
+ };
243
279
  // Iterate over the document nodes within the range
244
280
  doc.nodesBetween(from, to, function (node, pos) {
245
281
  if (coarseTableCellsOnly && isInsideTable(coarseTables, pos)) {
@@ -248,7 +284,7 @@ var calculateNodesForBlockDecoration = function calculateNodesForBlockDecoration
248
284
  return;
249
285
  }
250
286
  }
251
- if (node.isBlock && (!requireContainedBlocks || pos >= from) && pos + node.nodeSize <= to) {
287
+ if (node.isBlock && isContained(node, pos)) {
252
288
  var _nodeEnd = pos + node.nodeSize;
253
289
  var _isActive = isRangeActive(activeIndexPos, pos, _nodeEnd, attributionKey);
254
290
  decorations.push.apply(decorations, _toConsumableArray(createBlockChangedDecoration({
@@ -707,6 +743,9 @@ var calculateDiffDecorationsInner = function calculateDiffDecorationsInner(_ref8
707
743
  })));
708
744
  }
709
745
  decorations.push.apply(decorations, _toConsumableArray(calculateNodesForBlockDecoration({
746
+ // A deleted widget placed below anchors at the change's end, inside the very block
747
+ // this would let the decoration claim.
748
+ allowTrailingCloseTokens: !isDeletedWidgetBelow,
710
749
  attributionKey: attributionKey,
711
750
  doc: tr.doc,
712
751
  from: change.fromB,
@@ -9,6 +9,7 @@ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length)
9
9
  import { simplifyChanges, ChangeSet } from 'prosemirror-changeset';
10
10
  import { Mark } from '@atlaskit/editor-prosemirror/model';
11
11
  import { Mapping, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
12
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
12
13
  import { getAttributionKey } from '../decorations/colorSchemes/attributions';
13
14
  import { buildCharsByOffset } from '../utils/charsByOffset';
14
15
  import { attrAwareTokenEncoder } from './attrAwareTokenEncoder';
@@ -16,6 +17,16 @@ import { optimizeChanges } from './optimizeChanges';
16
17
  var WORD_CHAR_REGEX = /(?:[0-9A-Z_a-z\xAA\xB2\xB3\xB5\xB9\xBA\xBC-\xBE\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0560-\u0588\u05D0-\u05EA\u05EF-\u05F2\u0620-\u064A\u0660-\u0669\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07C0-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u0860-\u086A\u0870-\u0887\u0889-\u088F\u08A0-\u08C9\u0904-\u0939\u093D\u0950\u0958-\u0961\u0966-\u096F\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09E6-\u09F1\u09F4-\u09F9\u09FC\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A66-\u0A6F\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AE6-\u0AEF\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B66-\u0B6F\u0B71-\u0B77\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0BE6-\u0BF2\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C5C\u0C5D\u0C60\u0C61\u0C66-\u0C6F\u0C78-\u0C7E\u0C80\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDC-\u0CDE\u0CE0\u0CE1\u0CE6-\u0CEF\u0CF1\u0CF2\u0D04-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D54-\u0D56\u0D58-\u0D61\u0D66-\u0D78\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DE6-\u0DEF\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E86-\u0E8A\u0E8C-\u0EA3\u0EA5\u0EA7-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F20-\u0F33\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F-\u1049\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u1090-\u1099\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1369-\u137C\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u1711\u171F-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1820-\u1878\u1880-\u1884\u1887-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A16\u1A20-\u1A54\u1A80-\u1A89\u1A90-\u1A99\u1AA7\u1B05-\u1B33\u1B45-\u1B4C\u1B50-\u1B59\u1B83-\u1BA0\u1BAE-\u1BE5\u1C00-\u1C23\u1C40-\u1C49\u1C4D-\u1C7D\u1C80-\u1C8A\u1C90-\u1CBA\u1CBD-\u1CBF\u1CE9-\u1CEC\u1CEE-\u1CF3\u1CF5\u1CF6\u1CFA\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2070\u2071\u2074-\u2079\u207F-\u2089\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2150-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2C00-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2CFD\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312F\u3131-\u318E\u3192-\u3195\u31A0-\u31BF\u31F0-\u31FF\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\u3400-\u4DBF\u4E00-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7DC\uA7F1-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA830-\uA835\uA840-\uA873\uA882-\uA8B3\uA8D0-\uA8D9\uA8F2-\uA8F7\uA8FB\uA8FD\uA8FE\uA900-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF-\uA9D9\uA9E0-\uA9E4\uA9E6-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA50-\uAA59\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB69\uAB70-\uABE2\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD07-\uDD33\uDD40-\uDD78\uDD8A\uDD8B\uDE80-\uDE9C\uDEA0-\uDED0\uDEE1-\uDEFB\uDF00-\uDF23\uDF2D-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDCB0-\uDCD3\uDCD8-\uDCFB\uDD00-\uDD27\uDD30-\uDD63\uDD70-\uDD7A\uDD7C-\uDD8A\uDD8C-\uDD92\uDD94\uDD95\uDD97-\uDDA1\uDDA3-\uDDB1\uDDB3-\uDDB9\uDDBB\uDDBC\uDDC0-\uDDF3\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67\uDF80-\uDF85\uDF87-\uDFB0\uDFB2-\uDFBA]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC58-\uDC76\uDC79-\uDC9E\uDCA7-\uDCAF\uDCE0-\uDCF2\uDCF4\uDCF5\uDCFB-\uDD1B\uDD20-\uDD39\uDD40-\uDD59\uDD80-\uDDB7\uDDBC-\uDDCF\uDDD2-\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE35\uDE40-\uDE48\uDE60-\uDE7E\uDE80-\uDE9F\uDEC0-\uDEC7\uDEC9-\uDEE4\uDEEB-\uDEEF\uDF00-\uDF35\uDF40-\uDF55\uDF58-\uDF72\uDF78-\uDF91\uDFA9-\uDFAF]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2\uDCFA-\uDD23\uDD30-\uDD39\uDD40-\uDD65\uDD6F-\uDD85\uDE60-\uDE7E\uDE80-\uDEA9\uDEB0\uDEB1\uDEC2-\uDEC7\uDF00-\uDF27\uDF30-\uDF45\uDF51-\uDF54\uDF70-\uDF81\uDFB0-\uDFCB\uDFE0-\uDFF6]|\uD804[\uDC03-\uDC37\uDC52-\uDC6F\uDC71\uDC72\uDC75\uDC83-\uDCAF\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD03-\uDD26\uDD36-\uDD3F\uDD44\uDD47\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDD0-\uDDDA\uDDDC\uDDE1-\uDDF4\uDE00-\uDE11\uDE13-\uDE2B\uDE3F\uDE40\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDEF0-\uDEF9\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61\uDF80-\uDF89\uDF8B\uDF8E\uDF90-\uDFB5\uDFB7\uDFD1\uDFD3]|\uD805[\uDC00-\uDC34\uDC47-\uDC4A\uDC50-\uDC59\uDC5F-\uDC61\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE50-\uDE59\uDE80-\uDEAA\uDEB8\uDEC0-\uDEC9\uDED0-\uDEE3\uDF00-\uDF1A\uDF30-\uDF3B\uDF40-\uDF46]|\uD806[\uDC00-\uDC2B\uDCA0-\uDCF2\uDCFF-\uDD06\uDD09\uDD0C-\uDD13\uDD15\uDD16\uDD18-\uDD2F\uDD3F\uDD41\uDD50-\uDD59\uDDA0-\uDDA7\uDDAA-\uDDD0\uDDE1\uDDE3\uDE00\uDE0B-\uDE32\uDE3A\uDE50\uDE5C-\uDE89\uDE9D\uDEB0-\uDEF8\uDFC0-\uDFE0\uDFF0-\uDFF9]|\uD807[\uDC00-\uDC08\uDC0A-\uDC2E\uDC40\uDC50-\uDC6C\uDC72-\uDC8F\uDD00-\uDD06\uDD08\uDD09\uDD0B-\uDD30\uDD46\uDD50-\uDD59\uDD60-\uDD65\uDD67\uDD68\uDD6A-\uDD89\uDD98\uDDA0-\uDDA9\uDDB0-\uDDDB\uDDE0-\uDDE9\uDEE0-\uDEF2\uDF02\uDF04-\uDF10\uDF12-\uDF33\uDF50-\uDF59\uDFB0\uDFC0-\uDFD4]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|\uD80B[\uDF90-\uDFF0]|[\uD80C\uD80E\uD80F\uD81C-\uD822\uD840-\uD868\uD86A-\uD86D\uD86F-\uD872\uD874-\uD879\uD880-\uD883\uD885-\uD88C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2F\uDC41-\uDC46\uDC60-\uDFFF]|\uD810[\uDC00-\uDFFA]|\uD811[\uDC00-\uDE46]|\uD818[\uDD00-\uDD1D\uDD30-\uDD39]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDE70-\uDEBE\uDEC0-\uDEC9\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF50-\uDF59\uDF5B-\uDF61\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDD40-\uDD6C\uDD70-\uDD79\uDE40-\uDE96\uDEA0-\uDEB8\uDEBB-\uDED3\uDF00-\uDF4A\uDF50\uDF93-\uDF9F\uDFE0\uDFE1\uDFE3\uDFF2-\uDFF6]|\uD823[\uDC00-\uDCD5\uDCFF-\uDD1E\uDD80-\uDDF2]|\uD82B[\uDFF0-\uDFF3\uDFF5-\uDFFB\uDFFD\uDFFE]|\uD82C[\uDC00-\uDD22\uDD32\uDD50-\uDD52\uDD55\uDD64-\uDD67\uDD70-\uDEFB]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD833[\uDCF0-\uDCF9]|\uD834[\uDEC0-\uDED3\uDEE0-\uDEF3\uDF60-\uDF78]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD837[\uDF00-\uDF1E\uDF25-\uDF2A]|\uD838[\uDC30-\uDC6D\uDD00-\uDD2C\uDD37-\uDD3D\uDD40-\uDD49\uDD4E\uDE90-\uDEAD\uDEC0-\uDEEB\uDEF0-\uDEF9]|\uD839[\uDCD0-\uDCEB\uDCF0-\uDCF9\uDDD0-\uDDED\uDDF0-\uDDFA\uDEC0-\uDEDE\uDEE0-\uDEE2\uDEE4\uDEE5\uDEE7-\uDEED\uDEF0-\uDEF4\uDEFE\uDEFF\uDFE0-\uDFE6\uDFE8-\uDFEB\uDFED\uDFEE\uDFF0-\uDFFE]|\uD83A[\uDC00-\uDCC4\uDCC7-\uDCCF\uDD00-\uDD43\uDD4B\uDD50-\uDD59]|\uD83B[\uDC71-\uDCAB\uDCAD-\uDCAF\uDCB1-\uDCB4\uDD01-\uDD2D\uDD2F-\uDD3D\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD83C[\uDD00-\uDD0C]|\uD83E[\uDFF0-\uDFF9]|\uD869[\uDC00-\uDEDF\uDF00-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEAD\uDEB0-\uDFFF]|\uD87A[\uDC00-\uDFE0\uDFF0-\uDFFF]|\uD87B[\uDC00-\uDE5D]|\uD87E[\uDC00-\uDE1D]|\uD884[\uDC00-\uDF4A\uDF50-\uDFFF]|\uD88D[\uDC00-\uDC79])/;
17
18
  var PUNCTUATION_REGEX = /(?:[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061D-\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C77\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B4E\u1B4F\u1B5A-\u1B60\u1B7D-\u1B7F\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4F\u2E52-\u2E5D\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDD6E\uDEAD\uDED0\uDF55-\uDF59\uDF86-\uDF89]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9\uDFD4\uDFD5\uDFD7\uDFD8]|\uD805[\uDC4B-\uDC4F\uDC5A\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDEB9\uDF3C-\uDF3E]|\uD806[\uDC3B\uDD44-\uDD46\uDDE2\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2\uDF00-\uDF09\uDFE1]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8\uDF43-\uDF4F\uDFFF]|\uD809[\uDC70-\uDC74]|\uD80B[\uDFF1\uDFF2]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDD6D-\uDD6F\uDE97-\uDE9A\uDFE2]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD839\uDDFF|\uD83A[\uDD5E\uDD5F])/;
18
19
  var WHITESPACE_REGEX = /[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]/;
20
+
21
+ /**
22
+ * Whether a same-type replacement of `node` is diffed granularly rather than as a whole node.
23
+ * `isolating` nodes (table cells, layout columns, expands, bodied extensions, …) keep edits inside
24
+ * their boundary, so replacing one wholesale is an edit of its content, not a new node. Tables are
25
+ * excluded: `groupDeletedColumnChanges` relies on a replaced table being one whole-table change.
26
+ */
27
+ var isGranularIsolatingNode = function isGranularIsolatingNode(node) {
28
+ return !!node.type.spec.isolating && node.type.spec.tableRole !== 'table';
29
+ };
19
30
  var mapPosition = function mapPosition(mapping, pos) {
20
31
  return mapping.map(pos);
21
32
  };
@@ -218,6 +229,8 @@ var mergeOverlappingByNewDocRange = function mergeOverlappingByNewDocRange(chang
218
229
  * - The replaced slice is not open
219
230
  * - The replaced slice has only one child
220
231
  * - The replacing slice has only one child
232
+ * - Both children are the same textblock type, or (behind `platform_editor_ai_show_diff_patch_2`)
233
+ * the same isolating, non-table node type whose text content differs
221
234
  * - The replaced slice and replacing slice have the same text content
222
235
  * - The replaced slice and replacing slice have the same child marks (if text content is equal)
223
236
  */
@@ -236,13 +249,27 @@ var shouldCheckGranularDiff = function shouldCheckGranularDiff(step, before, fro
236
249
  }
237
250
  var replacedNode = replacedSlice.content.firstChild;
238
251
  var replacingNode = replacingSlice.content.firstChild;
239
- if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name) || !(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock)) {
252
+ if ((replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.type.name) !== (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.type.name)) {
253
+ return false;
254
+ }
255
+
256
+ // Replacing a whole isolating node (e.g. an AI `replaceNode` on a table cell) would otherwise
257
+ // report the entire node as changed, painting a cell overlay over content that was only
258
+ // edited inside it. Diff its content granularly instead, so only the inner edits are decorated.
259
+ var isIsolatingNode = fg('platform_editor_ai_show_diff_patch_2') && replacedNode !== null && isGranularIsolatingNode(replacedNode);
260
+ if (!(replacedNode !== null && replacedNode !== void 0 && replacedNode.type.isTextblock) && !isIsolatingNode) {
240
261
  return false;
241
262
  }
242
263
  if (!Mark.sameSet((_replacedNode$marks = replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.marks) !== null && _replacedNode$marks !== void 0 ? _replacedNode$marks : [], (_replacingNode$marks = replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.marks) !== null && _replacingNode$marks !== void 0 ? _replacingNode$marks : [])) {
243
264
  return false;
244
265
  }
245
266
  var isTextContentEqual = (replacedNode === null || replacedNode === void 0 ? void 0 : replacedNode.textContent) === (replacingNode === null || replacingNode === void 0 ? void 0 : replacingNode.textContent);
267
+
268
+ // `hasSameChildMarks` only compares an isolating node's direct (block) children, so it cannot
269
+ // vouch for one with unchanged text. Keep the existing whole-node fallback for that case.
270
+ if (isIsolatingNode) {
271
+ return !isTextContentEqual;
272
+ }
246
273
  return !isTextContentEqual || isTextContentEqual && hasSameChildMarks(replacedNode, replacingNode);
247
274
  };
248
275
  export var diffBySteps = function diffBySteps(originalDoc, steps, stepAttributions) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "23.0.0",
3
+ "version": "23.0.2",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -39,7 +39,7 @@
39
39
  "@atlaskit/platform-feature-experiments": "^0.3.0",
40
40
  "@atlaskit/platform-feature-flags": "^2.2.0",
41
41
  "@atlaskit/primitives": "^22.5.0",
42
- "@atlaskit/tmp-editor-statsig": "^224.0.0",
42
+ "@atlaskit/tmp-editor-statsig": "^226.0.0",
43
43
  "@atlaskit/tokens": "^20.3.0",
44
44
  "@babel/runtime": "^7.0.0",
45
45
  "@compiled/react": "^1.0.2",
@@ -71,7 +71,7 @@
71
71
  "react-intl": "^7.0.0"
72
72
  },
73
73
  "peerDependencies": {
74
- "@atlaskit/editor-common": "^129.0.0",
74
+ "@atlaskit/editor-common": "^129.1.0",
75
75
  "react": "^18.2.0 || ^19.2.0",
76
76
  "react-dom": "^18.2.0 || ^19.2.0",
77
77
  "react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"