UNPKG

@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
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; }