@atlaskit/editor-plugin-code-block
Version:
Code block plugin for @atlaskit/editor-core
258 lines (254 loc) • 10.8 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.copyContentToClipboardWithAnalytics = exports.copyContentToClipboard = exports.changeLanguage = void 0;
exports.createInsertCodeBlockTransaction = createInsertCodeBlockTransaction;
exports.ignoreFollowingMutations = void 0;
exports.insertCodeBlockWithAnalytics = insertCodeBlockWithAnalytics;
exports.toggleWordWrapStateForCodeBlockNode = exports.resetShouldIgnoreFollowingMutations = exports.resetCopiedState = exports.removeCodeBlockWithAnalytics = exports.removeCodeBlock = void 0;
var _analytics = require("@atlaskit/editor-common/analytics");
var _clipboard = require("@atlaskit/editor-common/clipboard");
var _codeBlock = require("@atlaskit/editor-common/code-block");
var _editorAnalytics = require("@atlaskit/editor-common/editor-analytics");
var _insert = require("@atlaskit/editor-common/insert");
var _transforms = require("@atlaskit/editor-common/transforms");
var _state = require("@atlaskit/editor-prosemirror/state");
var _utils = require("@atlaskit/editor-prosemirror/utils");
var _actions = require("../pm-plugins/actions");
var _codeBlockCopySelectionPlugin = require("../pm-plugins/codeBlockCopySelectionPlugin");
var _pluginKey = require("../pm-plugins/plugin-key");
var _transformToCodeBlock = require("../pm-plugins/transform-to-code-block");
var removeCodeBlockWithAnalytics = exports.removeCodeBlockWithAnalytics = function removeCodeBlockWithAnalytics(editorAnalyticsAPI) {
return (0, _editorAnalytics.withAnalytics)(editorAnalyticsAPI, {
action: _analytics.ACTION.DELETED,
actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
attributes: {
inputMethod: _analytics.INPUT_METHOD.FLOATING_TB
},
eventType: _analytics.EVENT_TYPE.TRACK
})(removeCodeBlock);
};
var removeCodeBlock = exports.removeCodeBlock = function removeCodeBlock(state, dispatch) {
var nodes = state.schema.nodes,
tr = state.tr;
if (dispatch) {
var removeTr = tr;
if ((0, _utils.findSelectedNodeOfType)(nodes.codeBlock)(tr.selection)) {
removeTr = (0, _utils.removeSelectedNode)(tr);
} else {
removeTr = (0, _utils.removeParentNodeOfType)(nodes.codeBlock)(tr);
}
dispatch(removeTr);
}
return true;
};
var changeLanguage = exports.changeLanguage = function changeLanguage(editorAnalyticsAPI) {
return function (language) {
return function (state, dispatch) {
var _pluginKey$getState;
var codeBlock = state.schema.nodes.codeBlock;
var pos = (_pluginKey$getState = _pluginKey.pluginKey.getState(state)) === null || _pluginKey$getState === void 0 ? void 0 : _pluginKey$getState.pos;
if (typeof pos !== 'number') {
return false;
}
var tr = state.tr.setNodeMarkup(pos, codeBlock, {
language: language
}).setMeta('scrollIntoView', false);
var selection = (0, _utils.isNodeSelection)(state.selection) ? _state.NodeSelection.create(tr.doc, pos) : tr.selection;
var result = tr.setSelection(selection);
if (dispatch) {
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
action: _analytics.ACTION.LANGUAGE_SELECTED,
actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
attributes: {
language: language
},
eventType: _analytics.EVENT_TYPE.TRACK
})(result);
dispatch(result);
}
return true;
};
};
};
var copyContentToClipboardWithAnalytics = exports.copyContentToClipboardWithAnalytics = function copyContentToClipboardWithAnalytics(editorAnalyticsAPI) {
return function (state, dispatch) {
var nodes = state.schema.nodes,
tr = state.tr;
var codeBlock = (0, _utils.findParentNodeOfType)(nodes.codeBlock)(tr.selection);
var textContent = codeBlock && codeBlock.node.textContent;
if (textContent) {
(0, _clipboard.copyToClipboard)(textContent);
var copyToClipboardTr = tr;
copyToClipboardTr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_COPIED_TO_CLIPBOARD,
data: true
});
copyToClipboardTr.setMeta(_codeBlockCopySelectionPlugin.copySelectionPluginKey, 'remove-selection');
if (editorAnalyticsAPI) {
var analyticsPayload = (0, _clipboard.getAnalyticsPayload)(state, _analytics.ACTION.COPIED);
if (analyticsPayload) {
analyticsPayload.attributes.inputMethod = _analytics.INPUT_METHOD.FLOATING_TB;
analyticsPayload.attributes.nodeType = codeBlock === null || codeBlock === void 0 ? void 0 : codeBlock.node.type.name;
editorAnalyticsAPI.attachAnalyticsEvent(analyticsPayload)(copyToClipboardTr);
}
}
if (dispatch) {
dispatch(copyToClipboardTr);
}
}
return true;
};
};
var copyContentToClipboard = exports.copyContentToClipboard = function copyContentToClipboard(state, dispatch) {
var nodes = state.schema.nodes,
tr = state.tr;
var codeBlock = (0, _utils.findParentNodeOfType)(nodes.codeBlock)(tr.selection);
var textContent = codeBlock && codeBlock.node.textContent;
if (textContent) {
(0, _clipboard.copyToClipboard)(textContent);
var copyToClipboardTr = tr;
copyToClipboardTr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_COPIED_TO_CLIPBOARD,
data: true
});
copyToClipboardTr.setMeta(_codeBlockCopySelectionPlugin.copySelectionPluginKey, 'remove-selection');
if (dispatch) {
dispatch(copyToClipboardTr);
}
}
return true;
};
var resetCopiedState = exports.resetCopiedState = function resetCopiedState(state, dispatch) {
var tr = state.tr;
var codeBlockState = _pluginKey.pluginKey.getState(state);
var resetCopiedStateTr = tr;
if (codeBlockState && codeBlockState.contentCopied) {
resetCopiedStateTr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_COPIED_TO_CLIPBOARD,
data: false
});
resetCopiedStateTr.setMeta(_codeBlockCopySelectionPlugin.copySelectionPluginKey, 'remove-selection');
if (dispatch) {
dispatch(resetCopiedStateTr);
}
} else {
var clearSelectionStateTransaction = state.tr;
clearSelectionStateTransaction.setMeta(_codeBlockCopySelectionPlugin.copySelectionPluginKey, 'remove-selection');
// note: dispatch should always be defined when called from the
// floating toolbar. Howver the Command type which floating toolbar uses
// (and resetCopiedState) uses suggests it's optional.
if (dispatch) {
dispatch(clearSelectionStateTransaction);
}
}
return true;
};
var ignoreFollowingMutations = exports.ignoreFollowingMutations = function ignoreFollowingMutations(state, dispatch) {
var tr = state.tr;
var ignoreFollowingMutationsTr = tr;
ignoreFollowingMutationsTr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS,
data: true
});
if (dispatch) {
dispatch(ignoreFollowingMutationsTr);
}
return true;
};
var resetShouldIgnoreFollowingMutations = exports.resetShouldIgnoreFollowingMutations = function resetShouldIgnoreFollowingMutations(state, dispatch) {
var tr = state.tr;
var ignoreFollowingMutationsTr = tr;
ignoreFollowingMutationsTr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_SHOULD_IGNORE_FOLLOWING_MUTATIONS,
data: false
});
if (dispatch) {
dispatch(ignoreFollowingMutationsTr);
}
return true;
};
/**
* This function creates a new transaction that inserts a code block,
* if there is text selected it will wrap the current selection if not it will
* append the codeblock to the end of the document.
*/
function createInsertCodeBlockTransaction(_ref) {
var state = _ref.state;
var tr = state.tr;
var from = state.selection.from;
var codeBlock = state.schema.nodes.codeBlock;
var grandParentNode = state.selection.$from.node(-1);
var grandParentNodeType = grandParentNode === null || grandParentNode === void 0 ? void 0 : grandParentNode.type;
var parentNodeType = state.selection.$from.parent.type;
/** We always want to append a codeBlock unless we're inserting into a paragraph
* AND it's a valid child of the grandparent node.
* Insert the current selection as codeBlock content unless it contains nodes other
* than paragraphs and inline.
*/
var canInsertCodeBlock = (0, _insert.shouldSplitSelectedNodeOnNodeInsertion)({
parentNodeType: parentNodeType,
grandParentNodeType: grandParentNodeType,
content: codeBlock.createAndFill()
}) && (0, _insert.contentAllowedInCodeBlock)(state);
if (canInsertCodeBlock) {
tr = (0, _transformToCodeBlock.transformToCodeBlockAction)(state, from, undefined);
} else {
(0, _utils.safeInsert)(codeBlock.createAndFill())(tr).scrollIntoView();
}
return tr;
}
function insertCodeBlockWithAnalytics(inputMethod, analyticsAPI) {
return (0, _editorAnalytics.withAnalytics)(analyticsAPI, {
action: _analytics.ACTION.INSERTED,
actionSubject: _analytics.ACTION_SUBJECT.DOCUMENT,
actionSubjectId: _analytics.ACTION_SUBJECT_ID.CODE_BLOCK,
attributes: {
inputMethod: inputMethod
},
eventType: _analytics.EVENT_TYPE.TRACK
})(function (state, dispatch) {
var tr = createInsertCodeBlockTransaction({
state: state
});
if (dispatch) {
dispatch(tr);
}
return true;
});
}
/**
* Add the given node to the codeBlockWrappedStates WeakMap with the toggle boolean value.
*/
var toggleWordWrapStateForCodeBlockNode = exports.toggleWordWrapStateForCodeBlockNode = function toggleWordWrapStateForCodeBlockNode(editorAnalyticsAPI) {
return function (state, dispatch) {
var _findCodeBlock;
var codeBlockNode = (_findCodeBlock = (0, _transforms.findCodeBlock)(state)) === null || _findCodeBlock === void 0 ? void 0 : _findCodeBlock.node;
var tr = state.tr;
if (!_codeBlock.codeBlockWrappedStates || !codeBlockNode) {
return false;
}
var updatedToggleState = !(0, _codeBlock.isCodeBlockWordWrapEnabled)(codeBlockNode);
_codeBlock.codeBlockWrappedStates.set(codeBlockNode, updatedToggleState);
tr.setMeta(_pluginKey.pluginKey, {
type: _actions.ACTIONS.SET_IS_WRAPPED,
data: updatedToggleState
});
if (dispatch) {
editorAnalyticsAPI === null || editorAnalyticsAPI === void 0 || editorAnalyticsAPI.attachAnalyticsEvent({
action: _analytics.ACTION.TOGGLE_CODE_BLOCK_WRAP,
actionSubject: _analytics.ACTION_SUBJECT.CODE_BLOCK,
attributes: {
platform: _analytics.PLATFORMS.WEB,
mode: _analytics.MODE.EDITOR,
wordWrapEnabled: updatedToggleState,
codeBlockNodeSize: codeBlockNode.nodeSize
},
eventType: _analytics.EVENT_TYPE.TRACK
})(tr);
dispatch(tr);
}
return true;
};
};