@atlaskit/editor-plugin-show-diff 24.0.1 → 24.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.
Files changed (25) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/pm-plugins/decorations/createBlockChangedDecoration.js +1 -9
  3. package/dist/cjs/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
  4. package/dist/cjs/pm-plugins/decorations/decorationKeys.js +9 -1
  5. package/dist/cjs/pm-plugins/decorations/extractContributorTags.js +4 -1
  6. package/dist/cjs/pm-plugins/decorations/utils/getWidgetElement.js +16 -0
  7. package/dist/cjs/pm-plugins/getDeletedWidgets.js +2 -12
  8. package/dist/cjs/pm-plugins/main.js +26 -0
  9. package/dist/es2019/pm-plugins/decorations/createBlockChangedDecoration.js +1 -5
  10. package/dist/es2019/pm-plugins/decorations/createNodeChangedDecorationWidget.js +8 -8
  11. package/dist/es2019/pm-plugins/decorations/decorationKeys.js +7 -0
  12. package/dist/es2019/pm-plugins/decorations/extractContributorTags.js +4 -1
  13. package/dist/es2019/pm-plugins/decorations/utils/getWidgetElement.js +11 -0
  14. package/dist/es2019/pm-plugins/getDeletedWidgets.js +1 -12
  15. package/dist/es2019/pm-plugins/main.js +26 -0
  16. package/dist/esm/pm-plugins/decorations/createBlockChangedDecoration.js +1 -9
  17. package/dist/esm/pm-plugins/decorations/createNodeChangedDecorationWidget.js +4 -2
  18. package/dist/esm/pm-plugins/decorations/decorationKeys.js +9 -1
  19. package/dist/esm/pm-plugins/decorations/extractContributorTags.js +4 -1
  20. package/dist/esm/pm-plugins/decorations/utils/getWidgetElement.js +10 -0
  21. package/dist/esm/pm-plugins/getDeletedWidgets.js +1 -11
  22. package/dist/esm/pm-plugins/main.js +26 -0
  23. package/dist/types/pm-plugins/decorations/decorationKeys.d.ts +2 -0
  24. package/dist/types/pm-plugins/decorations/utils/getWidgetElement.d.ts +2 -0
  25. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @atlaskit/editor-plugin-show-diff
2
2
 
3
+ ## 24.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`646c02ae8de28`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/646c02ae8de28) -
8
+ Fix contributor tag and step mismatch in show diff: the spacer widget no longer becomes an
9
+ untagged navigation stop when contributor tags are shown, and block cards inside a table now carry
10
+ attribution.
11
+ - [`7b18b1db6b6d3`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/7b18b1db6b6d3) -
12
+ EDITOR-9415 Allow native browser selection and copying within diff widgets behind
13
+ platform_editor_ai_show_diff_patch_2
14
+
3
15
  ## 24.0.1
4
16
 
5
17
  ### Patch Changes
@@ -8,7 +8,6 @@ exports.createBlockChangedDecoration = void 0;
8
8
  var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
9
9
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
10
  var _lazyNodeView = require("@atlaskit/editor-common/lazy-node-view");
11
- var _utils = require("@atlaskit/editor-prosemirror/utils");
12
11
  var _view = require("@atlaskit/editor-prosemirror/view");
13
12
  var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled");
14
13
  var _fg = require("@atlaskit/platform-feature-flags/fg");
@@ -34,13 +33,6 @@ var UNSTYLED_NODES = ['mediaSingle', 'mediaGroup', 'table',
34
33
  'heading', 'hardBreak', 'decisionList', 'taskList', 'bulletList', 'orderedList', 'layoutSection'];
35
34
  var CELL_NODES = ['tableCell', 'tableHeader'];
36
35
 
37
- /** Panels, rules and media can also sit in a table cell, which is out of scope for block tags. */
38
- var isInsideTable = function isInsideTable(doc, pos) {
39
- return (0, _utils.findParentNodeClosestToPos)(doc.resolve(pos), function (node) {
40
- return node.type.name === 'table';
41
- }) !== undefined;
42
- };
43
-
44
36
  /**
45
37
  * Whether this block can host a contributor tag of its own.
46
38
  *
@@ -56,7 +48,7 @@ var canTagBlock = function canTagBlock(_ref) {
56
48
  return false;
57
49
  }
58
50
  var nodeType = (_doc$nodeAt = doc.nodeAt(from)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type;
59
- return nodeType !== undefined && (0, _taggableBlockNodes.isTaggableBlockNode)(nodeType) && !isInsideTable(doc, from);
51
+ return nodeType !== undefined && (0, _taggableBlockNodes.isTaggableBlockNode)(nodeType);
60
52
  };
61
53
 
62
54
  /** Positioning context for the cell overlay widget decorations. */
@@ -657,12 +657,14 @@ var createNodeChangedDecorationWidget = exports.createNodeChangedDecorationWidge
657
657
  if ((0, _fg.fg)('platform_editor_ai_show_diff_patch_1')) {
658
658
  defaultSpacer.style.setProperty('scroll-margin-top', _decorationKeys.scrollMarginTopValue);
659
659
  }
660
- decorations.push(_view.Decoration.widget(safeInsertPos, defaultSpacer, _objectSpread({}, (0, _decorationKeys.buildDiffDecorationSpec)({
660
+ decorations.push(_view.Decoration.widget(safeInsertPos, defaultSpacer,
661
+ // Spacing only: a diff spec would make it an untagged navigation stop.
662
+ showContributorTags ? {} : (0, _decorationKeys.buildDiffDecorationSpec)({
661
663
  colorScheme: colorScheme,
662
664
  decorationType: 'widget',
663
665
  diffId: crypto.randomUUID(),
664
666
  isInserted: isInserted
665
- }))));
667
+ })));
666
668
  }
667
669
  }
668
670
  return decorations;
@@ -9,6 +9,7 @@ exports.buildAnchorDecorationSpec = buildAnchorDecorationSpec;
9
9
  exports.scrollMarginTopValue = exports.scrollMarginTopStyle = exports.isDiffDecorationSpec = exports.isDiffDecoration = exports.isAnchorDecorationSpec = exports.extractDiffDescriptors = exports.buildDiffDecorationSpec = exports.buildDiffDecorationKey = exports.buildContributorTagDecorationSpec = void 0;
10
10
  var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof"));
11
11
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
12
+ var _fg = require("@atlaskit/platform-feature-flags/fg");
12
13
  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; }
13
14
  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; }
14
15
  /**
@@ -81,7 +82,7 @@ var buildDiffDecorationSpec = exports.buildDiffDecorationSpec = function buildDi
81
82
  leftAnchorId = _ref3.leftAnchorId,
82
83
  nodeName = _ref3.nodeName,
83
84
  side = _ref3.side;
84
- return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
85
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
85
86
  decorationFamily: DecorationFamily.diff,
86
87
  decorationType: decorationType,
87
88
  diffId: diffId,
@@ -104,6 +105,13 @@ var buildDiffDecorationSpec = exports.buildDiffDecorationSpec = function buildDi
104
105
  nodeName: nodeName
105
106
  } : {}), side !== undefined ? {
106
107
  side: side
108
+ } : {}), decorationType === 'widget' && (0, _fg.fg)('platform_editor_ai_show_diff_patch_2') ? {
109
+ // Widget content is outside the document. Keep its native DOM selection
110
+ // and let the browser handle events within it.
111
+ ignoreSelection: true,
112
+ stopEvent: function stopEvent() {
113
+ return true;
114
+ }
107
115
  } : {});
108
116
  };
109
117
  function buildAnchorDecorationSpec(_ref4) {
@@ -54,7 +54,10 @@ var leadsReplacement = function leadsReplacement(widget) {
54
54
  * inline/widget range that merely overlaps the block is a separate change (EDITOR-9473).
55
55
  */
56
56
  var isSameBlockChange = function isSameBlockChange(inner, block) {
57
- return inner.spec.attributionKey === block.spec.attributionKey && block.from <= inner.from && inner.to <= block.to;
57
+ return inner.spec.attributionKey === block.spec.attributionKey && (inner.spec.decorationType === 'widget' ?
58
+ // Deleted content is zero-width and sits at the start of what replaced it, so a widget at the
59
+ // block's edge is beside the block rather than within it and keeps its own tag.
60
+ block.from < inner.from && inner.to < block.to : block.from <= inner.from && inner.to <= block.to);
58
61
  };
59
62
 
60
63
  /**
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.getWidgetElement = void 0;
7
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
8
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
9
+
10
+ // The element a widget renders, or undefined if it renders via a factory.
11
+ var getWidgetElement = exports.getWidgetElement = function getWidgetElement(decoration) {
12
+ var _type;
13
+ var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
14
+ toDOM = _ref.toDOM;
15
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
16
+ };
@@ -5,18 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.getDeletedWidgets = void 0;
7
7
  var _decorationKeys = require("./decorations/decorationKeys");
8
+ var _getWidgetElement = require("./decorations/utils/getWidgetElement");
8
9
  var _main = require("./main");
9
- // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
10
- // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
11
-
12
- // The element a deleted-content widget renders, or undefined if it renders via a factory.
13
- var getWidgetElement = function getWidgetElement(decoration) {
14
- var _type;
15
- var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
16
- toDOM = _ref.toDOM;
17
- return toDOM instanceof HTMLElement ? toDOM : undefined;
18
- };
19
-
20
10
  /**
21
11
  * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
22
12
  * ordered by position. Deleted content is rendered as widget decorations rather than document
@@ -34,7 +24,7 @@ var getDeletedWidgets = exports.getDeletedWidgets = function getDeletedWidgets(e
34
24
  return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, function (spec) {
35
25
  return (0, _decorationKeys.isDiffDecorationSpec)(spec) && spec.decorationType === 'widget';
36
26
  }).reduce(function (widgets, decoration) {
37
- var element = getWidgetElement(decoration);
27
+ var element = (0, _getWidgetElement.getWidgetElement)(decoration);
38
28
  if (element) {
39
29
  widgets.push({
40
30
  element: element,
@@ -16,6 +16,7 @@ var _fg = require("@atlaskit/platform-feature-flags/fg");
16
16
  var _announceActiveDiff = require("../ui/DiffNavigation/announceActiveDiff");
17
17
  var _calculateDiffDecorations = require("./calculateDiff/calculateDiffDecorations");
18
18
  var _decorationKeys = require("./decorations/decorationKeys");
19
+ var _getWidgetElement = require("./decorations/utils/getWidgetElement");
19
20
  var _enforceCustomStepRegisters = require("./enforceCustomStepRegisters");
20
21
  var _getDefaultDiffType = require("./getDefaultDiffType");
21
22
  var _getScrollableDecorations = require("./getScrollableDecorations");
@@ -306,6 +307,31 @@ var createPlugin = exports.createPlugin = function createPlugin(config, getIntl,
306
307
  };
307
308
  },
308
309
  props: {
310
+ handleDOMEvents: {
311
+ // Bypass ProseMirror's copy handler without preventing native browser copy
312
+ // when the selection is completely contained within an inverted diff widget
313
+ copy: function copy(view) {
314
+ if (!(0, _fg.fg)('platform_editor_ai_show_diff_patch_2')) {
315
+ return false;
316
+ }
317
+ var pluginState = showDiffPluginKey.getState(view.state);
318
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDisplayingChanges) || !pluginState.isInverted) {
319
+ return false;
320
+ }
321
+ var selection = view.dom.ownerDocument.getSelection();
322
+ if (!selection || selection.isCollapsed || selection.rangeCount !== 1) {
323
+ return false;
324
+ }
325
+ var range = selection.getRangeAt(0);
326
+ return pluginState.decorations.find().filter(_decorationKeys.isDiffDecoration).some(function (decoration) {
327
+ if (decoration.spec.decorationType !== 'widget') {
328
+ return false;
329
+ }
330
+ var dom = (0, _getWidgetElement.getWidgetElement)(decoration);
331
+ return Boolean(dom && view.dom.contains(dom) && dom.contains(range.startContainer) && dom.contains(range.endContainer));
332
+ });
333
+ }
334
+ },
309
335
  decorations: function decorations(state) {
310
336
  var pluginState = showDiffPluginKey.getState(state);
311
337
  return pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations;
@@ -1,5 +1,4 @@
1
1
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
2
- import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
3
2
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
4
3
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
5
4
  import { fg } from '@atlaskit/platform-feature-flags/fg';
@@ -23,9 +22,6 @@ const UNSTYLED_NODES = ['mediaSingle', 'mediaGroup', 'table',
23
22
  'heading', 'hardBreak', 'decisionList', 'taskList', 'bulletList', 'orderedList', 'layoutSection'];
24
23
  const CELL_NODES = ['tableCell', 'tableHeader'];
25
24
 
26
- /** Panels, rules and media can also sit in a table cell, which is out of scope for block tags. */
27
- const isInsideTable = (doc, pos) => findParentNodeClosestToPos(doc.resolve(pos), node => node.type.name === 'table') !== undefined;
28
-
29
25
  /**
30
26
  * Whether this block can host a contributor tag of its own.
31
27
  *
@@ -42,7 +38,7 @@ const canTagBlock = ({
42
38
  return false;
43
39
  }
44
40
  const nodeType = (_doc$nodeAt = doc.nodeAt(from)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type;
45
- return nodeType !== undefined && isTaggableBlockNode(nodeType) && !isInsideTable(doc, from);
41
+ return nodeType !== undefined && isTaggableBlockNode(nodeType);
46
42
  };
47
43
 
48
44
  /** Positioning context for the cell overlay widget decorations. */
@@ -641,14 +641,14 @@ export const createNodeChangedDecorationWidget = ({
641
641
  if (fg('platform_editor_ai_show_diff_patch_1')) {
642
642
  defaultSpacer.style.setProperty('scroll-margin-top', scrollMarginTopValue);
643
643
  }
644
- decorations.push(Decoration.widget(safeInsertPos, defaultSpacer, {
645
- ...buildDiffDecorationSpec({
646
- colorScheme,
647
- decorationType: 'widget',
648
- diffId: crypto.randomUUID(),
649
- isInserted
650
- })
651
- }));
644
+ decorations.push(Decoration.widget(safeInsertPos, defaultSpacer,
645
+ // Spacing only: a diff spec would make it an untagged navigation stop.
646
+ showContributorTags ? {} : buildDiffDecorationSpec({
647
+ colorScheme,
648
+ decorationType: 'widget',
649
+ diffId: crypto.randomUUID(),
650
+ isInserted
651
+ })));
652
652
  }
653
653
  }
654
654
  return decorations;
@@ -1,3 +1,4 @@
1
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
1
2
  /**
2
3
  * Decoration families produced by the show-diff plugin.
3
4
  * Each family owns its own key space and spec shape.
@@ -98,6 +99,12 @@ export const buildDiffDecorationSpec = ({
98
99
  } : {}),
99
100
  ...(side !== undefined ? {
100
101
  side
102
+ } : {}),
103
+ ...(decorationType === 'widget' && fg('platform_editor_ai_show_diff_patch_2') ? {
104
+ // Widget content is outside the document. Keep its native DOM selection
105
+ // and let the browser handle events within it.
106
+ ignoreSelection: true,
107
+ stopEvent: () => true
101
108
  } : {})
102
109
  });
103
110
  export function buildAnchorDecorationSpec({
@@ -33,7 +33,10 @@ const leadsReplacement = widget => fg('confluence_ncs_step_diffing_version_histo
33
33
  * block keeps the tag — one tag per block. Only when the block fully covers `inner`; a wider
34
34
  * inline/widget range that merely overlaps the block is a separate change (EDITOR-9473).
35
35
  */
36
- const isSameBlockChange = (inner, block) => inner.spec.attributionKey === block.spec.attributionKey && block.from <= inner.from && inner.to <= block.to;
36
+ const isSameBlockChange = (inner, block) => inner.spec.attributionKey === block.spec.attributionKey && (inner.spec.decorationType === 'widget' ?
37
+ // Deleted content is zero-width and sits at the start of what replaced it, so a widget at the
38
+ // block's edge is beside the block rather than within it and keeps its own tag.
39
+ block.from < inner.from && inner.to < block.to : block.from <= inner.from && inner.to <= block.to);
37
40
 
38
41
  /**
39
42
  * Whether `outer` is the box `inner` sits in, for one contributor. Nested blocks they inserted read
@@ -0,0 +1,11 @@
1
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
2
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
3
+
4
+ // The element a widget renders, or undefined if it renders via a factory.
5
+ export const getWidgetElement = decoration => {
6
+ var _type;
7
+ const {
8
+ toDOM
9
+ } = (_type = decoration.type) !== null && _type !== void 0 ? _type : {};
10
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
11
+ };
@@ -1,18 +1,7 @@
1
1
  import { isDiffDecorationSpec } from './decorations/decorationKeys';
2
+ import { getWidgetElement } from './decorations/utils/getWidgetElement';
2
3
  import { showDiffPluginKey } from './main';
3
4
 
4
- // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
5
- // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
6
-
7
- // The element a deleted-content widget renders, or undefined if it renders via a factory.
8
- const getWidgetElement = decoration => {
9
- var _type;
10
- const {
11
- toDOM
12
- } = (_type = decoration.type) !== null && _type !== void 0 ? _type : {};
13
- return toDOM instanceof HTMLElement ? toDOM : undefined;
14
- };
15
-
16
5
  /**
17
6
  * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
18
7
  * ordered by position. Deleted content is rendered as widget decorations rather than document
@@ -8,6 +8,7 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
8
8
  import { getActiveDiffAnnouncement } from '../ui/DiffNavigation/announceActiveDiff';
9
9
  import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
10
10
  import { isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
11
+ import { getWidgetElement } from './decorations/utils/getWidgetElement';
11
12
  import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
12
13
  import { getDefaultDiffType } from './getDefaultDiffType';
13
14
  import { getScrollableDecorations } from './getScrollableDecorations';
@@ -305,6 +306,31 @@ export const createPlugin = (config, getIntl, api, onEditorView) => {
305
306
  };
306
307
  },
307
308
  props: {
309
+ handleDOMEvents: {
310
+ // Bypass ProseMirror's copy handler without preventing native browser copy
311
+ // when the selection is completely contained within an inverted diff widget
312
+ copy: view => {
313
+ if (!fg('platform_editor_ai_show_diff_patch_2')) {
314
+ return false;
315
+ }
316
+ const pluginState = showDiffPluginKey.getState(view.state);
317
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDisplayingChanges) || !pluginState.isInverted) {
318
+ return false;
319
+ }
320
+ const selection = view.dom.ownerDocument.getSelection();
321
+ if (!selection || selection.isCollapsed || selection.rangeCount !== 1) {
322
+ return false;
323
+ }
324
+ const range = selection.getRangeAt(0);
325
+ return pluginState.decorations.find().filter(isDiffDecoration).some(decoration => {
326
+ if (decoration.spec.decorationType !== 'widget') {
327
+ return false;
328
+ }
329
+ const dom = getWidgetElement(decoration);
330
+ return Boolean(dom && view.dom.contains(dom) && dom.contains(range.startContainer) && dom.contains(range.endContainer));
331
+ });
332
+ }
333
+ },
308
334
  decorations: state => {
309
335
  const pluginState = showDiffPluginKey.getState(state);
310
336
  return pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations;
@@ -3,7 +3,6 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
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
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
5
  import { convertToInlineCss } from '@atlaskit/editor-common/lazy-node-view';
6
- import { findParentNodeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
7
6
  import { Decoration } from '@atlaskit/editor-prosemirror/view';
8
7
  import { isExperimentEnabled } from '@atlaskit/platform-feature-experiments/is-experiment-enabled';
9
8
  import { fg } from '@atlaskit/platform-feature-flags/fg';
@@ -27,13 +26,6 @@ var UNSTYLED_NODES = ['mediaSingle', 'mediaGroup', 'table',
27
26
  'heading', 'hardBreak', 'decisionList', 'taskList', 'bulletList', 'orderedList', 'layoutSection'];
28
27
  var CELL_NODES = ['tableCell', 'tableHeader'];
29
28
 
30
- /** Panels, rules and media can also sit in a table cell, which is out of scope for block tags. */
31
- var isInsideTable = function isInsideTable(doc, pos) {
32
- return findParentNodeClosestToPos(doc.resolve(pos), function (node) {
33
- return node.type.name === 'table';
34
- }) !== undefined;
35
- };
36
-
37
29
  /**
38
30
  * Whether this block can host a contributor tag of its own.
39
31
  *
@@ -49,7 +41,7 @@ var canTagBlock = function canTagBlock(_ref) {
49
41
  return false;
50
42
  }
51
43
  var nodeType = (_doc$nodeAt = doc.nodeAt(from)) === null || _doc$nodeAt === void 0 ? void 0 : _doc$nodeAt.type;
52
- return nodeType !== undefined && isTaggableBlockNode(nodeType) && !isInsideTable(doc, from);
44
+ return nodeType !== undefined && isTaggableBlockNode(nodeType);
53
45
  };
54
46
 
55
47
  /** Positioning context for the cell overlay widget decorations. */
@@ -651,12 +651,14 @@ export var createNodeChangedDecorationWidget = function createNodeChangedDecorat
651
651
  if (fg('platform_editor_ai_show_diff_patch_1')) {
652
652
  defaultSpacer.style.setProperty('scroll-margin-top', scrollMarginTopValue);
653
653
  }
654
- decorations.push(Decoration.widget(safeInsertPos, defaultSpacer, _objectSpread({}, buildDiffDecorationSpec({
654
+ decorations.push(Decoration.widget(safeInsertPos, defaultSpacer,
655
+ // Spacing only: a diff spec would make it an untagged navigation stop.
656
+ showContributorTags ? {} : buildDiffDecorationSpec({
655
657
  colorScheme: colorScheme,
656
658
  decorationType: 'widget',
657
659
  diffId: crypto.randomUUID(),
658
660
  isInserted: isInserted
659
- }))));
661
+ })));
660
662
  }
661
663
  }
662
664
  return decorations;
@@ -2,6 +2,7 @@ import _typeof from "@babel/runtime/helpers/typeof";
2
2
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
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
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
+ import { fg } from '@atlaskit/platform-feature-flags/fg';
5
6
  /**
6
7
  * Decoration families produced by the show-diff plugin.
7
8
  * Each family owns its own key space and spec shape.
@@ -72,7 +73,7 @@ export var buildDiffDecorationSpec = function buildDiffDecorationSpec(_ref3) {
72
73
  leftAnchorId = _ref3.leftAnchorId,
73
74
  nodeName = _ref3.nodeName,
74
75
  side = _ref3.side;
75
- return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
76
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread(_objectSpread({
76
77
  decorationFamily: DecorationFamily.diff,
77
78
  decorationType: decorationType,
78
79
  diffId: diffId,
@@ -95,6 +96,13 @@ export var buildDiffDecorationSpec = function buildDiffDecorationSpec(_ref3) {
95
96
  nodeName: nodeName
96
97
  } : {}), side !== undefined ? {
97
98
  side: side
99
+ } : {}), decorationType === 'widget' && fg('platform_editor_ai_show_diff_patch_2') ? {
100
+ // Widget content is outside the document. Keep its native DOM selection
101
+ // and let the browser handle events within it.
102
+ ignoreSelection: true,
103
+ stopEvent: function stopEvent() {
104
+ return true;
105
+ }
98
106
  } : {});
99
107
  };
100
108
  export function buildAnchorDecorationSpec(_ref4) {
@@ -48,7 +48,10 @@ var leadsReplacement = function leadsReplacement(widget) {
48
48
  * inline/widget range that merely overlaps the block is a separate change (EDITOR-9473).
49
49
  */
50
50
  var isSameBlockChange = function isSameBlockChange(inner, block) {
51
- return inner.spec.attributionKey === block.spec.attributionKey && block.from <= inner.from && inner.to <= block.to;
51
+ return inner.spec.attributionKey === block.spec.attributionKey && (inner.spec.decorationType === 'widget' ?
52
+ // Deleted content is zero-width and sits at the start of what replaced it, so a widget at the
53
+ // block's edge is beside the block rather than within it and keeps its own tag.
54
+ block.from < inner.from && inner.to < block.to : block.from <= inner.from && inner.to <= block.to);
52
55
  };
53
56
 
54
57
  /**
@@ -0,0 +1,10 @@
1
+ // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
2
+ // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
3
+
4
+ // The element a widget renders, or undefined if it renders via a factory.
5
+ export var getWidgetElement = function getWidgetElement(decoration) {
6
+ var _type;
7
+ var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
8
+ toDOM = _ref.toDOM;
9
+ return toDOM instanceof HTMLElement ? toDOM : undefined;
10
+ };
@@ -1,17 +1,7 @@
1
1
  import { isDiffDecorationSpec } from './decorations/decorationKeys';
2
+ import { getWidgetElement } from './decorations/utils/getWidgetElement';
2
3
  import { showDiffPluginKey } from './main';
3
4
 
4
- // prosemirror-view does not type `Decoration.type`; a widget's `type.toDOM` is the node passed to
5
- // `Decoration.widget()` (an element or a factory — the `WidgetConstructor` union).
6
-
7
- // The element a deleted-content widget renders, or undefined if it renders via a factory.
8
- var getWidgetElement = function getWidgetElement(decoration) {
9
- var _type;
10
- var _ref = (_type = decoration.type) !== null && _type !== void 0 ? _type : {},
11
- toDOM = _ref.toDOM;
12
- return toDOM instanceof HTMLElement ? toDOM : undefined;
13
- };
14
-
15
5
  /**
16
6
  * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
17
7
  * ordered by position. Deleted content is rendered as widget decorations rather than document
@@ -11,6 +11,7 @@ import { fg } from '@atlaskit/platform-feature-flags/fg';
11
11
  import { getActiveDiffAnnouncement } from '../ui/DiffNavigation/announceActiveDiff';
12
12
  import { calculateDiffDecorations } from './calculateDiff/calculateDiffDecorations';
13
13
  import { isDiffDecoration, isDiffDecorationSpec } from './decorations/decorationKeys';
14
+ import { getWidgetElement } from './decorations/utils/getWidgetElement';
14
15
  import { enforceCustomStepRegisters } from './enforceCustomStepRegisters';
15
16
  import { getDefaultDiffType } from './getDefaultDiffType';
16
17
  import { getScrollableDecorations } from './getScrollableDecorations';
@@ -299,6 +300,31 @@ export var createPlugin = function createPlugin(config, getIntl, api, onEditorVi
299
300
  };
300
301
  },
301
302
  props: {
303
+ handleDOMEvents: {
304
+ // Bypass ProseMirror's copy handler without preventing native browser copy
305
+ // when the selection is completely contained within an inverted diff widget
306
+ copy: function copy(view) {
307
+ if (!fg('platform_editor_ai_show_diff_patch_2')) {
308
+ return false;
309
+ }
310
+ var pluginState = showDiffPluginKey.getState(view.state);
311
+ if (!(pluginState !== null && pluginState !== void 0 && pluginState.isDisplayingChanges) || !pluginState.isInverted) {
312
+ return false;
313
+ }
314
+ var selection = view.dom.ownerDocument.getSelection();
315
+ if (!selection || selection.isCollapsed || selection.rangeCount !== 1) {
316
+ return false;
317
+ }
318
+ var range = selection.getRangeAt(0);
319
+ return pluginState.decorations.find().filter(isDiffDecoration).some(function (decoration) {
320
+ if (decoration.spec.decorationType !== 'widget') {
321
+ return false;
322
+ }
323
+ var dom = getWidgetElement(decoration);
324
+ return Boolean(dom && view.dom.contains(dom) && dom.contains(range.startContainer) && dom.contains(range.endContainer));
325
+ });
326
+ }
327
+ },
302
328
  decorations: function decorations(state) {
303
329
  var pluginState = showDiffPluginKey.getState(state);
304
330
  return pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations;
@@ -30,6 +30,7 @@ export type DiffDecorationSpec = BaseDecorationSpec<typeof DecorationFamily.diff
30
30
  colorScheme?: ColorScheme;
31
31
  decorationType: DiffDescriptor['type'];
32
32
  diffId: string;
33
+ ignoreSelection?: boolean;
33
34
  /**
34
35
  * The change currently stepped to. Needed on the spec because `activeIndex` indexes the filtered,
35
36
  * re-sorted scrollable decorations, not `diffDescriptors`.
@@ -50,6 +51,7 @@ export type DiffDecorationSpec = BaseDecorationSpec<typeof DecorationFamily.diff
50
51
  * consumed by `scrollToDiff`; never present on a decoration in the plugin's `DecorationSet`.
51
52
  */
52
53
  scrollTarget?: Decoration;
54
+ stopEvent?: (event: Event) => boolean;
53
55
  };
54
56
  export declare const AnchorTypeKey: {
55
57
  readonly from: 'from';
@@ -0,0 +1,2 @@
1
+ import type { Decoration } from '@atlaskit/editor-prosemirror/view';
2
+ export declare const getWidgetElement: (decoration: Decoration) => HTMLElement | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "24.0.1",
3
+ "version": "24.0.2",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",