@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.
Files changed (214) hide show
  1. package/dist/index.cjs +4934 -4574
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +3576 -0
  4. package/dist/index.d.ts +3576 -0
  5. package/dist/index.js +4839 -4481
  6. package/dist/index.js.map +1 -1
  7. package/package.json +6 -8
  8. package/src/Editor.ts +66 -10
  9. package/src/EventEmitter.ts +9 -0
  10. package/src/Extension.ts +4 -3
  11. package/src/ExtensionManager.ts +18 -12
  12. package/src/InputRule.ts +45 -30
  13. package/src/Mark.ts +4 -3
  14. package/src/Node.ts +23 -3
  15. package/src/NodePos.ts +9 -4
  16. package/src/NodeView.ts +43 -12
  17. package/src/PasteRule.ts +96 -42
  18. package/src/commands/focus.ts +1 -6
  19. package/src/commands/insertContent.ts +9 -9
  20. package/src/commands/insertContentAt.ts +23 -3
  21. package/src/commands/selectAll.ts +10 -5
  22. package/src/commands/setContent.ts +10 -14
  23. package/src/commands/setMeta.ts +3 -1
  24. package/src/commands/setNode.ts +9 -2
  25. package/src/commands/splitListItem.ts +27 -17
  26. package/src/commands/toggleNode.ts +11 -2
  27. package/src/commands/updateAttributes.ts +72 -12
  28. package/src/extensions/drop.ts +26 -0
  29. package/src/extensions/index.ts +2 -0
  30. package/src/extensions/keymap.ts +5 -2
  31. package/src/extensions/paste.ts +26 -0
  32. package/src/helpers/createDocument.ts +4 -2
  33. package/src/helpers/createNodeFromContent.ts +11 -2
  34. package/src/helpers/getAttributesFromExtensions.ts +1 -1
  35. package/src/helpers/getMarkRange.ts +35 -8
  36. package/src/helpers/getMarksBetween.ts +1 -1
  37. package/src/helpers/getRenderedAttributes.ts +3 -0
  38. package/src/helpers/getSchemaByResolvedExtensions.ts +3 -2
  39. package/src/helpers/isList.ts +1 -1
  40. package/src/helpers/isNodeEmpty.ts +33 -12
  41. package/src/inputRules/markInputRule.ts +1 -1
  42. package/src/inputRules/nodeInputRule.ts +1 -1
  43. package/src/inputRules/textInputRule.ts +1 -1
  44. package/src/inputRules/textblockTypeInputRule.ts +1 -1
  45. package/src/inputRules/wrappingInputRule.ts +1 -1
  46. package/src/pasteRules/markPasteRule.ts +1 -1
  47. package/src/pasteRules/nodePasteRule.ts +15 -6
  48. package/src/pasteRules/textPasteRule.ts +1 -1
  49. package/src/style.ts +2 -2
  50. package/src/types.ts +107 -19
  51. package/src/utilities/mergeAttributes.ts +18 -1
  52. package/dist/index.umd.js +0 -5130
  53. package/dist/index.umd.js.map +0 -1
  54. package/dist/packages/core/src/CommandManager.d.ts +0 -20
  55. package/dist/packages/core/src/Editor.d.ts +0 -159
  56. package/dist/packages/core/src/EventEmitter.d.ts +0 -11
  57. package/dist/packages/core/src/Extension.d.ts +0 -343
  58. package/dist/packages/core/src/ExtensionManager.d.ts +0 -55
  59. package/dist/packages/core/src/InputRule.d.ts +0 -42
  60. package/dist/packages/core/src/Mark.d.ts +0 -451
  61. package/dist/packages/core/src/Node.d.ts +0 -611
  62. package/dist/packages/core/src/NodePos.d.ts +0 -44
  63. package/dist/packages/core/src/NodeView.d.ts +0 -31
  64. package/dist/packages/core/src/PasteRule.d.ts +0 -50
  65. package/dist/packages/core/src/Tracker.d.ts +0 -11
  66. package/dist/packages/core/src/commands/blur.d.ts +0 -13
  67. package/dist/packages/core/src/commands/clearContent.d.ts +0 -14
  68. package/dist/packages/core/src/commands/clearNodes.d.ts +0 -13
  69. package/dist/packages/core/src/commands/command.d.ts +0 -18
  70. package/dist/packages/core/src/commands/createParagraphNear.d.ts +0 -13
  71. package/dist/packages/core/src/commands/cut.d.ts +0 -20
  72. package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +0 -13
  73. package/dist/packages/core/src/commands/deleteNode.d.ts +0 -15
  74. package/dist/packages/core/src/commands/deleteRange.d.ts +0 -14
  75. package/dist/packages/core/src/commands/deleteSelection.d.ts +0 -13
  76. package/dist/packages/core/src/commands/enter.d.ts +0 -13
  77. package/dist/packages/core/src/commands/exitCode.d.ts +0 -13
  78. package/dist/packages/core/src/commands/extendMarkRange.d.ts +0 -25
  79. package/dist/packages/core/src/commands/first.d.ts +0 -14
  80. package/dist/packages/core/src/commands/focus.d.ts +0 -27
  81. package/dist/packages/core/src/commands/forEach.d.ts +0 -14
  82. package/dist/packages/core/src/commands/index.d.ts +0 -55
  83. package/dist/packages/core/src/commands/insertContent.d.ts +0 -34
  84. package/dist/packages/core/src/commands/insertContentAt.d.ts +0 -47
  85. package/dist/packages/core/src/commands/join.d.ts +0 -41
  86. package/dist/packages/core/src/commands/joinItemBackward.d.ts +0 -13
  87. package/dist/packages/core/src/commands/joinItemForward.d.ts +0 -13
  88. package/dist/packages/core/src/commands/joinTextblockBackward.d.ts +0 -12
  89. package/dist/packages/core/src/commands/joinTextblockForward.d.ts +0 -12
  90. package/dist/packages/core/src/commands/keyboardShortcut.d.ts +0 -14
  91. package/dist/packages/core/src/commands/lift.d.ts +0 -17
  92. package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +0 -13
  93. package/dist/packages/core/src/commands/liftListItem.d.ts +0 -15
  94. package/dist/packages/core/src/commands/newlineInCode.d.ts +0 -13
  95. package/dist/packages/core/src/commands/resetAttributes.d.ts +0 -16
  96. package/dist/packages/core/src/commands/scrollIntoView.d.ts +0 -13
  97. package/dist/packages/core/src/commands/selectAll.d.ts +0 -13
  98. package/dist/packages/core/src/commands/selectNodeBackward.d.ts +0 -13
  99. package/dist/packages/core/src/commands/selectNodeForward.d.ts +0 -13
  100. package/dist/packages/core/src/commands/selectParentNode.d.ts +0 -13
  101. package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +0 -13
  102. package/dist/packages/core/src/commands/selectTextblockStart.d.ts +0 -13
  103. package/dist/packages/core/src/commands/setContent.d.ts +0 -40
  104. package/dist/packages/core/src/commands/setMark.d.ts +0 -15
  105. package/dist/packages/core/src/commands/setMeta.d.ts +0 -15
  106. package/dist/packages/core/src/commands/setNode.d.ts +0 -16
  107. package/dist/packages/core/src/commands/setNodeSelection.d.ts +0 -14
  108. package/dist/packages/core/src/commands/setTextSelection.d.ts +0 -14
  109. package/dist/packages/core/src/commands/sinkListItem.d.ts +0 -15
  110. package/dist/packages/core/src/commands/splitBlock.d.ts +0 -17
  111. package/dist/packages/core/src/commands/splitListItem.d.ts +0 -15
  112. package/dist/packages/core/src/commands/toggleList.d.ts +0 -18
  113. package/dist/packages/core/src/commands/toggleMark.d.ts +0 -30
  114. package/dist/packages/core/src/commands/toggleNode.d.ts +0 -17
  115. package/dist/packages/core/src/commands/toggleWrap.d.ts +0 -16
  116. package/dist/packages/core/src/commands/undoInputRule.d.ts +0 -13
  117. package/dist/packages/core/src/commands/unsetAllMarks.d.ts +0 -13
  118. package/dist/packages/core/src/commands/unsetMark.d.ts +0 -25
  119. package/dist/packages/core/src/commands/updateAttributes.d.ts +0 -24
  120. package/dist/packages/core/src/commands/wrapIn.d.ts +0 -16
  121. package/dist/packages/core/src/commands/wrapInList.d.ts +0 -16
  122. package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +0 -5
  123. package/dist/packages/core/src/extensions/commands.d.ts +0 -3
  124. package/dist/packages/core/src/extensions/editable.d.ts +0 -2
  125. package/dist/packages/core/src/extensions/focusEvents.d.ts +0 -2
  126. package/dist/packages/core/src/extensions/index.d.ts +0 -6
  127. package/dist/packages/core/src/extensions/keymap.d.ts +0 -2
  128. package/dist/packages/core/src/extensions/tabindex.d.ts +0 -2
  129. package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +0 -10
  130. package/dist/packages/core/src/helpers/createChainableState.d.ts +0 -10
  131. package/dist/packages/core/src/helpers/createDocument.d.ts +0 -12
  132. package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +0 -15
  133. package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +0 -7
  134. package/dist/packages/core/src/helpers/findChildren.d.ts +0 -9
  135. package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +0 -10
  136. package/dist/packages/core/src/helpers/findParentNode.d.ts +0 -16
  137. package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +0 -17
  138. package/dist/packages/core/src/helpers/generateHTML.d.ts +0 -8
  139. package/dist/packages/core/src/helpers/generateJSON.d.ts +0 -8
  140. package/dist/packages/core/src/helpers/generateText.d.ts +0 -12
  141. package/dist/packages/core/src/helpers/getAttributes.d.ts +0 -9
  142. package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +0 -6
  143. package/dist/packages/core/src/helpers/getChangedRanges.d.ts +0 -11
  144. package/dist/packages/core/src/helpers/getDebugJSON.d.ts +0 -8
  145. package/dist/packages/core/src/helpers/getExtensionField.d.ts +0 -9
  146. package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +0 -2
  147. package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +0 -3
  148. package/dist/packages/core/src/helpers/getMarkRange.d.ts +0 -3
  149. package/dist/packages/core/src/helpers/getMarkType.d.ts +0 -2
  150. package/dist/packages/core/src/helpers/getMarksBetween.d.ts +0 -3
  151. package/dist/packages/core/src/helpers/getNodeAtPosition.d.ts +0 -11
  152. package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +0 -3
  153. package/dist/packages/core/src/helpers/getNodeType.d.ts +0 -2
  154. package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +0 -3
  155. package/dist/packages/core/src/helpers/getSchema.d.ts +0 -4
  156. package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +0 -10
  157. package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +0 -8
  158. package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +0 -8
  159. package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +0 -9
  160. package/dist/packages/core/src/helpers/getText.d.ts +0 -15
  161. package/dist/packages/core/src/helpers/getTextBetween.d.ts +0 -14
  162. package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +0 -8
  163. package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +0 -8
  164. package/dist/packages/core/src/helpers/index.d.ts +0 -50
  165. package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +0 -9
  166. package/dist/packages/core/src/helpers/isActive.d.ts +0 -2
  167. package/dist/packages/core/src/helpers/isAtEndOfNode.d.ts +0 -2
  168. package/dist/packages/core/src/helpers/isAtStartOfNode.d.ts +0 -2
  169. package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +0 -2
  170. package/dist/packages/core/src/helpers/isList.d.ts +0 -2
  171. package/dist/packages/core/src/helpers/isMarkActive.d.ts +0 -3
  172. package/dist/packages/core/src/helpers/isNodeActive.d.ts +0 -3
  173. package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +0 -8
  174. package/dist/packages/core/src/helpers/isNodeSelection.d.ts +0 -2
  175. package/dist/packages/core/src/helpers/isTextSelection.d.ts +0 -2
  176. package/dist/packages/core/src/helpers/posToDOMRect.d.ts +0 -2
  177. package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +0 -4
  178. package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +0 -2
  179. package/dist/packages/core/src/helpers/splitExtensions.d.ts +0 -9
  180. package/dist/packages/core/src/index.d.ts +0 -24
  181. package/dist/packages/core/src/inputRules/index.d.ts +0 -5
  182. package/dist/packages/core/src/inputRules/markInputRule.d.ts +0 -13
  183. package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +0 -23
  184. package/dist/packages/core/src/inputRules/textInputRule.d.ts +0 -10
  185. package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +0 -15
  186. package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +0 -28
  187. package/dist/packages/core/src/pasteRules/index.d.ts +0 -3
  188. package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +0 -13
  189. package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +0 -13
  190. package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +0 -10
  191. package/dist/packages/core/src/style.d.ts +0 -1
  192. package/dist/packages/core/src/types.d.ts +0 -253
  193. package/dist/packages/core/src/utilities/callOrReturn.d.ts +0 -9
  194. package/dist/packages/core/src/utilities/createStyleTag.d.ts +0 -1
  195. package/dist/packages/core/src/utilities/deleteProps.d.ts +0 -6
  196. package/dist/packages/core/src/utilities/elementFromString.d.ts +0 -1
  197. package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +0 -1
  198. package/dist/packages/core/src/utilities/findDuplicates.d.ts +0 -1
  199. package/dist/packages/core/src/utilities/fromString.d.ts +0 -1
  200. package/dist/packages/core/src/utilities/index.d.ts +0 -20
  201. package/dist/packages/core/src/utilities/isAndroid.d.ts +0 -1
  202. package/dist/packages/core/src/utilities/isEmptyObject.d.ts +0 -1
  203. package/dist/packages/core/src/utilities/isFunction.d.ts +0 -1
  204. package/dist/packages/core/src/utilities/isMacOS.d.ts +0 -1
  205. package/dist/packages/core/src/utilities/isNumber.d.ts +0 -1
  206. package/dist/packages/core/src/utilities/isPlainObject.d.ts +0 -1
  207. package/dist/packages/core/src/utilities/isRegExp.d.ts +0 -1
  208. package/dist/packages/core/src/utilities/isString.d.ts +0 -1
  209. package/dist/packages/core/src/utilities/isiOS.d.ts +0 -1
  210. package/dist/packages/core/src/utilities/mergeAttributes.d.ts +0 -1
  211. package/dist/packages/core/src/utilities/mergeDeep.d.ts +0 -1
  212. package/dist/packages/core/src/utilities/minMax.d.ts +0 -1
  213. package/dist/packages/core/src/utilities/objectIncludes.d.ts +0 -8
  214. package/dist/packages/core/src/utilities/removeDuplicates.d.ts +0 -8
package/src/PasteRule.ts CHANGED
@@ -1,8 +1,10 @@
1
+ import { Fragment, Node as ProseMirrorNode } from '@tiptap/pm/model'
1
2
  import { EditorState, Plugin } from '@tiptap/pm/state'
2
3
 
3
4
  import { CommandManager } from './CommandManager.js'
4
5
  import { Editor } from './Editor.js'
5
6
  import { createChainableState } from './helpers/createChainableState.js'
7
+ import { getHTMLFromFragment } from './helpers/getHTMLFromFragment.js'
6
8
  import {
7
9
  CanCommands,
8
10
  ChainedCommands,
@@ -14,45 +16,47 @@ import { isNumber } from './utilities/isNumber.js'
14
16
  import { isRegExp } from './utilities/isRegExp.js'
15
17
 
16
18
  export type PasteRuleMatch = {
17
- index: number
18
- text: string
19
- replaceWith?: string
20
- match?: RegExpMatchArray
21
- data?: Record<string, any>
22
- }
19
+ index: number;
20
+ text: string;
21
+ replaceWith?: string;
22
+ match?: RegExpMatchArray;
23
+ data?: Record<string, any>;
24
+ };
23
25
 
24
- export type PasteRuleFinder = RegExp | ((text: string, event?: ClipboardEvent | null) => PasteRuleMatch[] | null | undefined)
26
+ export type PasteRuleFinder =
27
+ | RegExp
28
+ | ((text: string, event?: ClipboardEvent | null) => PasteRuleMatch[] | null | undefined);
25
29
 
26
30
  /**
27
31
  * Paste rules are used to react to pasted content.
28
- * @see https://tiptap.dev/guide/custom-extensions/#paste-rules
32
+ * @see https://tiptap.dev/docs/editor/extensions/custom-extensions/extend-existing#paste-rules
29
33
  */
30
34
  export class PasteRule {
31
35
  find: PasteRuleFinder
32
36
 
33
37
  handler: (props: {
34
- state: EditorState
35
- range: Range
36
- match: ExtendedRegExpMatchArray
37
- commands: SingleCommands
38
- chain: () => ChainedCommands
39
- can: () => CanCommands
40
- pasteEvent: ClipboardEvent | null
41
- dropEvent: DragEvent | null
38
+ state: EditorState;
39
+ range: Range;
40
+ match: ExtendedRegExpMatchArray;
41
+ commands: SingleCommands;
42
+ chain: () => ChainedCommands;
43
+ can: () => CanCommands;
44
+ pasteEvent: ClipboardEvent | null;
45
+ dropEvent: DragEvent | null;
42
46
  }) => void | null
43
47
 
44
48
  constructor(config: {
45
- find: PasteRuleFinder
49
+ find: PasteRuleFinder;
46
50
  handler: (props: {
47
- can: () => CanCommands
48
- chain: () => ChainedCommands
49
- commands: SingleCommands
50
- dropEvent: DragEvent | null
51
- match: ExtendedRegExpMatchArray
52
- pasteEvent: ClipboardEvent | null
53
- range: Range
54
- state: EditorState
55
- }) => void | null
51
+ can: () => CanCommands;
52
+ chain: () => ChainedCommands;
53
+ commands: SingleCommands;
54
+ dropEvent: DragEvent | null;
55
+ match: ExtendedRegExpMatchArray;
56
+ pasteEvent: ClipboardEvent | null;
57
+ range: Range;
58
+ state: EditorState;
59
+ }) => void | null;
56
60
  }) {
57
61
  this.find = config.find
58
62
  this.handler = config.handler
@@ -96,13 +100,13 @@ const pasteRuleMatcherHandler = (
96
100
  }
97
101
 
98
102
  function run(config: {
99
- editor: Editor
100
- state: EditorState
101
- from: number
102
- to: number
103
- rule: PasteRule
104
- pasteEvent: ClipboardEvent | null
105
- dropEvent: DragEvent | null
103
+ editor: Editor;
104
+ state: EditorState;
105
+ from: number;
106
+ to: number;
107
+ rule: PasteRule;
108
+ pasteEvent: ClipboardEvent | null;
109
+ dropEvent: DragEvent | null;
106
110
  }): boolean {
107
111
  const {
108
112
  editor, state, from, to, rule, pasteEvent, dropEvent,
@@ -158,6 +162,9 @@ function run(config: {
158
162
  return success
159
163
  }
160
164
 
165
+ // When dragging across editors, must get another editor instance to delete selection content.
166
+ let tiptapDragFromOtherEditor: Editor | null = null
167
+
161
168
  const createClipboardPasteEvent = (text: string) => {
162
169
  const event = new ClipboardEvent('paste', {
163
170
  clipboardData: new DataTransfer(),
@@ -179,7 +186,13 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
179
186
  let isPastedFromProseMirror = false
180
187
  let isDroppedFromProseMirror = false
181
188
  let pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null
182
- let dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null
189
+ let dropEvent: DragEvent | null
190
+
191
+ try {
192
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null
193
+ } catch (e) {
194
+ dropEvent = null
195
+ }
183
196
 
184
197
  const processEvent = ({
185
198
  state,
@@ -188,11 +201,11 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
188
201
  rule,
189
202
  pasteEvt,
190
203
  }: {
191
- state: EditorState
192
- from: number
193
- to: { b: number }
194
- rule: PasteRule
195
- pasteEvt: ClipboardEvent | null
204
+ state: EditorState;
205
+ from: number;
206
+ to: { b: number };
207
+ rule: PasteRule;
208
+ pasteEvt: ClipboardEvent | null;
196
209
  }) => {
197
210
  const tr = state.tr
198
211
  const chainableState = createChainableState({
@@ -214,7 +227,11 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
214
227
  return
215
228
  }
216
229
 
217
- dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null
230
+ try {
231
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null
232
+ } catch (e) {
233
+ dropEvent = null
234
+ }
218
235
  pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null
219
236
 
220
237
  return tr
@@ -228,13 +245,25 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
228
245
  dragSourceElement = view.dom.parentElement?.contains(event.target as Element)
229
246
  ? view.dom.parentElement
230
247
  : null
248
+
249
+ if (dragSourceElement) {
250
+ tiptapDragFromOtherEditor = editor
251
+ }
252
+ }
253
+
254
+ const handleDragend = () => {
255
+ if (tiptapDragFromOtherEditor) {
256
+ tiptapDragFromOtherEditor = null
257
+ }
231
258
  }
232
259
 
233
260
  window.addEventListener('dragstart', handleDragstart)
261
+ window.addEventListener('dragend', handleDragend)
234
262
 
235
263
  return {
236
264
  destroy() {
237
265
  window.removeEventListener('dragstart', handleDragstart)
266
+ window.removeEventListener('dragend', handleDragend)
238
267
  },
239
268
  }
240
269
  },
@@ -245,6 +274,20 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
245
274
  isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement
246
275
  dropEvent = event as DragEvent
247
276
 
277
+ if (!isDroppedFromProseMirror) {
278
+ const dragFromOtherEditor = tiptapDragFromOtherEditor
279
+
280
+ if (dragFromOtherEditor) {
281
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
282
+ setTimeout(() => {
283
+ const selection = dragFromOtherEditor.state.selection
284
+
285
+ if (selection) {
286
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to })
287
+ }
288
+ }, 10)
289
+ }
290
+ }
248
291
  return false
249
292
  },
250
293
 
@@ -266,7 +309,9 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
266
309
  const isDrop = transaction.getMeta('uiEvent') === 'drop' && !isDroppedFromProseMirror
267
310
 
268
311
  // if PasteRule is triggered by insertContent()
269
- const simulatedPasteMeta = transaction.getMeta('applyPasteRules')
312
+ const simulatedPasteMeta = transaction.getMeta('applyPasteRules') as
313
+ | undefined
314
+ | { from: number; text: string | ProseMirrorNode | Fragment }
270
315
  const isSimulatedPaste = !!simulatedPasteMeta
271
316
 
272
317
  if (!isPaste && !isDrop && !isSimulatedPaste) {
@@ -275,8 +320,17 @@ export function pasteRulesPlugin(props: { editor: Editor; rules: PasteRule[] }):
275
320
 
276
321
  // Handle simulated paste
277
322
  if (isSimulatedPaste) {
278
- const { from, text } = simulatedPasteMeta
323
+ let { text } = simulatedPasteMeta
324
+
325
+ if (typeof text === 'string') {
326
+ text = text as string
327
+ } else {
328
+ text = getHTMLFromFragment(Fragment.from(text), state.schema)
329
+ }
330
+
331
+ const { from } = simulatedPasteMeta
279
332
  const to = from + text.length
333
+
280
334
  const pasteEvt = createClipboardPasteEvent(text)
281
335
 
282
336
  return processEvent({
@@ -1,7 +1,6 @@
1
1
  import { isTextSelection } from '../helpers/isTextSelection.js'
2
2
  import { resolveFocusPosition } from '../helpers/resolveFocusPosition.js'
3
3
  import { FocusPosition, RawCommands } from '../types.js'
4
- import { isiOS } from '../utilities/isiOS.js'
5
4
 
6
5
  declare module '@tiptap/core' {
7
6
  interface Commands<ReturnType> {
@@ -43,11 +42,7 @@ export const focus: RawCommands['focus'] = (position = null, options = {}) => ({
43
42
  }
44
43
 
45
44
  const delayedFocus = () => {
46
- // focus within `requestAnimationFrame` breaks focus on iOS
47
- // so we have to call this
48
- if (isiOS()) {
49
- (view.dom as HTMLElement).focus()
50
- }
45
+ (view.dom as HTMLElement).focus()
51
46
 
52
47
  // For React we have to focus asynchronously. Otherwise wild things happen.
53
48
  // see: https://github.com/ueberdosis/tiptap/issues/1520
@@ -1,4 +1,4 @@
1
- import { ParseOptions } from '@tiptap/pm/model'
1
+ import { Fragment, Node as ProseMirrorNode, ParseOptions } from '@tiptap/pm/model'
2
2
 
3
3
  import { Content, RawCommands } from '../types.js'
4
4
 
@@ -14,7 +14,7 @@ declare module '@tiptap/core' {
14
14
  /**
15
15
  * The ProseMirror content to insert.
16
16
  */
17
- value: Content,
17
+ value: Content | ProseMirrorNode | Fragment,
18
18
 
19
19
  /**
20
20
  * Optional options
@@ -23,17 +23,17 @@ declare module '@tiptap/core' {
23
23
  /**
24
24
  * Options for parsing the content.
25
25
  */
26
- parseOptions?: ParseOptions
26
+ parseOptions?: ParseOptions;
27
27
 
28
28
  /**
29
29
  * Whether to update the selection after inserting the content.
30
30
  */
31
- updateSelection?: boolean
32
- applyInputRules?: boolean
33
- applyPasteRules?: boolean
34
- },
35
- ) => ReturnType
36
- }
31
+ updateSelection?: boolean;
32
+ applyInputRules?: boolean;
33
+ applyPasteRules?: boolean;
34
+ }
35
+ ) => ReturnType;
36
+ };
37
37
  }
38
38
  }
39
39
 
@@ -20,7 +20,7 @@ declare module '@tiptap/core' {
20
20
  /**
21
21
  * The ProseMirror content to insert.
22
22
  */
23
- value: Content,
23
+ value: Content | ProseMirrorNode | Fragment,
24
24
 
25
25
  /**
26
26
  * Optional options
@@ -63,7 +63,7 @@ const isFragment = (nodeOrFragment: ProseMirrorNode | Fragment): nodeOrFragment
63
63
  export const insertContentAt: RawCommands['insertContentAt'] = (position, value, options) => ({ tr, dispatch, editor }) => {
64
64
  if (dispatch) {
65
65
  options = {
66
- parseOptions: {},
66
+ parseOptions: editor.options.parseOptions,
67
67
  updateSelection: true,
68
68
  applyInputRules: false,
69
69
  applyPasteRules: false,
@@ -71,6 +71,7 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
71
71
  }
72
72
 
73
73
  let content: Fragment | ProseMirrorNode
74
+ const { selection } = editor.state
74
75
 
75
76
  try {
76
77
  content = createNodeFromContent(value, editor.schema, {
@@ -85,7 +86,9 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
85
86
  editor,
86
87
  error: e as Error,
87
88
  disableCollaboration: () => {
88
- console.error('[tiptap error]: Unable to disable collaboration at this point in time')
89
+ if (editor.storage.collaboration) {
90
+ editor.storage.collaboration.isDisabled = true
91
+ }
89
92
  },
90
93
  })
91
94
  return false
@@ -130,6 +133,16 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
130
133
  // otherwise if it is an array, we have to join it
131
134
  if (Array.isArray(value)) {
132
135
  newContent = value.map(v => v.text || '').join('')
136
+ } else if (value instanceof Fragment) {
137
+ let text = ''
138
+
139
+ value.forEach(node => {
140
+ if (node.text) {
141
+ text += node.text
142
+ }
143
+ })
144
+
145
+ newContent = text
133
146
  } else if (typeof value === 'object' && !!value && !!value.text) {
134
147
  newContent = value.text
135
148
  } else {
@@ -140,6 +153,13 @@ export const insertContentAt: RawCommands['insertContentAt'] = (position, value,
140
153
  } else {
141
154
  newContent = content
142
155
 
156
+ const fromSelectionAtStart = selection.$from.parentOffset === 0
157
+ const isTextSelection = selection.$from.node().isText || selection.$from.node().isTextblock
158
+
159
+ if (fromSelectionAtStart && isTextSelection) {
160
+ from = Math.max(0, from - 1)
161
+ }
162
+
143
163
  tr.replaceWith(from, to, newContent)
144
164
  }
145
165
 
@@ -1,3 +1,5 @@
1
+ import { AllSelection } from '@tiptap/pm/state'
2
+
1
3
  import { RawCommands } from '../types.js'
2
4
 
3
5
  declare module '@tiptap/core' {
@@ -12,9 +14,12 @@ declare module '@tiptap/core' {
12
14
  }
13
15
  }
14
16
 
15
- export const selectAll: RawCommands['selectAll'] = () => ({ tr, commands }) => {
16
- return commands.setTextSelection({
17
- from: 0,
18
- to: tr.doc.content.size,
19
- })
17
+ export const selectAll: RawCommands['selectAll'] = () => ({ tr, dispatch }) => {
18
+ if (dispatch) {
19
+ const selection = new AllSelection(tr.doc)
20
+
21
+ tr.setSelection(selection)
22
+ }
23
+
24
+ return true
20
25
  }
@@ -1,4 +1,4 @@
1
- import { ParseOptions } from '@tiptap/pm/model'
1
+ import { Fragment, Node as ProseMirrorNode, ParseOptions } from '@tiptap/pm/model'
2
2
 
3
3
  import { createDocument } from '../helpers/createDocument.js'
4
4
  import { Content, RawCommands } from '../types.js'
@@ -17,7 +17,7 @@ declare module '@tiptap/core' {
17
17
  /**
18
18
  * The new content.
19
19
  */
20
- content: Content,
20
+ content: Content | Fragment | ProseMirrorNode,
21
21
 
22
22
  /**
23
23
  * Whether to emit an update event.
@@ -37,10 +37,10 @@ declare module '@tiptap/core' {
37
37
  /**
38
38
  * Whether to throw an error if the content is invalid.
39
39
  */
40
- errorOnInvalidContent?: boolean
41
- },
42
- ) => ReturnType
43
- }
40
+ errorOnInvalidContent?: boolean;
41
+ }
42
+ ) => ReturnType;
43
+ };
44
44
  }
45
45
  }
46
46
 
@@ -66,12 +66,8 @@ export const setContent: RawCommands['setContent'] = (content, emitUpdate = fals
66
66
  tr.setMeta('preventUpdate', !emitUpdate)
67
67
  }
68
68
 
69
- return commands.insertContentAt(
70
- { from: 0, to: doc.content.size },
71
- content,
72
- {
73
- parseOptions,
74
- errorOnInvalidContent: options.errorOnInvalidContent ?? editor.options.enableContentCheck,
75
- },
76
- )
69
+ return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
70
+ parseOptions,
71
+ errorOnInvalidContent: options.errorOnInvalidContent ?? editor.options.enableContentCheck,
72
+ })
77
73
  }
@@ -1,3 +1,5 @@
1
+ import type { Plugin, PluginKey } from '@tiptap/pm/state'
2
+
1
3
  import { RawCommands } from '../types.js'
2
4
 
3
5
  declare module '@tiptap/core' {
@@ -9,7 +11,7 @@ declare module '@tiptap/core' {
9
11
  * @param value The value to store.
10
12
  * @example editor.commands.setMeta('foo', 'bar')
11
13
  */
12
- setMeta: (key: string, value: any) => ReturnType,
14
+ setMeta: (key: string | Plugin | PluginKey, value: any) => ReturnType,
13
15
  }
14
16
  }
15
17
  }
@@ -21,6 +21,13 @@ declare module '@tiptap/core' {
21
21
  export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
22
22
  const type = getNodeType(typeOrName, state.schema)
23
23
 
24
+ let attributesToCopy: Record<string, any> | undefined
25
+
26
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
27
+ // only copy attributes if the selection is pointing to a node of the same type
28
+ attributesToCopy = state.selection.$anchor.parent.attrs
29
+ }
30
+
24
31
  // TODO: use a fallback like insertContent?
25
32
  if (!type.isTextblock) {
26
33
  console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.')
@@ -32,7 +39,7 @@ export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) =>
32
39
  chain()
33
40
  // try to convert node to default node if needed
34
41
  .command(({ commands }) => {
35
- const canSetBlock = setBlockType(type, attributes)(state)
42
+ const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state)
36
43
 
37
44
  if (canSetBlock) {
38
45
  return true
@@ -41,7 +48,7 @@ export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) =>
41
48
  return commands.clearNodes()
42
49
  })
43
50
  .command(({ state: updatedState }) => {
44
- return setBlockType(type, attributes)(updatedState, dispatch)
51
+ return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch)
45
52
  })
46
53
  .run()
47
54
  )
@@ -14,14 +14,15 @@ declare module '@tiptap/core' {
14
14
  /**
15
15
  * Splits one list item into two list items.
16
16
  * @param typeOrName The type or name of the node.
17
+ * @param overrideAttrs The attributes to ensure on the new node.
17
18
  * @example editor.commands.splitListItem('listItem')
18
19
  */
19
- splitListItem: (typeOrName: string | NodeType) => ReturnType
20
+ splitListItem: (typeOrName: string | NodeType, overrideAttrs?: Record<string, any>) => ReturnType
20
21
  }
21
22
  }
22
23
  }
23
24
 
24
- export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
25
+ export const splitListItem: RawCommands['splitListItem'] = (typeOrName, overrideAttrs = {}) => ({
25
26
  tr, state, dispatch, editor,
26
27
  }) => {
27
28
  const type = getNodeType(typeOrName, state.schema)
@@ -70,11 +71,14 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
70
71
  const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
71
72
 
72
73
  // Add a second list item with an empty default start node
73
- const newNextTypeAttributes = getSplittedAttributes(
74
- extensionAttributes,
75
- $from.node().type.name,
76
- $from.node().attrs,
77
- )
74
+ const newNextTypeAttributes = {
75
+ ...getSplittedAttributes(
76
+ extensionAttributes,
77
+ $from.node().type.name,
78
+ $from.node().attrs,
79
+ ),
80
+ ...overrideAttrs,
81
+ }
78
82
  const nextType = type.contentMatch.defaultType?.createAndFill(newNextTypeAttributes) || undefined
79
83
 
80
84
  wrap = wrap.append(Fragment.from(type.createAndFill(null, nextType) || undefined))
@@ -107,16 +111,22 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
107
111
 
108
112
  const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null
109
113
 
110
- const newTypeAttributes = getSplittedAttributes(
111
- extensionAttributes,
112
- grandParent.type.name,
113
- grandParent.attrs,
114
- )
115
- const newNextTypeAttributes = getSplittedAttributes(
116
- extensionAttributes,
117
- $from.node().type.name,
118
- $from.node().attrs,
119
- )
114
+ const newTypeAttributes = {
115
+ ...getSplittedAttributes(
116
+ extensionAttributes,
117
+ grandParent.type.name,
118
+ grandParent.attrs,
119
+ ),
120
+ ...overrideAttrs,
121
+ }
122
+ const newNextTypeAttributes = {
123
+ ...getSplittedAttributes(
124
+ extensionAttributes,
125
+ $from.node().type.name,
126
+ $from.node().attrs,
127
+ ),
128
+ ...overrideAttrs,
129
+ }
120
130
 
121
131
  tr.delete($from.pos, $to.pos)
122
132
 
@@ -28,9 +28,18 @@ export const toggleNode: RawCommands['toggleNode'] = (typeOrName, toggleTypeOrNa
28
28
  const toggleType = getNodeType(toggleTypeOrName, state.schema)
29
29
  const isActive = isNodeActive(state, type, attributes)
30
30
 
31
+ let attributesToCopy: Record<string, any> | undefined
32
+
33
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
34
+ // only copy attributes if the selection is pointing to a node of the same type
35
+ attributesToCopy = state.selection.$anchor.parent.attrs
36
+ }
37
+
31
38
  if (isActive) {
32
- return commands.setNode(toggleType)
39
+ return commands.setNode(toggleType, attributesToCopy)
33
40
  }
34
41
 
35
- return commands.setNode(type, attributes)
42
+ // If the node is not active, we want to set the new node type with the given attributes
43
+ // Copying over the attributes from the current node if the selection is pointing to a node of the same type
44
+ return commands.setNode(type, { ...attributesToCopy, ...attributes })
36
45
  }