UNPKG

@atlaskit/editor-plugin-block-menu

Version:

BlockMenu plugin for @atlaskit/editor-core

155 lines (150 loc) 6.18 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isTextNode = exports.isListNode = exports.getTargetNodeTypeNameInContext = exports.getSelectedNode = exports.getBlockNodesInRange = exports.createTextContent = exports.convertTextNodeToParagraph = exports.convertNestedExpandToExpand = exports.convertExpandToNestedExpand = void 0; var _state = require("@atlaskit/editor-prosemirror/state"); var _utils = require("@atlaskit/editor-prosemirror/utils"); var _editorTables = require("@atlaskit/editor-tables"); var _types = require("./types"); /** * Determines if a node is a text node (heading or paragraph). * Text nodes can have their content converted to paragraphs when they can't be wrapped directly. */ var isTextNode = exports.isTextNode = function isTextNode(node) { var category = _types.NODE_CATEGORY_BY_TYPE[node.type.name]; return category === 'text'; }; var isListNode = exports.isListNode = function isListNode(node) { return ['bulletList', 'orderedList', 'taskList'].includes(node.type.name); }; var getSelectedNode = exports.getSelectedNode = function getSelectedNode(selection) { if (selection instanceof _state.NodeSelection) { return { node: selection.node, pos: selection.$from.pos, start: 0, // ? depth: selection.$from.depth }; } if (selection instanceof _editorTables.CellSelection) { var tableSelected = (0, _utils.findParentNodeOfType)(selection.$from.doc.type.schema.nodes.table)(selection); return tableSelected; } if (selection instanceof _state.TextSelection) { var _selection$$from$doc$ = selection.$from.doc.type.schema.nodes, blockquote = _selection$$from$doc$.blockquote, bulletList = _selection$$from$doc$.bulletList, orderedList = _selection$$from$doc$.orderedList, taskList = _selection$$from$doc$.taskList, codeBlock = _selection$$from$doc$.codeBlock, paragraph = _selection$$from$doc$.paragraph, heading = _selection$$from$doc$.heading; var quoteSelected = (0, _utils.findParentNodeOfType)([blockquote])(selection); if (quoteSelected) { return quoteSelected; } var codeBlockSelected = (0, _utils.findParentNodeOfType)([codeBlock])(selection); if (codeBlockSelected) { return codeBlockSelected; } var listSelected = (0, _utils.findParentNodeOfType)([bulletList, taskList, orderedList])(selection); if (listSelected) { return listSelected; } var paragraphOrHeading = (0, _utils.findParentNodeOfType)([paragraph, heading])(selection); if (paragraphOrHeading) { return paragraphOrHeading; } } return undefined; }; var getTargetNodeTypeNameInContext = exports.getTargetNodeTypeNameInContext = function getTargetNodeTypeNameInContext(nodeTypeName, isNested, parentNode) { if (parentNode && isNested && (parentNode.type.name === 'layoutColumn' || parentNode.type.name === 'bodiedSyncBlock')) { return nodeTypeName; } if (nodeTypeName === 'expand' && isNested) { return 'nestedExpand'; } return nodeTypeName; }; /** * Converts a nestedExpand to a regular expand node. * NestedExpands can only exist inside expands, so when breaking out or placing * in containers that don't support nesting, they must be converted. */ var convertNestedExpandToExpand = exports.convertNestedExpandToExpand = function convertNestedExpandToExpand(node, schema) { var _node$attrs; var expandType = schema.nodes.expand; if (!expandType) { return null; } return expandType.createAndFill({ title: ((_node$attrs = node.attrs) === null || _node$attrs === void 0 ? void 0 : _node$attrs.title) || '', localId: crypto.randomUUID() }, node.content); }; /** * Converts an expand to a nestedExpand node. * When placing an expand inside another expand, it must become a nestedExpand * since expand cannot be a direct child of expand. */ var convertExpandToNestedExpand = exports.convertExpandToNestedExpand = function convertExpandToNestedExpand(node, schema) { var _node$attrs2; var nestedExpandType = schema.nodes.nestedExpand; if (!nestedExpandType) { return null; } return nestedExpandType.createAndFill({ title: ((_node$attrs2 = node.attrs) === null || _node$attrs2 === void 0 ? void 0 : _node$attrs2.title) || '', localId: crypto.randomUUID() }, node.content); }; /** * Converts a text node (heading, paragraph) to a paragraph preserving its inline content. * This is used when a text node can't be wrapped directly in the target container * (e.g., heading can't go in blockquote, so it becomes a paragraph). */ var convertTextNodeToParagraph = exports.convertTextNodeToParagraph = function convertTextNodeToParagraph(node, schema) { var _schema$nodes$paragra; // If it's already a paragraph, return as-is if (node.type.name === 'paragraph') { return node; } // Convert heading (or other text node) to paragraph with same inline content return (_schema$nodes$paragra = schema.nodes.paragraph.createAndFill({}, node.content)) !== null && _schema$nodes$paragra !== void 0 ? _schema$nodes$paragra : null; }; var getBlockNodesInRange = exports.getBlockNodesInRange = function getBlockNodesInRange(range) { if (range.startIndex === range.endIndex) { return []; } if (range.endIndex - range.startIndex <= 1) { return [range.parent.child(range.startIndex)]; } var blockNodes = []; for (var i = range.startIndex; i < range.endIndex; i++) { if (range.parent.child(i).isBlock) { blockNodes.push(range.parent.child(i)); } } return blockNodes; }; /** * Iterates over a nodes children and extracting text content, removing all other inline content and converting * hardbreaks to newlines. * * @param node - The node to create text content from (should be paragraph) * @returns The text content string. */ var createTextContent = exports.createTextContent = function createTextContent(node) { var textContent = node.children.map(function (child) { if (child.isText) { return child.text; } else if (child.type.name === 'hardBreak') { return '\n'; } return ''; }); return textContent.join(''); };