@lobehub/editor
Version:
A powerful and extensible rich text editor built on Meta's Lexical framework, providing a modern editing experience with React integration.
88 lines • 4.19 kB
JavaScript
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
import { $createListItemNode, $createListNode, $isListNode } from '@lexical/list';
import { $filter, $getNearestBlockElementAncestorOrThrow } from '@lexical/utils';
import { $createRangeSelection, $isBlockElementNode, $normalizeSelection__EXPERIMENTAL } from 'lexical';
// Amount of spaces that define indentation level
// TODO: should be an option
var LIST_INDENT_SIZE = 4;
function getIndent(whitespaces) {
var tabs = whitespaces.match(/\t/g);
var spaces = whitespaces.match(/ /g);
var indent = 0;
if (tabs) {
indent += tabs.length;
}
if (spaces) {
indent += Math.floor(spaces.length / LIST_INDENT_SIZE);
}
return indent;
}
export var listReplace = function listReplace(listType) {
return function (parentNode, children, match, isImport) {
var previousNode = parentNode.getPreviousSibling();
var nextNode = parentNode.getNextSibling();
var listItem = $createListItemNode(listType === 'check' ? match[3] === 'x' : undefined);
if ($isListNode(nextNode) && nextNode.getListType() === listType) {
var firstChild = nextNode.getFirstChild();
if (firstChild !== null) {
firstChild.insertBefore(listItem);
} else {
// should never happen, but let's handle gracefully, just in case.
nextNode.append(listItem);
}
parentNode.remove();
} else if ($isListNode(previousNode) && previousNode.getListType() === listType) {
previousNode.append(listItem);
parentNode.remove();
} else {
var list = $createListNode(listType, listType === 'number' ? Number(match[2]) : undefined);
list.append(listItem);
parentNode.replace(list);
}
listItem.append.apply(listItem, _toConsumableArray(children));
if (!isImport) {
listItem.select(0, 0);
}
var indent = getIndent(match[1]);
if (indent) {
listItem.setIndent(indent);
}
};
};
export function $indentOverTab(selection) {
// const handled = new Set();
var nodes = selection.getNodes();
var canIndentBlockNodes = $filter(nodes, function (node) {
if ($isBlockElementNode(node) && node.canIndent()) {
return node;
}
return null;
});
// 1. If selection spans across canIndent block nodes: indent
if (canIndentBlockNodes.length > 0) {
return true;
}
// 2. If first (anchor/focus) is at block start: indent
var anchor = selection.anchor;
var focus = selection.focus;
var first = focus.isBefore(anchor) ? focus : anchor;
var firstNode = first.getNode();
var firstBlock = $getNearestBlockElementAncestorOrThrow(firstNode);
if (firstBlock.canIndent()) {
var firstBlockKey = firstBlock.getKey();
var selectionAtStart = $createRangeSelection();
selectionAtStart.anchor.set(firstBlockKey, 0, 'element');
selectionAtStart.focus.set(firstBlockKey, 0, 'element');
selectionAtStart = $normalizeSelection__EXPERIMENTAL(selectionAtStart);
if (selectionAtStart.anchor.is(first)) {
return true;
}
}
// 3. Else: tab
return false;
}