@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
139 lines (134 loc) • 5.58 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isType = exports.isText = exports.isSupportedInParent = exports.isParagraph = exports.isNodeSelectedOrInRange = exports.isNodeBeforeMediaNode = exports.isMediaNode = exports.isLinkMark = exports.findChangedNodesFromTransaction = exports.SelectedState = void 0;
exports.nodeToJSON = nodeToJSON;
exports.toJSON = toJSON;
exports.validateNodes = exports.validNode = void 0;
var _editorJsonTransformer = require("@atlaskit/editor-json-transformer");
var _utils = require("@atlaskit/editor-prosemirror/utils");
/**
* Finds all top level nodes affected by the transaction
* Uses from/to positions in transaction's steps to work out which nodes will
* be changed by the transaction
*/
var findChangedNodesFromTransaction = exports.findChangedNodesFromTransaction = function findChangedNodesFromTransaction(tr) {
var nodes = [];
var steps = tr.steps || [];
steps.forEach(function (step) {
step.getMap().forEach(function (oldStart, oldEnd, newStart, newEnd) {
tr.doc.nodesBetween(newStart, Math.min(newEnd, tr.doc.content.size), function (node) {
if (!nodes.find(function (n) {
return n === node;
})) {
nodes.push(node);
}
return false;
});
});
});
return nodes;
};
var validNode = exports.validNode = function validNode(node) {
try {
node.check(); // this will throw an error if the node is invalid
} catch (error) {
return false;
}
return true;
};
/** Validates prosemirror nodes, and returns true only if all nodes are valid */
var validateNodes = exports.validateNodes = function validateNodes(nodes) {
return nodes.every(validNode);
};
var isType = exports.isType = function isType(node, type) {
return type && node && node.type === type;
};
var isParagraph = exports.isParagraph = function isParagraph(node, schema) {
return isType(node, schema.nodes.paragraph);
};
var isText = exports.isText = function isText(node, schema) {
return isType(node, schema.nodes.text);
};
var isLinkMark = exports.isLinkMark = function isLinkMark(node, schema) {
return isType(node, schema.marks.link);
};
var SelectedState = exports.SelectedState = /*#__PURE__*/function (SelectedState) {
SelectedState[SelectedState["selectedInRange"] = 0] = "selectedInRange";
SelectedState[SelectedState["selectedInside"] = 1] = "selectedInside";
return SelectedState;
}({});
/**
* Returns if the current selection from achor-head is selecting the node.
* If the node is not selected then null is returned.
* If the node is selected then an enum is returned that describes weather the node
* is fully selected by a range or if the "inside" of the node has been selected or clicked.
*/
var isNodeSelectedOrInRange = exports.isNodeSelectedOrInRange = function isNodeSelectedOrInRange(anchorPosition, headPosition, nodePosition, nodeSize) {
if (typeof nodePosition !== 'number') {
return null;
}
var rangeStart = Math.min(anchorPosition, headPosition);
var rangeEnd = Math.max(anchorPosition, headPosition);
var nodeStart = nodePosition;
var nodeEnd = nodePosition + nodeSize;
if (anchorPosition === headPosition) {
return null;
}
if (rangeStart <= nodeStart && nodeEnd < rangeEnd || rangeStart < nodeStart && nodeEnd <= rangeEnd) {
return SelectedState.selectedInRange;
}
if (nodeStart <= anchorPosition && headPosition <= nodeEnd) {
return SelectedState.selectedInside;
}
return null;
};
/**
* Checks if a particular node fragment is supported in the parent
* @param state EditorState
* @param fragment The fragment to be checked for
*/
var isSupportedInParent = exports.isSupportedInParent = function isSupportedInParent(state, fragment, currentAppearance) {
var depth = currentAppearance === 'embed' || currentAppearance === 'block' ? undefined : -1;
var parent = state.selection.$from.node(depth);
return parent && parent.type.validContent(fragment);
};
/**
* Checks if the passed in node is a media node
* Includes media, mediaInline, mediaGroup, mediaSingle
* @param node The PM node to be checked
*/
var isMediaNode = exports.isMediaNode = function isMediaNode(node) {
return ['media', 'mediaInline', 'mediaGroup', 'mediaSingle'].includes(node.type.name);
};
/**
* Checks if the node before selection is a media node
* If there is no node before, checks the node before the parent node
* Includes media, mediaInline, mediaGroup, mediaSingle
* @param $pos The position of the selection
* @param state The editor state
*/
var isNodeBeforeMediaNode = exports.isNodeBeforeMediaNode = function isNodeBeforeMediaNode($pos, state) {
var nodeBefore = $pos.nodeBefore;
if (!nodeBefore) {
var depthOfParent = $pos.depth - 1 || 1;
var parentNode = (0, _utils.findParentNodeOfType)([state.schema.nodes["".concat($pos.node(depthOfParent).type.name)]])(state.selection);
var resolvedPosOfParentNode = parentNode ? state.tr.doc.resolve(parentNode.pos) : undefined;
var nodeBeforeParent = resolvedPosOfParentNode && resolvedPosOfParentNode.pos < state.doc.nodeSize ? resolvedPosOfParentNode.nodeBefore : undefined;
if (nodeBeforeParent) {
nodeBefore = nodeBeforeParent;
}
}
if (nodeBefore) {
return ['media', 'mediaInline', 'mediaGroup', 'mediaSingle'].includes(nodeBefore.type.name);
}
return false;
};
var transformer = new _editorJsonTransformer.JSONTransformer();
function toJSON(node) {
return transformer.encode(node);
}
function nodeToJSON(node) {
return transformer.encodeNode(node);
}