@tiptap/core 3.0.0-next.3 → 3.0.0-next.5

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.
Files changed (146) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +5 -1
  3. package/dist/index.cjs +2627 -2651
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +2423 -2688
  6. package/dist/index.d.ts +2423 -2688
  7. package/dist/index.js +2639 -2684
  8. package/dist/index.js.map +1 -1
  9. package/dist/jsx-runtime/jsx-runtime.cjs +56 -0
  10. package/dist/jsx-runtime/jsx-runtime.cjs.map +1 -0
  11. package/dist/jsx-runtime/jsx-runtime.d.cts +22 -0
  12. package/dist/jsx-runtime/jsx-runtime.d.ts +22 -0
  13. package/dist/jsx-runtime/jsx-runtime.js +26 -0
  14. package/dist/jsx-runtime/jsx-runtime.js.map +1 -0
  15. package/jsx-runtime/index.cjs +1 -0
  16. package/jsx-runtime/index.d.cts +1 -0
  17. package/jsx-runtime/index.d.ts +1 -0
  18. package/jsx-runtime/index.js +1 -0
  19. package/package.json +27 -6
  20. package/src/CommandManager.ts +2 -9
  21. package/src/Editor.ts +191 -94
  22. package/src/EventEmitter.ts +7 -10
  23. package/src/Extendable.ts +483 -0
  24. package/src/Extension.ts +5 -496
  25. package/src/ExtensionManager.ts +81 -135
  26. package/src/InputRule.ts +35 -48
  27. package/src/Mark.ts +135 -623
  28. package/src/MarkView.ts +66 -0
  29. package/src/Node.ts +325 -829
  30. package/src/NodePos.ts +1 -3
  31. package/src/NodeView.ts +10 -20
  32. package/src/PasteRule.ts +43 -55
  33. package/src/Tracker.ts +7 -9
  34. package/src/commands/blur.ts +14 -12
  35. package/src/commands/clearContent.ts +12 -5
  36. package/src/commands/clearNodes.ts +32 -30
  37. package/src/commands/command.ts +1 -1
  38. package/src/commands/createParagraphNear.ts +5 -3
  39. package/src/commands/cut.ts +12 -10
  40. package/src/commands/deleteCurrentNode.ts +23 -21
  41. package/src/commands/deleteNode.ts +18 -16
  42. package/src/commands/deleteRange.ts +10 -8
  43. package/src/commands/deleteSelection.ts +5 -3
  44. package/src/commands/enter.ts +6 -4
  45. package/src/commands/exitCode.ts +5 -3
  46. package/src/commands/extendMarkRange.ts +14 -12
  47. package/src/commands/first.ts +2 -4
  48. package/src/commands/focus.ts +51 -48
  49. package/src/commands/forEach.ts +2 -2
  50. package/src/commands/insertContent.ts +12 -14
  51. package/src/commands/insertContentAt.ts +105 -98
  52. package/src/commands/join.ts +20 -12
  53. package/src/commands/joinItemBackward.ts +16 -18
  54. package/src/commands/joinItemForward.ts +16 -18
  55. package/src/commands/joinTextblockBackward.ts +5 -3
  56. package/src/commands/joinTextblockForward.ts +5 -3
  57. package/src/commands/keyboardShortcut.ts +29 -34
  58. package/src/commands/lift.ts +10 -8
  59. package/src/commands/liftEmptyBlock.ts +6 -4
  60. package/src/commands/liftListItem.ts +6 -4
  61. package/src/commands/newlineInCode.ts +5 -3
  62. package/src/commands/resetAttributes.ts +36 -41
  63. package/src/commands/scrollIntoView.ts +9 -7
  64. package/src/commands/selectAll.ts +10 -8
  65. package/src/commands/selectNodeBackward.ts +5 -3
  66. package/src/commands/selectNodeForward.ts +5 -3
  67. package/src/commands/selectParentNode.ts +5 -3
  68. package/src/commands/selectTextblockEnd.ts +5 -3
  69. package/src/commands/selectTextblockStart.ts +5 -3
  70. package/src/commands/setContent.ts +37 -36
  71. package/src/commands/setMark.ts +55 -57
  72. package/src/commands/setMeta.ts +7 -5
  73. package/src/commands/setNode.ts +32 -30
  74. package/src/commands/setNodeSelection.ts +11 -9
  75. package/src/commands/setTextSelection.ts +15 -13
  76. package/src/commands/sinkListItem.ts +6 -4
  77. package/src/commands/splitBlock.ts +67 -76
  78. package/src/commands/splitListItem.ts +93 -106
  79. package/src/commands/toggleList.ts +73 -71
  80. package/src/commands/toggleMark.ts +11 -9
  81. package/src/commands/toggleNode.ts +18 -16
  82. package/src/commands/toggleWrap.ts +10 -8
  83. package/src/commands/undoInputRule.ts +31 -29
  84. package/src/commands/unsetAllMarks.ts +16 -14
  85. package/src/commands/unsetMark.ts +27 -25
  86. package/src/commands/updateAttributes.ts +92 -100
  87. package/src/commands/wrapIn.ts +6 -4
  88. package/src/commands/wrapInList.ts +6 -4
  89. package/src/extensions/clipboardTextSerializer.ts +2 -4
  90. package/src/extensions/delete.ts +89 -0
  91. package/src/extensions/focusEvents.ts +2 -6
  92. package/src/extensions/index.ts +1 -0
  93. package/src/extensions/keymap.ts +58 -50
  94. package/src/extensions/paste.ts +0 -1
  95. package/src/extensions/tabindex.ts +1 -1
  96. package/src/helpers/combineTransactionSteps.ts +1 -4
  97. package/src/helpers/createChainableState.ts +1 -4
  98. package/src/helpers/createDocument.ts +1 -3
  99. package/src/helpers/createNodeFromContent.ts +4 -10
  100. package/src/helpers/findChildrenInRange.ts +1 -5
  101. package/src/helpers/findParentNode.ts +3 -1
  102. package/src/helpers/flattenExtensions.ts +30 -0
  103. package/src/helpers/getAttributes.ts +1 -4
  104. package/src/helpers/getAttributesFromExtensions.ts +28 -37
  105. package/src/helpers/getChangedRanges.ts +13 -11
  106. package/src/helpers/getExtensionField.ts +11 -11
  107. package/src/helpers/getMarkAttributes.ts +1 -4
  108. package/src/helpers/getMarkRange.ts +5 -15
  109. package/src/helpers/getMarkType.ts +1 -3
  110. package/src/helpers/getNodeAttributes.ts +1 -4
  111. package/src/helpers/getNodeType.ts +1 -3
  112. package/src/helpers/getRenderedAttributes.ts +1 -3
  113. package/src/helpers/getSchema.ts +2 -2
  114. package/src/helpers/getSchemaByResolvedExtensions.ts +45 -77
  115. package/src/helpers/getSplittedAttributes.ts +4 -4
  116. package/src/helpers/getTextContentFromNodes.ts +8 -11
  117. package/src/helpers/index.ts +4 -0
  118. package/src/helpers/injectExtensionAttributesToParseRule.ts +1 -1
  119. package/src/helpers/isActive.ts +1 -5
  120. package/src/helpers/isExtensionRulesEnabled.ts +1 -3
  121. package/src/helpers/isNodeEmpty.ts +2 -2
  122. package/src/helpers/resolveExtensions.ts +25 -0
  123. package/src/helpers/resolveFocusPosition.ts +3 -14
  124. package/src/helpers/rewriteUnknownContent.ts +149 -0
  125. package/src/helpers/sortExtensions.ts +26 -0
  126. package/src/index.ts +3 -7
  127. package/src/inputRules/markInputRule.ts +1 -5
  128. package/src/inputRules/nodeInputRule.ts +2 -9
  129. package/src/inputRules/textInputRule.ts +1 -4
  130. package/src/inputRules/textblockTypeInputRule.ts +2 -8
  131. package/src/inputRules/wrappingInputRule.ts +13 -19
  132. package/src/jsx-runtime.ts +64 -0
  133. package/src/pasteRules/markPasteRule.ts +1 -3
  134. package/src/pasteRules/nodePasteRule.ts +2 -8
  135. package/src/pasteRules/textPasteRule.ts +1 -4
  136. package/src/types.ts +529 -174
  137. package/src/utilities/createStyleTag.ts +3 -1
  138. package/src/utilities/deleteProps.ts +7 -11
  139. package/src/utilities/elementFromString.ts +3 -0
  140. package/src/utilities/findDuplicates.ts +4 -1
  141. package/src/utilities/index.ts +1 -0
  142. package/src/utilities/isFunction.ts +1 -0
  143. package/src/utilities/isMacOS.ts +1 -3
  144. package/src/utilities/isiOS.ts +5 -10
  145. package/src/utilities/mergeAttributes.ts +17 -7
  146. package/src/utilities/removeDuplicates.ts +1 -3
@@ -18,38 +18,40 @@ declare module '@tiptap/core' {
18
18
  }
19
19
  }
20
20
 
21
- export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
22
- const type = getNodeType(typeOrName, state.schema)
21
+ export const setNode: RawCommands['setNode'] =
22
+ (typeOrName, attributes = {}) =>
23
+ ({ state, dispatch, chain }) => {
24
+ const type = getNodeType(typeOrName, state.schema)
23
25
 
24
- let attributesToCopy: Record<string, any> | undefined
26
+ let attributesToCopy: Record<string, any> | undefined
25
27
 
26
- if (state.selection.$anchor.sameParent(state.selection.$head)) {
27
- // only copy attributes if the selection is pointing to a node of the same type
28
- attributesToCopy = state.selection.$anchor.parent.attrs
29
- }
28
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
29
+ // only copy attributes if the selection is pointing to a node of the same type
30
+ attributesToCopy = state.selection.$anchor.parent.attrs
31
+ }
30
32
 
31
- // TODO: use a fallback like insertContent?
32
- if (!type.isTextblock) {
33
- console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.')
33
+ // TODO: use a fallback like insertContent?
34
+ if (!type.isTextblock) {
35
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.')
34
36
 
35
- return false
36
- }
37
+ return false
38
+ }
37
39
 
38
- return (
39
- chain()
40
- // try to convert node to default node if needed
41
- .command(({ commands }) => {
42
- const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state)
43
-
44
- if (canSetBlock) {
45
- return true
46
- }
47
-
48
- return commands.clearNodes()
49
- })
50
- .command(({ state: updatedState }) => {
51
- return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch)
52
- })
53
- .run()
54
- )
55
- }
40
+ return (
41
+ chain()
42
+ // try to convert node to default node if needed
43
+ .command(({ commands }) => {
44
+ const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state)
45
+
46
+ if (canSetBlock) {
47
+ return true
48
+ }
49
+
50
+ return commands.clearNodes()
51
+ })
52
+ .command(({ state: updatedState }) => {
53
+ return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch)
54
+ })
55
+ .run()
56
+ )
57
+ }
@@ -16,14 +16,16 @@ declare module '@tiptap/core' {
16
16
  }
17
17
  }
18
18
 
19
- export const setNodeSelection: RawCommands['setNodeSelection'] = position => ({ tr, dispatch }) => {
20
- if (dispatch) {
21
- const { doc } = tr
22
- const from = minMax(position, 0, doc.content.size)
23
- const selection = NodeSelection.create(doc, from)
19
+ export const setNodeSelection: RawCommands['setNodeSelection'] =
20
+ position =>
21
+ ({ tr, dispatch }) => {
22
+ if (dispatch) {
23
+ const { doc } = tr
24
+ const from = minMax(position, 0, doc.content.size)
25
+ const selection = NodeSelection.create(doc, from)
24
26
 
25
- tr.setSelection(selection)
26
- }
27
+ tr.setSelection(selection)
28
+ }
27
29
 
28
- return true
29
- }
30
+ return true
31
+ }
@@ -16,18 +16,20 @@ declare module '@tiptap/core' {
16
16
  }
17
17
  }
18
18
 
19
- export const setTextSelection: RawCommands['setTextSelection'] = position => ({ tr, dispatch }) => {
20
- if (dispatch) {
21
- const { doc } = tr
22
- const { from, to } = typeof position === 'number' ? { from: position, to: position } : position
23
- const minPos = TextSelection.atStart(doc).from
24
- const maxPos = TextSelection.atEnd(doc).to
25
- const resolvedFrom = minMax(from, minPos, maxPos)
26
- const resolvedEnd = minMax(to, minPos, maxPos)
27
- const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
19
+ export const setTextSelection: RawCommands['setTextSelection'] =
20
+ position =>
21
+ ({ tr, dispatch }) => {
22
+ if (dispatch) {
23
+ const { doc } = tr
24
+ const { from, to } = typeof position === 'number' ? { from: position, to: position } : position
25
+ const minPos = TextSelection.atStart(doc).from
26
+ const maxPos = TextSelection.atEnd(doc).to
27
+ const resolvedFrom = minMax(from, minPos, maxPos)
28
+ const resolvedEnd = minMax(to, minPos, maxPos)
29
+ const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
28
30
 
29
- tr.setSelection(selection)
30
- }
31
+ tr.setSelection(selection)
32
+ }
31
33
 
32
- return true
33
- }
34
+ return true
35
+ }
@@ -17,8 +17,10 @@ declare module '@tiptap/core' {
17
17
  }
18
18
  }
19
19
 
20
- export const sinkListItem: RawCommands['sinkListItem'] = typeOrName => ({ state, dispatch }) => {
21
- const type = getNodeType(typeOrName, state.schema)
20
+ export const sinkListItem: RawCommands['sinkListItem'] =
21
+ typeOrName =>
22
+ ({ state, dispatch }) => {
23
+ const type = getNodeType(typeOrName, state.schema)
22
24
 
23
- return originalSinkListItem(type)(state, dispatch)
24
- }
25
+ return originalSinkListItem(type)(state, dispatch)
26
+ }
@@ -29,95 +29,86 @@ declare module '@tiptap/core' {
29
29
  }
30
30
  }
31
31
 
32
- export const splitBlock: RawCommands['splitBlock'] = ({ keepMarks = true } = {}) => ({
33
- tr, state, dispatch, editor,
34
- }) => {
35
- const { selection, doc } = tr
36
- const { $from, $to } = selection
37
- const extensionAttributes = editor.extensionManager.attributes
38
- const newAttributes = getSplittedAttributes(
39
- extensionAttributes,
40
- $from.node().type.name,
41
- $from.node().attrs,
42
- )
43
-
44
- if (selection instanceof NodeSelection && selection.node.isBlock) {
45
- if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
46
- return false
47
- }
32
+ export const splitBlock: RawCommands['splitBlock'] =
33
+ ({ keepMarks = true } = {}) =>
34
+ ({ tr, state, dispatch, editor }) => {
35
+ const { selection, doc } = tr
36
+ const { $from, $to } = selection
37
+ const extensionAttributes = editor.extensionManager.attributes
38
+ const newAttributes = getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs)
39
+
40
+ if (selection instanceof NodeSelection && selection.node.isBlock) {
41
+ if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
42
+ return false
43
+ }
48
44
 
49
- if (dispatch) {
50
- if (keepMarks) {
51
- ensureMarks(state, editor.extensionManager.splittableMarks)
45
+ if (dispatch) {
46
+ if (keepMarks) {
47
+ ensureMarks(state, editor.extensionManager.splittableMarks)
48
+ }
49
+
50
+ tr.split($from.pos).scrollIntoView()
52
51
  }
53
52
 
54
- tr.split($from.pos).scrollIntoView()
53
+ return true
55
54
  }
56
55
 
57
- return true
58
- }
59
-
60
- if (!$from.parent.isBlock) {
61
- return false
62
- }
56
+ if (!$from.parent.isBlock) {
57
+ return false
58
+ }
63
59
 
64
- const atEnd = $to.parentOffset === $to.parent.content.size
65
-
66
- const deflt = $from.depth === 0
67
- ? undefined
68
- : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
69
-
70
- let types = atEnd && deflt
71
- ? [
72
- {
73
- type: deflt,
74
- attrs: newAttributes,
75
- },
76
- ]
77
- : undefined
78
-
79
- let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
80
-
81
- if (
82
- !types
83
- && !can
84
- && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)
85
- ) {
86
- can = true
87
- types = deflt
88
- ? [
89
- {
90
- type: deflt,
91
- attrs: newAttributes,
92
- },
93
- ]
94
- : undefined
95
- }
60
+ const atEnd = $to.parentOffset === $to.parent.content.size
61
+
62
+ const deflt = $from.depth === 0 ? undefined : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
63
+
64
+ let types =
65
+ atEnd && deflt
66
+ ? [
67
+ {
68
+ type: deflt,
69
+ attrs: newAttributes,
70
+ },
71
+ ]
72
+ : undefined
73
+
74
+ let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
75
+
76
+ if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
77
+ can = true
78
+ types = deflt
79
+ ? [
80
+ {
81
+ type: deflt,
82
+ attrs: newAttributes,
83
+ },
84
+ ]
85
+ : undefined
86
+ }
96
87
 
97
- if (dispatch) {
98
- if (can) {
99
- if (selection instanceof TextSelection) {
100
- tr.deleteSelection()
101
- }
88
+ if (dispatch) {
89
+ if (can) {
90
+ if (selection instanceof TextSelection) {
91
+ tr.deleteSelection()
92
+ }
102
93
 
103
- tr.split(tr.mapping.map($from.pos), 1, types)
94
+ tr.split(tr.mapping.map($from.pos), 1, types)
104
95
 
105
- if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
106
- const first = tr.mapping.map($from.before())
107
- const $first = tr.doc.resolve(first)
96
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
97
+ const first = tr.mapping.map($from.before())
98
+ const $first = tr.doc.resolve(first)
108
99
 
109
- if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
110
- tr.setNodeMarkup(tr.mapping.map($from.before()), deflt)
100
+ if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
101
+ tr.setNodeMarkup(tr.mapping.map($from.before()), deflt)
102
+ }
111
103
  }
112
104
  }
113
- }
114
105
 
115
- if (keepMarks) {
116
- ensureMarks(state, editor.extensionManager.splittableMarks)
106
+ if (keepMarks) {
107
+ ensureMarks(state, editor.extensionManager.splittableMarks)
108
+ }
109
+
110
+ tr.scrollIntoView()
117
111
  }
118
112
 
119
- tr.scrollIntoView()
113
+ return can
120
114
  }
121
-
122
- return can
123
- }
@@ -1,6 +1,4 @@
1
- import {
2
- Fragment, Node as ProseMirrorNode, NodeType, Slice,
3
- } from '@tiptap/pm/model'
1
+ import { Fragment, Node as ProseMirrorNode, NodeType, Slice } from '@tiptap/pm/model'
4
2
  import { TextSelection } from '@tiptap/pm/state'
5
3
  import { canSplit } from '@tiptap/pm/transform'
6
4
 
@@ -22,140 +20,129 @@ declare module '@tiptap/core' {
22
20
  }
23
21
  }
24
22
 
25
- export const splitListItem: RawCommands['splitListItem'] = (typeOrName, overrideAttrs = {}) => ({
26
- tr, state, dispatch, editor,
27
- }) => {
28
- const type = getNodeType(typeOrName, state.schema)
29
- const { $from, $to } = state.selection
23
+ export const splitListItem: RawCommands['splitListItem'] =
24
+ (typeOrName, overrideAttrs = {}) =>
25
+ ({ tr, state, dispatch, editor }) => {
26
+ const type = getNodeType(typeOrName, state.schema)
27
+ const { $from, $to } = state.selection
30
28
 
31
- // @ts-ignore
32
- // eslint-disable-next-line
29
+ // @ts-ignore
30
+ // eslint-disable-next-line
33
31
  const node: ProseMirrorNode = state.selection.node
34
32
 
35
- if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) {
36
- return false
37
- }
38
-
39
- const grandParent = $from.node(-1)
33
+ if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) {
34
+ return false
35
+ }
40
36
 
41
- if (grandParent.type !== type) {
42
- return false
43
- }
37
+ const grandParent = $from.node(-1)
44
38
 
45
- const extensionAttributes = editor.extensionManager.attributes
46
-
47
- if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
48
- // In an empty block. If this is a nested list, the wrapping
49
- // list item should be split. Otherwise, bail out and let next
50
- // command handle lifting.
51
- if (
52
- $from.depth === 2
53
- || $from.node(-3).type !== type
54
- || $from.index(-2) !== $from.node(-2).childCount - 1
55
- ) {
39
+ if (grandParent.type !== type) {
56
40
  return false
57
41
  }
58
42
 
59
- if (dispatch) {
60
- let wrap = Fragment.empty
61
- // eslint-disable-next-line
62
- const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3
43
+ const extensionAttributes = editor.extensionManager.attributes
63
44
 
64
- // Build a fragment containing empty versions of the structure
65
- // from the outer list item to the parent node of the cursor
66
- for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
67
- wrap = Fragment.from($from.node(d).copy(wrap))
45
+ if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
46
+ // In an empty block. If this is a nested list, the wrapping
47
+ // list item should be split. Otherwise, bail out and let next
48
+ // command handle lifting.
49
+ if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
50
+ return false
68
51
  }
69
52
 
70
- // eslint-disable-next-line
71
- const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
72
-
73
- // Add a second list item with an empty default start node
74
- const newNextTypeAttributes = {
75
- ...getSplittedAttributes(
76
- extensionAttributes,
77
- $from.node().type.name,
78
- $from.node().attrs,
79
- ),
80
- ...overrideAttrs,
81
- }
82
- const nextType = type.contentMatch.defaultType?.createAndFill(newNextTypeAttributes) || undefined
53
+ if (dispatch) {
54
+ let wrap = Fragment.empty
55
+ // eslint-disable-next-line
56
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3
83
57
 
84
- wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType) || undefined))
58
+ // Build a fragment containing empty versions of the structure
59
+ // from the outer list item to the parent node of the cursor
60
+ for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
61
+ wrap = Fragment.from($from.node(d).copy(wrap))
62
+ }
85
63
 
86
- const start = $from.before($from.depth - (depthBefore - 1))
64
+ const depthAfter =
65
+ // eslint-disable-next-line no-nested-ternary
66
+ $from.indexAfter(-1) < $from.node(-2).childCount
67
+ ? 1
68
+ : $from.indexAfter(-2) < $from.node(-3).childCount
69
+ ? 2
70
+ : 3
71
+
72
+ // Add a second list item with an empty default start node
73
+ const newNextTypeAttributes = {
74
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
75
+ ...overrideAttrs,
76
+ }
77
+ const nextType = type.contentMatch.defaultType?.createAndFill(newNextTypeAttributes) || undefined
87
78
 
88
- tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0))
79
+ wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType) || undefined))
89
80
 
90
- let sel = -1
81
+ const start = $from.before($from.depth - (depthBefore - 1))
91
82
 
92
- tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
93
- if (sel > -1) {
94
- return false
95
- }
83
+ tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0))
84
+
85
+ let sel = -1
96
86
 
97
- if (n.isTextblock && n.content.size === 0) {
98
- sel = pos + 1
87
+ tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
88
+ if (sel > -1) {
89
+ return false
90
+ }
91
+
92
+ if (n.isTextblock && n.content.size === 0) {
93
+ sel = pos + 1
94
+ }
95
+ })
96
+
97
+ if (sel > -1) {
98
+ tr.setSelection(TextSelection.near(tr.doc.resolve(sel)))
99
99
  }
100
- })
101
100
 
102
- if (sel > -1) {
103
- tr.setSelection(TextSelection.near(tr.doc.resolve(sel)))
101
+ tr.scrollIntoView()
104
102
  }
105
103
 
106
- tr.scrollIntoView()
104
+ return true
107
105
  }
108
106
 
109
- return true
110
- }
107
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null
111
108
 
112
- const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null
109
+ const newTypeAttributes = {
110
+ ...getSplittedAttributes(extensionAttributes, grandParent.type.name, grandParent.attrs),
111
+ ...overrideAttrs,
112
+ }
113
+ const newNextTypeAttributes = {
114
+ ...getSplittedAttributes(extensionAttributes, $from.node().type.name, $from.node().attrs),
115
+ ...overrideAttrs,
116
+ }
113
117
 
114
- const newTypeAttributes = {
115
- ...getSplittedAttributes(
116
- extensionAttributes,
117
- grandParent.type.name,
118
- grandParent.attrs,
119
- ),
120
- ...overrideAttrs,
121
- }
122
- const newNextTypeAttributes = {
123
- ...getSplittedAttributes(
124
- extensionAttributes,
125
- $from.node().type.name,
126
- $from.node().attrs,
127
- ),
128
- ...overrideAttrs,
129
- }
118
+ tr.delete($from.pos, $to.pos)
130
119
 
131
- tr.delete($from.pos, $to.pos)
120
+ const types = nextType
121
+ ? [
122
+ { type, attrs: newTypeAttributes },
123
+ { type: nextType, attrs: newNextTypeAttributes },
124
+ ]
125
+ : [{ type, attrs: newTypeAttributes }]
132
126
 
133
- const types = nextType
134
- ? [
135
- { type, attrs: newTypeAttributes },
136
- { type: nextType, attrs: newNextTypeAttributes },
137
- ]
138
- : [{ type, attrs: newTypeAttributes }]
127
+ if (!canSplit(tr.doc, $from.pos, 2)) {
128
+ return false
129
+ }
139
130
 
140
- if (!canSplit(tr.doc, $from.pos, 2)) {
141
- return false
142
- }
131
+ if (dispatch) {
132
+ const { selection, storedMarks } = state
133
+ const { splittableMarks } = editor.extensionManager
134
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
143
135
 
144
- if (dispatch) {
145
- const { selection, storedMarks } = state
146
- const { splittableMarks } = editor.extensionManager
147
- const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
136
+ tr.split($from.pos, 2, types).scrollIntoView()
148
137
 
149
- tr.split($from.pos, 2, types).scrollIntoView()
138
+ if (!marks || !dispatch) {
139
+ return true
140
+ }
150
141
 
151
- if (!marks || !dispatch) {
152
- return true
153
- }
142
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
154
143
 
155
- const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
144
+ tr.ensureMarks(filteredMarks)
145
+ }
156
146
 
157
- tr.ensureMarks(filteredMarks)
147
+ return true
158
148
  }
159
-
160
- return true
161
- }