@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.
- package/LICENSE.md +21 -0
- package/README.md +5 -1
- package/dist/index.cjs +2627 -2651
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2423 -2688
- package/dist/index.d.ts +2423 -2688
- package/dist/index.js +2639 -2684
- package/dist/index.js.map +1 -1
- package/dist/jsx-runtime/jsx-runtime.cjs +56 -0
- package/dist/jsx-runtime/jsx-runtime.cjs.map +1 -0
- package/dist/jsx-runtime/jsx-runtime.d.cts +22 -0
- package/dist/jsx-runtime/jsx-runtime.d.ts +22 -0
- package/dist/jsx-runtime/jsx-runtime.js +26 -0
- package/dist/jsx-runtime/jsx-runtime.js.map +1 -0
- package/jsx-runtime/index.cjs +1 -0
- package/jsx-runtime/index.d.cts +1 -0
- package/jsx-runtime/index.d.ts +1 -0
- package/jsx-runtime/index.js +1 -0
- package/package.json +27 -6
- package/src/CommandManager.ts +2 -9
- package/src/Editor.ts +191 -94
- package/src/EventEmitter.ts +7 -10
- package/src/Extendable.ts +483 -0
- package/src/Extension.ts +5 -496
- package/src/ExtensionManager.ts +81 -135
- package/src/InputRule.ts +35 -48
- package/src/Mark.ts +135 -623
- package/src/MarkView.ts +66 -0
- package/src/Node.ts +325 -829
- package/src/NodePos.ts +1 -3
- package/src/NodeView.ts +10 -20
- package/src/PasteRule.ts +43 -55
- package/src/Tracker.ts +7 -9
- package/src/commands/blur.ts +14 -12
- package/src/commands/clearContent.ts +12 -5
- package/src/commands/clearNodes.ts +32 -30
- package/src/commands/command.ts +1 -1
- package/src/commands/createParagraphNear.ts +5 -3
- package/src/commands/cut.ts +12 -10
- package/src/commands/deleteCurrentNode.ts +23 -21
- package/src/commands/deleteNode.ts +18 -16
- package/src/commands/deleteRange.ts +10 -8
- package/src/commands/deleteSelection.ts +5 -3
- package/src/commands/enter.ts +6 -4
- package/src/commands/exitCode.ts +5 -3
- package/src/commands/extendMarkRange.ts +14 -12
- package/src/commands/first.ts +2 -4
- package/src/commands/focus.ts +51 -48
- package/src/commands/forEach.ts +2 -2
- package/src/commands/insertContent.ts +12 -14
- package/src/commands/insertContentAt.ts +105 -98
- package/src/commands/join.ts +20 -12
- package/src/commands/joinItemBackward.ts +16 -18
- package/src/commands/joinItemForward.ts +16 -18
- package/src/commands/joinTextblockBackward.ts +5 -3
- package/src/commands/joinTextblockForward.ts +5 -3
- package/src/commands/keyboardShortcut.ts +29 -34
- package/src/commands/lift.ts +10 -8
- package/src/commands/liftEmptyBlock.ts +6 -4
- package/src/commands/liftListItem.ts +6 -4
- package/src/commands/newlineInCode.ts +5 -3
- package/src/commands/resetAttributes.ts +36 -41
- package/src/commands/scrollIntoView.ts +9 -7
- package/src/commands/selectAll.ts +10 -8
- package/src/commands/selectNodeBackward.ts +5 -3
- package/src/commands/selectNodeForward.ts +5 -3
- package/src/commands/selectParentNode.ts +5 -3
- package/src/commands/selectTextblockEnd.ts +5 -3
- package/src/commands/selectTextblockStart.ts +5 -3
- package/src/commands/setContent.ts +37 -36
- package/src/commands/setMark.ts +55 -57
- package/src/commands/setMeta.ts +7 -5
- package/src/commands/setNode.ts +32 -30
- package/src/commands/setNodeSelection.ts +11 -9
- package/src/commands/setTextSelection.ts +15 -13
- package/src/commands/sinkListItem.ts +6 -4
- package/src/commands/splitBlock.ts +67 -76
- package/src/commands/splitListItem.ts +93 -106
- package/src/commands/toggleList.ts +73 -71
- package/src/commands/toggleMark.ts +11 -9
- package/src/commands/toggleNode.ts +18 -16
- package/src/commands/toggleWrap.ts +10 -8
- package/src/commands/undoInputRule.ts +31 -29
- package/src/commands/unsetAllMarks.ts +16 -14
- package/src/commands/unsetMark.ts +27 -25
- package/src/commands/updateAttributes.ts +92 -100
- package/src/commands/wrapIn.ts +6 -4
- package/src/commands/wrapInList.ts +6 -4
- package/src/extensions/clipboardTextSerializer.ts +2 -4
- package/src/extensions/delete.ts +89 -0
- package/src/extensions/focusEvents.ts +2 -6
- package/src/extensions/index.ts +1 -0
- package/src/extensions/keymap.ts +58 -50
- package/src/extensions/paste.ts +0 -1
- package/src/extensions/tabindex.ts +1 -1
- package/src/helpers/combineTransactionSteps.ts +1 -4
- package/src/helpers/createChainableState.ts +1 -4
- package/src/helpers/createDocument.ts +1 -3
- package/src/helpers/createNodeFromContent.ts +4 -10
- package/src/helpers/findChildrenInRange.ts +1 -5
- package/src/helpers/findParentNode.ts +3 -1
- package/src/helpers/flattenExtensions.ts +30 -0
- package/src/helpers/getAttributes.ts +1 -4
- package/src/helpers/getAttributesFromExtensions.ts +28 -37
- package/src/helpers/getChangedRanges.ts +13 -11
- package/src/helpers/getExtensionField.ts +11 -11
- package/src/helpers/getMarkAttributes.ts +1 -4
- package/src/helpers/getMarkRange.ts +5 -15
- package/src/helpers/getMarkType.ts +1 -3
- package/src/helpers/getNodeAttributes.ts +1 -4
- package/src/helpers/getNodeType.ts +1 -3
- package/src/helpers/getRenderedAttributes.ts +1 -3
- package/src/helpers/getSchema.ts +2 -2
- package/src/helpers/getSchemaByResolvedExtensions.ts +45 -77
- package/src/helpers/getSplittedAttributes.ts +4 -4
- package/src/helpers/getTextContentFromNodes.ts +8 -11
- package/src/helpers/index.ts +4 -0
- package/src/helpers/injectExtensionAttributesToParseRule.ts +1 -1
- package/src/helpers/isActive.ts +1 -5
- package/src/helpers/isExtensionRulesEnabled.ts +1 -3
- package/src/helpers/isNodeEmpty.ts +2 -2
- package/src/helpers/resolveExtensions.ts +25 -0
- package/src/helpers/resolveFocusPosition.ts +3 -14
- package/src/helpers/rewriteUnknownContent.ts +149 -0
- package/src/helpers/sortExtensions.ts +26 -0
- package/src/index.ts +3 -7
- package/src/inputRules/markInputRule.ts +1 -5
- package/src/inputRules/nodeInputRule.ts +2 -9
- package/src/inputRules/textInputRule.ts +1 -4
- package/src/inputRules/textblockTypeInputRule.ts +2 -8
- package/src/inputRules/wrappingInputRule.ts +13 -19
- package/src/jsx-runtime.ts +64 -0
- package/src/pasteRules/markPasteRule.ts +1 -3
- package/src/pasteRules/nodePasteRule.ts +2 -8
- package/src/pasteRules/textPasteRule.ts +1 -4
- package/src/types.ts +529 -174
- package/src/utilities/createStyleTag.ts +3 -1
- package/src/utilities/deleteProps.ts +7 -11
- package/src/utilities/elementFromString.ts +3 -0
- package/src/utilities/findDuplicates.ts +4 -1
- package/src/utilities/index.ts +1 -0
- package/src/utilities/isFunction.ts +1 -0
- package/src/utilities/isMacOS.ts +1 -3
- package/src/utilities/isiOS.ts +5 -10
- package/src/utilities/mergeAttributes.ts +17 -7
- package/src/utilities/removeDuplicates.ts +1 -3
package/src/commands/setNode.ts
CHANGED
|
@@ -18,38 +18,40 @@ declare module '@tiptap/core' {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const setNode: RawCommands['setNode'] =
|
|
22
|
-
|
|
21
|
+
export const setNode: RawCommands['setNode'] =
|
|
22
|
+
(typeOrName, attributes = {}) =>
|
|
23
|
+
({ state, dispatch, chain }) => {
|
|
24
|
+
const type = getNodeType(typeOrName, state.schema)
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
let attributesToCopy: Record<string, any> | undefined
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
+
return false
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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'] =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
|
|
27
|
+
tr.setSelection(selection)
|
|
28
|
+
}
|
|
27
29
|
|
|
28
|
-
|
|
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'] =
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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
|
-
|
|
30
|
-
|
|
31
|
+
tr.setSelection(selection)
|
|
32
|
+
}
|
|
31
33
|
|
|
32
|
-
|
|
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'] =
|
|
21
|
-
|
|
20
|
+
export const sinkListItem: RawCommands['sinkListItem'] =
|
|
21
|
+
typeOrName =>
|
|
22
|
+
({ state, dispatch }) => {
|
|
23
|
+
const type = getNodeType(typeOrName, state.schema)
|
|
22
24
|
|
|
23
|
-
|
|
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'] =
|
|
33
|
-
|
|
34
|
-
}) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
|
|
53
|
+
return true
|
|
55
54
|
}
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (!$from.parent.isBlock) {
|
|
61
|
-
return false
|
|
62
|
-
}
|
|
56
|
+
if (!$from.parent.isBlock) {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
88
|
+
if (dispatch) {
|
|
89
|
+
if (can) {
|
|
90
|
+
if (selection instanceof TextSelection) {
|
|
91
|
+
tr.deleteSelection()
|
|
92
|
+
}
|
|
102
93
|
|
|
103
|
-
|
|
94
|
+
tr.split(tr.mapping.map($from.pos), 1, types)
|
|
104
95
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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
|
-
|
|
110
|
-
|
|
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
|
-
|
|
116
|
-
|
|
106
|
+
if (keepMarks) {
|
|
107
|
+
ensureMarks(state, editor.extensionManager.splittableMarks)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
tr.scrollIntoView()
|
|
117
111
|
}
|
|
118
112
|
|
|
119
|
-
|
|
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'] =
|
|
26
|
-
|
|
27
|
-
}) => {
|
|
28
|
-
|
|
29
|
-
|
|
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
|
-
|
|
32
|
-
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
// eslint-disable-next-line
|
|
33
31
|
const node: ProseMirrorNode = state.selection.node
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
42
|
-
return false
|
|
43
|
-
}
|
|
37
|
+
const grandParent = $from.node(-1)
|
|
44
38
|
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
79
|
+
wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType) || undefined))
|
|
89
80
|
|
|
90
|
-
|
|
81
|
+
const start = $from.before($from.depth - (depthBefore - 1))
|
|
91
82
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
}
|
|
83
|
+
tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0))
|
|
84
|
+
|
|
85
|
+
let sel = -1
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
sel
|
|
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
|
-
|
|
103
|
-
tr.setSelection(TextSelection.near(tr.doc.resolve(sel)))
|
|
101
|
+
tr.scrollIntoView()
|
|
104
102
|
}
|
|
105
103
|
|
|
106
|
-
|
|
104
|
+
return true
|
|
107
105
|
}
|
|
108
106
|
|
|
109
|
-
|
|
110
|
-
}
|
|
107
|
+
const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null
|
|
111
108
|
|
|
112
|
-
|
|
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
|
-
|
|
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
|
-
|
|
120
|
+
const types = nextType
|
|
121
|
+
? [
|
|
122
|
+
{ type, attrs: newTypeAttributes },
|
|
123
|
+
{ type: nextType, attrs: newNextTypeAttributes },
|
|
124
|
+
]
|
|
125
|
+
: [{ type, attrs: newTypeAttributes }]
|
|
132
126
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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
|
-
|
|
141
|
-
|
|
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
|
-
|
|
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
|
-
|
|
138
|
+
if (!marks || !dispatch) {
|
|
139
|
+
return true
|
|
140
|
+
}
|
|
150
141
|
|
|
151
|
-
|
|
152
|
-
return true
|
|
153
|
-
}
|
|
142
|
+
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
154
143
|
|
|
155
|
-
|
|
144
|
+
tr.ensureMarks(filteredMarks)
|
|
145
|
+
}
|
|
156
146
|
|
|
157
|
-
|
|
147
|
+
return true
|
|
158
148
|
}
|
|
159
|
-
|
|
160
|
-
return true
|
|
161
|
-
}
|