@tiptap/core 3.0.0-next.0 → 3.0.0-next.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +4934 -4574
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3576 -0
- package/dist/index.d.ts +3576 -0
- package/dist/index.js +4839 -4481
- package/dist/index.js.map +1 -1
- package/package.json +6 -8
- package/src/Editor.ts +66 -10
- package/src/EventEmitter.ts +9 -0
- package/src/Extension.ts +4 -3
- package/src/ExtensionManager.ts +18 -12
- package/src/InputRule.ts +45 -30
- package/src/Mark.ts +4 -3
- package/src/Node.ts +23 -3
- package/src/NodePos.ts +9 -4
- package/src/NodeView.ts +43 -12
- package/src/PasteRule.ts +96 -42
- package/src/commands/focus.ts +1 -6
- package/src/commands/insertContent.ts +9 -9
- package/src/commands/insertContentAt.ts +23 -3
- package/src/commands/selectAll.ts +10 -5
- package/src/commands/setContent.ts +10 -14
- package/src/commands/setMeta.ts +3 -1
- package/src/commands/setNode.ts +9 -2
- package/src/commands/splitListItem.ts +27 -17
- package/src/commands/toggleNode.ts +11 -2
- package/src/commands/updateAttributes.ts +72 -12
- package/src/extensions/drop.ts +26 -0
- package/src/extensions/index.ts +2 -0
- package/src/extensions/keymap.ts +5 -2
- package/src/extensions/paste.ts +26 -0
- package/src/helpers/createDocument.ts +4 -2
- package/src/helpers/createNodeFromContent.ts +11 -2
- package/src/helpers/getAttributesFromExtensions.ts +1 -1
- package/src/helpers/getMarkRange.ts +35 -8
- package/src/helpers/getMarksBetween.ts +1 -1
- package/src/helpers/getRenderedAttributes.ts +3 -0
- package/src/helpers/getSchemaByResolvedExtensions.ts +3 -2
- package/src/helpers/isList.ts +1 -1
- package/src/helpers/isNodeEmpty.ts +33 -12
- package/src/inputRules/markInputRule.ts +1 -1
- package/src/inputRules/nodeInputRule.ts +1 -1
- package/src/inputRules/textInputRule.ts +1 -1
- package/src/inputRules/textblockTypeInputRule.ts +1 -1
- package/src/inputRules/wrappingInputRule.ts +1 -1
- package/src/pasteRules/markPasteRule.ts +1 -1
- package/src/pasteRules/nodePasteRule.ts +15 -6
- package/src/pasteRules/textPasteRule.ts +1 -1
- package/src/style.ts +2 -2
- package/src/types.ts +107 -19
- package/src/utilities/mergeAttributes.ts +18 -1
- package/dist/index.umd.js +0 -5130
- package/dist/index.umd.js.map +0 -1
- package/dist/packages/core/src/CommandManager.d.ts +0 -20
- package/dist/packages/core/src/Editor.d.ts +0 -159
- package/dist/packages/core/src/EventEmitter.d.ts +0 -11
- package/dist/packages/core/src/Extension.d.ts +0 -343
- package/dist/packages/core/src/ExtensionManager.d.ts +0 -55
- package/dist/packages/core/src/InputRule.d.ts +0 -42
- package/dist/packages/core/src/Mark.d.ts +0 -451
- package/dist/packages/core/src/Node.d.ts +0 -611
- package/dist/packages/core/src/NodePos.d.ts +0 -44
- package/dist/packages/core/src/NodeView.d.ts +0 -31
- package/dist/packages/core/src/PasteRule.d.ts +0 -50
- package/dist/packages/core/src/Tracker.d.ts +0 -11
- package/dist/packages/core/src/commands/blur.d.ts +0 -13
- package/dist/packages/core/src/commands/clearContent.d.ts +0 -14
- package/dist/packages/core/src/commands/clearNodes.d.ts +0 -13
- package/dist/packages/core/src/commands/command.d.ts +0 -18
- package/dist/packages/core/src/commands/createParagraphNear.d.ts +0 -13
- package/dist/packages/core/src/commands/cut.d.ts +0 -20
- package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/deleteNode.d.ts +0 -15
- package/dist/packages/core/src/commands/deleteRange.d.ts +0 -14
- package/dist/packages/core/src/commands/deleteSelection.d.ts +0 -13
- package/dist/packages/core/src/commands/enter.d.ts +0 -13
- package/dist/packages/core/src/commands/exitCode.d.ts +0 -13
- package/dist/packages/core/src/commands/extendMarkRange.d.ts +0 -25
- package/dist/packages/core/src/commands/first.d.ts +0 -14
- package/dist/packages/core/src/commands/focus.d.ts +0 -27
- package/dist/packages/core/src/commands/forEach.d.ts +0 -14
- package/dist/packages/core/src/commands/index.d.ts +0 -55
- package/dist/packages/core/src/commands/insertContent.d.ts +0 -34
- package/dist/packages/core/src/commands/insertContentAt.d.ts +0 -47
- package/dist/packages/core/src/commands/join.d.ts +0 -41
- package/dist/packages/core/src/commands/joinItemBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinItemForward.d.ts +0 -13
- package/dist/packages/core/src/commands/joinTextblockBackward.d.ts +0 -12
- package/dist/packages/core/src/commands/joinTextblockForward.d.ts +0 -12
- package/dist/packages/core/src/commands/keyboardShortcut.d.ts +0 -14
- package/dist/packages/core/src/commands/lift.d.ts +0 -17
- package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +0 -13
- package/dist/packages/core/src/commands/liftListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/newlineInCode.d.ts +0 -13
- package/dist/packages/core/src/commands/resetAttributes.d.ts +0 -16
- package/dist/packages/core/src/commands/scrollIntoView.d.ts +0 -13
- package/dist/packages/core/src/commands/selectAll.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeBackward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectNodeForward.d.ts +0 -13
- package/dist/packages/core/src/commands/selectParentNode.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +0 -13
- package/dist/packages/core/src/commands/selectTextblockStart.d.ts +0 -13
- package/dist/packages/core/src/commands/setContent.d.ts +0 -40
- package/dist/packages/core/src/commands/setMark.d.ts +0 -15
- package/dist/packages/core/src/commands/setMeta.d.ts +0 -15
- package/dist/packages/core/src/commands/setNode.d.ts +0 -16
- package/dist/packages/core/src/commands/setNodeSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/setTextSelection.d.ts +0 -14
- package/dist/packages/core/src/commands/sinkListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/splitBlock.d.ts +0 -17
- package/dist/packages/core/src/commands/splitListItem.d.ts +0 -15
- package/dist/packages/core/src/commands/toggleList.d.ts +0 -18
- package/dist/packages/core/src/commands/toggleMark.d.ts +0 -30
- package/dist/packages/core/src/commands/toggleNode.d.ts +0 -17
- package/dist/packages/core/src/commands/toggleWrap.d.ts +0 -16
- package/dist/packages/core/src/commands/undoInputRule.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetAllMarks.d.ts +0 -13
- package/dist/packages/core/src/commands/unsetMark.d.ts +0 -25
- package/dist/packages/core/src/commands/updateAttributes.d.ts +0 -24
- package/dist/packages/core/src/commands/wrapIn.d.ts +0 -16
- package/dist/packages/core/src/commands/wrapInList.d.ts +0 -16
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +0 -5
- package/dist/packages/core/src/extensions/commands.d.ts +0 -3
- package/dist/packages/core/src/extensions/editable.d.ts +0 -2
- package/dist/packages/core/src/extensions/focusEvents.d.ts +0 -2
- package/dist/packages/core/src/extensions/index.d.ts +0 -6
- package/dist/packages/core/src/extensions/keymap.d.ts +0 -2
- package/dist/packages/core/src/extensions/tabindex.d.ts +0 -2
- package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +0 -10
- package/dist/packages/core/src/helpers/createChainableState.d.ts +0 -10
- package/dist/packages/core/src/helpers/createDocument.d.ts +0 -12
- package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +0 -15
- package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +0 -7
- package/dist/packages/core/src/helpers/findChildren.d.ts +0 -9
- package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +0 -10
- package/dist/packages/core/src/helpers/findParentNode.d.ts +0 -16
- package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +0 -17
- package/dist/packages/core/src/helpers/generateHTML.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateText.d.ts +0 -12
- package/dist/packages/core/src/helpers/getAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +0 -6
- package/dist/packages/core/src/helpers/getChangedRanges.d.ts +0 -11
- package/dist/packages/core/src/helpers/getDebugJSON.d.ts +0 -8
- package/dist/packages/core/src/helpers/getExtensionField.d.ts +0 -9
- package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkRange.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarksBetween.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeAtPosition.d.ts +0 -11
- package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getSchema.d.ts +0 -4
- package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +0 -10
- package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +0 -8
- package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +0 -9
- package/dist/packages/core/src/helpers/getText.d.ts +0 -15
- package/dist/packages/core/src/helpers/getTextBetween.d.ts +0 -14
- package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +0 -8
- package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +0 -8
- package/dist/packages/core/src/helpers/index.d.ts +0 -50
- package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +0 -9
- package/dist/packages/core/src/helpers/isActive.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isAtStartOfNode.d.ts +0 -2
- package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +0 -2
- package/dist/packages/core/src/helpers/isList.d.ts +0 -2
- package/dist/packages/core/src/helpers/isMarkActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +0 -8
- package/dist/packages/core/src/helpers/isNodeSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/isTextSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/posToDOMRect.d.ts +0 -2
- package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +0 -4
- package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +0 -2
- package/dist/packages/core/src/helpers/splitExtensions.d.ts +0 -9
- package/dist/packages/core/src/index.d.ts +0 -24
- package/dist/packages/core/src/inputRules/index.d.ts +0 -5
- package/dist/packages/core/src/inputRules/markInputRule.d.ts +0 -13
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +0 -23
- package/dist/packages/core/src/inputRules/textInputRule.d.ts +0 -10
- package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +0 -15
- package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +0 -28
- package/dist/packages/core/src/pasteRules/index.d.ts +0 -3
- package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +0 -13
- package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +0 -10
- package/dist/packages/core/src/style.d.ts +0 -1
- package/dist/packages/core/src/types.d.ts +0 -253
- package/dist/packages/core/src/utilities/callOrReturn.d.ts +0 -9
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +0 -1
- package/dist/packages/core/src/utilities/deleteProps.d.ts +0 -6
- package/dist/packages/core/src/utilities/elementFromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +0 -1
- package/dist/packages/core/src/utilities/findDuplicates.d.ts +0 -1
- package/dist/packages/core/src/utilities/fromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/index.d.ts +0 -20
- package/dist/packages/core/src/utilities/isAndroid.d.ts +0 -1
- package/dist/packages/core/src/utilities/isEmptyObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isFunction.d.ts +0 -1
- package/dist/packages/core/src/utilities/isMacOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/isNumber.d.ts +0 -1
- package/dist/packages/core/src/utilities/isPlainObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isRegExp.d.ts +0 -1
- package/dist/packages/core/src/utilities/isString.d.ts +0 -1
- package/dist/packages/core/src/utilities/isiOS.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeAttributes.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeDeep.d.ts +0 -1
- package/dist/packages/core/src/utilities/minMax.d.ts +0 -1
- package/dist/packages/core/src/utilities/objectIncludes.d.ts +0 -8
- package/dist/packages/core/src/utilities/removeDuplicates.d.ts +0 -8
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Mark, MarkType, Node, NodeType,
|
|
3
|
+
} from '@tiptap/pm/model'
|
|
4
|
+
import { SelectionRange } from '@tiptap/pm/state'
|
|
2
5
|
|
|
3
6
|
import { getMarkType } from '../helpers/getMarkType.js'
|
|
4
7
|
import { getNodeType } from '../helpers/getNodeType.js'
|
|
@@ -30,6 +33,7 @@ declare module '@tiptap/core' {
|
|
|
30
33
|
}
|
|
31
34
|
|
|
32
35
|
export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
|
|
36
|
+
|
|
33
37
|
let nodeType: NodeType | null = null
|
|
34
38
|
let markType: MarkType | null = null
|
|
35
39
|
|
|
@@ -51,24 +55,80 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
if (dispatch) {
|
|
54
|
-
tr.selection.ranges.forEach(range => {
|
|
58
|
+
tr.selection.ranges.forEach((range: SelectionRange) => {
|
|
59
|
+
|
|
55
60
|
const from = range.$from.pos
|
|
56
61
|
const to = range.$to.pos
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
63
|
+
let lastPos: number | undefined
|
|
64
|
+
let lastNode: Node | undefined
|
|
65
|
+
let trimmedFrom: number
|
|
66
|
+
let trimmedTo: number
|
|
67
|
+
|
|
68
|
+
if (tr.selection.empty) {
|
|
69
|
+
state.doc.nodesBetween(from, to, (node: Node, pos: number) => {
|
|
70
|
+
|
|
71
|
+
if (nodeType && nodeType === node.type) {
|
|
72
|
+
trimmedFrom = Math.max(pos, from)
|
|
73
|
+
trimmedTo = Math.min(pos + node.nodeSize, to)
|
|
74
|
+
lastPos = pos
|
|
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) {
|
|
89
|
+
|
|
90
|
+
if (nodeType && nodeType === node.type) {
|
|
91
|
+
tr.setNodeMarkup(pos, undefined, {
|
|
92
|
+
...node.attrs,
|
|
93
|
+
...attributes,
|
|
94
|
+
})
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (markType && node.marks.length) {
|
|
98
|
+
node.marks.forEach((mark: Mark) => {
|
|
99
|
+
|
|
100
|
+
if (markType === mark.type) {
|
|
101
|
+
const trimmedFrom2 = Math.max(pos, from)
|
|
102
|
+
const trimmedTo2 = Math.min(pos + node.nodeSize, to)
|
|
103
|
+
|
|
104
|
+
tr.addMark(
|
|
105
|
+
trimmedFrom2,
|
|
106
|
+
trimmedTo2,
|
|
107
|
+
markType.create({
|
|
108
|
+
...mark.attrs,
|
|
109
|
+
...attributes,
|
|
110
|
+
}),
|
|
111
|
+
)
|
|
112
|
+
}
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (lastNode) {
|
|
120
|
+
|
|
121
|
+
if (lastPos !== undefined) {
|
|
122
|
+
tr.setNodeMarkup(lastPos, undefined, {
|
|
123
|
+
...lastNode.attrs,
|
|
62
124
|
...attributes,
|
|
63
125
|
})
|
|
64
126
|
}
|
|
65
127
|
|
|
66
|
-
if (markType &&
|
|
67
|
-
|
|
68
|
-
if (markType === mark.type) {
|
|
69
|
-
const trimmedFrom = Math.max(pos, from)
|
|
70
|
-
const trimmedTo = Math.min(pos + node.nodeSize, to)
|
|
128
|
+
if (markType && lastNode.marks.length) {
|
|
129
|
+
lastNode.marks.forEach((mark: Mark) => {
|
|
71
130
|
|
|
131
|
+
if (markType === mark.type) {
|
|
72
132
|
tr.addMark(
|
|
73
133
|
trimmedFrom,
|
|
74
134
|
trimmedTo,
|
|
@@ -80,7 +140,7 @@ export const updateAttributes: RawCommands['updateAttributes'] = (typeOrName, at
|
|
|
80
140
|
}
|
|
81
141
|
})
|
|
82
142
|
}
|
|
83
|
-
}
|
|
143
|
+
}
|
|
84
144
|
})
|
|
85
145
|
}
|
|
86
146
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
|
2
|
+
|
|
3
|
+
import { Extension } from '../Extension.js'
|
|
4
|
+
|
|
5
|
+
export const Drop = Extension.create({
|
|
6
|
+
name: 'drop',
|
|
7
|
+
|
|
8
|
+
addProseMirrorPlugins() {
|
|
9
|
+
return [
|
|
10
|
+
new Plugin({
|
|
11
|
+
key: new PluginKey('tiptapDrop'),
|
|
12
|
+
|
|
13
|
+
props: {
|
|
14
|
+
handleDrop: (_, e, slice, moved) => {
|
|
15
|
+
this.editor.emit('drop', {
|
|
16
|
+
editor: this.editor,
|
|
17
|
+
event: e,
|
|
18
|
+
slice,
|
|
19
|
+
moved,
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
})
|
package/src/extensions/index.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { ClipboardTextSerializer } from './clipboardTextSerializer.js'
|
|
2
2
|
export { Commands } from './commands.js'
|
|
3
|
+
export { Drop } from './drop.js'
|
|
3
4
|
export { Editable } from './editable.js'
|
|
4
5
|
export { FocusEvents } from './focusEvents.js'
|
|
5
6
|
export { Keymap } from './keymap.js'
|
|
7
|
+
export { Paste } from './paste.js'
|
|
6
8
|
export { Tabindex } from './tabindex.js'
|
package/src/extensions/keymap.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { Plugin, PluginKey, Selection } from '@tiptap/pm/state'
|
|
|
3
3
|
import { CommandManager } from '../CommandManager.js'
|
|
4
4
|
import { Extension } from '../Extension.js'
|
|
5
5
|
import { createChainableState } from '../helpers/createChainableState.js'
|
|
6
|
+
import { isNodeEmpty } from '../helpers/isNodeEmpty.js'
|
|
6
7
|
import { isiOS } from '../utilities/isiOS.js'
|
|
7
8
|
import { isMacOS } from '../utilities/isMacOS.js'
|
|
8
9
|
|
|
@@ -106,7 +107,9 @@ export const Keymap = Extension.create({
|
|
|
106
107
|
const docChanges = transactions.some(transaction => transaction.docChanged)
|
|
107
108
|
&& !oldState.doc.eq(newState.doc)
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'))
|
|
111
|
+
|
|
112
|
+
if (!docChanges || ignoreTr) {
|
|
110
113
|
return
|
|
111
114
|
}
|
|
112
115
|
|
|
@@ -119,7 +122,7 @@ export const Keymap = Extension.create({
|
|
|
119
122
|
return
|
|
120
123
|
}
|
|
121
124
|
|
|
122
|
-
const isEmpty =
|
|
125
|
+
const isEmpty = isNodeEmpty(newState.doc)
|
|
123
126
|
|
|
124
127
|
if (!isEmpty) {
|
|
125
128
|
return
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
|
2
|
+
|
|
3
|
+
import { Extension } from '../Extension.js'
|
|
4
|
+
|
|
5
|
+
export const Paste = Extension.create({
|
|
6
|
+
name: 'paste',
|
|
7
|
+
|
|
8
|
+
addProseMirrorPlugins() {
|
|
9
|
+
|
|
10
|
+
return [
|
|
11
|
+
new Plugin({
|
|
12
|
+
key: new PluginKey('tiptapPaste'),
|
|
13
|
+
|
|
14
|
+
props: {
|
|
15
|
+
handlePaste: (_view, e, slice) => {
|
|
16
|
+
this.editor.emit('paste', {
|
|
17
|
+
editor: this.editor,
|
|
18
|
+
event: e,
|
|
19
|
+
slice,
|
|
20
|
+
})
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
}),
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
})
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
Fragment, Node as ProseMirrorNode, ParseOptions, Schema,
|
|
3
|
+
} from '@tiptap/pm/model'
|
|
2
4
|
|
|
3
5
|
import { Content } from '../types.js'
|
|
4
6
|
import { createNodeFromContent } from './createNodeFromContent.js'
|
|
@@ -11,7 +13,7 @@ import { createNodeFromContent } from './createNodeFromContent.js'
|
|
|
11
13
|
* @returns The created Prosemirror document node
|
|
12
14
|
*/
|
|
13
15
|
export function createDocument(
|
|
14
|
-
content: Content,
|
|
16
|
+
content: Content | ProseMirrorNode | Fragment,
|
|
15
17
|
schema: Schema,
|
|
16
18
|
parseOptions: ParseOptions = {},
|
|
17
19
|
options: { errorOnInvalidContent?: boolean } = {},
|
|
@@ -23,10 +23,13 @@ export type CreateNodeFromContentOptions = {
|
|
|
23
23
|
* @returns The created Prosemirror node or fragment
|
|
24
24
|
*/
|
|
25
25
|
export function createNodeFromContent(
|
|
26
|
-
content: Content,
|
|
26
|
+
content: Content | ProseMirrorNode | Fragment,
|
|
27
27
|
schema: Schema,
|
|
28
28
|
options?: CreateNodeFromContentOptions,
|
|
29
29
|
): ProseMirrorNode | Fragment {
|
|
30
|
+
if (content instanceof ProseMirrorNode || content instanceof Fragment) {
|
|
31
|
+
return content
|
|
32
|
+
}
|
|
30
33
|
options = {
|
|
31
34
|
slice: true,
|
|
32
35
|
parseOptions: {},
|
|
@@ -45,7 +48,13 @@ export function createNodeFromContent(
|
|
|
45
48
|
return Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)))
|
|
46
49
|
}
|
|
47
50
|
|
|
48
|
-
|
|
51
|
+
const node = schema.nodeFromJSON(content)
|
|
52
|
+
|
|
53
|
+
if (options.errorOnInvalidContent) {
|
|
54
|
+
node.check()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return node
|
|
49
58
|
} catch (error) {
|
|
50
59
|
if (options.errorOnInvalidContent) {
|
|
51
60
|
throw new Error('[tiptap error]: Invalid JSON content', { cause: error as Error })
|
|
@@ -9,7 +9,14 @@ function findMarkInSet(
|
|
|
9
9
|
attributes: Record<string, any> = {},
|
|
10
10
|
): ProseMirrorMark | undefined {
|
|
11
11
|
return marks.find(item => {
|
|
12
|
-
return
|
|
12
|
+
return (
|
|
13
|
+
item.type === type
|
|
14
|
+
&& objectIncludes(
|
|
15
|
+
// Only check equality for the attributes that are provided
|
|
16
|
+
Object.fromEntries(Object.keys(attributes).map(k => [k, item.attrs[k]])),
|
|
17
|
+
attributes,
|
|
18
|
+
)
|
|
19
|
+
)
|
|
13
20
|
})
|
|
14
21
|
}
|
|
15
22
|
|
|
@@ -21,25 +28,44 @@ function isMarkInSet(
|
|
|
21
28
|
return !!findMarkInSet(marks, type, attributes)
|
|
22
29
|
}
|
|
23
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Get the range of a mark at a resolved position.
|
|
33
|
+
*/
|
|
24
34
|
export function getMarkRange(
|
|
35
|
+
/**
|
|
36
|
+
* The position to get the mark range for.
|
|
37
|
+
*/
|
|
25
38
|
$pos: ResolvedPos,
|
|
39
|
+
/**
|
|
40
|
+
* The mark type to get the range for.
|
|
41
|
+
*/
|
|
26
42
|
type: MarkType,
|
|
27
|
-
|
|
43
|
+
/**
|
|
44
|
+
* The attributes to match against.
|
|
45
|
+
* If not provided, only the first mark at the position will be matched.
|
|
46
|
+
*/
|
|
47
|
+
attributes?: Record<string, any>,
|
|
28
48
|
): Range | void {
|
|
29
49
|
if (!$pos || !type) {
|
|
30
50
|
return
|
|
31
51
|
}
|
|
32
|
-
|
|
33
52
|
let start = $pos.parent.childAfter($pos.parentOffset)
|
|
34
53
|
|
|
35
|
-
|
|
54
|
+
// If the cursor is at the start of a text node that does not have the mark, look backward
|
|
55
|
+
if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
|
|
36
56
|
start = $pos.parent.childBefore($pos.parentOffset)
|
|
37
57
|
}
|
|
38
58
|
|
|
39
|
-
|
|
59
|
+
// If there is no text node with the mark even backward, return undefined
|
|
60
|
+
if (!start.node || !start.node.marks.some(mark => mark.type === type)) {
|
|
40
61
|
return
|
|
41
62
|
}
|
|
42
63
|
|
|
64
|
+
// Default to only matching against the first mark's attributes
|
|
65
|
+
attributes = attributes || start.node.marks[0]?.attrs
|
|
66
|
+
|
|
67
|
+
// We now know that the cursor is either at the start, middle or end of a text node with the specified mark
|
|
68
|
+
// so we can look it up on the targeted mark
|
|
43
69
|
const mark = findMarkInSet([...start.node.marks], type, attributes)
|
|
44
70
|
|
|
45
71
|
if (!mark) {
|
|
@@ -51,9 +77,10 @@ export function getMarkRange(
|
|
|
51
77
|
let endIndex = startIndex + 1
|
|
52
78
|
let endPos = startPos + start.node.nodeSize
|
|
53
79
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
80
|
+
while (
|
|
81
|
+
startIndex > 0
|
|
82
|
+
&& isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)
|
|
83
|
+
) {
|
|
57
84
|
startIndex -= 1
|
|
58
85
|
startPos -= $pos.parent.child(startIndex).nodeSize
|
|
59
86
|
}
|
|
@@ -12,7 +12,7 @@ export function getMarksBetween(from: number, to: number, doc: ProseMirrorNode):
|
|
|
12
12
|
.resolve(from)
|
|
13
13
|
.marks()
|
|
14
14
|
.forEach(mark => {
|
|
15
|
-
const $pos = doc.resolve(from
|
|
15
|
+
const $pos = doc.resolve(from)
|
|
16
16
|
const range = getMarkRange($pos, mark.type)
|
|
17
17
|
|
|
18
18
|
if (!range) {
|
|
@@ -8,6 +8,9 @@ export function getRenderedAttributes(
|
|
|
8
8
|
extensionAttributes: ExtensionAttribute[],
|
|
9
9
|
): Record<string, any> {
|
|
10
10
|
return extensionAttributes
|
|
11
|
+
.filter(
|
|
12
|
+
attribute => attribute.type === nodeOrMark.type.name,
|
|
13
|
+
)
|
|
11
14
|
.filter(item => item.attribute.rendered)
|
|
12
15
|
.map(item => {
|
|
13
16
|
if (!item.attribute.renderHTML) {
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
MarkSpec, NodeSpec, Schema, TagParseRule,
|
|
3
3
|
} from '@tiptap/pm/model'
|
|
4
4
|
|
|
5
|
-
import { Editor, MarkConfig, NodeConfig } from '../index.js'
|
|
5
|
+
import type { Editor, MarkConfig, NodeConfig } from '../index.js'
|
|
6
6
|
import { AnyConfig, Extensions } from '../types.js'
|
|
7
7
|
import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
8
8
|
import { isEmptyObject } from '../utilities/isEmptyObject.js'
|
|
@@ -78,6 +78,7 @@ export function getSchemaByResolvedExtensions(extensions: Extensions, editor?: E
|
|
|
78
78
|
),
|
|
79
79
|
code: callOrReturn(getExtensionField<NodeConfig['code']>(extension, 'code', context)),
|
|
80
80
|
whitespace: callOrReturn(getExtensionField<NodeConfig['whitespace']>(extension, 'whitespace', context)),
|
|
81
|
+
linebreakReplacement: callOrReturn(getExtensionField<NodeConfig['linebreakReplacement']>(extension, 'linebreakReplacement', context)),
|
|
81
82
|
defining: callOrReturn(
|
|
82
83
|
getExtensionField<NodeConfig['defining']>(extension, 'defining', context),
|
|
83
84
|
),
|
|
@@ -147,7 +148,7 @@ export function getSchemaByResolvedExtensions(extensions: Extensions, editor?: E
|
|
|
147
148
|
|
|
148
149
|
return {
|
|
149
150
|
...fields,
|
|
150
|
-
...(extendMarkSchema ? extendMarkSchema(extension) : {}),
|
|
151
|
+
...(extendMarkSchema ? extendMarkSchema(extension as any) : {}),
|
|
151
152
|
}
|
|
152
153
|
}, {})
|
|
153
154
|
|
package/src/helpers/isList.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getExtensionField } from '../helpers/getExtensionField.js'
|
|
2
|
-
import { NodeConfig } from '../index.js'
|
|
2
|
+
import type { NodeConfig } from '../index.js'
|
|
3
3
|
import { Extensions } from '../types.js'
|
|
4
4
|
import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
5
5
|
import { splitExtensions } from './splitExtensions.js'
|
|
@@ -1,40 +1,61 @@
|
|
|
1
1
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Returns true if the given node is empty.
|
|
5
|
-
* When `checkChildren` is true (default), it will also check if all children are empty.
|
|
4
|
+
* Returns true if the given prosemirror node is empty.
|
|
6
5
|
*/
|
|
7
6
|
export function isNodeEmpty(
|
|
8
7
|
node: ProseMirrorNode,
|
|
9
|
-
{
|
|
8
|
+
{
|
|
9
|
+
checkChildren = true,
|
|
10
|
+
ignoreWhitespace = false,
|
|
11
|
+
}: {
|
|
12
|
+
/**
|
|
13
|
+
* When true (default), it will also check if all children are empty.
|
|
14
|
+
*/
|
|
15
|
+
checkChildren?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* When true, it will ignore whitespace when checking for emptiness.
|
|
18
|
+
*/
|
|
19
|
+
ignoreWhitespace?: boolean;
|
|
20
|
+
} = {},
|
|
10
21
|
): boolean {
|
|
22
|
+
if (ignoreWhitespace) {
|
|
23
|
+
if (node.type.name === 'hardBreak') {
|
|
24
|
+
// Hard breaks are considered empty
|
|
25
|
+
return true
|
|
26
|
+
}
|
|
27
|
+
if (node.isText) {
|
|
28
|
+
return /^\s*$/m.test(node.text ?? '')
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
11
32
|
if (node.isText) {
|
|
12
33
|
return !node.text
|
|
13
34
|
}
|
|
14
35
|
|
|
15
|
-
if (node.
|
|
16
|
-
return
|
|
36
|
+
if (node.isAtom || node.isLeaf) {
|
|
37
|
+
return false
|
|
17
38
|
}
|
|
18
39
|
|
|
19
|
-
if (node.
|
|
20
|
-
return
|
|
40
|
+
if (node.content.childCount === 0) {
|
|
41
|
+
return true
|
|
21
42
|
}
|
|
22
43
|
|
|
23
44
|
if (checkChildren) {
|
|
24
|
-
let
|
|
45
|
+
let isContentEmpty = true
|
|
25
46
|
|
|
26
47
|
node.content.forEach(childNode => {
|
|
27
|
-
if (
|
|
48
|
+
if (isContentEmpty === false) {
|
|
28
49
|
// Exit early for perf
|
|
29
50
|
return
|
|
30
51
|
}
|
|
31
52
|
|
|
32
|
-
if (!isNodeEmpty(childNode)) {
|
|
33
|
-
|
|
53
|
+
if (!isNodeEmpty(childNode, { ignoreWhitespace, checkChildren })) {
|
|
54
|
+
isContentEmpty = false
|
|
34
55
|
}
|
|
35
56
|
})
|
|
36
57
|
|
|
37
|
-
return
|
|
58
|
+
return isContentEmpty
|
|
38
59
|
}
|
|
39
60
|
|
|
40
61
|
return false
|
|
@@ -8,7 +8,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
8
8
|
/**
|
|
9
9
|
* Build an input rule that adds a mark when the
|
|
10
10
|
* matched text is typed into it.
|
|
11
|
-
* @see https://tiptap.dev/
|
|
11
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
|
|
12
12
|
*/
|
|
13
13
|
export function markInputRule(config: {
|
|
14
14
|
find: InputRuleFinder
|
|
@@ -7,7 +7,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
7
7
|
/**
|
|
8
8
|
* Build an input rule that adds a node when the
|
|
9
9
|
* matched text is typed into it.
|
|
10
|
-
* @see https://tiptap.dev/
|
|
10
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
|
|
11
11
|
*/
|
|
12
12
|
export function nodeInputRule(config: {
|
|
13
13
|
/**
|
|
@@ -3,7 +3,7 @@ import { InputRule, InputRuleFinder } from '../InputRule.js'
|
|
|
3
3
|
/**
|
|
4
4
|
* Build an input rule that replaces text when the
|
|
5
5
|
* matched text is typed into it.
|
|
6
|
-
* @see https://tiptap.dev/
|
|
6
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
|
|
7
7
|
*/
|
|
8
8
|
export function textInputRule(config: {
|
|
9
9
|
find: InputRuleFinder,
|
|
@@ -9,7 +9,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
9
9
|
* matched text is typed into it. When using a regular expresion you’ll
|
|
10
10
|
* probably want the regexp to start with `^`, so that the pattern can
|
|
11
11
|
* only occur at the start of a textblock.
|
|
12
|
-
* @see https://tiptap.dev/
|
|
12
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
|
|
13
13
|
*/
|
|
14
14
|
export function textblockTypeInputRule(config: {
|
|
15
15
|
find: InputRuleFinder
|
|
@@ -19,7 +19,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
19
19
|
* two nodes. You can pass a join predicate, which takes a regular
|
|
20
20
|
* expression match and the node before the wrapped node, and can
|
|
21
21
|
* return a boolean to indicate whether a join should happen.
|
|
22
|
-
* @see https://tiptap.dev/
|
|
22
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#input-rules
|
|
23
23
|
*/
|
|
24
24
|
export function wrappingInputRule(config: {
|
|
25
25
|
find: InputRuleFinder,
|
|
@@ -8,7 +8,7 @@ import { callOrReturn } from '../utilities/callOrReturn.js'
|
|
|
8
8
|
/**
|
|
9
9
|
* Build an paste rule that adds a mark when the
|
|
10
10
|
* matched text is pasted into it.
|
|
11
|
-
* @see https://tiptap.dev/
|
|
11
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
|
|
12
12
|
*/
|
|
13
13
|
export function markPasteRule(config: {
|
|
14
14
|
find: PasteRuleFinder
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { NodeType } from '@tiptap/pm/model'
|
|
2
2
|
|
|
3
3
|
import { PasteRule, PasteRuleFinder } from '../PasteRule.js'
|
|
4
|
-
import { ExtendedRegExpMatchArray } from '../types.js'
|
|
4
|
+
import { ExtendedRegExpMatchArray, JSONContent } from '../types.js'
|
|
5
5
|
import { callOrReturn } from '../utilities/index.js'
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Build an paste rule that adds a node when the
|
|
9
9
|
* matched text is pasted into it.
|
|
10
|
-
* @see https://tiptap.dev/
|
|
10
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
|
|
11
11
|
*/
|
|
12
12
|
export function nodePasteRule(config: {
|
|
13
13
|
find: PasteRuleFinder
|
|
@@ -17,6 +17,11 @@ export function nodePasteRule(config: {
|
|
|
17
17
|
| ((match: ExtendedRegExpMatchArray, event: ClipboardEvent) => Record<string, any>)
|
|
18
18
|
| false
|
|
19
19
|
| null
|
|
20
|
+
getContent?:
|
|
21
|
+
| JSONContent[]
|
|
22
|
+
| ((attrs: Record<string, any>) => JSONContent[])
|
|
23
|
+
| false
|
|
24
|
+
| null
|
|
20
25
|
}) {
|
|
21
26
|
return new PasteRule({
|
|
22
27
|
find: config.find,
|
|
@@ -24,16 +29,20 @@ export function nodePasteRule(config: {
|
|
|
24
29
|
match, chain, range, pasteEvent,
|
|
25
30
|
}) {
|
|
26
31
|
const attributes = callOrReturn(config.getAttributes, undefined, match, pasteEvent)
|
|
32
|
+
const content = callOrReturn(config.getContent, undefined, attributes)
|
|
27
33
|
|
|
28
34
|
if (attributes === false || attributes === null) {
|
|
29
35
|
return null
|
|
30
36
|
}
|
|
31
37
|
|
|
38
|
+
const node = { type: config.type.name, attrs: attributes } as JSONContent
|
|
39
|
+
|
|
40
|
+
if (content) {
|
|
41
|
+
node.content = content
|
|
42
|
+
}
|
|
43
|
+
|
|
32
44
|
if (match.input) {
|
|
33
|
-
chain().deleteRange(range).insertContentAt(range.from,
|
|
34
|
-
type: config.type.name,
|
|
35
|
-
attrs: attributes,
|
|
36
|
-
})
|
|
45
|
+
chain().deleteRange(range).insertContentAt(range.from, node)
|
|
37
46
|
}
|
|
38
47
|
},
|
|
39
48
|
})
|
|
@@ -3,7 +3,7 @@ import { PasteRule, PasteRuleFinder } from '../PasteRule.js'
|
|
|
3
3
|
/**
|
|
4
4
|
* Build an paste rule that replaces text when the
|
|
5
5
|
* matched text is pasted into it.
|
|
6
|
-
* @see https://tiptap.dev/
|
|
6
|
+
* @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
|
|
7
7
|
*/
|
|
8
8
|
export function textPasteRule(config: {
|
|
9
9
|
find: PasteRuleFinder,
|
package/src/style.ts
CHANGED