@atlaskit/editor-plugin-synced-block 8.4.1 → 8.4.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 +21 -0
- package/dist/cjs/pm-plugins/main.js +52 -16
- package/dist/es2019/pm-plugins/main.js +36 -0
- package/dist/esm/pm-plugins/main.js +36 -0
- package/package.json +7 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-synced-block
|
|
2
2
|
|
|
3
|
+
## 8.4.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`085a281306c03`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/085a281306c03) -
|
|
8
|
+
Add defensive mechanisms for synced block EntityNotFound errors:
|
|
9
|
+
- Add retry with exponential backoff when fetching synced block references returns EntityNotFound
|
|
10
|
+
(up to 3 retries with 2s/4s/8s delays)
|
|
11
|
+
- Add transformPasted handler to convert any bodiedSyncBlock nodes arriving via paste into
|
|
12
|
+
syncBlock references, preventing createBlock from being called with the wrong parentId
|
|
13
|
+
|
|
14
|
+
Both changes are gated behind `platform_synced_block_patch_13`.
|
|
15
|
+
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
|
|
18
|
+
## 8.4.2
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- Updated dependencies
|
|
23
|
+
|
|
3
24
|
## 8.4.1
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
|
@@ -18,9 +18,10 @@ var _utils = require("@atlaskit/editor-common/utils");
|
|
|
18
18
|
var _editorPluginConnectivity = require("@atlaskit/editor-plugin-connectivity");
|
|
19
19
|
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
20
20
|
var _transform = require("@atlaskit/editor-prosemirror/transform");
|
|
21
|
-
var
|
|
21
|
+
var _view2 = require("@atlaskit/editor-prosemirror/view");
|
|
22
22
|
var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
|
|
23
23
|
var _utils2 = require("@atlaskit/editor-synced-block-provider/utils");
|
|
24
|
+
var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
|
|
24
25
|
var _expValEquals = require("@atlaskit/tmp-editor-statsig/exp-val-equals");
|
|
25
26
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
26
27
|
var _bodiedSyncedBlock = require("../nodeviews/bodiedSyncedBlock");
|
|
@@ -153,6 +154,7 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
153
154
|
// events this lets us triangulate cross-product paste behaviour without standing up a
|
|
154
155
|
// dedicated `cross_product_paste` event subject.
|
|
155
156
|
var isPaste = Boolean((_tr$getMeta = tr.getMeta('paste')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : tr.getMeta('uiEvent') === 'paste');
|
|
157
|
+
var isPasteOrDrop = isPaste || tr.getMeta('uiEvent') === 'drop';
|
|
156
158
|
syncBlockAdded.forEach(function (syncBlock) {
|
|
157
159
|
var _api$analytics2;
|
|
158
160
|
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.fireAnalyticsEvent({
|
|
@@ -180,6 +182,16 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
180
182
|
// After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
|
|
181
183
|
return true;
|
|
182
184
|
}
|
|
185
|
+
|
|
186
|
+
// Defense-in-depth: if a bodiedSyncBlock arrives via paste or drag-and-drop,
|
|
187
|
+
// it may have bypassed transformCopied (e.g. cut, browser clipboard).
|
|
188
|
+
// Do not call createBlock — it would use this page's parentId which may
|
|
189
|
+
// be wrong. The bodiedSyncBlock content will still be inserted but will
|
|
190
|
+
// not be registered as a source block in Block Service, which is safer
|
|
191
|
+
// than creating a zombie block under the wrong ARI.
|
|
192
|
+
if (isPasteOrDrop && (0, _platformFeatureFlags.fg)('platform_synced_block_patch_13')) {
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
183
195
|
(0, _handleBodiedSyncBlockCreation.handleBodiedSyncBlockCreation)(bodiedSyncBlockAdded, state, api);
|
|
184
196
|
return true;
|
|
185
197
|
}
|
|
@@ -232,7 +244,7 @@ var buildStatusDecorations = function buildStatusDecorations(doc, syncBlockStore
|
|
|
232
244
|
// Fast path: when all status flags are off and no creations are in flight,
|
|
233
245
|
// no node can produce a decoration — skip the full doc traversal.
|
|
234
246
|
if (!isOffline && !isViewMode && !isDragging && !syncBlockStore.sourceManager.hasPendingCreations()) {
|
|
235
|
-
return
|
|
247
|
+
return _view2.DecorationSet.empty;
|
|
236
248
|
}
|
|
237
249
|
var offlineDecorations = [];
|
|
238
250
|
var viewModeDecorations = [];
|
|
@@ -240,22 +252,22 @@ var buildStatusDecorations = function buildStatusDecorations(doc, syncBlockStore
|
|
|
240
252
|
var dragDecorations = [];
|
|
241
253
|
doc.descendants(function (node, pos) {
|
|
242
254
|
if (node.type.name === 'bodiedSyncBlock' && isOffline) {
|
|
243
|
-
offlineDecorations.push(
|
|
255
|
+
offlineDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
244
256
|
class: _syncBlock.SyncBlockStateCssClassName.disabledClassName
|
|
245
257
|
}));
|
|
246
258
|
}
|
|
247
259
|
if (syncBlockStore.isSyncBlock(node) && isViewMode) {
|
|
248
|
-
viewModeDecorations.push(
|
|
260
|
+
viewModeDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
249
261
|
class: _syncBlock.SyncBlockStateCssClassName.viewModeClassName
|
|
250
262
|
}));
|
|
251
263
|
}
|
|
252
264
|
if (node.type.name === 'bodiedSyncBlock' && syncBlockStore.sourceManager.isPendingCreation(node.attrs.resourceId)) {
|
|
253
|
-
loadingDecorations.push(
|
|
265
|
+
loadingDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
254
266
|
class: _syncBlock.SyncBlockStateCssClassName.creationLoadingClassName
|
|
255
267
|
}));
|
|
256
268
|
}
|
|
257
269
|
if (isDragging && syncBlockStore.isSyncBlock(node)) {
|
|
258
|
-
dragDecorations.push(
|
|
270
|
+
dragDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
259
271
|
class: _syncBlock.SyncBlockStateCssClassName.draggingClassName
|
|
260
272
|
}));
|
|
261
273
|
}
|
|
@@ -263,7 +275,7 @@ var buildStatusDecorations = function buildStatusDecorations(doc, syncBlockStore
|
|
|
263
275
|
// only traverse the top-level node of the document, as syncBlock and bodiedSyncBlock are top-level nodes
|
|
264
276
|
return false;
|
|
265
277
|
});
|
|
266
|
-
return
|
|
278
|
+
return _view2.DecorationSet.create(doc, [].concat(offlineDecorations, viewModeDecorations, loadingDecorations, dragDecorations));
|
|
267
279
|
};
|
|
268
280
|
|
|
269
281
|
/**
|
|
@@ -396,7 +408,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
396
408
|
// When the perf gate is ON and the doc has synced blocks we do a
|
|
397
409
|
// single traversal here; afterwards `apply()` will map or rebuild
|
|
398
410
|
// only when a status signal changes.
|
|
399
|
-
var initStatusDecorationSet = docHasSyncedBlocks && isPerfExperimentOn ? buildStatusDecorations(instance.doc, syncBlockStore, initIsOffline, initIsViewMode, initIsDragging) :
|
|
411
|
+
var initStatusDecorationSet = docHasSyncedBlocks && isPerfExperimentOn ? buildStatusDecorations(instance.doc, syncBlockStore, initIsOffline, initIsViewMode, initIsDragging) : _view2.DecorationSet.empty;
|
|
400
412
|
return {
|
|
401
413
|
selectionDecorationSet: (0, _selectionDecorations.calculateDecorations)(instance.doc, instance.selection, instance.schema),
|
|
402
414
|
activeFlag: false,
|
|
@@ -482,7 +494,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
482
494
|
if (isPerfExperimentOn) {
|
|
483
495
|
if (!nextHasSyncedBlocks) {
|
|
484
496
|
// No synced blocks → keep empty status decorations
|
|
485
|
-
nextStatusDecorationSet =
|
|
497
|
+
nextStatusDecorationSet = _view2.DecorationSet.empty;
|
|
486
498
|
} else {
|
|
487
499
|
var _api$connectivity4, _api$editorViewMode3, _api$userIntent3;
|
|
488
500
|
// Read current shared-state signals
|
|
@@ -570,7 +582,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
570
582
|
decorations: function decorations(state) {
|
|
571
583
|
var currentPluginState = syncedBlockPluginKey.getState(state);
|
|
572
584
|
if (!currentPluginState) {
|
|
573
|
-
return
|
|
585
|
+
return _view2.DecorationSet.empty;
|
|
574
586
|
}
|
|
575
587
|
var selectionDecorationSet = currentPluginState.selectionDecorationSet,
|
|
576
588
|
statusDecorationSet = currentPluginState.statusDecorationSet,
|
|
@@ -598,7 +610,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
598
610
|
// omit selection decorations (matches old behaviour).
|
|
599
611
|
var statusDecorations = statusDecorationSet.find();
|
|
600
612
|
if (statusDecorations.length === 0) {
|
|
601
|
-
return hasFocus ? selectionDecorationSet :
|
|
613
|
+
return hasFocus ? selectionDecorationSet : _view2.DecorationSet.empty;
|
|
602
614
|
} else {
|
|
603
615
|
return hasFocus ? selectionDecorationSet.add(state.doc, statusDecorations) : statusDecorationSet;
|
|
604
616
|
}
|
|
@@ -618,22 +630,22 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
618
630
|
var dragDecorations = [];
|
|
619
631
|
state.doc.descendants(function (node, pos) {
|
|
620
632
|
if (node.type.name === 'bodiedSyncBlock' && isOffline) {
|
|
621
|
-
offlineDecorations.push(
|
|
633
|
+
offlineDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
622
634
|
class: _syncBlock.SyncBlockStateCssClassName.disabledClassName
|
|
623
635
|
}));
|
|
624
636
|
}
|
|
625
637
|
if (_syncBlockStore.isSyncBlock(node) && isViewMode) {
|
|
626
|
-
viewModeDecorations.push(
|
|
638
|
+
viewModeDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
627
639
|
class: _syncBlock.SyncBlockStateCssClassName.viewModeClassName
|
|
628
640
|
}));
|
|
629
641
|
}
|
|
630
642
|
if (node.type.name === 'bodiedSyncBlock' && _syncBlockStore.sourceManager.isPendingCreation(node.attrs.resourceId)) {
|
|
631
|
-
loadingDecorations.push(
|
|
643
|
+
loadingDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
632
644
|
class: _syncBlock.SyncBlockStateCssClassName.creationLoadingClassName
|
|
633
645
|
}));
|
|
634
646
|
}
|
|
635
647
|
if (isDragging && _syncBlockStore.isSyncBlock(node)) {
|
|
636
|
-
dragDecorations.push(
|
|
648
|
+
dragDecorations.push(_view2.Decoration.node(pos, pos + node.nodeSize, {
|
|
637
649
|
class: _syncBlock.SyncBlockStateCssClassName.draggingClassName
|
|
638
650
|
}));
|
|
639
651
|
}
|
|
@@ -641,7 +653,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
641
653
|
if (api !== null && api !== void 0 && (_api$focus2 = api.focus) !== null && _api$focus2 !== void 0 && (_api$focus2 = _api$focus2.sharedState) !== null && _api$focus2 !== void 0 && (_api$focus2 = _api$focus2.currentState()) !== null && _api$focus2 !== void 0 && _api$focus2.hasFocus) {
|
|
642
654
|
return selectionDecorationSet.add(doc, offlineDecorations).add(doc, viewModeDecorations).add(doc, loadingDecorations).add(doc, dragDecorations);
|
|
643
655
|
} else {
|
|
644
|
-
return
|
|
656
|
+
return _view2.DecorationSet.empty.add(doc, offlineDecorations).add(doc, viewModeDecorations).add(doc, loadingDecorations).add(doc, dragDecorations);
|
|
645
657
|
}
|
|
646
658
|
}
|
|
647
659
|
},
|
|
@@ -662,6 +674,30 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
|
|
|
662
674
|
return false;
|
|
663
675
|
}
|
|
664
676
|
},
|
|
677
|
+
transformPasted: function transformPasted(slice, _view) {
|
|
678
|
+
if (!(0, _platformFeatureFlags.fg)('platform_synced_block_patch_13')) {
|
|
679
|
+
return slice;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
// Defense against bodiedSyncBlock nodes arriving via paste
|
|
683
|
+
// (e.g. drag-and-drop, cut-paste, or browser-level clipboard
|
|
684
|
+
// operations that bypass the transformCopied handler).
|
|
685
|
+
// We cannot convert to a syncBlock reference here because we don't
|
|
686
|
+
// know the source page's parentId (generateResourceIdForReference
|
|
687
|
+
// would use the current page's parentId which is wrong).
|
|
688
|
+
// Instead, strip the bodiedSyncBlock wrapper and keep only the
|
|
689
|
+
// inner content to prevent createBlock being called with the
|
|
690
|
+
// wrong parentId.
|
|
691
|
+
return (0, _utils.mapSlice)(slice, function (node) {
|
|
692
|
+
if (node.type.name === 'bodiedSyncBlock' && node.attrs.resourceId) {
|
|
693
|
+
// Return the inner content without the sync block wrapper.
|
|
694
|
+
// This is the same behavior as when a partial selection of
|
|
695
|
+
// a bodiedSyncBlock is copied (see transformCopied line 937).
|
|
696
|
+
return node.content;
|
|
697
|
+
}
|
|
698
|
+
return node;
|
|
699
|
+
});
|
|
700
|
+
},
|
|
665
701
|
transformCopied: function transformCopied(slice, _ref9) {
|
|
666
702
|
var state = _ref9.state;
|
|
667
703
|
var pluginState = syncedBlockPluginKey.getState(state);
|
|
@@ -11,6 +11,7 @@ import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/tra
|
|
|
11
11
|
import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
12
12
|
import { convertPMNodesToSyncBlockNodes, rebaseTransaction } from '@atlaskit/editor-synced-block-provider';
|
|
13
13
|
import { getSourceProductFromResourceIdSafe } from '@atlaskit/editor-synced-block-provider/utils';
|
|
14
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
14
15
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
15
16
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
16
17
|
import { bodiedSyncBlockNodeView, bodiedSyncBlockNodeViewOld } from '../nodeviews/bodiedSyncedBlock';
|
|
@@ -129,6 +130,7 @@ const filterTransactionOnline = ({
|
|
|
129
130
|
// events this lets us triangulate cross-product paste behaviour without standing up a
|
|
130
131
|
// dedicated `cross_product_paste` event subject.
|
|
131
132
|
const isPaste = Boolean((_tr$getMeta = tr.getMeta('paste')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : tr.getMeta('uiEvent') === 'paste');
|
|
133
|
+
const isPasteOrDrop = isPaste || tr.getMeta('uiEvent') === 'drop';
|
|
132
134
|
syncBlockAdded.forEach(syncBlock => {
|
|
133
135
|
var _api$analytics2, _api$analytics2$actio;
|
|
134
136
|
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$actio = _api$analytics2.actions) === null || _api$analytics2$actio === void 0 ? void 0 : _api$analytics2$actio.fireAnalyticsEvent({
|
|
@@ -156,6 +158,16 @@ const filterTransactionOnline = ({
|
|
|
156
158
|
// After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
|
|
157
159
|
return true;
|
|
158
160
|
}
|
|
161
|
+
|
|
162
|
+
// Defense-in-depth: if a bodiedSyncBlock arrives via paste or drag-and-drop,
|
|
163
|
+
// it may have bypassed transformCopied (e.g. cut, browser clipboard).
|
|
164
|
+
// Do not call createBlock — it would use this page's parentId which may
|
|
165
|
+
// be wrong. The bodiedSyncBlock content will still be inserted but will
|
|
166
|
+
// not be registered as a source block in Block Service, which is safer
|
|
167
|
+
// than creating a zombie block under the wrong ARI.
|
|
168
|
+
if (isPasteOrDrop && fg('platform_synced_block_patch_13')) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
159
171
|
handleBodiedSyncBlockCreation(bodiedSyncBlockAdded, state, api);
|
|
160
172
|
return true;
|
|
161
173
|
}
|
|
@@ -630,6 +642,30 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
630
642
|
return false;
|
|
631
643
|
}
|
|
632
644
|
},
|
|
645
|
+
transformPasted: (slice, _view) => {
|
|
646
|
+
if (!fg('platform_synced_block_patch_13')) {
|
|
647
|
+
return slice;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
// Defense against bodiedSyncBlock nodes arriving via paste
|
|
651
|
+
// (e.g. drag-and-drop, cut-paste, or browser-level clipboard
|
|
652
|
+
// operations that bypass the transformCopied handler).
|
|
653
|
+
// We cannot convert to a syncBlock reference here because we don't
|
|
654
|
+
// know the source page's parentId (generateResourceIdForReference
|
|
655
|
+
// would use the current page's parentId which is wrong).
|
|
656
|
+
// Instead, strip the bodiedSyncBlock wrapper and keep only the
|
|
657
|
+
// inner content to prevent createBlock being called with the
|
|
658
|
+
// wrong parentId.
|
|
659
|
+
return mapSlice(slice, node => {
|
|
660
|
+
if (node.type.name === 'bodiedSyncBlock' && node.attrs.resourceId) {
|
|
661
|
+
// Return the inner content without the sync block wrapper.
|
|
662
|
+
// This is the same behavior as when a partial selection of
|
|
663
|
+
// a bodiedSyncBlock is copied (see transformCopied line 937).
|
|
664
|
+
return node.content;
|
|
665
|
+
}
|
|
666
|
+
return node;
|
|
667
|
+
});
|
|
668
|
+
},
|
|
633
669
|
transformCopied: (slice, {
|
|
634
670
|
state
|
|
635
671
|
}) => {
|
|
@@ -19,6 +19,7 @@ import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/tra
|
|
|
19
19
|
import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
20
20
|
import { convertPMNodesToSyncBlockNodes, rebaseTransaction } from '@atlaskit/editor-synced-block-provider';
|
|
21
21
|
import { getSourceProductFromResourceIdSafe } from '@atlaskit/editor-synced-block-provider/utils';
|
|
22
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
22
23
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
23
24
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
24
25
|
import { bodiedSyncBlockNodeView, bodiedSyncBlockNodeViewOld } from '../nodeviews/bodiedSyncedBlock';
|
|
@@ -146,6 +147,7 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
146
147
|
// events this lets us triangulate cross-product paste behaviour without standing up a
|
|
147
148
|
// dedicated `cross_product_paste` event subject.
|
|
148
149
|
var isPaste = Boolean((_tr$getMeta = tr.getMeta('paste')) !== null && _tr$getMeta !== void 0 ? _tr$getMeta : tr.getMeta('uiEvent') === 'paste');
|
|
150
|
+
var isPasteOrDrop = isPaste || tr.getMeta('uiEvent') === 'drop';
|
|
149
151
|
syncBlockAdded.forEach(function (syncBlock) {
|
|
150
152
|
var _api$analytics2;
|
|
151
153
|
api === null || api === void 0 || (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 || (_api$analytics2 = _api$analytics2.actions) === null || _api$analytics2 === void 0 || _api$analytics2.fireAnalyticsEvent({
|
|
@@ -173,6 +175,16 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
173
175
|
// After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
|
|
174
176
|
return true;
|
|
175
177
|
}
|
|
178
|
+
|
|
179
|
+
// Defense-in-depth: if a bodiedSyncBlock arrives via paste or drag-and-drop,
|
|
180
|
+
// it may have bypassed transformCopied (e.g. cut, browser clipboard).
|
|
181
|
+
// Do not call createBlock — it would use this page's parentId which may
|
|
182
|
+
// be wrong. The bodiedSyncBlock content will still be inserted but will
|
|
183
|
+
// not be registered as a source block in Block Service, which is safer
|
|
184
|
+
// than creating a zombie block under the wrong ARI.
|
|
185
|
+
if (isPasteOrDrop && fg('platform_synced_block_patch_13')) {
|
|
186
|
+
return true;
|
|
187
|
+
}
|
|
176
188
|
handleBodiedSyncBlockCreation(bodiedSyncBlockAdded, state, api);
|
|
177
189
|
return true;
|
|
178
190
|
}
|
|
@@ -655,6 +667,30 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
655
667
|
return false;
|
|
656
668
|
}
|
|
657
669
|
},
|
|
670
|
+
transformPasted: function transformPasted(slice, _view) {
|
|
671
|
+
if (!fg('platform_synced_block_patch_13')) {
|
|
672
|
+
return slice;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Defense against bodiedSyncBlock nodes arriving via paste
|
|
676
|
+
// (e.g. drag-and-drop, cut-paste, or browser-level clipboard
|
|
677
|
+
// operations that bypass the transformCopied handler).
|
|
678
|
+
// We cannot convert to a syncBlock reference here because we don't
|
|
679
|
+
// know the source page's parentId (generateResourceIdForReference
|
|
680
|
+
// would use the current page's parentId which is wrong).
|
|
681
|
+
// Instead, strip the bodiedSyncBlock wrapper and keep only the
|
|
682
|
+
// inner content to prevent createBlock being called with the
|
|
683
|
+
// wrong parentId.
|
|
684
|
+
return mapSlice(slice, function (node) {
|
|
685
|
+
if (node.type.name === 'bodiedSyncBlock' && node.attrs.resourceId) {
|
|
686
|
+
// Return the inner content without the sync block wrapper.
|
|
687
|
+
// This is the same behavior as when a partial selection of
|
|
688
|
+
// a bodiedSyncBlock is copied (see transformCopied line 937).
|
|
689
|
+
return node.content;
|
|
690
|
+
}
|
|
691
|
+
return node;
|
|
692
|
+
});
|
|
693
|
+
},
|
|
658
694
|
transformCopied: function transformCopied(slice, _ref9) {
|
|
659
695
|
var state = _ref9.state;
|
|
660
696
|
var pluginState = syncedBlockPluginKey.getState(state);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-synced-block",
|
|
3
|
-
"version": "8.4.
|
|
3
|
+
"version": "8.4.3",
|
|
4
4
|
"description": "SyncedBlock plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"atlaskit:src": "src/index.ts",
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@atlaskit/adf-schema": "^52.14.0",
|
|
32
|
-
"@atlaskit/button": "23.11.
|
|
33
|
-
"@atlaskit/dropdown-menu": "16.9.
|
|
32
|
+
"@atlaskit/button": "23.11.8",
|
|
33
|
+
"@atlaskit/dropdown-menu": "16.9.5",
|
|
34
34
|
"@atlaskit/editor-json-transformer": "^8.32.0",
|
|
35
35
|
"@atlaskit/editor-plugin-analytics": "^10.1.0",
|
|
36
36
|
"@atlaskit/editor-plugin-block-menu": "^9.2.0",
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
"@atlaskit/editor-synced-block-provider": "^6.6.0",
|
|
47
47
|
"@atlaskit/editor-toolbar": "^1.7.0",
|
|
48
48
|
"@atlaskit/flag": "^17.12.0",
|
|
49
|
-
"@atlaskit/icon": "35.
|
|
50
|
-
"@atlaskit/icon-lab": "^6.
|
|
49
|
+
"@atlaskit/icon": "35.1.0",
|
|
50
|
+
"@atlaskit/icon-lab": "^6.10.0",
|
|
51
51
|
"@atlaskit/logo": "^20.1.0",
|
|
52
52
|
"@atlaskit/lozenge": "^13.8.0",
|
|
53
53
|
"@atlaskit/modal-dialog": "^15.2.0",
|
|
54
54
|
"@atlaskit/platform-feature-flags": "^1.1.0",
|
|
55
55
|
"@atlaskit/primitives": "^19.0.0",
|
|
56
56
|
"@atlaskit/spinner": "19.1.2",
|
|
57
|
-
"@atlaskit/tmp-editor-statsig": "^
|
|
57
|
+
"@atlaskit/tmp-editor-statsig": "^83.0.0",
|
|
58
58
|
"@atlaskit/tokens": "13.0.4",
|
|
59
59
|
"@atlaskit/tooltip": "^22.3.0",
|
|
60
60
|
"@atlaskit/visually-hidden": "^3.1.0",
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"date-fns": "^2.17.0"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"@atlaskit/editor-common": "^114.
|
|
67
|
+
"@atlaskit/editor-common": "^114.46.0",
|
|
68
68
|
"react": "^18.2.0",
|
|
69
69
|
"react-intl": "^5.25.1 || ^6.0.0 || ^7.0.0"
|
|
70
70
|
},
|