@atlaskit/editor-core 219.7.2 → 219.7.3
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 +15 -0
- package/dist/cjs/create-editor/ReactEditorView.js +192 -54
- package/dist/cjs/utils/extensions.js +16 -2
- package/dist/cjs/version-wrapper.js +1 -1
- package/dist/es2019/create-editor/ReactEditorView.js +159 -37
- package/dist/es2019/utils/extensions.js +17 -2
- package/dist/es2019/version-wrapper.js +1 -1
- package/dist/esm/create-editor/ReactEditorView.js +191 -53
- package/dist/esm/utils/extensions.js +17 -2
- package/dist/esm/version-wrapper.js +1 -1
- package/package.json +13 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @atlaskit/editor-core
|
|
2
2
|
|
|
3
|
+
## 219.7.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`911ea1f065d0f`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/911ea1f065d0f) -
|
|
8
|
+
[EDITOR-6965] Rebuild the schema in `ReactEditorView.reconfigureState` when toggling presets under
|
|
9
|
+
the `cc-markdown-mode` experiment, so each preset declares its honest schema (rather than sharing
|
|
10
|
+
the schema from first mount via `state.reconfigure`). Skips the existing plugin-availability
|
|
11
|
+
filter (which would evaluate against the OLD schema and drop e.g. `extensionPlugin` on a
|
|
12
|
+
markdown→rich toggle), and re-seeds `collabInitialised: true` on the new state because the
|
|
13
|
+
Confluence NCS provider does not implement `getInitPayload` (so the rebind path in
|
|
14
|
+
`editor-plugin-collab-edit/initialize.ts` is skipped). Also makes
|
|
15
|
+
`extensionProviderToQuickInsertProvider.getItems` schema-aware so the `/` menu does not surface
|
|
16
|
+
extension items when the live schema cannot accept them.
|
|
17
|
+
|
|
3
18
|
## 219.7.2
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
|
@@ -28,6 +28,7 @@ var _processRawValue = require("@atlaskit/editor-common/process-raw-value");
|
|
|
28
28
|
var _uiReact = require("@atlaskit/editor-common/ui-react");
|
|
29
29
|
var _analytics2 = require("@atlaskit/editor-common/utils/analytics");
|
|
30
30
|
var _document = require("@atlaskit/editor-common/utils/document");
|
|
31
|
+
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
31
32
|
var _state2 = require("@atlaskit/editor-prosemirror/state");
|
|
32
33
|
var _view = require("@atlaskit/editor-prosemirror/view");
|
|
33
34
|
var _editorSsrRenderer = require("@atlaskit/editor-ssr-renderer");
|
|
@@ -57,14 +58,45 @@ var _handleEditorFocus = require("./ReactEditorView/handleEditorFocus");
|
|
|
57
58
|
var _useDispatchTransaction = require("./ReactEditorView/useDispatchTransaction");
|
|
58
59
|
var _useFireFullWidthEvent = require("./ReactEditorView/useFireFullWidthEvent");
|
|
59
60
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
61
|
+
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; }
|
|
62
|
+
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; }
|
|
60
63
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
61
64
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
62
|
-
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
63
|
-
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; }
|
|
64
|
-
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; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
65
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } // eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
65
66
|
var EDIT_AREA_ID = 'ak-editor-textarea';
|
|
66
67
|
var SSR_TRACE_SEGMENT_NAME = 'reactEditorView';
|
|
67
68
|
var bootStartTime = (0, _isPerformanceApiAvailable.isPerformanceAPIAvailable)() ? performance.now() : undefined;
|
|
69
|
+
// `markdown↔rich` toggles drop different node/mark sets, so the unique
|
|
70
|
+
// name set is enough to detect when a destructive rebuild is needed.
|
|
71
|
+
function sameNames(a, b) {
|
|
72
|
+
var setA = new Set(a);
|
|
73
|
+
var setB = new Set(b);
|
|
74
|
+
if (setA.size !== setB.size) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
var _iterator = _createForOfIteratorHelper(setA),
|
|
78
|
+
_step;
|
|
79
|
+
try {
|
|
80
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
81
|
+
var name = _step.value;
|
|
82
|
+
if (!setB.has(name)) {
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (err) {
|
|
87
|
+
_iterator.e(err);
|
|
88
|
+
} finally {
|
|
89
|
+
_iterator.f();
|
|
90
|
+
}
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
function schemaShapeChanged(current, next) {
|
|
94
|
+
return !sameNames(Object.keys(current.nodes), next.nodes.map(function (n) {
|
|
95
|
+
return n.name;
|
|
96
|
+
})) || !sameNames(Object.keys(current.marks), next.marks.map(function (m) {
|
|
97
|
+
return m.name;
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
68
100
|
function ReactEditorView(props) {
|
|
69
101
|
var _pluginInjectionAPI$c, _media, _linking, _document$querySelect, _props$render, _props$render2;
|
|
70
102
|
// Should be always the first statement in the component
|
|
@@ -364,9 +396,10 @@ function ReactEditorView(props) {
|
|
|
364
396
|
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
365
397
|
bumpConfigVersion = _useState2[1];
|
|
366
398
|
|
|
367
|
-
// Preset reference last processed by
|
|
368
|
-
//
|
|
369
|
-
|
|
399
|
+
// Preset reference last processed by reconfigureState. Used to skip the
|
|
400
|
+
// destructive work (plugin filter, schema rebuild) when reconfigure is
|
|
401
|
+
// called with the same preset.
|
|
402
|
+
var lastProcessedPresetRef = (0, _react.useRef)(null);
|
|
370
403
|
var reconfigureState = (0, _react.useCallback)(function (props) {
|
|
371
404
|
if (!viewRef.current) {
|
|
372
405
|
return;
|
|
@@ -383,6 +416,35 @@ function ReactEditorView(props) {
|
|
|
383
416
|
var previousPluginNames = new Set(pluginInjectionAPI.current.getRegisteredPluginNames());
|
|
384
417
|
var editorPlugins = (0, _createPluginsList.default)(props.preset, 'allowBlockType' in props.editorProps ? props.editorProps : {}, pluginInjectionAPI.current);
|
|
385
418
|
|
|
419
|
+
// Capture once, before either downstream block updates the ref —
|
|
420
|
+
// both the filter and the schema rebuild are destructive and only
|
|
421
|
+
// want to run when the preset has actually changed.
|
|
422
|
+
var presetChanged = lastProcessedPresetRef.current !== props.preset;
|
|
423
|
+
|
|
424
|
+
// Build a candidate config from the *unfiltered* plugin list so we can
|
|
425
|
+
// decide whether the schema rebuild path will run. Both the rebuild
|
|
426
|
+
// decision and the drop-filter decision below depend on this answer,
|
|
427
|
+
// so it has to be computed up-front.
|
|
428
|
+
var buildConfig = function buildConfig(plugins) {
|
|
429
|
+
var c = (0, _createEditor.processPluginsList)(plugins);
|
|
430
|
+
if ((0, _expValEquals.expValEquals)('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
431
|
+
var _c$pmPlugins;
|
|
432
|
+
(_c$pmPlugins = c.pmPlugins).push.apply(_c$pmPlugins, (0, _toConsumableArray2.default)(pluginInjectionAPI.current.getInternalPMPlugins()));
|
|
433
|
+
}
|
|
434
|
+
return c;
|
|
435
|
+
};
|
|
436
|
+
var nextConfig = buildConfig(editorPlugins);
|
|
437
|
+
|
|
438
|
+
// `state.reconfigure` preserves the original schema, so a preset
|
|
439
|
+
// toggle that should change schema (markdown↔rich) needs a fresh
|
|
440
|
+
// `EditorState`. Resets all plugin state including undo history.
|
|
441
|
+
//
|
|
442
|
+
// Compare schema *shape* (node + mark name sets) rather than preset
|
|
443
|
+
// identity: consumers commonly recreate the preset object on every
|
|
444
|
+
// parent re-render, and a destructive rebuild on a no-op identity
|
|
445
|
+
// change tears down all plugin state (e.g. unmounts the AI palette).
|
|
446
|
+
var shouldRebuildSchema = presetChanged && schemaShapeChanged(viewRef.current.state.schema, nextConfig) && (0, _expValEqualsNoExposure.expValEqualsNoExposure)('cc-markdown-mode', 'isEnabled', true);
|
|
447
|
+
|
|
386
448
|
// `state.reconfigure` keeps the original schema, so switching presets
|
|
387
449
|
// can leave the editor inconsistent in two ways:
|
|
388
450
|
// 1. The new preset may add plugins that reference schema nodes or
|
|
@@ -391,17 +453,26 @@ function ReactEditorView(props) {
|
|
|
391
453
|
// injection API even when the new preset doesn't re-register
|
|
392
454
|
// them, so listeners still fire against a state that no longer
|
|
393
455
|
// has their pmPlugin.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
456
|
+
//
|
|
457
|
+
// When the schema is being rebuilt below, the new schema is built
|
|
458
|
+
// from the *unfiltered* plugin list — so dropping plugins whose
|
|
459
|
+
// nodes/marks the OLD schema lacks would wrongly remove the very
|
|
460
|
+
// plugins the rebuild is meant to admit. Skip the drop step in that
|
|
461
|
+
// case (purpose 1) but always reconcile the injection API
|
|
462
|
+
// (purpose 2). When NOT rebuilding, run both — even under the
|
|
463
|
+
// `cc-markdown-mode` experiment, otherwise no-op preset identity
|
|
464
|
+
// changes would silently leave a broken plugin/schema mismatch.
|
|
465
|
+
if (presetChanged && (0, _platformFeatureFlags.fg)('platform_editor_reconfigure_filter_plugins')) {
|
|
466
|
+
var dropped = [];
|
|
467
|
+
if (!shouldRebuildSchema) {
|
|
468
|
+
var _result = (0, _filterPluginsForReconfigure.filterPluginsForReconfigure)(editorPlugins, viewRef.current.state.schema, previousPluginNames);
|
|
469
|
+
if (_result.dropped.length > 0) {
|
|
470
|
+
editorPlugins = _result.kept;
|
|
471
|
+
// Plugin list changed — rebuild candidate config to match.
|
|
472
|
+
nextConfig = buildConfig(editorPlugins);
|
|
473
|
+
}
|
|
474
|
+
dropped = _result.dropped;
|
|
475
|
+
}
|
|
405
476
|
var keptPluginNames = new Set(editorPlugins.map(function (p) {
|
|
406
477
|
return p === null || p === void 0 ? void 0 : p.name;
|
|
407
478
|
}).filter(function (n) {
|
|
@@ -415,33 +486,77 @@ function ReactEditorView(props) {
|
|
|
415
486
|
evictedFromApi: evictedFromApi
|
|
416
487
|
});
|
|
417
488
|
}
|
|
418
|
-
lastFilteredPresetRef.current = props.preset;
|
|
419
|
-
}
|
|
420
|
-
config.current = (0, _createEditor.processPluginsList)(editorPlugins);
|
|
421
|
-
if ((0, _expValEquals.expValEquals)('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
422
|
-
var _config$current$pmPlu2;
|
|
423
|
-
(_config$current$pmPlu2 = config.current.pmPlugins).push.apply(_config$current$pmPlu2, (0, _toConsumableArray2.default)(pluginInjectionAPI.current.getInternalPMPlugins()));
|
|
424
489
|
}
|
|
490
|
+
config.current = nextConfig;
|
|
425
491
|
var state = viewRef.current.state;
|
|
426
|
-
var
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
492
|
+
var newState;
|
|
493
|
+
if (shouldRebuildSchema) {
|
|
494
|
+
var newSchema = (0, _createSchema.createSchema)(config.current);
|
|
495
|
+
var newDoc;
|
|
496
|
+
try {
|
|
497
|
+
newDoc = _model.Node.fromJSON(newSchema, state.doc.toJSON());
|
|
498
|
+
} catch (e) {
|
|
499
|
+
// eslint-disable-next-line no-console
|
|
500
|
+
console.error('[reconfigureState] Failed to migrate doc to new schema; resetting to empty doc', e);
|
|
501
|
+
var empty = newSchema.topNodeType.createAndFill();
|
|
502
|
+
if (!empty) {
|
|
503
|
+
throw new Error('reconfigureState: doc migration failed and new schema cannot create an empty top node');
|
|
504
|
+
}
|
|
505
|
+
newDoc = empty;
|
|
506
|
+
}
|
|
507
|
+
var newSelection;
|
|
508
|
+
try {
|
|
509
|
+
newSelection = _state2.Selection.fromJSON(newDoc, state.selection.toJSON());
|
|
510
|
+
} catch (_unused) {
|
|
511
|
+
// Old selection's positions / node types may not map onto the new schema.
|
|
512
|
+
newSelection = _state2.Selection.atStart(newDoc);
|
|
513
|
+
}
|
|
514
|
+
var plugins = (0, _createEditor.createPMPlugins)({
|
|
515
|
+
schema: newSchema,
|
|
516
|
+
dispatch: dispatch,
|
|
517
|
+
errorReporter: errorReporter,
|
|
518
|
+
editorConfig: config.current,
|
|
519
|
+
eventDispatcher: eventDispatcher,
|
|
520
|
+
providerFactory: props.providerFactory,
|
|
521
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
522
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
523
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
524
|
+
featureFlags: featureFlags,
|
|
525
|
+
getIntl: function getIntl() {
|
|
526
|
+
return props.intl;
|
|
527
|
+
},
|
|
528
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
529
|
+
});
|
|
530
|
+
newState = _state2.EditorState.create({
|
|
531
|
+
schema: newSchema,
|
|
532
|
+
doc: newDoc,
|
|
533
|
+
selection: newSelection,
|
|
534
|
+
plugins: plugins
|
|
535
|
+
});
|
|
536
|
+
} else {
|
|
537
|
+
var _plugins = (0, _createEditor.createPMPlugins)({
|
|
538
|
+
schema: state.schema,
|
|
539
|
+
dispatch: dispatch,
|
|
540
|
+
errorReporter: errorReporter,
|
|
541
|
+
editorConfig: config.current,
|
|
542
|
+
eventDispatcher: eventDispatcher,
|
|
543
|
+
providerFactory: props.providerFactory,
|
|
544
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
545
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
546
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
547
|
+
featureFlags: featureFlags,
|
|
548
|
+
getIntl: function getIntl() {
|
|
549
|
+
return props.intl;
|
|
550
|
+
},
|
|
551
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
552
|
+
});
|
|
553
|
+
newState = state.reconfigure({
|
|
554
|
+
plugins: _plugins
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
if (presetChanged) {
|
|
558
|
+
lastProcessedPresetRef.current = props.preset;
|
|
559
|
+
}
|
|
445
560
|
|
|
446
561
|
// need to update the state first so when the view builds the nodeviews it is
|
|
447
562
|
// using the latest plugins
|
|
@@ -450,9 +565,32 @@ function ReactEditorView(props) {
|
|
|
450
565
|
state: newState
|
|
451
566
|
}));
|
|
452
567
|
|
|
568
|
+
// The new collab-edit plugin instance starts with `isReady=false`.
|
|
569
|
+
// The rebind path in editor-plugin-collab-edit's initialize.ts is
|
|
570
|
+
// gated on `provider.getInitPayload`, which the Confluence NCS
|
|
571
|
+
// provider does not implement, so the placeholder spinner would
|
|
572
|
+
// never clear. Re-seeding here is safe: the prior state must have
|
|
573
|
+
// had `isReady=true` for the user to have triggered the toggle.
|
|
574
|
+
//
|
|
575
|
+
// Must run AFTER `view.update({ state: newState })`: that call resets
|
|
576
|
+
// the view's state to the captured `newState` reference, so a
|
|
577
|
+
// dispatch placed before it would advance `view.state` to a value
|
|
578
|
+
// that `update` then silently overwrites — discarding the meta and
|
|
579
|
+
// leaving `isReady=false`.
|
|
580
|
+
if (shouldRebuildSchema) {
|
|
581
|
+
// `state.collabEditPlugin$` is the property PM derives from the
|
|
582
|
+
// collab plugin's PluginKey; cast through `unknown` to read it.
|
|
583
|
+
var collabState = viewRef.current.state.collabEditPlugin$;
|
|
584
|
+
if (collabState && collabState.isReady !== true) {
|
|
585
|
+
viewRef.current.dispatch(viewRef.current.state.tr.setMeta('collabInitialised', true));
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
453
589
|
// EDITOR-6702: gated until we have a broader gate; reconfigure is a
|
|
454
590
|
// low-level path so use NoExposure.
|
|
455
591
|
if ((0, _expValEqualsNoExposure.expValEqualsNoExposure)('cc-markdown-mode', 'isEnabled', true)) {
|
|
592
|
+
// Force a render so PluginSlot picks up the new preset's content
|
|
593
|
+
// components against the new state.
|
|
456
594
|
bumpConfigVersion(function (v) {
|
|
457
595
|
return v + 1;
|
|
458
596
|
});
|
|
@@ -695,19 +833,19 @@ function ReactEditorView(props) {
|
|
|
695
833
|
return function () {
|
|
696
834
|
if (scrollElement.current) {
|
|
697
835
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
698
|
-
var
|
|
699
|
-
|
|
836
|
+
var _iterator2 = _createForOfIteratorHelper(possibleListeners.current),
|
|
837
|
+
_step2;
|
|
700
838
|
try {
|
|
701
|
-
for (
|
|
839
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
702
840
|
var _scrollElement$curren;
|
|
703
|
-
var possibleListener =
|
|
841
|
+
var possibleListener = _step2.value;
|
|
704
842
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
705
843
|
(_scrollElement$curren = scrollElement.current) === null || _scrollElement$curren === void 0 || _scrollElement$curren.removeEventListener.apply(_scrollElement$curren, (0, _toConsumableArray2.default)(possibleListener));
|
|
706
844
|
}
|
|
707
845
|
} catch (err) {
|
|
708
|
-
|
|
846
|
+
_iterator2.e(err);
|
|
709
847
|
} finally {
|
|
710
|
-
|
|
848
|
+
_iterator2.f();
|
|
711
849
|
}
|
|
712
850
|
}
|
|
713
851
|
scrollElement.current = null;
|
|
@@ -719,19 +857,19 @@ function ReactEditorView(props) {
|
|
|
719
857
|
scrollElement.current = document.querySelector('[data-editor-scroll-container]');
|
|
720
858
|
var cleanupListeners = function cleanupListeners() {
|
|
721
859
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
722
|
-
var
|
|
723
|
-
|
|
860
|
+
var _iterator3 = _createForOfIteratorHelper(possibleListeners.current),
|
|
861
|
+
_step3;
|
|
724
862
|
try {
|
|
725
|
-
for (
|
|
863
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
726
864
|
var _scrollElement$curren2;
|
|
727
|
-
var possibleListener =
|
|
865
|
+
var possibleListener = _step3.value;
|
|
728
866
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
729
867
|
(_scrollElement$curren2 = scrollElement.current) === null || _scrollElement$curren2 === void 0 || _scrollElement$curren2.removeEventListener.apply(_scrollElement$curren2, (0, _toConsumableArray2.default)(possibleListener));
|
|
730
868
|
}
|
|
731
869
|
} catch (err) {
|
|
732
|
-
|
|
870
|
+
_iterator3.e(err);
|
|
733
871
|
} finally {
|
|
734
|
-
|
|
872
|
+
_iterator3.f();
|
|
735
873
|
}
|
|
736
874
|
};
|
|
737
875
|
if (scrollElement.current) {
|
|
@@ -18,6 +18,11 @@ var _analytics2 = require("@atlaskit/editor-common/utils/analytics");
|
|
|
18
18
|
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
19
19
|
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; }
|
|
20
20
|
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; }
|
|
21
|
+
// Structural shape of the markdown-mode plugin's slice of the injection API.
|
|
22
|
+
// Used to read `isMarkdownMode` without importing the `MarkdownModePlugin`
|
|
23
|
+
// type — that would pull editor-plugin-markdown-mode into editor-core's
|
|
24
|
+
// dependency graph and force every consuming product to rebuild.
|
|
25
|
+
|
|
21
26
|
/**
|
|
22
27
|
* Utils to send analytics event when a extension is inserted using quickInsert
|
|
23
28
|
*/
|
|
@@ -89,6 +94,15 @@ function _extensionProviderToQuickInsertProvider() {
|
|
|
89
94
|
extensions = _context.sent;
|
|
90
95
|
return _context.abrupt("return", {
|
|
91
96
|
getItems: function getItems() {
|
|
97
|
+
var _apiRef$current;
|
|
98
|
+
// `extensionProvider` is supplied independently of the preset, so
|
|
99
|
+
// suppress its items in markdown mode where rich-only content cannot
|
|
100
|
+
// be inserted. See `MarkdownModeReader` above for why this is read
|
|
101
|
+
// via a structural cast rather than the typed plugin API.
|
|
102
|
+
var isMarkdownMode = (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.markdownMode) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.sharedState.currentState()) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.isMarkdownMode;
|
|
103
|
+
if (isMarkdownMode) {
|
|
104
|
+
return Promise.resolve([]);
|
|
105
|
+
}
|
|
92
106
|
var quickInsertItems = (0, _extensions.getQuickInsertItemsFromModule)(extensions, function (item) {
|
|
93
107
|
var Icon = (0, _reactLoadable.default)({
|
|
94
108
|
loader: item.icon,
|
|
@@ -120,8 +134,8 @@ function _extensionProviderToQuickInsertProvider() {
|
|
|
120
134
|
isDisabledOffline: true,
|
|
121
135
|
action: function action(insert, state, source) {
|
|
122
136
|
if (typeof item.node === 'function') {
|
|
123
|
-
var _apiRef$
|
|
124
|
-
var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$
|
|
137
|
+
var _apiRef$current2;
|
|
138
|
+
var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 || (_apiRef$current2 = _apiRef$current2.extension) === null || _apiRef$current2 === void 0 || (_apiRef$current2 = _apiRef$current2.actions) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.api();
|
|
125
139
|
// While this should only run when the extension some setups of editor
|
|
126
140
|
// may not have the extension API
|
|
127
141
|
if (extensionAPI) {
|
|
@@ -17,6 +17,7 @@ import { processRawValue, processRawValueWithoutValidation } from '@atlaskit/edi
|
|
|
17
17
|
import { ReactEditorViewContext } from '@atlaskit/editor-common/ui-react';
|
|
18
18
|
import { analyticsEventKey, getAnalyticsEventSeverity } from '@atlaskit/editor-common/utils/analytics';
|
|
19
19
|
import { isEmptyDocument } from '@atlaskit/editor-common/utils/document';
|
|
20
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
20
21
|
import { EditorState, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
21
22
|
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
22
23
|
import { EditorSSRRenderer } from '@atlaskit/editor-ssr-renderer';
|
|
@@ -48,6 +49,24 @@ import { useFireFullWidthEvent } from './ReactEditorView/useFireFullWidthEvent';
|
|
|
48
49
|
const EDIT_AREA_ID = 'ak-editor-textarea';
|
|
49
50
|
const SSR_TRACE_SEGMENT_NAME = 'reactEditorView';
|
|
50
51
|
const bootStartTime = isPerformanceAPIAvailable() ? performance.now() : undefined;
|
|
52
|
+
// `markdown↔rich` toggles drop different node/mark sets, so the unique
|
|
53
|
+
// name set is enough to detect when a destructive rebuild is needed.
|
|
54
|
+
function sameNames(a, b) {
|
|
55
|
+
const setA = new Set(a);
|
|
56
|
+
const setB = new Set(b);
|
|
57
|
+
if (setA.size !== setB.size) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
for (const name of setA) {
|
|
61
|
+
if (!setB.has(name)) {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
function schemaShapeChanged(current, next) {
|
|
68
|
+
return !sameNames(Object.keys(current.nodes), next.nodes.map(n => n.name)) || !sameNames(Object.keys(current.marks), next.marks.map(m => m.name));
|
|
69
|
+
}
|
|
51
70
|
export function ReactEditorView(props) {
|
|
52
71
|
var _pluginInjectionAPI$c, _pluginInjectionAPI$c2, _pluginInjectionAPI$c3, _media, _linking, _linking$smartLinks, _document$querySelect, _props$render, _props$render2;
|
|
53
72
|
// Should be always the first statement in the component
|
|
@@ -338,9 +357,10 @@ export function ReactEditorView(props) {
|
|
|
338
357
|
// components from the rebuilt preset).
|
|
339
358
|
const [, bumpConfigVersion] = useState(0);
|
|
340
359
|
|
|
341
|
-
// Preset reference last processed by
|
|
342
|
-
//
|
|
343
|
-
|
|
360
|
+
// Preset reference last processed by reconfigureState. Used to skip the
|
|
361
|
+
// destructive work (plugin filter, schema rebuild) when reconfigure is
|
|
362
|
+
// called with the same preset.
|
|
363
|
+
const lastProcessedPresetRef = useRef(null);
|
|
344
364
|
const reconfigureState = useCallback(props => {
|
|
345
365
|
if (!viewRef.current) {
|
|
346
366
|
return;
|
|
@@ -357,6 +377,34 @@ export function ReactEditorView(props) {
|
|
|
357
377
|
const previousPluginNames = new Set(pluginInjectionAPI.current.getRegisteredPluginNames());
|
|
358
378
|
let editorPlugins = createPluginsList(props.preset, 'allowBlockType' in props.editorProps ? props.editorProps : {}, pluginInjectionAPI.current);
|
|
359
379
|
|
|
380
|
+
// Capture once, before either downstream block updates the ref —
|
|
381
|
+
// both the filter and the schema rebuild are destructive and only
|
|
382
|
+
// want to run when the preset has actually changed.
|
|
383
|
+
const presetChanged = lastProcessedPresetRef.current !== props.preset;
|
|
384
|
+
|
|
385
|
+
// Build a candidate config from the *unfiltered* plugin list so we can
|
|
386
|
+
// decide whether the schema rebuild path will run. Both the rebuild
|
|
387
|
+
// decision and the drop-filter decision below depend on this answer,
|
|
388
|
+
// so it has to be computed up-front.
|
|
389
|
+
const buildConfig = plugins => {
|
|
390
|
+
const c = processPluginsList(plugins);
|
|
391
|
+
if (expValEquals('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
392
|
+
c.pmPlugins.push(...pluginInjectionAPI.current.getInternalPMPlugins());
|
|
393
|
+
}
|
|
394
|
+
return c;
|
|
395
|
+
};
|
|
396
|
+
let nextConfig = buildConfig(editorPlugins);
|
|
397
|
+
|
|
398
|
+
// `state.reconfigure` preserves the original schema, so a preset
|
|
399
|
+
// toggle that should change schema (markdown↔rich) needs a fresh
|
|
400
|
+
// `EditorState`. Resets all plugin state including undo history.
|
|
401
|
+
//
|
|
402
|
+
// Compare schema *shape* (node + mark name sets) rather than preset
|
|
403
|
+
// identity: consumers commonly recreate the preset object on every
|
|
404
|
+
// parent re-render, and a destructive rebuild on a no-op identity
|
|
405
|
+
// change tears down all plugin state (e.g. unmounts the AI palette).
|
|
406
|
+
const shouldRebuildSchema = presetChanged && schemaShapeChanged(viewRef.current.state.schema, nextConfig) && expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true);
|
|
407
|
+
|
|
360
408
|
// `state.reconfigure` keeps the original schema, so switching presets
|
|
361
409
|
// can leave the editor inconsistent in two ways:
|
|
362
410
|
// 1. The new preset may add plugins that reference schema nodes or
|
|
@@ -365,18 +413,26 @@ export function ReactEditorView(props) {
|
|
|
365
413
|
// injection API even when the new preset doesn't re-register
|
|
366
414
|
// them, so listeners still fire against a state that no longer
|
|
367
415
|
// has their pmPlugin.
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
416
|
+
//
|
|
417
|
+
// When the schema is being rebuilt below, the new schema is built
|
|
418
|
+
// from the *unfiltered* plugin list — so dropping plugins whose
|
|
419
|
+
// nodes/marks the OLD schema lacks would wrongly remove the very
|
|
420
|
+
// plugins the rebuild is meant to admit. Skip the drop step in that
|
|
421
|
+
// case (purpose 1) but always reconcile the injection API
|
|
422
|
+
// (purpose 2). When NOT rebuilding, run both — even under the
|
|
423
|
+
// `cc-markdown-mode` experiment, otherwise no-op preset identity
|
|
424
|
+
// changes would silently leave a broken plugin/schema mismatch.
|
|
425
|
+
if (presetChanged && fg('platform_editor_reconfigure_filter_plugins')) {
|
|
426
|
+
let dropped = [];
|
|
427
|
+
if (!shouldRebuildSchema) {
|
|
428
|
+
const result = filterPluginsForReconfigure(editorPlugins, viewRef.current.state.schema, previousPluginNames);
|
|
429
|
+
if (result.dropped.length > 0) {
|
|
430
|
+
editorPlugins = result.kept;
|
|
431
|
+
// Plugin list changed — rebuild candidate config to match.
|
|
432
|
+
nextConfig = buildConfig(editorPlugins);
|
|
433
|
+
}
|
|
434
|
+
dropped = result.dropped;
|
|
435
|
+
}
|
|
380
436
|
const keptPluginNames = new Set(editorPlugins.map(p => p === null || p === void 0 ? void 0 : p.name).filter(n => Boolean(n)));
|
|
381
437
|
const evictedFromApi = pluginInjectionAPI.current.retainPlugins(keptPluginNames);
|
|
382
438
|
if (dropped.length > 0 || evictedFromApi.length > 0) {
|
|
@@ -386,30 +442,73 @@ export function ReactEditorView(props) {
|
|
|
386
442
|
evictedFromApi
|
|
387
443
|
});
|
|
388
444
|
}
|
|
389
|
-
lastFilteredPresetRef.current = props.preset;
|
|
390
|
-
}
|
|
391
|
-
config.current = processPluginsList(editorPlugins);
|
|
392
|
-
if (expValEquals('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
393
|
-
config.current.pmPlugins.push(...pluginInjectionAPI.current.getInternalPMPlugins());
|
|
394
445
|
}
|
|
446
|
+
config.current = nextConfig;
|
|
395
447
|
const state = viewRef.current.state;
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
448
|
+
let newState;
|
|
449
|
+
if (shouldRebuildSchema) {
|
|
450
|
+
const newSchema = createSchema(config.current);
|
|
451
|
+
let newDoc;
|
|
452
|
+
try {
|
|
453
|
+
newDoc = PMNode.fromJSON(newSchema, state.doc.toJSON());
|
|
454
|
+
} catch (e) {
|
|
455
|
+
// eslint-disable-next-line no-console
|
|
456
|
+
console.error('[reconfigureState] Failed to migrate doc to new schema; resetting to empty doc', e);
|
|
457
|
+
const empty = newSchema.topNodeType.createAndFill();
|
|
458
|
+
if (!empty) {
|
|
459
|
+
throw new Error('reconfigureState: doc migration failed and new schema cannot create an empty top node');
|
|
460
|
+
}
|
|
461
|
+
newDoc = empty;
|
|
462
|
+
}
|
|
463
|
+
let newSelection;
|
|
464
|
+
try {
|
|
465
|
+
newSelection = Selection.fromJSON(newDoc, state.selection.toJSON());
|
|
466
|
+
} catch {
|
|
467
|
+
// Old selection's positions / node types may not map onto the new schema.
|
|
468
|
+
newSelection = Selection.atStart(newDoc);
|
|
469
|
+
}
|
|
470
|
+
const plugins = createPMPlugins({
|
|
471
|
+
schema: newSchema,
|
|
472
|
+
dispatch: dispatch,
|
|
473
|
+
errorReporter: errorReporter,
|
|
474
|
+
editorConfig: config.current,
|
|
475
|
+
eventDispatcher: eventDispatcher,
|
|
476
|
+
providerFactory: props.providerFactory,
|
|
477
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
478
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
479
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
480
|
+
featureFlags,
|
|
481
|
+
getIntl: () => props.intl,
|
|
482
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
483
|
+
});
|
|
484
|
+
newState = EditorState.create({
|
|
485
|
+
schema: newSchema,
|
|
486
|
+
doc: newDoc,
|
|
487
|
+
selection: newSelection,
|
|
488
|
+
plugins: plugins
|
|
489
|
+
});
|
|
490
|
+
} else {
|
|
491
|
+
const plugins = createPMPlugins({
|
|
492
|
+
schema: state.schema,
|
|
493
|
+
dispatch: dispatch,
|
|
494
|
+
errorReporter: errorReporter,
|
|
495
|
+
editorConfig: config.current,
|
|
496
|
+
eventDispatcher: eventDispatcher,
|
|
497
|
+
providerFactory: props.providerFactory,
|
|
498
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
499
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
500
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
501
|
+
featureFlags,
|
|
502
|
+
getIntl: () => props.intl,
|
|
503
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
504
|
+
});
|
|
505
|
+
newState = state.reconfigure({
|
|
506
|
+
plugins: plugins
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
if (presetChanged) {
|
|
510
|
+
lastProcessedPresetRef.current = props.preset;
|
|
511
|
+
}
|
|
413
512
|
|
|
414
513
|
// need to update the state first so when the view builds the nodeviews it is
|
|
415
514
|
// using the latest plugins
|
|
@@ -419,9 +518,32 @@ export function ReactEditorView(props) {
|
|
|
419
518
|
state: newState
|
|
420
519
|
});
|
|
421
520
|
|
|
521
|
+
// The new collab-edit plugin instance starts with `isReady=false`.
|
|
522
|
+
// The rebind path in editor-plugin-collab-edit's initialize.ts is
|
|
523
|
+
// gated on `provider.getInitPayload`, which the Confluence NCS
|
|
524
|
+
// provider does not implement, so the placeholder spinner would
|
|
525
|
+
// never clear. Re-seeding here is safe: the prior state must have
|
|
526
|
+
// had `isReady=true` for the user to have triggered the toggle.
|
|
527
|
+
//
|
|
528
|
+
// Must run AFTER `view.update({ state: newState })`: that call resets
|
|
529
|
+
// the view's state to the captured `newState` reference, so a
|
|
530
|
+
// dispatch placed before it would advance `view.state` to a value
|
|
531
|
+
// that `update` then silently overwrites — discarding the meta and
|
|
532
|
+
// leaving `isReady=false`.
|
|
533
|
+
if (shouldRebuildSchema) {
|
|
534
|
+
// `state.collabEditPlugin$` is the property PM derives from the
|
|
535
|
+
// collab plugin's PluginKey; cast through `unknown` to read it.
|
|
536
|
+
const collabState = viewRef.current.state.collabEditPlugin$;
|
|
537
|
+
if (collabState && collabState.isReady !== true) {
|
|
538
|
+
viewRef.current.dispatch(viewRef.current.state.tr.setMeta('collabInitialised', true));
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
422
542
|
// EDITOR-6702: gated until we have a broader gate; reconfigure is a
|
|
423
543
|
// low-level path so use NoExposure.
|
|
424
544
|
if (expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true)) {
|
|
545
|
+
// Force a render so PluginSlot picks up the new preset's content
|
|
546
|
+
// components against the new state.
|
|
425
547
|
bumpConfigVersion(v => v + 1);
|
|
426
548
|
}
|
|
427
549
|
return result;
|
|
@@ -5,6 +5,12 @@ import { getQuickInsertItemsFromModule, resolveImport } from '@atlaskit/editor-c
|
|
|
5
5
|
import { combineProviders } from '@atlaskit/editor-common/provider-helpers';
|
|
6
6
|
import { findInsertLocation } from '@atlaskit/editor-common/utils/analytics';
|
|
7
7
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
8
|
+
|
|
9
|
+
// Structural shape of the markdown-mode plugin's slice of the injection API.
|
|
10
|
+
// Used to read `isMarkdownMode` without importing the `MarkdownModePlugin`
|
|
11
|
+
// type — that would pull editor-plugin-markdown-mode into editor-core's
|
|
12
|
+
// dependency graph and force every consuming product to rebuild.
|
|
13
|
+
|
|
8
14
|
/**
|
|
9
15
|
* Utils to send analytics event when a extension is inserted using quickInsert
|
|
10
16
|
*/
|
|
@@ -54,6 +60,15 @@ export async function extensionProviderToQuickInsertProvider(extensionProvider,
|
|
|
54
60
|
const extensions = await extensionProvider.getExtensions();
|
|
55
61
|
return {
|
|
56
62
|
getItems: () => {
|
|
63
|
+
var _apiRef$current, _apiRef$current$markd, _apiRef$current$markd2;
|
|
64
|
+
// `extensionProvider` is supplied independently of the preset, so
|
|
65
|
+
// suppress its items in markdown mode where rich-only content cannot
|
|
66
|
+
// be inserted. See `MarkdownModeReader` above for why this is read
|
|
67
|
+
// via a structural cast rather than the typed plugin API.
|
|
68
|
+
const isMarkdownMode = (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 ? void 0 : (_apiRef$current$markd = _apiRef$current.markdownMode) === null || _apiRef$current$markd === void 0 ? void 0 : (_apiRef$current$markd2 = _apiRef$current$markd.sharedState.currentState()) === null || _apiRef$current$markd2 === void 0 ? void 0 : _apiRef$current$markd2.isMarkdownMode;
|
|
69
|
+
if (isMarkdownMode) {
|
|
70
|
+
return Promise.resolve([]);
|
|
71
|
+
}
|
|
57
72
|
const quickInsertItems = getQuickInsertItemsFromModule(extensions, item => {
|
|
58
73
|
const Icon = Loadable({
|
|
59
74
|
loader: item.icon,
|
|
@@ -81,8 +96,8 @@ export async function extensionProviderToQuickInsertProvider(extensionProvider,
|
|
|
81
96
|
isDisabledOffline: true,
|
|
82
97
|
action: (insert, state, source) => {
|
|
83
98
|
if (typeof item.node === 'function') {
|
|
84
|
-
var _apiRef$
|
|
85
|
-
const extensionAPI = apiRef === null || apiRef === void 0 ? void 0 : (_apiRef$
|
|
99
|
+
var _apiRef$current2, _apiRef$current2$exte, _apiRef$current2$exte2;
|
|
100
|
+
const extensionAPI = apiRef === null || apiRef === void 0 ? void 0 : (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 ? void 0 : (_apiRef$current2$exte = _apiRef$current2.extension) === null || _apiRef$current2$exte === void 0 ? void 0 : (_apiRef$current2$exte2 = _apiRef$current2$exte.actions) === null || _apiRef$current2$exte2 === void 0 ? void 0 : _apiRef$current2$exte2.api();
|
|
86
101
|
// While this should only run when the extension some setups of editor
|
|
87
102
|
// may not have the extension API
|
|
88
103
|
if (extensionAPI) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = "@atlaskit/editor-core";
|
|
2
|
-
export const version = "219.7.
|
|
2
|
+
export const version = "219.7.2";
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import _defineProperty from "@babel/runtime/helpers/defineProperty";
|
|
2
2
|
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
|
|
3
3
|
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
|
|
4
|
+
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; }
|
|
5
|
+
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
6
|
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
5
7
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
6
8
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
7
|
-
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; }
|
|
8
|
-
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; }
|
|
9
9
|
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState, useEffect } from 'react';
|
|
10
10
|
import { injectIntl } from 'react-intl';
|
|
11
11
|
// eslint-disable-next-line @atlaskit/platform/prefer-crypto-random-uuid -- Use crypto.randomUUID instead
|
|
@@ -25,6 +25,7 @@ import { processRawValue, processRawValueWithoutValidation } from '@atlaskit/edi
|
|
|
25
25
|
import { ReactEditorViewContext } from '@atlaskit/editor-common/ui-react';
|
|
26
26
|
import { analyticsEventKey, getAnalyticsEventSeverity } from '@atlaskit/editor-common/utils/analytics';
|
|
27
27
|
import { isEmptyDocument } from '@atlaskit/editor-common/utils/document';
|
|
28
|
+
import { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
28
29
|
import { EditorState, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
29
30
|
import { EditorView } from '@atlaskit/editor-prosemirror/view';
|
|
30
31
|
import { EditorSSRRenderer } from '@atlaskit/editor-ssr-renderer';
|
|
@@ -56,6 +57,37 @@ import { useFireFullWidthEvent } from './ReactEditorView/useFireFullWidthEvent';
|
|
|
56
57
|
var EDIT_AREA_ID = 'ak-editor-textarea';
|
|
57
58
|
var SSR_TRACE_SEGMENT_NAME = 'reactEditorView';
|
|
58
59
|
var bootStartTime = isPerformanceAPIAvailable() ? performance.now() : undefined;
|
|
60
|
+
// `markdown↔rich` toggles drop different node/mark sets, so the unique
|
|
61
|
+
// name set is enough to detect when a destructive rebuild is needed.
|
|
62
|
+
function sameNames(a, b) {
|
|
63
|
+
var setA = new Set(a);
|
|
64
|
+
var setB = new Set(b);
|
|
65
|
+
if (setA.size !== setB.size) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
var _iterator = _createForOfIteratorHelper(setA),
|
|
69
|
+
_step;
|
|
70
|
+
try {
|
|
71
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
72
|
+
var name = _step.value;
|
|
73
|
+
if (!setB.has(name)) {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
} catch (err) {
|
|
78
|
+
_iterator.e(err);
|
|
79
|
+
} finally {
|
|
80
|
+
_iterator.f();
|
|
81
|
+
}
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
function schemaShapeChanged(current, next) {
|
|
85
|
+
return !sameNames(Object.keys(current.nodes), next.nodes.map(function (n) {
|
|
86
|
+
return n.name;
|
|
87
|
+
})) || !sameNames(Object.keys(current.marks), next.marks.map(function (m) {
|
|
88
|
+
return m.name;
|
|
89
|
+
}));
|
|
90
|
+
}
|
|
59
91
|
export function ReactEditorView(props) {
|
|
60
92
|
var _pluginInjectionAPI$c, _media, _linking, _document$querySelect, _props$render, _props$render2;
|
|
61
93
|
// Should be always the first statement in the component
|
|
@@ -355,9 +387,10 @@ export function ReactEditorView(props) {
|
|
|
355
387
|
_useState2 = _slicedToArray(_useState, 2),
|
|
356
388
|
bumpConfigVersion = _useState2[1];
|
|
357
389
|
|
|
358
|
-
// Preset reference last processed by
|
|
359
|
-
//
|
|
360
|
-
|
|
390
|
+
// Preset reference last processed by reconfigureState. Used to skip the
|
|
391
|
+
// destructive work (plugin filter, schema rebuild) when reconfigure is
|
|
392
|
+
// called with the same preset.
|
|
393
|
+
var lastProcessedPresetRef = useRef(null);
|
|
361
394
|
var reconfigureState = useCallback(function (props) {
|
|
362
395
|
if (!viewRef.current) {
|
|
363
396
|
return;
|
|
@@ -374,6 +407,35 @@ export function ReactEditorView(props) {
|
|
|
374
407
|
var previousPluginNames = new Set(pluginInjectionAPI.current.getRegisteredPluginNames());
|
|
375
408
|
var editorPlugins = createPluginsList(props.preset, 'allowBlockType' in props.editorProps ? props.editorProps : {}, pluginInjectionAPI.current);
|
|
376
409
|
|
|
410
|
+
// Capture once, before either downstream block updates the ref —
|
|
411
|
+
// both the filter and the schema rebuild are destructive and only
|
|
412
|
+
// want to run when the preset has actually changed.
|
|
413
|
+
var presetChanged = lastProcessedPresetRef.current !== props.preset;
|
|
414
|
+
|
|
415
|
+
// Build a candidate config from the *unfiltered* plugin list so we can
|
|
416
|
+
// decide whether the schema rebuild path will run. Both the rebuild
|
|
417
|
+
// decision and the drop-filter decision below depend on this answer,
|
|
418
|
+
// so it has to be computed up-front.
|
|
419
|
+
var buildConfig = function buildConfig(plugins) {
|
|
420
|
+
var c = processPluginsList(plugins);
|
|
421
|
+
if (expValEquals('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
422
|
+
var _c$pmPlugins;
|
|
423
|
+
(_c$pmPlugins = c.pmPlugins).push.apply(_c$pmPlugins, _toConsumableArray(pluginInjectionAPI.current.getInternalPMPlugins()));
|
|
424
|
+
}
|
|
425
|
+
return c;
|
|
426
|
+
};
|
|
427
|
+
var nextConfig = buildConfig(editorPlugins);
|
|
428
|
+
|
|
429
|
+
// `state.reconfigure` preserves the original schema, so a preset
|
|
430
|
+
// toggle that should change schema (markdown↔rich) needs a fresh
|
|
431
|
+
// `EditorState`. Resets all plugin state including undo history.
|
|
432
|
+
//
|
|
433
|
+
// Compare schema *shape* (node + mark name sets) rather than preset
|
|
434
|
+
// identity: consumers commonly recreate the preset object on every
|
|
435
|
+
// parent re-render, and a destructive rebuild on a no-op identity
|
|
436
|
+
// change tears down all plugin state (e.g. unmounts the AI palette).
|
|
437
|
+
var shouldRebuildSchema = presetChanged && schemaShapeChanged(viewRef.current.state.schema, nextConfig) && expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true);
|
|
438
|
+
|
|
377
439
|
// `state.reconfigure` keeps the original schema, so switching presets
|
|
378
440
|
// can leave the editor inconsistent in two ways:
|
|
379
441
|
// 1. The new preset may add plugins that reference schema nodes or
|
|
@@ -382,17 +444,26 @@ export function ReactEditorView(props) {
|
|
|
382
444
|
// injection API even when the new preset doesn't re-register
|
|
383
445
|
// them, so listeners still fire against a state that no longer
|
|
384
446
|
// has their pmPlugin.
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
447
|
+
//
|
|
448
|
+
// When the schema is being rebuilt below, the new schema is built
|
|
449
|
+
// from the *unfiltered* plugin list — so dropping plugins whose
|
|
450
|
+
// nodes/marks the OLD schema lacks would wrongly remove the very
|
|
451
|
+
// plugins the rebuild is meant to admit. Skip the drop step in that
|
|
452
|
+
// case (purpose 1) but always reconcile the injection API
|
|
453
|
+
// (purpose 2). When NOT rebuilding, run both — even under the
|
|
454
|
+
// `cc-markdown-mode` experiment, otherwise no-op preset identity
|
|
455
|
+
// changes would silently leave a broken plugin/schema mismatch.
|
|
456
|
+
if (presetChanged && fg('platform_editor_reconfigure_filter_plugins')) {
|
|
457
|
+
var dropped = [];
|
|
458
|
+
if (!shouldRebuildSchema) {
|
|
459
|
+
var _result = filterPluginsForReconfigure(editorPlugins, viewRef.current.state.schema, previousPluginNames);
|
|
460
|
+
if (_result.dropped.length > 0) {
|
|
461
|
+
editorPlugins = _result.kept;
|
|
462
|
+
// Plugin list changed — rebuild candidate config to match.
|
|
463
|
+
nextConfig = buildConfig(editorPlugins);
|
|
464
|
+
}
|
|
465
|
+
dropped = _result.dropped;
|
|
466
|
+
}
|
|
396
467
|
var keptPluginNames = new Set(editorPlugins.map(function (p) {
|
|
397
468
|
return p === null || p === void 0 ? void 0 : p.name;
|
|
398
469
|
}).filter(function (n) {
|
|
@@ -406,33 +477,77 @@ export function ReactEditorView(props) {
|
|
|
406
477
|
evictedFromApi: evictedFromApi
|
|
407
478
|
});
|
|
408
479
|
}
|
|
409
|
-
lastFilteredPresetRef.current = props.preset;
|
|
410
|
-
}
|
|
411
|
-
config.current = processPluginsList(editorPlugins);
|
|
412
|
-
if (expValEquals('platform_editor_appearance_shared_state', 'isEnabled', true)) {
|
|
413
|
-
var _config$current$pmPlu2;
|
|
414
|
-
(_config$current$pmPlu2 = config.current.pmPlugins).push.apply(_config$current$pmPlu2, _toConsumableArray(pluginInjectionAPI.current.getInternalPMPlugins()));
|
|
415
480
|
}
|
|
481
|
+
config.current = nextConfig;
|
|
416
482
|
var state = viewRef.current.state;
|
|
417
|
-
var
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
483
|
+
var newState;
|
|
484
|
+
if (shouldRebuildSchema) {
|
|
485
|
+
var newSchema = createSchema(config.current);
|
|
486
|
+
var newDoc;
|
|
487
|
+
try {
|
|
488
|
+
newDoc = PMNode.fromJSON(newSchema, state.doc.toJSON());
|
|
489
|
+
} catch (e) {
|
|
490
|
+
// eslint-disable-next-line no-console
|
|
491
|
+
console.error('[reconfigureState] Failed to migrate doc to new schema; resetting to empty doc', e);
|
|
492
|
+
var empty = newSchema.topNodeType.createAndFill();
|
|
493
|
+
if (!empty) {
|
|
494
|
+
throw new Error('reconfigureState: doc migration failed and new schema cannot create an empty top node');
|
|
495
|
+
}
|
|
496
|
+
newDoc = empty;
|
|
497
|
+
}
|
|
498
|
+
var newSelection;
|
|
499
|
+
try {
|
|
500
|
+
newSelection = Selection.fromJSON(newDoc, state.selection.toJSON());
|
|
501
|
+
} catch (_unused) {
|
|
502
|
+
// Old selection's positions / node types may not map onto the new schema.
|
|
503
|
+
newSelection = Selection.atStart(newDoc);
|
|
504
|
+
}
|
|
505
|
+
var plugins = createPMPlugins({
|
|
506
|
+
schema: newSchema,
|
|
507
|
+
dispatch: dispatch,
|
|
508
|
+
errorReporter: errorReporter,
|
|
509
|
+
editorConfig: config.current,
|
|
510
|
+
eventDispatcher: eventDispatcher,
|
|
511
|
+
providerFactory: props.providerFactory,
|
|
512
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
513
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
514
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
515
|
+
featureFlags: featureFlags,
|
|
516
|
+
getIntl: function getIntl() {
|
|
517
|
+
return props.intl;
|
|
518
|
+
},
|
|
519
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
520
|
+
});
|
|
521
|
+
newState = EditorState.create({
|
|
522
|
+
schema: newSchema,
|
|
523
|
+
doc: newDoc,
|
|
524
|
+
selection: newSelection,
|
|
525
|
+
plugins: plugins
|
|
526
|
+
});
|
|
527
|
+
} else {
|
|
528
|
+
var _plugins = createPMPlugins({
|
|
529
|
+
schema: state.schema,
|
|
530
|
+
dispatch: dispatch,
|
|
531
|
+
errorReporter: errorReporter,
|
|
532
|
+
editorConfig: config.current,
|
|
533
|
+
eventDispatcher: eventDispatcher,
|
|
534
|
+
providerFactory: props.providerFactory,
|
|
535
|
+
portalProviderAPI: props.portalProviderAPI,
|
|
536
|
+
nodeViewPortalProviderAPI: props.nodeViewPortalProviderAPI,
|
|
537
|
+
dispatchAnalyticsEvent: dispatchAnalyticsEvent,
|
|
538
|
+
featureFlags: featureFlags,
|
|
539
|
+
getIntl: function getIntl() {
|
|
540
|
+
return props.intl;
|
|
541
|
+
},
|
|
542
|
+
onEditorStateUpdated: pluginInjectionAPI.current.onEditorViewUpdated
|
|
543
|
+
});
|
|
544
|
+
newState = state.reconfigure({
|
|
545
|
+
plugins: _plugins
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
if (presetChanged) {
|
|
549
|
+
lastProcessedPresetRef.current = props.preset;
|
|
550
|
+
}
|
|
436
551
|
|
|
437
552
|
// need to update the state first so when the view builds the nodeviews it is
|
|
438
553
|
// using the latest plugins
|
|
@@ -441,9 +556,32 @@ export function ReactEditorView(props) {
|
|
|
441
556
|
state: newState
|
|
442
557
|
}));
|
|
443
558
|
|
|
559
|
+
// The new collab-edit plugin instance starts with `isReady=false`.
|
|
560
|
+
// The rebind path in editor-plugin-collab-edit's initialize.ts is
|
|
561
|
+
// gated on `provider.getInitPayload`, which the Confluence NCS
|
|
562
|
+
// provider does not implement, so the placeholder spinner would
|
|
563
|
+
// never clear. Re-seeding here is safe: the prior state must have
|
|
564
|
+
// had `isReady=true` for the user to have triggered the toggle.
|
|
565
|
+
//
|
|
566
|
+
// Must run AFTER `view.update({ state: newState })`: that call resets
|
|
567
|
+
// the view's state to the captured `newState` reference, so a
|
|
568
|
+
// dispatch placed before it would advance `view.state` to a value
|
|
569
|
+
// that `update` then silently overwrites — discarding the meta and
|
|
570
|
+
// leaving `isReady=false`.
|
|
571
|
+
if (shouldRebuildSchema) {
|
|
572
|
+
// `state.collabEditPlugin$` is the property PM derives from the
|
|
573
|
+
// collab plugin's PluginKey; cast through `unknown` to read it.
|
|
574
|
+
var collabState = viewRef.current.state.collabEditPlugin$;
|
|
575
|
+
if (collabState && collabState.isReady !== true) {
|
|
576
|
+
viewRef.current.dispatch(viewRef.current.state.tr.setMeta('collabInitialised', true));
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
444
580
|
// EDITOR-6702: gated until we have a broader gate; reconfigure is a
|
|
445
581
|
// low-level path so use NoExposure.
|
|
446
582
|
if (expValEqualsNoExposure('cc-markdown-mode', 'isEnabled', true)) {
|
|
583
|
+
// Force a render so PluginSlot picks up the new preset's content
|
|
584
|
+
// components against the new state.
|
|
447
585
|
bumpConfigVersion(function (v) {
|
|
448
586
|
return v + 1;
|
|
449
587
|
});
|
|
@@ -686,19 +824,19 @@ export function ReactEditorView(props) {
|
|
|
686
824
|
return function () {
|
|
687
825
|
if (scrollElement.current) {
|
|
688
826
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
689
|
-
var
|
|
690
|
-
|
|
827
|
+
var _iterator2 = _createForOfIteratorHelper(possibleListeners.current),
|
|
828
|
+
_step2;
|
|
691
829
|
try {
|
|
692
|
-
for (
|
|
830
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
693
831
|
var _scrollElement$curren;
|
|
694
|
-
var possibleListener =
|
|
832
|
+
var possibleListener = _step2.value;
|
|
695
833
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
696
834
|
(_scrollElement$curren = scrollElement.current) === null || _scrollElement$curren === void 0 || _scrollElement$curren.removeEventListener.apply(_scrollElement$curren, _toConsumableArray(possibleListener));
|
|
697
835
|
}
|
|
698
836
|
} catch (err) {
|
|
699
|
-
|
|
837
|
+
_iterator2.e(err);
|
|
700
838
|
} finally {
|
|
701
|
-
|
|
839
|
+
_iterator2.f();
|
|
702
840
|
}
|
|
703
841
|
}
|
|
704
842
|
scrollElement.current = null;
|
|
@@ -710,19 +848,19 @@ export function ReactEditorView(props) {
|
|
|
710
848
|
scrollElement.current = document.querySelector('[data-editor-scroll-container]');
|
|
711
849
|
var cleanupListeners = function cleanupListeners() {
|
|
712
850
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
713
|
-
var
|
|
714
|
-
|
|
851
|
+
var _iterator3 = _createForOfIteratorHelper(possibleListeners.current),
|
|
852
|
+
_step3;
|
|
715
853
|
try {
|
|
716
|
-
for (
|
|
854
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
717
855
|
var _scrollElement$curren2;
|
|
718
|
-
var possibleListener =
|
|
856
|
+
var possibleListener = _step3.value;
|
|
719
857
|
// eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
|
|
720
858
|
(_scrollElement$curren2 = scrollElement.current) === null || _scrollElement$curren2 === void 0 || _scrollElement$curren2.removeEventListener.apply(_scrollElement$curren2, _toConsumableArray(possibleListener));
|
|
721
859
|
}
|
|
722
860
|
} catch (err) {
|
|
723
|
-
|
|
861
|
+
_iterator3.e(err);
|
|
724
862
|
} finally {
|
|
725
|
-
|
|
863
|
+
_iterator3.f();
|
|
726
864
|
}
|
|
727
865
|
};
|
|
728
866
|
if (scrollElement.current) {
|
|
@@ -10,6 +10,12 @@ import { getQuickInsertItemsFromModule, resolveImport } from '@atlaskit/editor-c
|
|
|
10
10
|
import { combineProviders } from '@atlaskit/editor-common/provider-helpers';
|
|
11
11
|
import { findInsertLocation } from '@atlaskit/editor-common/utils/analytics';
|
|
12
12
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
13
|
+
|
|
14
|
+
// Structural shape of the markdown-mode plugin's slice of the injection API.
|
|
15
|
+
// Used to read `isMarkdownMode` without importing the `MarkdownModePlugin`
|
|
16
|
+
// type — that would pull editor-plugin-markdown-mode into editor-core's
|
|
17
|
+
// dependency graph and force every consuming product to rebuild.
|
|
18
|
+
|
|
13
19
|
/**
|
|
14
20
|
* Utils to send analytics event when a extension is inserted using quickInsert
|
|
15
21
|
*/
|
|
@@ -81,6 +87,15 @@ function _extensionProviderToQuickInsertProvider() {
|
|
|
81
87
|
extensions = _context.sent;
|
|
82
88
|
return _context.abrupt("return", {
|
|
83
89
|
getItems: function getItems() {
|
|
90
|
+
var _apiRef$current;
|
|
91
|
+
// `extensionProvider` is supplied independently of the preset, so
|
|
92
|
+
// suppress its items in markdown mode where rich-only content cannot
|
|
93
|
+
// be inserted. See `MarkdownModeReader` above for why this is read
|
|
94
|
+
// via a structural cast rather than the typed plugin API.
|
|
95
|
+
var isMarkdownMode = (_apiRef$current = apiRef.current) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.markdownMode) === null || _apiRef$current === void 0 || (_apiRef$current = _apiRef$current.sharedState.currentState()) === null || _apiRef$current === void 0 ? void 0 : _apiRef$current.isMarkdownMode;
|
|
96
|
+
if (isMarkdownMode) {
|
|
97
|
+
return Promise.resolve([]);
|
|
98
|
+
}
|
|
84
99
|
var quickInsertItems = getQuickInsertItemsFromModule(extensions, function (item) {
|
|
85
100
|
var Icon = Loadable({
|
|
86
101
|
loader: item.icon,
|
|
@@ -112,8 +127,8 @@ function _extensionProviderToQuickInsertProvider() {
|
|
|
112
127
|
isDisabledOffline: true,
|
|
113
128
|
action: function action(insert, state, source) {
|
|
114
129
|
if (typeof item.node === 'function') {
|
|
115
|
-
var _apiRef$
|
|
116
|
-
var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$
|
|
130
|
+
var _apiRef$current2;
|
|
131
|
+
var extensionAPI = apiRef === null || apiRef === void 0 || (_apiRef$current2 = apiRef.current) === null || _apiRef$current2 === void 0 || (_apiRef$current2 = _apiRef$current2.extension) === null || _apiRef$current2 === void 0 || (_apiRef$current2 = _apiRef$current2.actions) === null || _apiRef$current2 === void 0 ? void 0 : _apiRef$current2.api();
|
|
117
132
|
// While this should only run when the extension some setups of editor
|
|
118
133
|
// may not have the extension API
|
|
119
134
|
if (extensionAPI) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export var name = "@atlaskit/editor-core";
|
|
2
|
-
export var version = "219.7.
|
|
2
|
+
export var version = "219.7.2";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-core",
|
|
3
|
-
"version": "219.7.
|
|
3
|
+
"version": "219.7.3",
|
|
4
4
|
"description": "A package contains Atlassian editor core functionality",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"@atlaskit/css": "^0.19.0",
|
|
56
56
|
"@atlaskit/editor-json-transformer": "^8.31.0",
|
|
57
57
|
"@atlaskit/editor-performance-metrics": "^2.1.0",
|
|
58
|
-
"@atlaskit/editor-plugin-connectivity": "^10.
|
|
58
|
+
"@atlaskit/editor-plugin-connectivity": "^10.1.0",
|
|
59
59
|
"@atlaskit/editor-plugin-quick-insert": "^10.4.0",
|
|
60
60
|
"@atlaskit/editor-plugin-user-preferences": "^8.2.0",
|
|
61
61
|
"@atlaskit/editor-plugins": "^13.1.0",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"@atlaskit/platform-feature-flags-react": "^0.5.0",
|
|
75
75
|
"@atlaskit/react-ufo": "^5.20.0",
|
|
76
76
|
"@atlaskit/task-decision": "^20.1.0",
|
|
77
|
-
"@atlaskit/tmp-editor-statsig": "^80.
|
|
77
|
+
"@atlaskit/tmp-editor-statsig": "^80.3.0",
|
|
78
78
|
"@atlaskit/tokens": "^13.0.0",
|
|
79
79
|
"@atlaskit/tooltip": "^22.2.0",
|
|
80
80
|
"@atlaskit/width-detector": "^5.1.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"uuid": "^3.1.0"
|
|
93
93
|
},
|
|
94
94
|
"peerDependencies": {
|
|
95
|
-
"@atlaskit/editor-common": "^114.
|
|
95
|
+
"@atlaskit/editor-common": "^114.31.0",
|
|
96
96
|
"@atlaskit/link-provider": "^4.4.0",
|
|
97
97
|
"@atlaskit/media-core": "^37.0.0",
|
|
98
98
|
"react": "^18.2.0",
|
|
@@ -105,9 +105,10 @@
|
|
|
105
105
|
"@af/visual-regression": "workspace:^",
|
|
106
106
|
"@atlaskit/adf-utils": "^19.29.0",
|
|
107
107
|
"@atlaskit/analytics-listeners": "^10.1.0",
|
|
108
|
+
"@atlaskit/code": "^17.5.0",
|
|
108
109
|
"@atlaskit/collab-provider": "^18.2.0",
|
|
109
110
|
"@atlaskit/editor-plugin-annotation": "^10.3.0",
|
|
110
|
-
"@atlaskit/editor-plugin-card": "^16.
|
|
111
|
+
"@atlaskit/editor-plugin-card": "^16.8.0",
|
|
111
112
|
"@atlaskit/editor-plugin-list": "^12.1.0",
|
|
112
113
|
"@atlaskit/editor-plugin-paste": "^11.2.0",
|
|
113
114
|
"@atlaskit/editor-test-helpers": "workspace:^",
|
|
@@ -118,6 +119,8 @@
|
|
|
118
119
|
"@atlaskit/media-integration-test-helpers": "workspace:^",
|
|
119
120
|
"@atlaskit/media-test-helpers": "^41.0.0",
|
|
120
121
|
"@atlaskit/modal-dialog": "^15.0.0",
|
|
122
|
+
"@atlaskit/popper": "^7.2.0",
|
|
123
|
+
"@atlaskit/portal": "^5.5.0",
|
|
121
124
|
"@atlaskit/renderer": "^130.6.0",
|
|
122
125
|
"@atlaskit/section-message": "^8.12.0",
|
|
123
126
|
"@atlaskit/synchrony-test-helpers": "workspace:^",
|
|
@@ -132,6 +135,7 @@
|
|
|
132
135
|
"@atlassian/search-client": "^1.7.0",
|
|
133
136
|
"@atlassian/search-provider": "^11.1.0",
|
|
134
137
|
"@atlassian/structured-docs-types": "workspace:^",
|
|
138
|
+
"@atlassian/user-profile-card": "^1.4.0",
|
|
135
139
|
"@emotion/jest": "^11.8.0",
|
|
136
140
|
"@testing-library/react": "^16.3.0",
|
|
137
141
|
"@types/diff": "^5.0.2",
|
|
@@ -174,6 +178,10 @@
|
|
|
174
178
|
"type": "boolean",
|
|
175
179
|
"referenceOnly": "true"
|
|
176
180
|
},
|
|
181
|
+
"people-teams_migrate-user-profile-card": {
|
|
182
|
+
"type": "boolean",
|
|
183
|
+
"referenceOnly": true
|
|
184
|
+
},
|
|
177
185
|
"editor_inline_comments_on_inline_nodes": {
|
|
178
186
|
"type": "boolean",
|
|
179
187
|
"referenceOnly": "true"
|