@atlaskit/editor-plugin-synced-block
Version:
SyncedBlock plugin for @atlaskit/editor-core
280 lines (274 loc) • 13.4 kB
JavaScript
"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);
};