@atlaskit/editor-core 204.5.5 → 204.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @atlaskit/editor-core
2
2
 
3
+ ## 204.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#129289](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/129289)
8
+ [`fe73b01aca5c2`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/fe73b01aca5c2) -
9
+ ED-26926 Don't validate nodes in remote replaceDocument transactions dispatched from collab edit
10
+ plugin.
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+
16
+ ## 204.5.6
17
+
18
+ ### Patch Changes
19
+
20
+ - [#130044](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/pull-requests/130044)
21
+ [`cad348d512cdf`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/cad348d512cdf) -
22
+ [ux] ED-26802 contextual formatting configuration
23
+ - Updated dependencies
24
+
3
25
  ## 204.5.5
4
26
 
5
27
  ### Patch Changes
@@ -1,21 +1,27 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
7
  exports.useDispatchTransaction = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
7
9
  var _react = require("react");
8
10
  var _analytics = require("@atlaskit/editor-common/analytics");
9
11
  var _coreUtils = require("@atlaskit/editor-common/core-utils");
10
12
  var _performanceMeasures = require("@atlaskit/editor-common/performance-measures");
13
+ var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
11
14
  var _findChangedNodesFromTransaction = require("../../utils/findChangedNodesFromTransaction");
12
15
  var _saferTransactions = require("../../utils/performance/safer-transactions");
13
16
  var _trackTransactions = require("../../utils/performance/track-transactions");
14
17
  var _validateNodes = require("../../utils/validateNodes");
18
+ 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; }
19
+ 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; }
15
20
  var useDispatchTransaction = exports.useDispatchTransaction = function useDispatchTransaction(_ref) {
16
21
  var onChange = _ref.onChange,
17
22
  dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
18
- onEditorViewUpdated = _ref.onEditorViewUpdated;
23
+ onEditorViewUpdated = _ref.onEditorViewUpdated,
24
+ isRemoteReplaceDocumentTransaction = _ref.isRemoteReplaceDocumentTransaction;
19
25
  // We need to have a ref to the latest `onChange` since the `dispatchTransaction` gets captured
20
26
  var onChangeRef = (0, _react.useRef)(onChange);
21
27
  (0, _react.useEffect)(function () {
@@ -31,7 +37,15 @@ var useDispatchTransaction = exports.useDispatchTransaction = function useDispat
31
37
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
32
38
  pluginKey: 'unknown-reacteditorview'
33
39
  }));
34
- if (changedNodesValid) {
40
+
41
+ // If the transaction is a remote replaceDocument transaction, we should skip validation.
42
+ // Remote replaceDocument transactions are fired when the document is replaced by initialization of editor-plugin-collab-edit
43
+ // If there is a discrepancy in the ProseMirror schema at initialization, it results in the editor being loaded with no content,
44
+ // giving the user the impression that content has been lost
45
+ var isRemoteReplace = isRemoteReplaceDocumentTransaction ?
46
+ // eslint-disable-next-line @atlaskit/platform/no-preconditioning
47
+ (0, _platformFeatureFlags.fg)('platform_editor_transaction_skip_validation') && isRemoteReplaceDocumentTransaction(transaction) : false;
48
+ if (changedNodesValid || isRemoteReplace) {
35
49
  var oldEditorState = view.state;
36
50
 
37
51
  // go ahead and update the state now we know the transaction is good
@@ -56,7 +70,8 @@ var useDispatchTransaction = exports.useDispatchTransaction = function useDispat
56
70
  });
57
71
  (0, _performanceMeasures.stopMeasure)(_trackTransactions.EVENT_NAME_ON_CHANGE);
58
72
  }
59
- } else {
73
+ }
74
+ if (!changedNodesValid) {
60
75
  var invalidNodes = nodes.filter(function (node) {
61
76
  return !(0, _validateNodes.validNode)(node);
62
77
  }).map(function (node) {
@@ -68,12 +83,14 @@ var useDispatchTransaction = exports.useDispatchTransaction = function useDispat
68
83
  action: _analytics.ACTION.DISPATCHED_INVALID_TRANSACTION,
69
84
  actionSubject: _analytics.ACTION_SUBJECT.EDITOR,
70
85
  eventType: _analytics.EVENT_TYPE.OPERATIONAL,
71
- attributes: {
86
+ attributes: _objectSpread({
72
87
  analyticsEventPayloads: (0, _analytics.getAnalyticsEventsFromTransaction)(transaction),
73
88
  invalidNodes: invalidNodes
74
- }
89
+ }, (0, _platformFeatureFlags.fg)('platform_editor_transaction_skip_validation') ? {
90
+ isRemoteReplaceDocumentTransaction: isRemoteReplace
91
+ } : {})
75
92
  });
76
93
  }
77
- }, [dispatchAnalyticsEvent, onEditorViewUpdated]);
94
+ }, [dispatchAnalyticsEvent, onEditorViewUpdated, isRemoteReplaceDocumentTransaction]);
78
95
  return dispatchTransaction;
79
96
  };
@@ -46,7 +46,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
46
46
  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; }
47
47
  var EDIT_AREA_ID = 'ak-editor-textarea';
48
48
  function ReactEditorView(props) {
49
- var _media, _linking, _props$render, _props$render2;
49
+ var _pluginInjectionAPI$c, _media, _linking, _props$render, _props$render2;
50
50
  var preset = props.preset,
51
51
  _props$editorProps = props.editorProps,
52
52
  nextAppearance = _props$editorProps.appearance,
@@ -233,7 +233,7 @@ function ReactEditorView(props) {
233
233
  return;
234
234
  }
235
235
 
236
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
236
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
237
237
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
238
238
  // nodes that haven't been re-rendered to the document yet.
239
239
  blur();
@@ -314,7 +314,7 @@ function ReactEditorView(props) {
314
314
  return;
315
315
  }
316
316
 
317
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
317
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
318
318
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
319
319
  // nodes that haven't been re-rendered to the document yet.
320
320
  blur();
@@ -374,7 +374,8 @@ function ReactEditorView(props) {
374
374
  var _dispatchTransaction = (0, _useDispatchTransaction.useDispatchTransaction)({
375
375
  onChange: props.editorProps.onChange,
376
376
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
377
- onEditorViewUpdated: onEditorViewUpdated
377
+ onEditorViewUpdated: onEditorViewUpdated,
378
+ isRemoteReplaceDocumentTransaction: (_pluginInjectionAPI$c = pluginInjectionAPI.current.api()) === null || _pluginInjectionAPI$c === void 0 || (_pluginInjectionAPI$c = _pluginInjectionAPI$c.collabEdit) === null || _pluginInjectionAPI$c === void 0 || (_pluginInjectionAPI$c = _pluginInjectionAPI$c.actions) === null || _pluginInjectionAPI$c === void 0 ? void 0 : _pluginInjectionAPI$c.isRemoteReplaceDocumentTransaction
378
379
  });
379
380
 
380
381
  // Ignored via go/ees007
@@ -399,7 +400,7 @@ function ReactEditorView(props) {
399
400
  state: state !== null && state !== void 0 ? state : getCurrentEditorState(),
400
401
  dispatchTransaction: function dispatchTransaction(tr) {
401
402
  // Block stale transactions:
402
- // Prevent runtime exeptions from async transactions that would attempt to
403
+ // Prevent runtime exceptions from async transactions that would attempt to
403
404
  // update the DOM after React has unmounted the Editor.
404
405
 
405
406
  if (canDispatchTransactions.current) {
@@ -422,10 +423,10 @@ function ReactEditorView(props) {
422
423
  distortedDuration = _ref3.distortedDuration;
423
424
  var proseMirrorRenderedSeverity = (0, _analytics2.getAnalyticsEventSeverity)(duration, _consts.PROSEMIRROR_RENDERED_NORMAL_SEVERITY_THRESHOLD, _consts.PROSEMIRROR_RENDERED_DEGRADED_SEVERITY_THRESHOLD);
424
425
  if (viewRef.current) {
425
- var _pluginInjectionAPI$c;
426
+ var _pluginInjectionAPI$c2;
426
427
  var nodes = (0, _getNodesCount.getNodesCount)(viewRef.current.state.doc);
427
428
  var ttfb = (0, _navigation.getResponseEndTime)();
428
- var contextIdentifier = (_pluginInjectionAPI$c = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c === void 0 ? void 0 : _pluginInjectionAPI$c.sharedState.currentState();
429
+ var contextIdentifier = (_pluginInjectionAPI$c2 = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c2 === void 0 ? void 0 : _pluginInjectionAPI$c2.sharedState.currentState();
429
430
  dispatchAnalyticsEvent({
430
431
  action: _analytics.ACTION.PROSEMIRROR_RENDERED,
431
432
  actionSubject: _analytics.ACTION_SUBJECT.EDITOR,
@@ -56,10 +56,13 @@ function createDefaultPreset(options) {
56
56
  isFullPage: isFullPage
57
57
  })]).add(_clipboard.clipboardPlugin).add(_focus.focusPlugin).add(_composition.compositionPlugin).add([_contextIdentifier.contextIdentifierPlugin, {
58
58
  contextIdentifierProvider: options.contextIdentifierProvider
59
- }]).add([_base.basePlugin, options.base]).add(_decorations.decorationsPlugin).add([_typeAhead.typeAheadPlugin, options.typeAhead]).maybeAdd(_history.historyPlugin, Boolean(options.allowUndoRedoButtons)).add(_primaryToolbar.primaryToolbarPlugin).maybeAdd(_undoRedo.undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([_blockType.blockTypePlugin, _objectSpread(_objectSpread({}, options.blockType), {}, {
59
+ }]).add([_base.basePlugin, options.base]).add(_decorations.decorationsPlugin).add([_typeAhead.typeAheadPlugin, options.typeAhead]).maybeAdd(_history.historyPlugin, Boolean(options.allowUndoRedoButtons)).add([_primaryToolbar.primaryToolbarPlugin, {
60
+ contextualFormattingEnabled: isFullPage
61
+ }]).maybeAdd(_undoRedo.undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([_blockType.blockTypePlugin, _objectSpread(_objectSpread({}, options.blockType), {}, {
60
62
  includeBlockQuoteAsTextstyleOption: isFullPage
61
63
  })]).add(_clearMarksOnEmptyDoc.clearMarksOnEmptyDocPlugin).add([_selectionToolbar.selectionToolbarPlugin, {
62
- preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection
64
+ preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection,
65
+ contextualFormattingEnabled: isFullPage
63
66
  }]).add([_hyperlink.hyperlinkPlugin, _objectSpread(_objectSpread({}, options.hyperlinkOptions), {}, {
64
67
  // @ts-ignore Temporary solution to check for Live Page editor.
65
68
  __livePage: options.__livePage
@@ -89,14 +89,24 @@ function _extensionProviderToQuickInsertProvider() {
89
89
  isDisabledOffline: true,
90
90
  action: function action(insert, state, source) {
91
91
  if (typeof item.node === 'function') {
92
- var _apiRef$current;
93
- var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.extension) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.actions) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.api();
94
- // While the api can be "undefined" there are no runtime scenarios where this is the case because:
95
- // - The quick insert API can only be called from an active editor
96
- // - The extension module handler can only be called from an active editor with the extension plugin
97
- // Therefore this should always be run unless there is something very wrong.
98
- if (extensionAPI) {
99
- (0, _extensions.resolveImport)(item.node(extensionAPI)).then(function (node) {
92
+ if ((0, _platformFeatureFlags.fg)('platform_editor_add_extension_api_to_quick_insert')) {
93
+ var _apiRef$current;
94
+ var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.extension) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.actions) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.api();
95
+ // While the api can be "undefined" there are no runtime scenarios where this is the case because:
96
+ // - The quick insert API can only be called from an active editor
97
+ // - The extension module handler can only be called from an active editor with the extension plugin
98
+ // Therefore this should always be run unless there is something very wrong.
99
+ if (extensionAPI) {
100
+ (0, _extensions.resolveImport)(item.node(extensionAPI)).then(function (node) {
101
+ sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
102
+ if (node) {
103
+ editorActions.replaceSelection(node);
104
+ }
105
+ });
106
+ }
107
+ } else {
108
+ // @ts-expect-error No longer supported without extension API - this will be removed once we cleanup the FG.
109
+ (0, _extensions.resolveImport)(item.node()).then(function (node) {
100
110
  sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
101
111
  if (node) {
102
112
  editorActions.replaceSelection(node);
@@ -5,4 +5,4 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.version = exports.name = void 0;
7
7
  var name = exports.name = "@atlaskit/editor-core";
8
- var version = exports.version = "204.5.5";
8
+ var version = exports.version = "204.6.0";
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef } from 'react';
2
2
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, getAnalyticsEventsFromTransaction } from '@atlaskit/editor-common/analytics';
3
3
  import { getDocStructure } from '@atlaskit/editor-common/core-utils';
4
4
  import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
5
+ import { fg } from '@atlaskit/platform-feature-flags';
5
6
  import { findChangedNodesFromTransaction } from '../../utils/findChangedNodesFromTransaction';
6
7
  import { freezeUnsafeTransactionProperties } from '../../utils/performance/safer-transactions';
7
8
  import { EVENT_NAME_ON_CHANGE } from '../../utils/performance/track-transactions';
@@ -9,7 +10,8 @@ import { validateNodes, validNode } from '../../utils/validateNodes';
9
10
  export const useDispatchTransaction = ({
10
11
  onChange,
11
12
  dispatchAnalyticsEvent,
12
- onEditorViewUpdated
13
+ onEditorViewUpdated,
14
+ isRemoteReplaceDocumentTransaction
13
15
  }) => {
14
16
  // We need to have a ref to the latest `onChange` since the `dispatchTransaction` gets captured
15
17
  const onChangeRef = useRef(onChange);
@@ -26,7 +28,15 @@ export const useDispatchTransaction = ({
26
28
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
27
29
  pluginKey: 'unknown-reacteditorview'
28
30
  }));
29
- if (changedNodesValid) {
31
+
32
+ // If the transaction is a remote replaceDocument transaction, we should skip validation.
33
+ // Remote replaceDocument transactions are fired when the document is replaced by initialization of editor-plugin-collab-edit
34
+ // If there is a discrepancy in the ProseMirror schema at initialization, it results in the editor being loaded with no content,
35
+ // giving the user the impression that content has been lost
36
+ const isRemoteReplace = isRemoteReplaceDocumentTransaction ?
37
+ // eslint-disable-next-line @atlaskit/platform/no-preconditioning
38
+ fg('platform_editor_transaction_skip_validation') && isRemoteReplaceDocumentTransaction(transaction) : false;
39
+ if (changedNodesValid || isRemoteReplace) {
30
40
  const oldEditorState = view.state;
31
41
 
32
42
  // go ahead and update the state now we know the transaction is good
@@ -52,7 +62,8 @@ export const useDispatchTransaction = ({
52
62
  });
53
63
  stopMeasure(EVENT_NAME_ON_CHANGE);
54
64
  }
55
- } else {
65
+ }
66
+ if (!changedNodesValid) {
56
67
  const invalidNodes = nodes.filter(node => !validNode(node)).map(node => getDocStructure(node, {
57
68
  compact: true
58
69
  }));
@@ -62,10 +73,13 @@ export const useDispatchTransaction = ({
62
73
  eventType: EVENT_TYPE.OPERATIONAL,
63
74
  attributes: {
64
75
  analyticsEventPayloads: getAnalyticsEventsFromTransaction(transaction),
65
- invalidNodes
76
+ invalidNodes,
77
+ ...(fg('platform_editor_transaction_skip_validation') ? {
78
+ isRemoteReplaceDocumentTransaction: isRemoteReplace
79
+ } : {})
66
80
  }
67
81
  });
68
82
  }
69
- }, [dispatchAnalyticsEvent, onEditorViewUpdated]);
83
+ }, [dispatchAnalyticsEvent, onEditorViewUpdated, isRemoteReplaceDocumentTransaction]);
70
84
  return dispatchTransaction;
71
85
  };
@@ -31,7 +31,7 @@ import { useDispatchTransaction } from './ReactEditorView/useDispatchTransaction
31
31
  import { useFireFullWidthEvent } from './ReactEditorView/useFireFullWidthEvent';
32
32
  const EDIT_AREA_ID = 'ak-editor-textarea';
33
33
  export function ReactEditorView(props) {
34
- var _media, _linking, _linking$smartLinks, _props$render, _props$render2;
34
+ var _pluginInjectionAPI$c, _pluginInjectionAPI$c2, _pluginInjectionAPI$c3, _media, _linking, _linking$smartLinks, _props$render, _props$render2;
35
35
  const {
36
36
  preset,
37
37
  editorProps: {
@@ -207,7 +207,7 @@ export function ReactEditorView(props) {
207
207
  return;
208
208
  }
209
209
 
210
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
210
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
211
211
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
212
212
  // nodes that haven't been re-rendered to the document yet.
213
213
  blur();
@@ -288,7 +288,7 @@ export function ReactEditorView(props) {
288
288
  return;
289
289
  }
290
290
 
291
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
291
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
292
292
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
293
293
  // nodes that haven't been re-rendered to the document yet.
294
294
  blur();
@@ -348,7 +348,8 @@ export function ReactEditorView(props) {
348
348
  const dispatchTransaction = useDispatchTransaction({
349
349
  onChange: props.editorProps.onChange,
350
350
  dispatchAnalyticsEvent,
351
- onEditorViewUpdated
351
+ onEditorViewUpdated,
352
+ isRemoteReplaceDocumentTransaction: (_pluginInjectionAPI$c = pluginInjectionAPI.current.api()) === null || _pluginInjectionAPI$c === void 0 ? void 0 : (_pluginInjectionAPI$c2 = _pluginInjectionAPI$c.collabEdit) === null || _pluginInjectionAPI$c2 === void 0 ? void 0 : (_pluginInjectionAPI$c3 = _pluginInjectionAPI$c2.actions) === null || _pluginInjectionAPI$c3 === void 0 ? void 0 : _pluginInjectionAPI$c3.isRemoteReplaceDocumentTransaction
352
353
  });
353
354
 
354
355
  // Ignored via go/ees007
@@ -373,7 +374,7 @@ export function ReactEditorView(props) {
373
374
  state: state !== null && state !== void 0 ? state : getCurrentEditorState(),
374
375
  dispatchTransaction: tr => {
375
376
  // Block stale transactions:
376
- // Prevent runtime exeptions from async transactions that would attempt to
377
+ // Prevent runtime exceptions from async transactions that would attempt to
377
378
  // update the DOM after React has unmounted the Editor.
378
379
 
379
380
  if (canDispatchTransactions.current) {
@@ -395,10 +396,10 @@ export function ReactEditorView(props) {
395
396
  }) => {
396
397
  const proseMirrorRenderedSeverity = getAnalyticsEventSeverity(duration, PROSEMIRROR_RENDERED_NORMAL_SEVERITY_THRESHOLD, PROSEMIRROR_RENDERED_DEGRADED_SEVERITY_THRESHOLD);
397
398
  if (viewRef.current) {
398
- var _pluginInjectionAPI$c;
399
+ var _pluginInjectionAPI$c4;
399
400
  const nodes = getNodesCount(viewRef.current.state.doc);
400
401
  const ttfb = getResponseEndTime();
401
- const contextIdentifier = (_pluginInjectionAPI$c = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c === void 0 ? void 0 : _pluginInjectionAPI$c.sharedState.currentState();
402
+ const contextIdentifier = (_pluginInjectionAPI$c4 = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c4 === void 0 ? void 0 : _pluginInjectionAPI$c4.sharedState.currentState();
402
403
  dispatchAnalyticsEvent({
403
404
  action: ACTION.PROSEMIRROR_RENDERED,
404
405
  actionSubject: ACTION_SUBJECT.EDITOR,
@@ -49,11 +49,14 @@ export function createDefaultPreset(options) {
49
49
  isFullPage
50
50
  }]).add(clipboardPlugin).add(focusPlugin).add(compositionPlugin).add([contextIdentifierPlugin, {
51
51
  contextIdentifierProvider: options.contextIdentifierProvider
52
- }]).add([basePlugin, options.base]).add(decorationsPlugin).add([typeAheadPlugin, options.typeAhead]).maybeAdd(historyPlugin, Boolean(options.allowUndoRedoButtons)).add(primaryToolbarPlugin).maybeAdd(undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([blockTypePlugin, {
52
+ }]).add([basePlugin, options.base]).add(decorationsPlugin).add([typeAheadPlugin, options.typeAhead]).maybeAdd(historyPlugin, Boolean(options.allowUndoRedoButtons)).add([primaryToolbarPlugin, {
53
+ contextualFormattingEnabled: isFullPage
54
+ }]).maybeAdd(undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([blockTypePlugin, {
53
55
  ...options.blockType,
54
56
  includeBlockQuoteAsTextstyleOption: isFullPage
55
57
  }]).add(clearMarksOnEmptyDocPlugin).add([selectionToolbarPlugin, {
56
- preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection
58
+ preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection,
59
+ contextualFormattingEnabled: isFullPage
57
60
  }]).add([hyperlinkPlugin, {
58
61
  ...options.hyperlinkOptions,
59
62
  // @ts-ignore Temporary solution to check for Live Page editor.
@@ -61,14 +61,24 @@ export async function extensionProviderToQuickInsertProvider(extensionProvider,
61
61
  isDisabledOffline: true,
62
62
  action: (insert, state, source) => {
63
63
  if (typeof item.node === 'function') {
64
- var _apiRef$current, _apiRef$current$exten, _apiRef$current$exten2;
65
- const extensionAPI = apiRef === null || apiRef === void 0 ? void 0 : (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : (_apiRef$current$exten = _apiRef$current.extension) === null || _apiRef$current$exten === void 0 ? void 0 : (_apiRef$current$exten2 = _apiRef$current$exten.actions) === null || _apiRef$current$exten2 === void 0 ? void 0 : _apiRef$current$exten2.api();
66
- // While the api can be "undefined" there are no runtime scenarios where this is the case because:
67
- // - The quick insert API can only be called from an active editor
68
- // - The extension module handler can only be called from an active editor with the extension plugin
69
- // Therefore this should always be run unless there is something very wrong.
70
- if (extensionAPI) {
71
- resolveImport(item.node(extensionAPI)).then(node => {
64
+ if (fg('platform_editor_add_extension_api_to_quick_insert')) {
65
+ var _apiRef$current, _apiRef$current$exten, _apiRef$current$exten2;
66
+ const extensionAPI = apiRef === null || apiRef === void 0 ? void 0 : (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : (_apiRef$current$exten = _apiRef$current.extension) === null || _apiRef$current$exten === void 0 ? void 0 : (_apiRef$current$exten2 = _apiRef$current$exten.actions) === null || _apiRef$current$exten2 === void 0 ? void 0 : _apiRef$current$exten2.api();
67
+ // While the api can be "undefined" there are no runtime scenarios where this is the case because:
68
+ // - The quick insert API can only be called from an active editor
69
+ // - The extension module handler can only be called from an active editor with the extension plugin
70
+ // Therefore this should always be run unless there is something very wrong.
71
+ if (extensionAPI) {
72
+ resolveImport(item.node(extensionAPI)).then(node => {
73
+ sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
74
+ if (node) {
75
+ editorActions.replaceSelection(node);
76
+ }
77
+ });
78
+ }
79
+ } else {
80
+ // @ts-expect-error No longer supported without extension API - this will be removed once we cleanup the FG.
81
+ resolveImport(item.node()).then(node => {
72
82
  sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
73
83
  if (node) {
74
84
  editorActions.replaceSelection(node);
@@ -1,2 +1,2 @@
1
1
  export const name = "@atlaskit/editor-core";
2
- export const version = "204.5.5";
2
+ export const version = "204.6.0";
@@ -1,7 +1,11 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
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
+ 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; }
1
4
  import { useCallback, useEffect, useRef } from 'react';
2
5
  import { ACTION, ACTION_SUBJECT, EVENT_TYPE, getAnalyticsEventsFromTransaction } from '@atlaskit/editor-common/analytics';
3
6
  import { getDocStructure } from '@atlaskit/editor-common/core-utils';
4
7
  import { startMeasure, stopMeasure } from '@atlaskit/editor-common/performance-measures';
8
+ import { fg } from '@atlaskit/platform-feature-flags';
5
9
  import { findChangedNodesFromTransaction } from '../../utils/findChangedNodesFromTransaction';
6
10
  import { freezeUnsafeTransactionProperties } from '../../utils/performance/safer-transactions';
7
11
  import { EVENT_NAME_ON_CHANGE } from '../../utils/performance/track-transactions';
@@ -9,7 +13,8 @@ import { validateNodes, validNode } from '../../utils/validateNodes';
9
13
  export var useDispatchTransaction = function useDispatchTransaction(_ref) {
10
14
  var onChange = _ref.onChange,
11
15
  dispatchAnalyticsEvent = _ref.dispatchAnalyticsEvent,
12
- onEditorViewUpdated = _ref.onEditorViewUpdated;
16
+ onEditorViewUpdated = _ref.onEditorViewUpdated,
17
+ isRemoteReplaceDocumentTransaction = _ref.isRemoteReplaceDocumentTransaction;
13
18
  // We need to have a ref to the latest `onChange` since the `dispatchTransaction` gets captured
14
19
  var onChangeRef = useRef(onChange);
15
20
  useEffect(function () {
@@ -25,7 +30,15 @@ export var useDispatchTransaction = function useDispatchTransaction(_ref) {
25
30
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
26
31
  pluginKey: 'unknown-reacteditorview'
27
32
  }));
28
- if (changedNodesValid) {
33
+
34
+ // If the transaction is a remote replaceDocument transaction, we should skip validation.
35
+ // Remote replaceDocument transactions are fired when the document is replaced by initialization of editor-plugin-collab-edit
36
+ // If there is a discrepancy in the ProseMirror schema at initialization, it results in the editor being loaded with no content,
37
+ // giving the user the impression that content has been lost
38
+ var isRemoteReplace = isRemoteReplaceDocumentTransaction ?
39
+ // eslint-disable-next-line @atlaskit/platform/no-preconditioning
40
+ fg('platform_editor_transaction_skip_validation') && isRemoteReplaceDocumentTransaction(transaction) : false;
41
+ if (changedNodesValid || isRemoteReplace) {
29
42
  var oldEditorState = view.state;
30
43
 
31
44
  // go ahead and update the state now we know the transaction is good
@@ -50,7 +63,8 @@ export var useDispatchTransaction = function useDispatchTransaction(_ref) {
50
63
  });
51
64
  stopMeasure(EVENT_NAME_ON_CHANGE);
52
65
  }
53
- } else {
66
+ }
67
+ if (!changedNodesValid) {
54
68
  var invalidNodes = nodes.filter(function (node) {
55
69
  return !validNode(node);
56
70
  }).map(function (node) {
@@ -62,12 +76,14 @@ export var useDispatchTransaction = function useDispatchTransaction(_ref) {
62
76
  action: ACTION.DISPATCHED_INVALID_TRANSACTION,
63
77
  actionSubject: ACTION_SUBJECT.EDITOR,
64
78
  eventType: EVENT_TYPE.OPERATIONAL,
65
- attributes: {
79
+ attributes: _objectSpread({
66
80
  analyticsEventPayloads: getAnalyticsEventsFromTransaction(transaction),
67
81
  invalidNodes: invalidNodes
68
- }
82
+ }, fg('platform_editor_transaction_skip_validation') ? {
83
+ isRemoteReplaceDocumentTransaction: isRemoteReplace
84
+ } : {})
69
85
  });
70
86
  }
71
- }, [dispatchAnalyticsEvent, onEditorViewUpdated]);
87
+ }, [dispatchAnalyticsEvent, onEditorViewUpdated, isRemoteReplaceDocumentTransaction]);
72
88
  return dispatchTransaction;
73
89
  };
@@ -35,7 +35,7 @@ import { useDispatchTransaction } from './ReactEditorView/useDispatchTransaction
35
35
  import { useFireFullWidthEvent } from './ReactEditorView/useFireFullWidthEvent';
36
36
  var EDIT_AREA_ID = 'ak-editor-textarea';
37
37
  export function ReactEditorView(props) {
38
- var _media, _linking, _props$render, _props$render2;
38
+ var _pluginInjectionAPI$c, _media, _linking, _props$render, _props$render2;
39
39
  var preset = props.preset,
40
40
  _props$editorProps = props.editorProps,
41
41
  nextAppearance = _props$editorProps.appearance,
@@ -222,7 +222,7 @@ export function ReactEditorView(props) {
222
222
  return;
223
223
  }
224
224
 
225
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
225
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
226
226
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
227
227
  // nodes that haven't been re-rendered to the document yet.
228
228
  blur();
@@ -303,7 +303,7 @@ export function ReactEditorView(props) {
303
303
  return;
304
304
  }
305
305
 
306
- // We cannot currently guarentee when all the portals will have re-rendered during a reconfigure
306
+ // We cannot currently guarantee when all the portals will have re-rendered during a reconfigure
307
307
  // so we blur here to stop ProseMirror from trying to apply selection to detached nodes or
308
308
  // nodes that haven't been re-rendered to the document yet.
309
309
  blur();
@@ -363,7 +363,8 @@ export function ReactEditorView(props) {
363
363
  var _dispatchTransaction = useDispatchTransaction({
364
364
  onChange: props.editorProps.onChange,
365
365
  dispatchAnalyticsEvent: dispatchAnalyticsEvent,
366
- onEditorViewUpdated: onEditorViewUpdated
366
+ onEditorViewUpdated: onEditorViewUpdated,
367
+ isRemoteReplaceDocumentTransaction: (_pluginInjectionAPI$c = pluginInjectionAPI.current.api()) === null || _pluginInjectionAPI$c === void 0 || (_pluginInjectionAPI$c = _pluginInjectionAPI$c.collabEdit) === null || _pluginInjectionAPI$c === void 0 || (_pluginInjectionAPI$c = _pluginInjectionAPI$c.actions) === null || _pluginInjectionAPI$c === void 0 ? void 0 : _pluginInjectionAPI$c.isRemoteReplaceDocumentTransaction
367
368
  });
368
369
 
369
370
  // Ignored via go/ees007
@@ -388,7 +389,7 @@ export function ReactEditorView(props) {
388
389
  state: state !== null && state !== void 0 ? state : getCurrentEditorState(),
389
390
  dispatchTransaction: function dispatchTransaction(tr) {
390
391
  // Block stale transactions:
391
- // Prevent runtime exeptions from async transactions that would attempt to
392
+ // Prevent runtime exceptions from async transactions that would attempt to
392
393
  // update the DOM after React has unmounted the Editor.
393
394
 
394
395
  if (canDispatchTransactions.current) {
@@ -411,10 +412,10 @@ export function ReactEditorView(props) {
411
412
  distortedDuration = _ref3.distortedDuration;
412
413
  var proseMirrorRenderedSeverity = getAnalyticsEventSeverity(duration, PROSEMIRROR_RENDERED_NORMAL_SEVERITY_THRESHOLD, PROSEMIRROR_RENDERED_DEGRADED_SEVERITY_THRESHOLD);
413
414
  if (viewRef.current) {
414
- var _pluginInjectionAPI$c;
415
+ var _pluginInjectionAPI$c2;
415
416
  var nodes = getNodesCount(viewRef.current.state.doc);
416
417
  var ttfb = getResponseEndTime();
417
- var contextIdentifier = (_pluginInjectionAPI$c = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c === void 0 ? void 0 : _pluginInjectionAPI$c.sharedState.currentState();
418
+ var contextIdentifier = (_pluginInjectionAPI$c2 = pluginInjectionAPI.current.api().base) === null || _pluginInjectionAPI$c2 === void 0 ? void 0 : _pluginInjectionAPI$c2.sharedState.currentState();
418
419
  dispatchAnalyticsEvent({
419
420
  action: ACTION.PROSEMIRROR_RENDERED,
420
421
  actionSubject: ACTION_SUBJECT.EDITOR,
@@ -51,10 +51,13 @@ export function createDefaultPreset(options) {
51
51
  isFullPage: isFullPage
52
52
  })]).add(clipboardPlugin).add(focusPlugin).add(compositionPlugin).add([contextIdentifierPlugin, {
53
53
  contextIdentifierProvider: options.contextIdentifierProvider
54
- }]).add([basePlugin, options.base]).add(decorationsPlugin).add([typeAheadPlugin, options.typeAhead]).maybeAdd(historyPlugin, Boolean(options.allowUndoRedoButtons)).add(primaryToolbarPlugin).maybeAdd(undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([blockTypePlugin, _objectSpread(_objectSpread({}, options.blockType), {}, {
54
+ }]).add([basePlugin, options.base]).add(decorationsPlugin).add([typeAheadPlugin, options.typeAhead]).maybeAdd(historyPlugin, Boolean(options.allowUndoRedoButtons)).add([primaryToolbarPlugin, {
55
+ contextualFormattingEnabled: isFullPage
56
+ }]).maybeAdd(undoRedoPlugin, Boolean((_options$featureFlags = (_options$featureFlags2 = options.featureFlags) === null || _options$featureFlags2 === void 0 ? void 0 : _options$featureFlags2.undoRedoButtons) !== null && _options$featureFlags !== void 0 ? _options$featureFlags : options.allowUndoRedoButtons)).add([blockTypePlugin, _objectSpread(_objectSpread({}, options.blockType), {}, {
55
57
  includeBlockQuoteAsTextstyleOption: isFullPage
56
58
  })]).add(clearMarksOnEmptyDocPlugin).add([selectionToolbarPlugin, {
57
- preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection
59
+ preferenceToolbarAboveSelection: !!options.preferenceToolbarAboveSelection,
60
+ contextualFormattingEnabled: isFullPage
58
61
  }]).add([hyperlinkPlugin, _objectSpread(_objectSpread({}, options.hyperlinkOptions), {}, {
59
62
  // @ts-ignore Temporary solution to check for Live Page editor.
60
63
  __livePage: options.__livePage
@@ -83,14 +83,24 @@ function _extensionProviderToQuickInsertProvider() {
83
83
  isDisabledOffline: true,
84
84
  action: function action(insert, state, source) {
85
85
  if (typeof item.node === 'function') {
86
- var _apiRef$current;
87
- var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.extension) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.actions) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.api();
88
- // While the api can be "undefined" there are no runtime scenarios where this is the case because:
89
- // - The quick insert API can only be called from an active editor
90
- // - The extension module handler can only be called from an active editor with the extension plugin
91
- // Therefore this should always be run unless there is something very wrong.
92
- if (extensionAPI) {
93
- resolveImport(item.node(extensionAPI)).then(function (node) {
86
+ if (fg('platform_editor_add_extension_api_to_quick_insert')) {
87
+ var _apiRef$current;
88
+ var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.extension) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.actions) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.api();
89
+ // While the api can be "undefined" there are no runtime scenarios where this is the case because:
90
+ // - The quick insert API can only be called from an active editor
91
+ // - The extension module handler can only be called from an active editor with the extension plugin
92
+ // Therefore this should always be run unless there is something very wrong.
93
+ if (extensionAPI) {
94
+ resolveImport(item.node(extensionAPI)).then(function (node) {
95
+ sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
96
+ if (node) {
97
+ editorActions.replaceSelection(node);
98
+ }
99
+ });
100
+ }
101
+ } else {
102
+ // @ts-expect-error No longer supported without extension API - this will be removed once we cleanup the FG.
103
+ resolveImport(item.node()).then(function (node) {
94
104
  sendExtensionQuickInsertAnalytics(item, state.selection, createAnalyticsEvent, source);
95
105
  if (node) {
96
106
  editorActions.replaceSelection(node);
@@ -1,2 +1,2 @@
1
1
  export var name = "@atlaskit/editor-core";
2
- export var version = "204.5.5";
2
+ export var version = "204.6.0";
@@ -4,9 +4,10 @@ import type { EditorView } from '@atlaskit/editor-prosemirror/view';
4
4
  import type { EditorViewStateUpdatedCallbackProps } from '../../types/editor-config';
5
5
  import type { EditorOnChangeHandler } from '../../types/editor-onchange';
6
6
  type DispatchTransaction = (view: EditorView | undefined, tr: Transaction) => void;
7
- export declare const useDispatchTransaction: ({ onChange, dispatchAnalyticsEvent, onEditorViewUpdated, }: {
7
+ export declare const useDispatchTransaction: ({ onChange, dispatchAnalyticsEvent, onEditorViewUpdated, isRemoteReplaceDocumentTransaction, }: {
8
8
  onChange: EditorOnChangeHandler | undefined;
9
9
  dispatchAnalyticsEvent: (payload: AnalyticsEventPayload) => void;
10
10
  onEditorViewUpdated: (params: EditorViewStateUpdatedCallbackProps) => void;
11
+ isRemoteReplaceDocumentTransaction?: ((tr: Transaction) => boolean) | undefined;
11
12
  }) => DispatchTransaction;
12
13
  export {};