@atlaskit/editor-plugin-show-diff 12.0.3 → 12.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/cjs/pm-plugins/calculateDiff/calculateDiffDecorations.js +104 -77
  3. package/dist/cjs/pm-plugins/decorations/createInlineChangedDecoration.js +14 -3
  4. package/dist/cjs/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -3
  5. package/dist/cjs/pm-plugins/getDeletedWidgets.js +48 -0
  6. package/dist/cjs/pm-plugins/main.js +3 -1
  7. package/dist/cjs/showDiffPlugin.js +13 -1
  8. package/dist/es2019/pm-plugins/calculateDiff/calculateDiffDecorations.js +41 -17
  9. package/dist/es2019/pm-plugins/decorations/createInlineChangedDecoration.js +13 -3
  10. package/dist/es2019/pm-plugins/decorations/utils/getAttrChangeRanges.js +4 -3
  11. package/dist/es2019/pm-plugins/getDeletedWidgets.js +40 -0
  12. package/dist/es2019/pm-plugins/main.js +3 -1
  13. package/dist/es2019/showDiffPlugin.js +86 -74
  14. package/dist/esm/pm-plugins/calculateDiff/calculateDiffDecorations.js +103 -76
  15. package/dist/esm/pm-plugins/decorations/createInlineChangedDecoration.js +14 -3
  16. package/dist/esm/pm-plugins/decorations/utils/getAttrChangeRanges.js +10 -3
  17. package/dist/esm/pm-plugins/getDeletedWidgets.js +43 -0
  18. package/dist/esm/pm-plugins/main.js +3 -1
  19. package/dist/esm/showDiffPlugin.js +13 -1
  20. package/dist/types/entry-points/show-diff-plugin-type.d.ts +1 -1
  21. package/dist/types/pm-plugins/calculateDiff/calculateDiffDecorations.d.ts +17 -0
  22. package/dist/types/pm-plugins/decorations/createInlineChangedDecoration.d.ts +2 -1
  23. package/dist/types/pm-plugins/getDeletedWidgets.d.ts +14 -0
  24. package/dist/types/pm-plugins/main.d.ts +2 -1
  25. package/dist/types/showDiffPluginType.d.ts +23 -0
  26. package/package.json +7 -7
@@ -2,6 +2,7 @@ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
2
  function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import { SetAttrsStep } from '@atlaskit/adf-schema/steps';
5
+ import { isExperimentEnabled } from '@atlaskit/editor-common/deprecated-platform-feature-experiments';
5
6
  import { AttrStep } from '@atlaskit/editor-prosemirror/transform';
6
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
7
8
  var filterUndefined = function filterUndefined(x) {
@@ -63,7 +64,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, steps, origin
63
64
  // date node: timestamp attribute change — highlight the date node itself (inline)
64
65
  if (stepAttrs.some(function (v) {
65
66
  return dateAttrs.includes(v);
66
- }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true)) {
67
+ }) && (nodeAtPos === null || nodeAtPos === void 0 ? void 0 : nodeAtPos.type.name) === 'date' && !isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
68
+ return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
69
+ })) {
67
70
  return {
68
71
  fromB: step.pos,
69
72
  toB: step.pos + nodeAtPos.nodeSize,
@@ -75,7 +78,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, steps, origin
75
78
  // The following inline node attr changes are gated behind platform_editor_improve_inline_diffs.
76
79
  // The changeset path (createDecorationsForChange) handles the deletion widget via
77
80
  // prosemirror-changeset; we only need to add the inline insertion highlight here.
78
- if (expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) && nodeAtPos) {
81
+ if (isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
82
+ return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
83
+ }) && nodeAtPos) {
79
84
  var nodeName = nodeAtPos.type.name;
80
85
  if (isInlineAttrChangeNodeName(nodeName)) {
81
86
  var watchedAttrs = inlineNodeAttrMap[nodeName];
@@ -136,7 +141,9 @@ export var getAttrChangeRanges = function getAttrChangeRanges(doc, steps, origin
136
141
  // Gated behind the same experiment as the inline node attr changes that introduced
137
142
  // the possibility of multiple ranges for the same node position.
138
143
  .filter(function (range, i, arr) {
139
- return !expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true) || arr.findIndex(function (r) {
144
+ return !isExperimentEnabled('platform_editor_improve_inline_diffs', function () {
145
+ return expValEquals('platform_editor_improve_inline_diffs', 'isEnabled', true);
146
+ }) || arr.findIndex(function (r) {
140
147
  return r.fromB === range.fromB;
141
148
  }) === i;
142
149
  });
@@ -0,0 +1,43 @@
1
+ import { isDiffDecorationSpec } from './decorations/decorationKeys';
2
+ import { showDiffPluginKey } from './main';
3
+
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
+ /**
16
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
17
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
18
+ * nodes, so this is how the element and the position it is anchored at are recovered.
19
+ *
20
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
21
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
22
+ */
23
+ export var getDeletedWidgets = function getDeletedWidgets(editorState, range) {
24
+ var _showDiffPluginKey$ge;
25
+ var decorations = (_showDiffPluginKey$ge = showDiffPluginKey.getState(editorState)) === null || _showDiffPluginKey$ge === void 0 ? void 0 : _showDiffPluginKey$ge.decorations;
26
+ if (!decorations) {
27
+ return [];
28
+ }
29
+ return decorations.find(range === null || range === void 0 ? void 0 : range.from, range === null || range === void 0 ? void 0 : range.to, function (spec) {
30
+ return isDiffDecorationSpec(spec) && spec.decorationType === 'widget';
31
+ }).reduce(function (widgets, decoration) {
32
+ var element = getWidgetElement(decoration);
33
+ if (element) {
34
+ widgets.push({
35
+ element: element,
36
+ position: decoration.from
37
+ });
38
+ }
39
+ return widgets;
40
+ }, []).sort(function (a, b) {
41
+ return a.position - b.position;
42
+ });
43
+ };
@@ -14,7 +14,7 @@ import { isExtendedEnabled } from './isExtendedEnabled';
14
14
  import { NodeViewSerializer } from './NodeViewSerializer';
15
15
  import { scrollToActiveDecoration, scrollToFirstDecoration } from './scrollToDiff';
16
16
  export var showDiffPluginKey = new PluginKey('showDiffPlugin');
17
- export var createPlugin = function createPlugin(config, getIntl, api) {
17
+ export var createPlugin = function createPlugin(config, getIntl, api, onEditorView) {
18
18
  enforceCustomStepRegisters();
19
19
  var nodeViewSerializer = new NodeViewSerializer({});
20
20
  var setNodeViewSerializer = function setNodeViewSerializer(editorView) {
@@ -155,6 +155,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
155
155
  },
156
156
  view: function view(editorView) {
157
157
  setNodeViewSerializer(editorView);
158
+ onEditorView === null || onEditorView === void 0 || onEditorView(editorView);
158
159
  var isFirst = true;
159
160
  var previousActiveIndex;
160
161
  var cancelPendingScrollToDecoration = null;
@@ -207,6 +208,7 @@ export var createPlugin = function createPlugin(config, getIntl, api) {
207
208
  var _cancelPendingScrollT3;
208
209
  (_cancelPendingScrollT3 = cancelPendingScrollToDecoration) === null || _cancelPendingScrollT3 === void 0 || _cancelPendingScrollT3();
209
210
  cancelPendingScrollToDecoration = null;
211
+ onEditorView === null || onEditorView === void 0 || onEditorView(undefined);
210
212
  }
211
213
  };
212
214
  },
@@ -3,14 +3,26 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
3
3
  function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import React from 'react';
5
5
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
6
+ import { getDeletedWidgets as _getDeletedWidgets } from './pm-plugins/getDeletedWidgets';
6
7
  import { getScrollableDecorations } from './pm-plugins/getScrollableDecorations';
7
8
  import { createPlugin, showDiffPluginKey } from './pm-plugins/main';
8
9
  import { IndicatorBarContentComponent } from './ui/IndicatorBar/IndicatorBarContentComponent';
9
10
  export var showDiffPlugin = function showDiffPlugin(_ref) {
10
11
  var api = _ref.api,
11
12
  config = _ref.config;
13
+ // Captured from the plugin's view lifecycle (see `createPlugin`) so read-only actions can access
14
+ // the current state without exposing the plugin key to consumers.
15
+ var editorView;
16
+ var setEditorView = function setEditorView(view) {
17
+ editorView = view;
18
+ };
12
19
  return {
13
20
  name: 'showDiff',
21
+ actions: {
22
+ getDeletedWidgets: function getDeletedWidgets(range) {
23
+ return editorView ? _getDeletedWidgets(editorView.state, range) : [];
24
+ }
25
+ },
14
26
  commands: {
15
27
  showDiff: function showDiff(params) {
16
28
  return function (_ref2) {
@@ -57,7 +69,7 @@ export var showDiffPlugin = function showDiffPlugin(_ref) {
57
69
  name: 'showDiffPlugin',
58
70
  plugin: function plugin(_ref6) {
59
71
  var getIntl = _ref6.getIntl;
60
- return createPlugin(config, getIntl, api);
72
+ return createPlugin(config, getIntl, api, setEditorView);
61
73
  }
62
74
  }];
63
75
  },
@@ -1 +1 @@
1
- export type { DeletedDiffPlacement, DiffParams, DiffType, PMDiffParams, ShowDiffPlugin, SmartDiffThresholds, } from '../showDiffPluginType';
1
+ export type { DeletedDiffPlacement, DeletedDiffWidget, DiffParams, DiffType, PMDiffParams, ShowDiffPlugin, SmartDiffThresholds, } from '../showDiffPluginType';
@@ -1,4 +1,5 @@
1
1
  import { type MemoizedFn } from 'memoize-one';
2
+ import { type Change } from 'prosemirror-changeset';
2
3
  import type { IntlShape } from 'react-intl';
3
4
  import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
5
  import type { EditorState } from '@atlaskit/editor-prosemirror/state';
@@ -10,6 +11,22 @@ type CalculatedDiffs = {
10
11
  decorations: DecorationSet;
11
12
  diffDescriptors: DiffDescriptor[];
12
13
  };
14
+ /**
15
+ * Whether deleted content for `change` renders after the new content instead of before it.
16
+ *
17
+ * show-diff splits this across two options by change granularity, so the level decides which one
18
+ * applies:
19
+ * - node/paragraph-level: `deletedDiffPlacement` (default `'top'`). Pure deletions are promoted to
20
+ * node level, so they are governed here too.
21
+ * - inline/sentence-level: `inlineDeletedDiffPlacement` (default `'before'`).
22
+ *
23
+ * Callers are responsible for the `smart` diffType and gate checks.
24
+ */
25
+ export declare const isDeletedContentPlacedBelow: ({ change, deletedDiffPlacement, inlineDeletedDiffPlacement, }: {
26
+ change: Change;
27
+ deletedDiffPlacement?: DeletedDiffPlacement;
28
+ inlineDeletedDiffPlacement?: InlineDeletedDiffPlacement;
29
+ }) => boolean;
13
30
  export declare const calculateDiffDecorations: MemoizedFn<({ state, pluginState, nodeViewSerializer, colorScheme, intl, activeIndexPos, api, hideDeletedDiffs, hideAddedDiffsUnderline, showIndicators, }: {
14
31
  activeIndexPos?: {
15
32
  from: number;
@@ -8,7 +8,7 @@ import type { InlineAttrChangeNodeName } from './utils/getAttrChangeRanges';
8
8
  * @param change Changeset "change" containing information about the change content + range
9
9
  * @returns Prosemirror inline decoration
10
10
  */
11
- export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, isAtomicInlineNode, shouldHideDeleted, showIndicators, doc, diffType, hideAddedDiffsUnderline, inlineNodeName, hasDeletedWidget, }: {
11
+ export declare const createInlineChangedDecoration: ({ change, colorScheme, isActive, isInserted, isAtomicInlineNode, shouldHideDeleted, showIndicators, doc, diffType, hideAddedDiffsUnderline, inlineNodeName, hasDeletedWidget, isDeletedWidgetBelow, }: {
12
12
  change: {
13
13
  fromB: number;
14
14
  toB: number;
@@ -21,6 +21,7 @@ export declare const createInlineChangedDecoration: ({ change, colorScheme, isAc
21
21
  inlineNodeName?: InlineAttrChangeNodeName;
22
22
  isActive?: boolean;
23
23
  isAtomicInlineNode?: boolean;
24
+ isDeletedWidgetBelow?: boolean;
24
25
  isInserted?: boolean;
25
26
  shouldHideDeleted?: boolean;
26
27
  showIndicators?: boolean;
@@ -0,0 +1,14 @@
1
+ import type { EditorState } from 'prosemirror-state';
2
+ import type { DeletedDiffWidget } from '../showDiffPluginType';
3
+ /**
4
+ * The rendered deleted-content widgets in `editorState`, optionally restricted to `[from, to]`,
5
+ * ordered by position. Deleted content is rendered as widget decorations rather than document
6
+ * nodes, so this is how the element and the position it is anchored at are recovered.
7
+ *
8
+ * Kept internal and surfaced only through the `getDeletedWidgets` plugin action, so consumers never
9
+ * receive the plugin key or the decoration set (which would let them mutate plugin behaviour).
10
+ */
11
+ export declare const getDeletedWidgets: (editorState: EditorState, range?: {
12
+ from: number;
13
+ to: number;
14
+ }) => DeletedDiffWidget[];
@@ -4,6 +4,7 @@ import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
4
4
  import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
6
  import { Step as ProseMirrorStep } from '@atlaskit/editor-prosemirror/transform';
7
+ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
7
8
  import { DecorationSet } from '@atlaskit/editor-prosemirror/view';
8
9
  import type { DeletedDiffPlacement, DiffDescriptor, DiffParams, DiffType, InlineDeletedDiffPlacement, ShowDiffPlugin, SmartDiffThresholds } from '../showDiffPluginType';
9
10
  export declare const showDiffPluginKey: PluginKey<ShowDiffPluginState>;
@@ -49,4 +50,4 @@ export type ShowDiffPluginState = {
49
50
  smartThresholds?: Partial<SmartDiffThresholds>;
50
51
  steps: ProseMirrorStep[];
51
52
  };
52
- export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined) => SafePlugin<ShowDiffPluginState>;
53
+ export declare const createPlugin: (config: DiffParams | undefined, getIntl: () => IntlShape, api: ExtractInjectionAPI<ShowDiffPlugin> | undefined, onEditorView?: (editorView: EditorView | undefined) => void) => SafePlugin<ShowDiffPluginState>;
@@ -23,6 +23,17 @@ export type DeletedDiffPlacement = 'top' | 'bottom';
23
23
  * - `'after'`: the deleted content is anchored after the new content.
24
24
  */
25
25
  export type InlineDeletedDiffPlacement = 'before' | 'after';
26
+ /**
27
+ * A rendered deleted-content widget: the DOM element show-diff renders for a piece of deleted
28
+ * content, together with the document position it is anchored at. Deleted content is rendered as
29
+ * widget decorations rather than document nodes, so this is how consumers recover the element and
30
+ * its position — via the `getDeletedWidgets` action — without reaching into the plugin's internal
31
+ * state.
32
+ */
33
+ export type DeletedDiffWidget = {
34
+ element: HTMLElement;
35
+ position: number;
36
+ };
26
37
  export type SmartDiffThresholds = SmartDiffThresholdsInternal;
27
38
  export type DiffDescriptor = {
28
39
  id: string;
@@ -86,6 +97,18 @@ export type PMDiffParams = {
86
97
  };
87
98
  export type ACTION = 'SHOW_DIFF' | 'HIDE_DIFF' | 'SCROLL_TO_NEXT' | 'SCROLL_TO_PREVIOUS';
88
99
  export type ShowDiffPlugin = NextEditorPlugin<'showDiff', {
100
+ actions: {
101
+ /**
102
+ * The rendered deleted-content widgets currently displayed, optionally restricted to a
103
+ * document range, ordered by position. This is the safe, read-only way to recover deleted
104
+ * content's element and position (e.g. to position UI relative to it) without access to the
105
+ * plugin's internal decoration set. Returns an empty array when no diff is displayed.
106
+ */
107
+ getDeletedWidgets: (range?: {
108
+ from: number;
109
+ to: number;
110
+ }) => DeletedDiffWidget[];
111
+ };
89
112
  commands: {
90
113
  hideDiff: EditorCommand;
91
114
  scrollToNext: EditorCommand;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-show-diff",
3
- "version": "12.0.3",
3
+ "version": "12.1.1",
4
4
  "description": "ShowDiff plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",
@@ -20,15 +20,15 @@
20
20
  "sideEffects": false,
21
21
  "atlaskit:src": "src/index.ts",
22
22
  "dependencies": {
23
- "@atlaskit/adf-schema": "^56.6.0",
23
+ "@atlaskit/adf-schema": "^56.7.0",
24
24
  "@atlaskit/custom-steps": "^1.0.0",
25
25
  "@atlaskit/editor-plugin-analytics": "^14.0.0",
26
26
  "@atlaskit/editor-plugin-user-intent": "^12.0.0",
27
27
  "@atlaskit/editor-prosemirror": "^8.0.0",
28
28
  "@atlaskit/editor-tables": "^3.0.0",
29
29
  "@atlaskit/platform-feature-flags": "^2.1.0",
30
- "@atlaskit/tmp-editor-statsig": "^145.0.0",
31
- "@atlaskit/tokens": "^16.5.0",
30
+ "@atlaskit/tmp-editor-statsig": "^146.0.0",
31
+ "@atlaskit/tokens": "^16.6.0",
32
32
  "@babel/runtime": "^7.0.0",
33
33
  "@compiled/react": "^1.0.0",
34
34
  "lodash": "^4.17.21",
@@ -42,10 +42,10 @@
42
42
  "@atlaskit/dropdown-menu": "^18.0.0",
43
43
  "@atlaskit/editor-core": "^223.0.0",
44
44
  "@atlaskit/editor-json-transformer": "^9.2.0",
45
- "@atlaskit/form": "^16.1.0",
45
+ "@atlaskit/form": "^17.0.0",
46
46
  "@atlaskit/primitives": "^22.2.0",
47
47
  "@atlaskit/section-message": "^10.0.0",
48
- "@atlaskit/textarea": "^9.1.0",
48
+ "@atlaskit/textarea": "^10.0.0",
49
49
  "@atlassian/confluence-presets": "workspace:^",
50
50
  "@atlassian/content-reconciliation": "^0.1.3506",
51
51
  "@atlassian/structured-docs-types": "workspace:^",
@@ -53,7 +53,7 @@
53
53
  "react-intl": "^7.0.0"
54
54
  },
55
55
  "peerDependencies": {
56
- "@atlaskit/editor-common": "^118.2.0",
56
+ "@atlaskit/editor-common": "^118.5.0",
57
57
  "react": "^18.2.0 || ^19.2.0"
58
58
  },
59
59
  "techstack": {