@atlaskit/editor-plugin-block-menu
Version:
BlockMenu plugin for @atlaskit/editor-core
155 lines (150 loc) • 6.18 kB
JavaScript
"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('');
};