@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
|
@@ -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
|
+
}
|
|
@@ -30,34 +30,36 @@ declare module '@tiptap/core' {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
export const unsetMark: RawCommands['unsetMark'] =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
export const unsetMark: RawCommands['unsetMark'] =
|
|
34
|
+
(typeOrName, options = {}) =>
|
|
35
|
+
({ tr, state, dispatch }) => {
|
|
36
|
+
const { extendEmptyMarkRange = false } = options
|
|
37
|
+
const { selection } = tr
|
|
38
|
+
const type = getMarkType(typeOrName, state.schema)
|
|
39
|
+
const { $from, empty, ranges } = selection
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
if (!dispatch) {
|
|
42
|
+
return true
|
|
43
|
+
}
|
|
42
44
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
if (empty && extendEmptyMarkRange) {
|
|
46
|
+
let { from, to } = selection
|
|
47
|
+
const attrs = $from.marks().find(mark => mark.type === type)?.attrs
|
|
48
|
+
const range = getMarkRange($from, type, attrs)
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
if (range) {
|
|
51
|
+
from = range.from
|
|
52
|
+
to = range.to
|
|
53
|
+
}
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
tr.removeMark(from, to, type)
|
|
56
|
+
} else {
|
|
57
|
+
ranges.forEach(range => {
|
|
58
|
+
tr.removeMark(range.$from.pos, range.$to.pos, type)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
tr.removeStoredMark(type)
|
|
61
63
|
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
+
return true
|
|
65
|
+
}
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Mark, MarkType, Node, NodeType,
|
|
3
|
-
} from '@tiptap/pm/model'
|
|
1
|
+
import { Mark, MarkType, Node, NodeType } from '@tiptap/pm/model'
|
|
4
2
|
import { SelectionRange } from '@tiptap/pm/state'
|
|
5
3
|
|
|
6
4
|
import { getMarkType } from '../helpers/getMarkType.js'
|
|
@@ -32,117 +30,111 @@ declare module '@tiptap/core' {
|
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
export const updateAttributes: RawCommands['updateAttributes'] =
|
|
33
|
+
export const updateAttributes: RawCommands['updateAttributes'] =
|
|
34
|
+
(typeOrName, attributes = {}) =>
|
|
35
|
+
({ tr, state, dispatch }) => {
|
|
36
|
+
let nodeType: NodeType | null = null
|
|
37
|
+
let markType: MarkType | null = null
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
const schemaType = getSchemaTypeNameByName(
|
|
40
|
+
typeof typeOrName === 'string' ? typeOrName : typeOrName.name,
|
|
41
|
+
state.schema,
|
|
42
|
+
)
|
|
39
43
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
if (!schemaType) {
|
|
46
|
-
return false
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
if (schemaType === 'node') {
|
|
50
|
-
nodeType = getNodeType(typeOrName as NodeType, state.schema)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (schemaType === 'mark') {
|
|
54
|
-
markType = getMarkType(typeOrName as MarkType, state.schema)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (dispatch) {
|
|
58
|
-
tr.selection.ranges.forEach((range: SelectionRange) => {
|
|
44
|
+
if (!schemaType) {
|
|
45
|
+
return false
|
|
46
|
+
}
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
|
|
48
|
+
if (schemaType === 'node') {
|
|
49
|
+
nodeType = getNodeType(typeOrName as NodeType, state.schema)
|
|
50
|
+
}
|
|
62
51
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
let trimmedTo: number
|
|
52
|
+
if (schemaType === 'mark') {
|
|
53
|
+
markType = getMarkType(typeOrName as MarkType, state.schema)
|
|
54
|
+
}
|
|
67
55
|
|
|
68
|
-
|
|
69
|
-
|
|
56
|
+
if (dispatch) {
|
|
57
|
+
tr.selection.ranges.forEach((range: SelectionRange) => {
|
|
58
|
+
const from = range.$from.pos
|
|
59
|
+
const to = range.$to.pos
|
|
70
60
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
lastNode = node
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
} else {
|
|
79
|
-
state.doc.nodesBetween(from, to, (node: Node, pos: number) => {
|
|
80
|
-
|
|
81
|
-
if (pos < from && nodeType && nodeType === node.type) {
|
|
82
|
-
trimmedFrom = Math.max(pos, from)
|
|
83
|
-
trimmedTo = Math.min(pos + node.nodeSize, to)
|
|
84
|
-
lastPos = pos
|
|
85
|
-
lastNode = node
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (pos >= from && pos <= to) {
|
|
61
|
+
let lastPos: number | undefined
|
|
62
|
+
let lastNode: Node | undefined
|
|
63
|
+
let trimmedFrom: number
|
|
64
|
+
let trimmedTo: number
|
|
89
65
|
|
|
66
|
+
if (tr.selection.empty) {
|
|
67
|
+
state.doc.nodesBetween(from, to, (node: Node, pos: number) => {
|
|
90
68
|
if (nodeType && nodeType === node.type) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
69
|
+
trimmedFrom = Math.max(pos, from)
|
|
70
|
+
trimmedTo = Math.min(pos + node.nodeSize, to)
|
|
71
|
+
lastPos = pos
|
|
72
|
+
lastNode = node
|
|
95
73
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
tr.addMark(
|
|
105
|
-
trimmedFrom2,
|
|
106
|
-
trimmedTo2,
|
|
107
|
-
markType.create({
|
|
108
|
-
...mark.attrs,
|
|
109
|
-
...attributes,
|
|
110
|
-
}),
|
|
111
|
-
)
|
|
112
|
-
}
|
|
113
|
-
})
|
|
74
|
+
})
|
|
75
|
+
} else {
|
|
76
|
+
state.doc.nodesBetween(from, to, (node: Node, pos: number) => {
|
|
77
|
+
if (pos < from && nodeType && nodeType === node.type) {
|
|
78
|
+
trimmedFrom = Math.max(pos, from)
|
|
79
|
+
trimmedTo = Math.min(pos + node.nodeSize, to)
|
|
80
|
+
lastPos = pos
|
|
81
|
+
lastNode = node
|
|
114
82
|
}
|
|
115
|
-
}
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
83
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
84
|
+
if (pos >= from && pos <= to) {
|
|
85
|
+
if (nodeType && nodeType === node.type) {
|
|
86
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
87
|
+
...node.attrs,
|
|
88
|
+
...attributes,
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (markType && node.marks.length) {
|
|
93
|
+
node.marks.forEach((mark: Mark) => {
|
|
94
|
+
if (markType === mark.type) {
|
|
95
|
+
const trimmedFrom2 = Math.max(pos, from)
|
|
96
|
+
const trimmedTo2 = Math.min(pos + node.nodeSize, to)
|
|
97
|
+
|
|
98
|
+
tr.addMark(
|
|
99
|
+
trimmedFrom2,
|
|
100
|
+
trimmedTo2,
|
|
101
|
+
markType.create({
|
|
102
|
+
...mark.attrs,
|
|
103
|
+
...attributes,
|
|
104
|
+
}),
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
}
|
|
125
110
|
})
|
|
126
111
|
}
|
|
127
112
|
|
|
128
|
-
if (
|
|
129
|
-
|
|
113
|
+
if (lastNode) {
|
|
114
|
+
if (lastPos !== undefined) {
|
|
115
|
+
tr.setNodeMarkup(lastPos, undefined, {
|
|
116
|
+
...lastNode.attrs,
|
|
117
|
+
...attributes,
|
|
118
|
+
})
|
|
119
|
+
}
|
|
130
120
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
121
|
+
if (markType && lastNode.marks.length) {
|
|
122
|
+
lastNode.marks.forEach((mark: Mark) => {
|
|
123
|
+
if (markType === mark.type) {
|
|
124
|
+
tr.addMark(
|
|
125
|
+
trimmedFrom,
|
|
126
|
+
trimmedTo,
|
|
127
|
+
markType.create({
|
|
128
|
+
...mark.attrs,
|
|
129
|
+
...attributes,
|
|
130
|
+
}),
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
})
|
|
134
|
+
}
|
|
142
135
|
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
136
|
+
})
|
|
137
|
+
}
|
|
146
138
|
|
|
147
|
-
|
|
148
|
-
}
|
|
139
|
+
return true
|
|
140
|
+
}
|
package/src/commands/wrapIn.ts
CHANGED
|
@@ -18,8 +18,10 @@ declare module '@tiptap/core' {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export const wrapIn: RawCommands['wrapIn'] =
|
|
22
|
-
|
|
21
|
+
export const wrapIn: RawCommands['wrapIn'] =
|
|
22
|
+
(typeOrName, attributes = {}) =>
|
|
23
|
+
({ state, dispatch }) => {
|
|
24
|
+
const type = getNodeType(typeOrName, state.schema)
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
+
return originalWrapIn(type, attributes)(state, dispatch)
|
|
27
|
+
}
|