@tiptap/core 2.1.4 → 2.2.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2011,261 +2011,6 @@ function getMarkAttributes(state, typeOrName) {
2011
2011
  return { ...mark.attrs };
2012
2012
  }
2013
2013
 
2014
- const findListItemPos = (typeOrName, state) => {
2015
- const { $from } = state.selection;
2016
- const nodeType = getNodeType(typeOrName, state.schema);
2017
- let currentNode = null;
2018
- let currentDepth = $from.depth;
2019
- let currentPos = $from.pos;
2020
- let targetDepth = null;
2021
- while (currentDepth > 0 && targetDepth === null) {
2022
- currentNode = $from.node(currentDepth);
2023
- if (currentNode.type === nodeType) {
2024
- targetDepth = currentDepth;
2025
- }
2026
- else {
2027
- currentDepth -= 1;
2028
- currentPos -= 1;
2029
- }
2030
- }
2031
- if (targetDepth === null) {
2032
- return null;
2033
- }
2034
- return { $pos: state.doc.resolve(currentPos), depth: targetDepth };
2035
- };
2036
-
2037
- /**
2038
- * Finds the first node of a given type or name in the current selection.
2039
- * @param state The editor state.
2040
- * @param typeOrName The node type or name.
2041
- * @param pos The position to start searching from.
2042
- * @param maxDepth The maximum depth to search.
2043
- * @returns The node and the depth as an array.
2044
- */
2045
- const getNodeAtPosition = (state, typeOrName, pos, maxDepth = 20) => {
2046
- const $pos = state.doc.resolve(pos);
2047
- let currentDepth = maxDepth;
2048
- let node = null;
2049
- while (currentDepth > 0 && node === null) {
2050
- const currentNode = $pos.node(currentDepth);
2051
- if ((currentNode === null || currentNode === void 0 ? void 0 : currentNode.type.name) === typeOrName) {
2052
- node = currentNode;
2053
- }
2054
- else {
2055
- currentDepth -= 1;
2056
- }
2057
- }
2058
- return [node, currentDepth];
2059
- };
2060
-
2061
- const getNextListDepth = (typeOrName, state) => {
2062
- const listItemPos = findListItemPos(typeOrName, state);
2063
- if (!listItemPos) {
2064
- return false;
2065
- }
2066
- const [, depth] = getNodeAtPosition(state, typeOrName, listItemPos.$pos.pos + 4);
2067
- return depth;
2068
- };
2069
-
2070
- const isAtStartOfNode = (state) => {
2071
- const { $from, $to } = state.selection;
2072
- if ($from.parentOffset > 0 || $from.pos !== $to.pos) {
2073
- return false;
2074
- }
2075
- return true;
2076
- };
2077
-
2078
- const hasListBefore = (editorState, name, parentListTypes) => {
2079
- const { $anchor } = editorState.selection;
2080
- const previousNodePos = Math.max(0, $anchor.pos - 2);
2081
- const previousNode = editorState.doc.resolve(previousNodePos).node();
2082
- if (!previousNode || !parentListTypes.includes(previousNode.type.name)) {
2083
- return false;
2084
- }
2085
- return true;
2086
- };
2087
-
2088
- const hasListItemBefore = (typeOrName, state) => {
2089
- var _a;
2090
- const { $anchor } = state.selection;
2091
- const $targetPos = state.doc.resolve($anchor.pos - 2);
2092
- if ($targetPos.index() === 0) {
2093
- return false;
2094
- }
2095
- if (((_a = $targetPos.nodeBefore) === null || _a === void 0 ? void 0 : _a.type.name) !== typeOrName) {
2096
- return false;
2097
- }
2098
- return true;
2099
- };
2100
-
2101
- const listItemHasSubList = (typeOrName, state, node) => {
2102
- if (!node) {
2103
- return false;
2104
- }
2105
- const nodeType = getNodeType(typeOrName, state.schema);
2106
- let hasSubList = false;
2107
- node.descendants(child => {
2108
- if (child.type === nodeType) {
2109
- hasSubList = true;
2110
- }
2111
- });
2112
- return hasSubList;
2113
- };
2114
-
2115
- const handleBackspace = (editor, name, parentListTypes) => {
2116
- // this is required to still handle the undo handling
2117
- if (editor.commands.undoInputRule()) {
2118
- return true;
2119
- }
2120
- // if the current item is NOT inside a list item &
2121
- // the previous item is a list (orderedList or bulletList)
2122
- // move the cursor into the list and delete the current item
2123
- if (!isNodeActive(editor.state, name) && hasListBefore(editor.state, name, parentListTypes)) {
2124
- const { $anchor } = editor.state.selection;
2125
- const $listPos = editor.state.doc.resolve($anchor.before() - 1);
2126
- const listDescendants = [];
2127
- $listPos.node().descendants((node, pos) => {
2128
- if (node.type.name === name) {
2129
- listDescendants.push({ node, pos });
2130
- }
2131
- });
2132
- const lastItem = listDescendants.at(-1);
2133
- if (!lastItem) {
2134
- return false;
2135
- }
2136
- const $lastItemPos = editor.state.doc.resolve($listPos.start() + lastItem.pos + 1);
2137
- return editor.chain().cut({ from: $anchor.start() - 1, to: $anchor.end() + 1 }, $lastItemPos.end()).joinForward().run();
2138
- }
2139
- // if the cursor is not inside the current node type
2140
- // do nothing and proceed
2141
- if (!isNodeActive(editor.state, name)) {
2142
- return false;
2143
- }
2144
- // if the cursor is not at the start of a node
2145
- // do nothing and proceed
2146
- if (!isAtStartOfNode(editor.state)) {
2147
- return false;
2148
- }
2149
- const listItemPos = findListItemPos(name, editor.state);
2150
- if (!listItemPos) {
2151
- return false;
2152
- }
2153
- const $prev = editor.state.doc.resolve(listItemPos.$pos.pos - 2);
2154
- const prevNode = $prev.node(listItemPos.depth);
2155
- const previousListItemHasSubList = listItemHasSubList(name, editor.state, prevNode);
2156
- // if the previous item is a list item and doesn't have a sublist, join the list items
2157
- if (hasListItemBefore(name, editor.state) && !previousListItemHasSubList) {
2158
- return editor.commands.joinItemBackward();
2159
- }
2160
- // otherwise in the end, a backspace should
2161
- // always just lift the list item if
2162
- // joining / merging is not possible
2163
- return editor.chain().liftListItem(name).run();
2164
- };
2165
-
2166
- function findParentNodeClosestToPos($pos, predicate) {
2167
- for (let i = $pos.depth; i > 0; i -= 1) {
2168
- const node = $pos.node(i);
2169
- if (predicate(node)) {
2170
- return {
2171
- pos: i > 0 ? $pos.before(i) : 0,
2172
- start: $pos.start(i),
2173
- depth: i,
2174
- node,
2175
- };
2176
- }
2177
- }
2178
- }
2179
-
2180
- function findParentNode(predicate) {
2181
- return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2182
- }
2183
-
2184
- const isAtEndOfNode = (state, nodeType) => {
2185
- const { $from, $to, $anchor } = state.selection;
2186
- if (nodeType) {
2187
- const parentNode = findParentNode(node => node.type.name === nodeType)(state.selection);
2188
- if (!parentNode) {
2189
- return false;
2190
- }
2191
- const $parentPos = state.doc.resolve(parentNode.pos + 1);
2192
- if ($anchor.pos + 1 === $parentPos.end()) {
2193
- return true;
2194
- }
2195
- return false;
2196
- }
2197
- if ($to.parentOffset < $to.parent.nodeSize - 2 || $from.pos !== $to.pos) {
2198
- return false;
2199
- }
2200
- return true;
2201
- };
2202
-
2203
- const nextListIsDeeper = (typeOrName, state) => {
2204
- const listDepth = getNextListDepth(typeOrName, state);
2205
- const listItemPos = findListItemPos(typeOrName, state);
2206
- if (!listItemPos || !listDepth) {
2207
- return false;
2208
- }
2209
- if (listDepth > listItemPos.depth) {
2210
- return true;
2211
- }
2212
- return false;
2213
- };
2214
-
2215
- const nextListIsHigher = (typeOrName, state) => {
2216
- const listDepth = getNextListDepth(typeOrName, state);
2217
- const listItemPos = findListItemPos(typeOrName, state);
2218
- if (!listItemPos || !listDepth) {
2219
- return false;
2220
- }
2221
- if (listDepth < listItemPos.depth) {
2222
- return true;
2223
- }
2224
- return false;
2225
- };
2226
-
2227
- const handleDelete = (editor, name) => {
2228
- // if the cursor is not inside the current node type
2229
- // do nothing and proceed
2230
- if (!isNodeActive(editor.state, name)) {
2231
- return false;
2232
- }
2233
- // if the cursor is not at the end of a node
2234
- // do nothing and proceed
2235
- if (!isAtEndOfNode(editor.state, name)) {
2236
- return false;
2237
- }
2238
- // check if the next node is a list with a deeper depth
2239
- if (nextListIsDeeper(name, editor.state)) {
2240
- return editor
2241
- .chain()
2242
- .focus(editor.state.selection.from + 4)
2243
- .lift(name)
2244
- .joinBackward()
2245
- .run();
2246
- }
2247
- if (nextListIsHigher(name, editor.state)) {
2248
- return editor.chain()
2249
- .joinForward()
2250
- .joinBackward()
2251
- .run();
2252
- }
2253
- return editor.commands.joinItemForward();
2254
- };
2255
-
2256
- const hasListItemAfter = (typeOrName, state) => {
2257
- var _a;
2258
- const { $anchor } = state.selection;
2259
- const $targetPos = state.doc.resolve($anchor.pos - $anchor.parentOffset - 2);
2260
- if ($targetPos.index() === $targetPos.parent.childCount - 1) {
2261
- return false;
2262
- }
2263
- if (((_a = $targetPos.nodeAfter) === null || _a === void 0 ? void 0 : _a.type.name) !== typeOrName) {
2264
- return false;
2265
- }
2266
- return true;
2267
- };
2268
-
2269
2014
  /**
2270
2015
  * Returns a new `Transform` based on all steps of the passed transactions.
2271
2016
  */
@@ -2327,6 +2072,24 @@ function findChildrenInRange(node, range, predicate) {
2327
2072
  return nodesWithPos;
2328
2073
  }
2329
2074
 
2075
+ function findParentNodeClosestToPos($pos, predicate) {
2076
+ for (let i = $pos.depth; i > 0; i -= 1) {
2077
+ const node = $pos.node(i);
2078
+ if (predicate(node)) {
2079
+ return {
2080
+ pos: i > 0 ? $pos.before(i) : 0,
2081
+ start: $pos.start(i),
2082
+ depth: i,
2083
+ node,
2084
+ };
2085
+ }
2086
+ }
2087
+ }
2088
+
2089
+ function findParentNode(predicate) {
2090
+ return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2091
+ }
2092
+
2330
2093
  function getHTMLFromFragment(fragment, schema) {
2331
2094
  const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
2332
2095
  const temporaryDocument = document.implementation.createHTMLDocument();
@@ -2544,6 +2307,30 @@ function getMarksBetween(from, to, doc) {
2544
2307
  return marks;
2545
2308
  }
2546
2309
 
2310
+ /**
2311
+ * Finds the first node of a given type or name in the current selection.
2312
+ * @param state The editor state.
2313
+ * @param typeOrName The node type or name.
2314
+ * @param pos The position to start searching from.
2315
+ * @param maxDepth The maximum depth to search.
2316
+ * @returns The node and the depth as an array.
2317
+ */
2318
+ const getNodeAtPosition = (state, typeOrName, pos, maxDepth = 20) => {
2319
+ const $pos = state.doc.resolve(pos);
2320
+ let currentDepth = maxDepth;
2321
+ let node = null;
2322
+ while (currentDepth > 0 && node === null) {
2323
+ const currentNode = $pos.node(currentDepth);
2324
+ if ((currentNode === null || currentNode === void 0 ? void 0 : currentNode.type.name) === typeOrName) {
2325
+ node = currentNode;
2326
+ }
2327
+ else {
2328
+ currentDepth -= 1;
2329
+ }
2330
+ }
2331
+ return [node, currentDepth];
2332
+ };
2333
+
2547
2334
  function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2548
2335
  return Object.fromEntries(Object
2549
2336
  .entries(attributes)
@@ -2634,6 +2421,33 @@ function isActive(state, name, attributes = {}) {
2634
2421
  return false;
2635
2422
  }
2636
2423
 
2424
+ const isAtEndOfNode = (state, nodeType) => {
2425
+ const { $from, $to, $anchor } = state.selection;
2426
+ if (nodeType) {
2427
+ const parentNode = findParentNode(node => node.type.name === nodeType)(state.selection);
2428
+ if (!parentNode) {
2429
+ return false;
2430
+ }
2431
+ const $parentPos = state.doc.resolve(parentNode.pos + 1);
2432
+ if ($anchor.pos + 1 === $parentPos.end()) {
2433
+ return true;
2434
+ }
2435
+ return false;
2436
+ }
2437
+ if ($to.parentOffset < $to.parent.nodeSize - 2 || $from.pos !== $to.pos) {
2438
+ return false;
2439
+ }
2440
+ return true;
2441
+ };
2442
+
2443
+ const isAtStartOfNode = (state) => {
2444
+ const { $from, $to } = state.selection;
2445
+ if ($from.parentOffset > 0 || $from.pos !== $to.pos) {
2446
+ return false;
2447
+ }
2448
+ return true;
2449
+ };
2450
+
2637
2451
  function isList(name, extensions) {
2638
2452
  const { nodeExtensions } = splitExtensions(extensions);
2639
2453
  const extension = nodeExtensions.find(item => item.name === name);
@@ -4572,5 +4386,5 @@ class Tracker {
4572
4386
  }
4573
4387
  }
4574
4388
 
4575
- export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, extensions, findChildren, findChildrenInRange, findDuplicates, findListItemPos, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNextListDepth, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, handleBackspace, handleDelete, hasListBefore, hasListItemAfter, hasListItemBefore, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, listItemHasSubList, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nextListIsDeeper, nextListIsHigher, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4389
+ export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4576
4390
  //# sourceMappingURL=index.js.map