@tiptap/core 3.0.0-next.2 → 3.0.0-next.4
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 +2402 -2540
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1355 -1273
- package/dist/index.d.ts +1355 -1273
- package/dist/index.js +2408 -2562
- package/dist/index.js.map +1 -1
- package/package.json +9 -5
- package/src/CommandManager.ts +2 -9
- package/src/Editor.ts +87 -72
- package/src/EventEmitter.ts +7 -10
- package/src/Extension.ts +8 -14
- package/src/ExtensionManager.ts +26 -125
- package/src/InputRule.ts +35 -48
- package/src/Mark.ts +9 -9
- package/src/Node.ts +9 -9
- 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 +6 -4
- 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 +45 -48
- package/src/commands/forEach.ts +2 -2
- package/src/commands/insertContent.ts +12 -14
- package/src/commands/insertContentAt.ts +101 -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 +25 -25
- 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/focusEvents.ts +2 -6
- package/src/extensions/keymap.ts +54 -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 +1 -4
- 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/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/pasteRules/markPasteRule.ts +1 -3
- package/src/pasteRules/nodePasteRule.ts +2 -8
- package/src/pasteRules/textPasteRule.ts +1 -4
- package/src/types.ts +212 -172
- package/src/utilities/createStyleTag.ts +3 -1
- package/src/utilities/deleteProps.ts +7 -11
- package/src/utilities/findDuplicates.ts +4 -1
- 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 +16 -6
- package/src/utilities/removeDuplicates.ts +1 -3
|
@@ -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
|
-
}
|
|
@@ -68,90 +68,92 @@ declare module '@tiptap/core' {
|
|
|
68
68
|
* @param attributes Attributes for the new list.
|
|
69
69
|
* @example editor.commands.toggleList('bulletList', 'listItem')
|
|
70
70
|
*/
|
|
71
|
-
toggleList: (
|
|
71
|
+
toggleList: (
|
|
72
|
+
listTypeOrName: string | NodeType,
|
|
73
|
+
itemTypeOrName: string | NodeType,
|
|
74
|
+
keepMarks?: boolean,
|
|
75
|
+
attributes?: Record<string, any>,
|
|
76
|
+
) => ReturnType
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
}
|
|
75
80
|
|
|
76
|
-
export const toggleList: RawCommands['toggleList'] =
|
|
77
|
-
|
|
78
|
-
}) => {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
export const toggleList: RawCommands['toggleList'] =
|
|
82
|
+
(listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) =>
|
|
83
|
+
({ editor, tr, state, dispatch, chain, commands, can }) => {
|
|
84
|
+
const { extensions, splittableMarks } = editor.extensionManager
|
|
85
|
+
const listType = getNodeType(listTypeOrName, state.schema)
|
|
86
|
+
const itemType = getNodeType(itemTypeOrName, state.schema)
|
|
87
|
+
const { selection, storedMarks } = state
|
|
88
|
+
const { $from, $to } = selection
|
|
89
|
+
const range = $from.blockRange($to)
|
|
85
90
|
|
|
86
|
-
|
|
91
|
+
const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
|
|
87
92
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const parentList = findParentNode(node => isList(node.type.name, extensions))(selection)
|
|
93
|
+
if (!range) {
|
|
94
|
+
return false
|
|
95
|
+
}
|
|
93
96
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (parentList.
|
|
97
|
-
|
|
97
|
+
const parentList = findParentNode(node => isList(node.type.name, extensions))(selection)
|
|
98
|
+
|
|
99
|
+
if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
|
|
100
|
+
// remove list
|
|
101
|
+
if (parentList.node.type === listType) {
|
|
102
|
+
return commands.liftListItem(itemType)
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// change list type
|
|
106
|
+
if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
|
|
107
|
+
return chain()
|
|
108
|
+
.command(() => {
|
|
109
|
+
tr.setNodeMarkup(parentList.pos, listType)
|
|
110
|
+
|
|
111
|
+
return true
|
|
112
|
+
})
|
|
113
|
+
.command(() => joinListBackwards(tr, listType))
|
|
114
|
+
.command(() => joinListForwards(tr, listType))
|
|
115
|
+
.run()
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!keepMarks || !marks || !dispatch) {
|
|
119
|
+
return (
|
|
120
|
+
chain()
|
|
121
|
+
// try to convert node to default node if needed
|
|
122
|
+
.command(() => {
|
|
123
|
+
const canWrapInList = can().wrapInList(listType, attributes)
|
|
124
|
+
|
|
125
|
+
if (canWrapInList) {
|
|
126
|
+
return true
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return commands.clearNodes()
|
|
130
|
+
})
|
|
131
|
+
.wrapInList(listType, attributes)
|
|
132
|
+
.command(() => joinListBackwards(tr, listType))
|
|
133
|
+
.command(() => joinListForwards(tr, listType))
|
|
134
|
+
.run()
|
|
135
|
+
)
|
|
98
136
|
}
|
|
99
137
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
&& listType.validContent(parentList.node.content)
|
|
104
|
-
&& dispatch
|
|
105
|
-
) {
|
|
106
|
-
return chain()
|
|
138
|
+
return (
|
|
139
|
+
chain()
|
|
140
|
+
// try to convert node to default node if needed
|
|
107
141
|
.command(() => {
|
|
108
|
-
|
|
142
|
+
const canWrapInList = can().wrapInList(listType, attributes)
|
|
109
143
|
|
|
110
|
-
|
|
144
|
+
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
145
|
+
|
|
146
|
+
tr.ensureMarks(filteredMarks)
|
|
147
|
+
|
|
148
|
+
if (canWrapInList) {
|
|
149
|
+
return true
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return commands.clearNodes()
|
|
111
153
|
})
|
|
154
|
+
.wrapInList(listType, attributes)
|
|
112
155
|
.command(() => joinListBackwards(tr, listType))
|
|
113
156
|
.command(() => joinListForwards(tr, listType))
|
|
114
157
|
.run()
|
|
115
|
-
|
|
158
|
+
)
|
|
116
159
|
}
|
|
117
|
-
if (!keepMarks || !marks || !dispatch) {
|
|
118
|
-
|
|
119
|
-
return chain()
|
|
120
|
-
// try to convert node to default node if needed
|
|
121
|
-
.command(() => {
|
|
122
|
-
const canWrapInList = can().wrapInList(listType, attributes)
|
|
123
|
-
|
|
124
|
-
if (canWrapInList) {
|
|
125
|
-
return true
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return commands.clearNodes()
|
|
129
|
-
})
|
|
130
|
-
.wrapInList(listType, attributes)
|
|
131
|
-
.command(() => joinListBackwards(tr, listType))
|
|
132
|
-
.command(() => joinListForwards(tr, listType))
|
|
133
|
-
.run()
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
chain()
|
|
138
|
-
// try to convert node to default node if needed
|
|
139
|
-
.command(() => {
|
|
140
|
-
const canWrapInList = can().wrapInList(listType, attributes)
|
|
141
|
-
|
|
142
|
-
const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
|
|
143
|
-
|
|
144
|
-
tr.ensureMarks(filteredMarks)
|
|
145
|
-
|
|
146
|
-
if (canWrapInList) {
|
|
147
|
-
return true
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return commands.clearNodes()
|
|
151
|
-
})
|
|
152
|
-
.wrapInList(listType, attributes)
|
|
153
|
-
.command(() => joinListBackwards(tr, listType))
|
|
154
|
-
.command(() => joinListForwards(tr, listType))
|
|
155
|
-
.run()
|
|
156
|
-
)
|
|
157
|
-
}
|
|
@@ -36,14 +36,16 @@ declare module '@tiptap/core' {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
export const toggleMark: RawCommands['toggleMark'] =
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
39
|
+
export const toggleMark: RawCommands['toggleMark'] =
|
|
40
|
+
(typeOrName, attributes = {}, options = {}) =>
|
|
41
|
+
({ state, commands }) => {
|
|
42
|
+
const { extendEmptyMarkRange = false } = options
|
|
43
|
+
const type = getMarkType(typeOrName, state.schema)
|
|
44
|
+
const isActive = isMarkActive(state, type, attributes)
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if (isActive) {
|
|
47
|
+
return commands.unsetMark(type, { extendEmptyMarkRange })
|
|
48
|
+
}
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
+
return commands.setMark(type, attributes)
|
|
51
|
+
}
|
|
@@ -23,23 +23,25 @@ declare module '@tiptap/core' {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
export const toggleNode: RawCommands['toggleNode'] =
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
export const toggleNode: RawCommands['toggleNode'] =
|
|
27
|
+
(typeOrName, toggleTypeOrName, attributes = {}) =>
|
|
28
|
+
({ state, commands }) => {
|
|
29
|
+
const type = getNodeType(typeOrName, state.schema)
|
|
30
|
+
const toggleType = getNodeType(toggleTypeOrName, state.schema)
|
|
31
|
+
const isActive = isNodeActive(state, type, attributes)
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
let attributesToCopy: Record<string, any> | undefined
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
if (state.selection.$anchor.sameParent(state.selection.$head)) {
|
|
36
|
+
// only copy attributes if the selection is pointing to a node of the same type
|
|
37
|
+
attributesToCopy = state.selection.$anchor.parent.attrs
|
|
38
|
+
}
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
if (isActive) {
|
|
41
|
+
return commands.setNode(toggleType, attributesToCopy)
|
|
42
|
+
}
|
|
41
43
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
44
|
+
// If the node is not active, we want to set the new node type with the given attributes
|
|
45
|
+
// Copying over the attributes from the current node if the selection is pointing to a node of the same type
|
|
46
|
+
return commands.setNode(type, { ...attributesToCopy, ...attributes })
|
|
47
|
+
}
|
|
@@ -18,13 +18,15 @@ declare module '@tiptap/core' {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const toggleWrap: RawCommands['toggleWrap'] =
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
export const toggleWrap: RawCommands['toggleWrap'] =
|
|
22
|
+
(typeOrName, attributes = {}) =>
|
|
23
|
+
({ state, commands }) => {
|
|
24
|
+
const type = getNodeType(typeOrName, state.schema)
|
|
25
|
+
const isActive = isNodeActive(state, type, attributes)
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
if (isActive) {
|
|
28
|
+
return commands.lift(type)
|
|
29
|
+
}
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
+
return commands.wrapIn(type, attributes)
|
|
32
|
+
}
|
|
@@ -7,41 +7,43 @@ declare module '@tiptap/core' {
|
|
|
7
7
|
* Undo an input rule.
|
|
8
8
|
* @example editor.commands.undoInputRule()
|
|
9
9
|
*/
|
|
10
|
-
undoInputRule: () => ReturnType
|
|
10
|
+
undoInputRule: () => ReturnType
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const undoInputRule: RawCommands['undoInputRule'] =
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
export const undoInputRule: RawCommands['undoInputRule'] =
|
|
16
|
+
() =>
|
|
17
|
+
({ state, dispatch }) => {
|
|
18
|
+
const plugins = state.plugins
|
|
19
|
+
|
|
20
|
+
for (let i = 0; i < plugins.length; i += 1) {
|
|
21
|
+
const plugin = plugins[i]
|
|
22
|
+
let undoable
|
|
23
|
+
|
|
24
|
+
// @ts-ignore
|
|
25
|
+
// eslint-disable-next-line
|
|
26
|
+
if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
|
|
27
|
+
if (dispatch) {
|
|
28
|
+
const tr = state.tr
|
|
29
|
+
const toUndo = undoable.transform
|
|
30
|
+
|
|
31
|
+
for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
|
|
32
|
+
tr.step(toUndo.steps[j].invert(toUndo.docs[j]))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (undoable.text) {
|
|
36
|
+
const marks = tr.doc.resolve(undoable.from).marks()
|
|
37
|
+
|
|
38
|
+
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks))
|
|
39
|
+
} else {
|
|
40
|
+
tr.delete(undoable.from, undoable.to)
|
|
41
|
+
}
|
|
31
42
|
}
|
|
32
43
|
|
|
33
|
-
|
|
34
|
-
const marks = tr.doc.resolve(undoable.from).marks()
|
|
35
|
-
|
|
36
|
-
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks))
|
|
37
|
-
} else {
|
|
38
|
-
tr.delete(undoable.from, undoable.to)
|
|
39
|
-
}
|
|
44
|
+
return true
|
|
40
45
|
}
|
|
41
|
-
|
|
42
|
-
return true
|
|
43
46
|
}
|
|
44
|
-
}
|
|
45
47
|
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
+
return false
|
|
49
|
+
}
|
|
@@ -7,24 +7,26 @@ declare module '@tiptap/core' {
|
|
|
7
7
|
* Remove all marks in the current selection.
|
|
8
8
|
* @example editor.commands.unsetAllMarks()
|
|
9
9
|
*/
|
|
10
|
-
unsetAllMarks: () => ReturnType
|
|
10
|
+
unsetAllMarks: () => ReturnType
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export const unsetAllMarks: RawCommands['unsetAllMarks'] =
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
export const unsetAllMarks: RawCommands['unsetAllMarks'] =
|
|
16
|
+
() =>
|
|
17
|
+
({ tr, dispatch }) => {
|
|
18
|
+
const { selection } = tr
|
|
19
|
+
const { empty, ranges } = selection
|
|
18
20
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
if (empty) {
|
|
22
|
+
return true
|
|
23
|
+
}
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
if (dispatch) {
|
|
26
|
+
ranges.forEach(range => {
|
|
27
|
+
tr.removeMark(range.$from.pos, range.$to.pos)
|
|
28
|
+
})
|
|
29
|
+
}
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
+
return true
|
|
32
|
+
}
|