UNPKG

@atlaskit/editor-plugin-synced-block

Version:

SyncedBlock plugin for @atlaskit/editor-core

280 lines (274 loc) 13.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.unsync = exports.removeSyncedBlockAtPos = exports.removeSyncedBlock = exports.editSyncedBlockSource = exports.createSyncedBlock = exports.copySyncedBlockReferenceToClipboardEditorCommand = exports.copySyncedBlockReferenceToClipboard = void 0; var _schemaDefault = require("@atlaskit/adf-schema/schema-default"); var _analytics = require("@atlaskit/editor-common/analytics"); var _copyButton = require("@atlaskit/editor-common/copy-button"); var _model = require("@atlaskit/editor-prosemirror/model"); var _state = require("@atlaskit/editor-prosemirror/state"); var _utils = require("@atlaskit/editor-prosemirror/utils"); var _main = require("../pm-plugins/main"); var _utils2 = require("../pm-plugins/utils/utils"); var _types = require("../types"); var _utils3 = require("./utils"); var createSyncedBlock = exports.createSyncedBlock = function createSyncedBlock(_ref) { var tr = _ref.tr, syncBlockStore = _ref.syncBlockStore, typeAheadInsert = _ref.typeAheadInsert, fireAnalyticsEvent = _ref.fireAnalyticsEvent; var _tr$doc$type$schema$n = tr.doc.type.schema.nodes, bodiedSyncBlock = _tr$doc$type$schema$n.bodiedSyncBlock, paragraph = _tr$doc$type$schema$n.paragraph; // If the selection is empty, we want to insert the sync block on a new line if (tr.selection.empty) { var attrs = syncBlockStore.sourceManager.generateBodiedSyncBlockAttrs(); var paragraphNode = paragraph.createAndFill({}); var newBodiedSyncBlockNode = bodiedSyncBlock.createAndFill(attrs, paragraphNode ? [paragraphNode] : []); if (!newBodiedSyncBlockNode) { fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 || fireAnalyticsEvent({ action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE, attributes: { error: 'Create and fill for empty content failed' }, eventType: _analytics.EVENT_TYPE.OPERATIONAL }); return false; } if (typeAheadInsert) { tr = typeAheadInsert(newBodiedSyncBlockNode); } else { tr = (0, _utils.safeInsert)(newBodiedSyncBlockNode)(tr).scrollIntoView(); } } else { var conversionInfo = (0, _utils2.canBeConvertedToSyncBlock)(tr.selection); if (!conversionInfo) { fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 || fireAnalyticsEvent({ action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE, attributes: { error: 'Content cannot be converted to sync block' }, eventType: _analytics.EVENT_TYPE.OPERATIONAL }); return false; } var _attrs = syncBlockStore.sourceManager.generateBodiedSyncBlockAttrs(); var _newBodiedSyncBlockNode = bodiedSyncBlock.createAndFill(_attrs, conversionInfo.contentToInclude); if (!_newBodiedSyncBlockNode) { fireAnalyticsEvent === null || fireAnalyticsEvent === void 0 || fireAnalyticsEvent({ action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_CREATE, attributes: { error: 'Create and fill for content failed' }, eventType: _analytics.EVENT_TYPE.OPERATIONAL }); return false; } tr.replaceWith(conversionInfo.from, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView(); // set selection to the start of the previous selection for the position taken up by the start of the new synced block tr.setSelection(_state.TextSelection.create(tr.doc, conversionInfo.from)); } return tr; }; var copySyncedBlockReferenceToClipboardEditorCommand = exports.copySyncedBlockReferenceToClipboardEditorCommand = function copySyncedBlockReferenceToClipboardEditorCommand(syncBlockStore, inputMethod, api) { return function (_ref2) { var tr = _ref2.tr; if (copySyncedBlockReferenceToClipboardInternal(tr.doc.type.schema, tr.selection, syncBlockStore, inputMethod, api)) { return tr; } return null; }; }; var copySyncedBlockReferenceToClipboard = exports.copySyncedBlockReferenceToClipboard = function copySyncedBlockReferenceToClipboard(syncBlockStore, inputMethod, api) { return function (state, _dispatch, _view) { return copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection, syncBlockStore, inputMethod, api); }; }; var copySyncedBlockReferenceToClipboardInternal = function copySyncedBlockReferenceToClipboardInternal(schema, selection, syncBlockStore, inputMethod, api) { var syncBlockFindResult = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(schema, selection); if (!syncBlockFindResult) { var _api$analytics; api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || (_api$analytics = _api$analytics.actions) === null || _api$analytics === void 0 || _api$analytics.fireAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_COPY, attributes: { error: 'No sync block found in selection', inputMethod: inputMethod } }); return false; } var isBodiedSyncBlock = (0, _utils2.isBodiedSyncBlockNode)(syncBlockFindResult.node, schema.nodes.bodiedSyncBlock); var referenceSyncBlockNode = null; if (isBodiedSyncBlock) { var syncBlock = schema.nodes.syncBlock; // create sync block reference node referenceSyncBlockNode = syncBlock.createAndFill({ resourceId: syncBlockStore.referenceManager.generateResourceIdForReference(syncBlockFindResult.node.attrs.resourceId) }); if (!referenceSyncBlockNode) { var _api$analytics2; 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({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_COPY, attributes: { error: 'Failed to create reference sync block node', resourceId: syncBlockFindResult.node.attrs.resourceId, inputMethod: inputMethod } }); return false; } } else { referenceSyncBlockNode = syncBlockFindResult.node; } if (!referenceSyncBlockNode) { var _api$analytics3; api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || (_api$analytics3 = _api$analytics3.actions) === null || _api$analytics3 === void 0 || _api$analytics3.fireAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_COPY, attributes: { error: 'No reference sync block node available', inputMethod: inputMethod } }); return false; } var domNode = (0, _copyButton.toDOM)(referenceSyncBlockNode, schema); (0, _copyButton.copyDomNode)(domNode, referenceSyncBlockNode.type, selection); (0, _utils2.deferDispatch)(function () { api === null || api === void 0 || api.core.actions.execute(function (_ref3) { var _api$analytics4; var tr = _ref3.tr; api === null || api === void 0 || (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 || (_api$analytics4 = _api$analytics4.actions) === null || _api$analytics4 === void 0 || _api$analytics4.fireAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.COPIED, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_COPY, attributes: { resourceId: referenceSyncBlockNode.attrs.resourceId, inputMethod: inputMethod } }); return tr.setMeta(_main.syncedBlockPluginKey, { activeFlag: { id: _types.FLAG_ID.SYNC_BLOCK_COPIED } }); }); }); return true; }; var editSyncedBlockSource = exports.editSyncedBlockSource = function editSyncedBlockSource(syncBlockStore, api) { return function (state, dispatch, _view) { var _syncBlock$node; var syncBlock = (0, _utils2.findSyncBlock)(state.schema, state.selection); var resourceId = syncBlock === null || syncBlock === void 0 || (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 || (_syncBlock$node = _syncBlock$node.attrs) === null || _syncBlock$node === void 0 ? void 0 : _syncBlock$node.resourceId; if (!resourceId) { return false; } var syncBlockURL = syncBlockStore.referenceManager.getSyncBlockURL(resourceId); if (syncBlockURL) { var _api$analytics5; api === null || api === void 0 || (_api$analytics5 = api.analytics) === null || _api$analytics5 === void 0 || _api$analytics5.actions.fireAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.SYNCED_BLOCK_EDIT_SOURCE, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_SOURCE_URL, attributes: { resourceId: resourceId } }); window.open(syncBlockURL, '_blank'); } else { var _api$analytics6; var tr = state.tr; api === null || api === void 0 || (_api$analytics6 = api.analytics) === null || _api$analytics6 === void 0 || (_api$analytics6 = _api$analytics6.actions) === null || _api$analytics6 === void 0 || _api$analytics6.attachAnalyticsEvent({ eventType: _analytics.EVENT_TYPE.OPERATIONAL, action: _analytics.ACTION.ERROR, actionSubject: _analytics.ACTION_SUBJECT.SYNCED_BLOCK, actionSubjectId: _analytics.ACTION_SUBJECT_ID.SYNCED_BLOCK_SOURCE_URL, attributes: { error: 'No URL resolved for synced block' } })(tr); dispatch === null || dispatch === void 0 || dispatch(tr); } return true; }; }; var removeSyncedBlock = exports.removeSyncedBlock = function removeSyncedBlock(api) { return function (state, dispatch, _view) { var nodes = state.schema.nodes, tr = state.tr; if (!dispatch) { return false; } var removeTr = tr; if ((0, _utils.findSelectedNodeOfType)(nodes.syncBlock)(tr.selection) || (0, _utils.findSelectedNodeOfType)(nodes.bodiedSyncBlock)(tr.selection)) { removeTr = (0, _utils.removeSelectedNode)(tr); } else { removeTr = (0, _utils.removeParentNodeOfType)(nodes.bodiedSyncBlock)(tr); } if (!removeTr) { return false; } dispatch(removeTr); api === null || api === void 0 || api.core.actions.focus(); return true; }; }; var removeSyncedBlockAtPos = exports.removeSyncedBlockAtPos = function removeSyncedBlockAtPos(api, pos) { api === null || api === void 0 || api.core.actions.execute(function (_ref4) { var tr = _ref4.tr; var node = tr.doc.nodeAt(pos); if ((node === null || node === void 0 ? void 0 : node.type.name) === 'syncBlock') { var _node$nodeSize; return tr.replace(pos, pos + ((_node$nodeSize = node === null || node === void 0 ? void 0 : node.nodeSize) !== null && _node$nodeSize !== void 0 ? _node$nodeSize : 0)); } return tr; }); }; /** * Deletes (bodied)SyncBlock node and paste its content to the editor */ var unsync = exports.unsync = function unsync(storeManager, isBodiedSyncBlock, view) { var _storeManager$referen; if (!view) { return false; } var state = view.state; var syncBlock = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(state.schema, state.selection); if (!syncBlock) { return false; } if (isBodiedSyncBlock) { var content = syncBlock === null || syncBlock === void 0 ? void 0 : syncBlock.node.content; var tr = state.tr; tr.replaceWith(syncBlock.pos, syncBlock.pos + syncBlock.node.nodeSize, content).setMeta('deletionReason', 'source-block-unsynced'); view.dispatch(tr); return true; } // handle syncBlock unsync var syncBlockContent = (_storeManager$referen = storeManager.referenceManager.getFromCache(syncBlock.node.attrs.resourceId)) === null || _storeManager$referen === void 0 || (_storeManager$referen = _storeManager$referen.data) === null || _storeManager$referen === void 0 ? void 0 : _storeManager$referen.content; if (!syncBlockContent) { return false; } // use defaultSchema for serialization so we can serialize any type of nodes and marks despite current editor's schema might not allow it var contentFragment = _model.Fragment.fromJSON(_schemaDefault.defaultSchema, syncBlockContent); var contentDOM = _model.DOMSerializer.fromSchema(_schemaDefault.defaultSchema).serializeFragment(contentFragment); return (0, _utils3.pasteSyncBlockHTMLContent)(contentDOM, view); };