@lobehub/editor
Version:
A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.
167 lines (162 loc) • 5.17 kB
JavaScript
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
import { $getNodeByKey, createEditor } from 'lexical';
// DOM
export var DOM_ELEMENT_TYPE = 1;
export var DOM_TEXT_TYPE = 3;
export var DOM_DOCUMENT_TYPE = 9;
export var DOM_DOCUMENT_FRAGMENT_TYPE = 11;
export function genServiceId(name) {
return {
__serviceId: name
};
}
export var noop = function noop() {};
export function createEmptyEditorState() {
// Create a temporary editor to get an empty state
var tempEditor = createEditor();
return tempEditor.getEditorState();
}
export function assert(cond, message) {
if (cond) {
return;
}
throw new Error(message);
}
export function getNodeKeyFromDOMNode(dom, editor) {
var prop = "__lexicalKey_".concat(editor._key);
return dom[prop];
}
export function $getNodeFromDOMNode(dom, editor, editorState) {
var key = getNodeKeyFromDOMNode(dom, editor);
if (key !== undefined) {
return $getNodeByKey(key, editorState);
}
return null;
}
/**
* @param x - The element being tested
* @returns Returns true if x is a DOM Node, false otherwise.
*/
export function isDOMNode(x) {
return _typeof(x) === 'object' && x !== null && 'nodeType' in x && typeof x.nodeType === 'number';
}
/**
* @param x - The element being testing
* @returns Returns true if x is a document fragment, false otherwise.
*/
export function isDocumentFragment(x) {
return isDOMNode(x) && x.nodeType === DOM_DOCUMENT_FRAGMENT_TYPE;
}
export function getParentElement(node) {
var parentElement = node.assignedSlot || node.parentElement;
return isDocumentFragment(parentElement) ? parentElement.host : parentElement;
}
export function $getNearestNodeFromDOMNode(startingDOM, editor, editorState) {
var dom = startingDOM;
while (dom !== null) {
var node = $getNodeFromDOMNode(dom, editor, editorState);
if (node !== null) {
return node;
}
dom = getParentElement(dom);
}
return null;
}
export function getKernelFromEditor(editor) {
var _editor$_createEditor;
// @ts-expect-error __kernel is injected into the lexical editor instance
return ((_editor$_createEditor = editor._createEditorArgs) === null || _editor$_createEditor === void 0 ? void 0 : _editor$_createEditor.__kernel) || editor._kernel;
}
var EditorId = 0;
export var EDITOR_THEME_KEY = '__editorId';
export function generateEditorId() {
EditorId += 1;
return "editor-".concat(EditorId);
}
var EditorMap = new Map();
export function registerEditorKernel(id, kernel) {
EditorMap.set(id, kernel);
}
export function unregisterEditorKernel(id) {
EditorMap.delete(id);
}
export function getKernelFromEditorConfig(config) {
var id = config.theme[EDITOR_THEME_KEY];
return EditorMap.get(id) || null;
}
/**
*
* @param nodeA
* @param nodeB
* @returns
*/
export function compareNodeOrder(nodeA, nodeB) {
if (nodeA === nodeB) {
return 0;
}
var pathA = [];
var pathB = [];
var currentA = nodeA;
var currentB = nodeB;
while (currentA) {
pathA.unshift(currentA);
currentA = currentA.getParent();
}
while (currentB) {
pathB.unshift(currentB);
currentB = currentB.getParent();
}
var minLength = Math.min(pathA.length, pathB.length);
for (var i = 0; i < minLength; i++) {
if (pathA[i] !== pathB[i]) {
var _pathA$i$getParent;
var siblings = ((_pathA$i$getParent = pathA[i].getParent()) === null || _pathA$i$getParent === void 0 ? void 0 : _pathA$i$getParent.getChildren()) || [];
return siblings.indexOf(pathA[i]) - siblings.indexOf(pathB[i]);
}
}
// If all nodes in the shorter path are the same, the shorter path's node comes first
if (pathA.length !== pathB.length) {
return pathA.length - pathB.length;
}
// This case should not happen as we checked for equality at the start
return 0;
}
export function $closest(node, test) {
var current = node;
while (current) {
if (test(current)) {
return current;
}
current = current.getParent();
}
return null;
}
export function $closestNodeType(node, type) {
return $closest(node, function (n) {
return Array.isArray(type) ? type.includes(n.getType()) : n.getType() === type;
});
}
export function moment() {
return new Promise(function (resolve) {
queueMicrotask(function () {
return resolve(true);
});
});
}
function cloneDecorators(editor) {
var currentDecorators = editor._decorators;
var pendingDecorators = Object.assign({}, currentDecorators);
editor._pendingDecorators = pendingDecorators;
return pendingDecorators;
}
export function reconcileDecorator(activeEditor, key, decorator) {
var pendingDecorators = activeEditor._pendingDecorators;
var currentDecorators = activeEditor._decorators;
if (pendingDecorators === null) {
if (currentDecorators[key] === decorator) {
return;
}
pendingDecorators = cloneDecorators(activeEditor);
}
pendingDecorators[key] = decorator;
}