UNPKG

@atlaskit/editor-plugin-block-menu

Version:

BlockMenu plugin for @atlaskit/editor-core

202 lines (200 loc) • 11.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.transformNode = void 0; var _expand2 = require("@atlaskit/editor-common/expand"); var _performanceMeasures = require("@atlaskit/editor-common/performance-measures"); var _utils = require("@atlaskit/editor-common/selection/utils"); var _model = require("@atlaskit/editor-prosemirror/model"); var _state = require("@atlaskit/editor-prosemirror/state"); var _transform = require("@atlaskit/editor-prosemirror/transform"); var _cellSelection = require("@atlaskit/editor-tables/cell-selection"); var _isExperimentEnabled = require("@atlaskit/platform-feature-experiments/is-experiment-enabled"); var _transformSource = require("../editor-actions/transformSource"); var _isNestedNode = require("../ui/utils/isNestedNode"); var _isEmptyLine = require("./is-empty-line"); var _transformAnalytics = require("./transform-analytics"); var _transform2 = require("./transform-node-utils/transform"); var _utils2 = require("./transform-node-utils/utils"); var transformNode = exports.transformNode = function transformNode(api, transformRegistry) { return function (targetType, metadata) { return function (_ref) { var _api$blockControls; var tr = _ref.tr; var preservedSelection = api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.sharedState.currentState()) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.preservedSelection; if (!preservedSelection) { return tr; } var isSmallTextTransform = (metadata === null || metadata === void 0 ? void 0 : metadata.targetTypeName) === 'smallText'; var isTextFormattingTransform = ((metadata === null || metadata === void 0 ? void 0 : metadata.marksToAdd) !== undefined || (metadata === null || metadata === void 0 ? void 0 : metadata.marksToRemove) !== undefined) && (0, _isExperimentEnabled.isExperimentEnabled)('platform_editor_block_menu_small_text'); if (isSmallTextTransform && !isTextFormattingTransform) { return null; } var analytics = (0, _transformAnalytics.createTransformAnalytics)(api, tr, preservedSelection); var _expandSelectionToBlo = (0, _utils.expandSelectionToBlockRange)(preservedSelection), $from = _expandSelectionToBlo.$from, $to = _expandSelectionToBlo.$to, range = _expandSelectionToBlo.range; var sourceNode = (0, _transformSource.getSingleTransformSourceNode)(preservedSelection, range); if ((0, _transformSource.isExtensionTransformSource)(sourceNode)) { var _metadata$targetTypeN; var context = { source: sourceNode.toJSON(), targetTypeName: (_metadata$targetTypeN = metadata === null || metadata === void 0 ? void 0 : metadata.targetTypeName) !== null && _metadata$targetTypeN !== void 0 ? _metadata$targetTypeN : targetType.name }; var resolution = transformRegistry === null || transformRegistry === void 0 ? void 0 : transformRegistry.resolve(context); if (!resolution || resolution.status === 'unsupported') { return tr; } var _measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now()); (0, _performanceMeasures.startMeasure)(_measureId); try { var _api$blockControls2, _api$blockControls3; var transformResult = resolution.transform.transform(context); if (!transformResult) { (0, _performanceMeasures.stopMeasure)(_measureId); return tr; } if (!Array.isArray(transformResult.output) || transformResult.output.length === 0) { throw new Error('Block menu transform returned no output'); } var resultNodes = transformResult.output.map(function (nodeAdf) { var node = _model.Node.fromJSON(tr.doc.type.schema, nodeAdf); node.check(); return node; }); if (!range || !range.parent.canReplace(range.startIndex, range.endIndex, _model.Fragment.from(resultNodes))) { throw new Error('Block menu transform output is invalid at the selected position'); } var sliceStart = $from.pos; tr.replaceWith(sliceStart, $to.pos, resultNodes); var insertedNode = tr.doc.nodeAt(sliceStart); var nextSelection = insertedNode && _state.NodeSelection.isSelectable(insertedNode) ? _state.NodeSelection.create(tr.doc, sliceStart) : _state.Selection.near(tr.doc.resolve(sliceStart)); tr.setSelection(nextSelection); api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.stopPreservingSelection()({ tr: tr }); api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || _api$blockControls3.commands.toggleBlockMenu({ closeMenu: true })({ tr: tr }); var _tr$doc$type$schema$n = tr.doc.type.schema.nodes, expand = _tr$doc$type$schema$n.expand, nestedExpand = _tr$doc$type$schema$n.nestedExpand; resultNodes.forEach(function (node) { if (node.type === expand || node.type === nestedExpand) { _expand2.expandedState.set(node, true); } }); (0, _performanceMeasures.stopMeasure)(_measureId, function (duration, startTime) { analytics.transformed(duration, startTime, { isNested: (0, _isNestedNode.isNestedNode)(preservedSelection, ''), isSuggested: Boolean(metadata === null || metadata === void 0 ? void 0 : metadata.isSuggested), outputNodesCount: resultNodes.length, sourceNodes: [sourceNode], targetNodeType: targetType.name }); }); } catch (error) { (0, _performanceMeasures.stopMeasure)(_measureId); analytics.errored(error, [sourceNode], targetType.name); } return tr; } var measureId = "transformNode_".concat(targetType.name, "_").concat(Date.now()); (0, _performanceMeasures.startMeasure)(measureId); var docBeforeTransform = tr.doc; var nodes = tr.doc.type.schema.nodes; var selectedParent = $from.parent; var isParentLayout = selectedParent.type === nodes.layoutColumn; var isNested = (0, _isNestedNode.isNestedNode)(preservedSelection, '') && !isParentLayout; var isList = (0, _utils2.isListNode)(selectedParent); var sourceNodes = (0, _utils.getSourceNodesFromSelectionRange)(tr, preservedSelection); var isSuggested = Boolean(metadata === null || metadata === void 0 ? void 0 : metadata.isSuggested); try { var _api$blockControls6; var _resultNodes = (0, _transform2.convertNodesToTargetType)({ sourceNodes: sourceNodes, targetNodeType: targetType, schema: tr.doc.type.schema, isNested: isNested, targetAttrs: metadata === null || metadata === void 0 ? void 0 : metadata.targetAttrs, marksToAdd: isTextFormattingTransform ? metadata === null || metadata === void 0 ? void 0 : metadata.marksToAdd : undefined, marksToRemove: isTextFormattingTransform ? metadata === null || metadata === void 0 ? void 0 : metadata.marksToRemove : undefined, parentNode: selectedParent }); var content = _resultNodes.length > 0 ? _resultNodes : sourceNodes; var _sliceStart = isList ? $from.pos - 1 : $from.pos; var _expand = nodes.expand, _nestedExpand = nodes.nestedExpand; content.forEach(function (node) { if (node.type === _expand || node.type === _nestedExpand) { _expand2.expandedState.set(node, true); } }); if (preservedSelection instanceof _state.NodeSelection && preservedSelection.node.type === nodes.mediaSingle) { var _api$blockControls4; // when node is media single, use tr.replaceWith freeze editor, if modify position, tr.replaceWith creates duplicats var deleteFrom = $from.pos; var deleteTo = $to.pos; tr.delete(deleteFrom, deleteTo); // After deletion, recalculate the insertion position to ensure it's valid // especially when mediaSingle with caption is at the bottom of the document var insertPos = Math.min(deleteFrom, tr.doc.content.size); tr.insert(insertPos, content); // when we replace and insert content, we need to manually map the preserved selection // through the transaction, otherwise it will treat the selection as having been deleted // and stop preserving it var oldSize = sourceNodes.reduce(function (sum, node) { return sum + node.nodeSize; }, 0); var newSize = content.reduce(function (sum, node) { return sum + node.nodeSize; }, 0); api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || _api$blockControls4.commands.mapPreservedSelection(new _transform.Mapping([new _transform.StepMap([0, oldSize, newSize])]))({ tr: tr }); } else { tr.replaceWith(_sliceStart, $to.pos, content); } if (isTextFormattingTransform && tr.doc.eq(docBeforeTransform)) { (0, _performanceMeasures.stopMeasure)(measureId); return null; } if (preservedSelection instanceof _cellSelection.CellSelection) { var _insertedNode = tr.doc.nodeAt($from.pos); var isSelectable = _insertedNode && _state.NodeSelection.isSelectable(_insertedNode); if (isSelectable) { var _api$blockControls5; var nodeSelection = _state.NodeSelection.create(tr.doc, $from.pos); tr.setSelection(nodeSelection); api === null || api === void 0 || (_api$blockControls5 = api.blockControls) === null || _api$blockControls5 === void 0 || _api$blockControls5.commands.startPreservingSelection()({ tr: tr }); } } api === null || api === void 0 || (_api$blockControls6 = api.blockControls) === null || _api$blockControls6 === void 0 || _api$blockControls6.commands.toggleBlockMenu({ closeMenu: true })({ tr: tr }); (0, _performanceMeasures.stopMeasure)(measureId, function (duration, startTime) { analytics.transformed(duration, startTime, { isEmptyLine: (0, _isEmptyLine.isEmptyLine)(sourceNodes), isNested: isNested, isSuggested: isSuggested, outputNodesCount: content.length, sourceNodes: sourceNodes, targetNodeType: isSmallTextTransform ? 'smallText' : targetType.name }); }); } catch (error) { (0, _performanceMeasures.stopMeasure)(measureId); analytics.errored(error, sourceNodes, targetType.name); } return tr; }; }; };