@tiptap/core 2.0.0-beta.99 → 2.0.0-rc.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 (297) hide show
  1. package/README.md +3 -3
  2. package/dist/index.cjs +4360 -0
  3. package/dist/index.cjs.map +1 -0
  4. package/dist/{tiptap-core.esm.js → index.js} +2349 -1447
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.umd.js +4358 -0
  7. package/dist/index.umd.js.map +1 -0
  8. package/dist/packages/core/src/CommandManager.d.ts +14 -7
  9. package/dist/packages/core/src/Editor.d.ts +25 -11
  10. package/dist/packages/core/src/EventEmitter.d.ts +8 -4
  11. package/dist/packages/core/src/Extension.d.ts +63 -29
  12. package/dist/packages/core/src/ExtensionManager.d.ts +3 -4
  13. package/dist/packages/core/src/InputRule.d.ts +42 -0
  14. package/dist/packages/core/src/Mark.d.ts +94 -36
  15. package/dist/packages/core/src/Node.d.ts +104 -45
  16. package/dist/packages/core/src/NodeView.d.ts +8 -8
  17. package/dist/packages/core/src/PasteRule.d.ts +42 -0
  18. package/dist/packages/core/src/Tracker.d.ts +1 -1
  19. package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +12 -0
  20. package/dist/packages/core/src/commands/deleteNode.d.ts +1 -1
  21. package/dist/packages/core/src/commands/deleteRange.d.ts +1 -1
  22. package/dist/packages/core/src/commands/extendMarkRange.d.ts +1 -1
  23. package/dist/packages/core/src/commands/focus.d.ts +4 -2
  24. package/dist/packages/core/src/commands/index.d.ts +50 -0
  25. package/dist/packages/core/src/commands/insertContent.d.ts +6 -3
  26. package/dist/packages/core/src/commands/insertContentAt.d.ts +6 -3
  27. package/dist/packages/core/src/commands/join.d.ts +33 -0
  28. package/dist/packages/core/src/commands/lift.d.ts +1 -1
  29. package/dist/packages/core/src/commands/liftListItem.d.ts +1 -1
  30. package/dist/packages/core/src/commands/resetAttributes.d.ts +1 -1
  31. package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +12 -0
  32. package/dist/packages/core/src/commands/selectTextblockStart.d.ts +12 -0
  33. package/dist/packages/core/src/commands/setContent.d.ts +2 -2
  34. package/dist/packages/core/src/commands/setMark.d.ts +1 -1
  35. package/dist/packages/core/src/commands/setNode.d.ts +1 -1
  36. package/dist/packages/core/src/commands/setTextSelection.d.ts +1 -1
  37. package/dist/packages/core/src/commands/sinkListItem.d.ts +1 -1
  38. package/dist/packages/core/src/commands/splitListItem.d.ts +1 -1
  39. package/dist/packages/core/src/commands/toggleList.d.ts +2 -2
  40. package/dist/packages/core/src/commands/toggleMark.d.ts +7 -2
  41. package/dist/packages/core/src/commands/toggleNode.d.ts +1 -1
  42. package/dist/packages/core/src/commands/toggleWrap.d.ts +1 -1
  43. package/dist/packages/core/src/commands/unsetMark.d.ts +7 -2
  44. package/dist/packages/core/src/commands/updateAttributes.d.ts +1 -1
  45. package/dist/packages/core/src/commands/wrapIn.d.ts +1 -1
  46. package/dist/packages/core/src/commands/wrapInList.d.ts +1 -1
  47. package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +1 -1
  48. package/dist/packages/core/src/extensions/commands.d.ts +2 -97
  49. package/dist/packages/core/src/extensions/editable.d.ts +1 -1
  50. package/dist/packages/core/src/extensions/focusEvents.d.ts +1 -1
  51. package/dist/packages/core/src/extensions/index.d.ts +1 -0
  52. package/dist/packages/core/src/extensions/keymap.d.ts +1 -1
  53. package/dist/packages/core/src/extensions/tabindex.d.ts +2 -0
  54. package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +7 -0
  55. package/dist/packages/core/src/helpers/createChainableState.d.ts +5 -0
  56. package/dist/packages/core/src/helpers/createDocument.d.ts +2 -2
  57. package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +2 -2
  58. package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +2 -0
  59. package/dist/packages/core/src/helpers/findChildren.d.ts +3 -3
  60. package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +3 -3
  61. package/dist/packages/core/src/helpers/findParentNode.d.ts +3 -4
  62. package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +3 -3
  63. package/dist/packages/core/src/helpers/generateHTML.d.ts +1 -1
  64. package/dist/packages/core/src/helpers/generateJSON.d.ts +1 -1
  65. package/dist/packages/core/src/helpers/generateText.d.ts +5 -0
  66. package/dist/packages/core/src/helpers/getAttributes.d.ts +3 -3
  67. package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +2 -2
  68. package/dist/packages/core/src/helpers/getChangedRanges.d.ts +11 -0
  69. package/dist/packages/core/src/helpers/getDebugJSON.d.ts +2 -5
  70. package/dist/packages/core/src/helpers/getExtensionField.d.ts +2 -2
  71. package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +2 -2
  72. package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +3 -3
  73. package/dist/packages/core/src/helpers/getMarkRange.d.ts +2 -2
  74. package/dist/packages/core/src/helpers/getMarkType.d.ts +2 -2
  75. package/dist/packages/core/src/helpers/getMarksBetween.d.ts +2 -2
  76. package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +3 -3
  77. package/dist/packages/core/src/helpers/getNodeType.d.ts +2 -2
  78. package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +2 -2
  79. package/dist/packages/core/src/helpers/getSchema.d.ts +2 -2
  80. package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +2 -2
  81. package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +2 -2
  82. package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +2 -2
  83. package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +1 -1
  84. package/dist/packages/core/src/helpers/getText.d.ts +6 -0
  85. package/dist/packages/core/src/helpers/getTextBetween.d.ts +6 -0
  86. package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +2 -0
  87. package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +3 -0
  88. package/dist/packages/core/src/helpers/index.d.ts +47 -0
  89. package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +2 -2
  90. package/dist/packages/core/src/helpers/isActive.d.ts +2 -2
  91. package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +2 -0
  92. package/dist/packages/core/src/helpers/isList.d.ts +1 -1
  93. package/dist/packages/core/src/helpers/isMarkActive.d.ts +3 -3
  94. package/dist/packages/core/src/helpers/isNodeActive.d.ts +3 -3
  95. package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +2 -2
  96. package/dist/packages/core/src/helpers/isNodeSelection.d.ts +2 -2
  97. package/dist/packages/core/src/helpers/isTextSelection.d.ts +2 -2
  98. package/dist/packages/core/src/helpers/posToDOMRect.d.ts +2 -2
  99. package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +4 -0
  100. package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +2 -2
  101. package/dist/packages/core/src/helpers/splitExtensions.d.ts +6 -6
  102. package/dist/packages/core/src/index.d.ts +12 -34
  103. package/dist/packages/core/src/inputRules/index.d.ts +5 -0
  104. package/dist/packages/core/src/inputRules/markInputRule.d.ts +12 -3
  105. package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +12 -3
  106. package/dist/packages/core/src/inputRules/textInputRule.d.ts +9 -0
  107. package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +14 -0
  108. package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +27 -0
  109. package/dist/packages/core/src/pasteRules/index.d.ts +3 -0
  110. package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +12 -3
  111. package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +12 -0
  112. package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +9 -0
  113. package/dist/packages/core/src/style.d.ts +1 -2
  114. package/dist/packages/core/src/types.d.ts +70 -40
  115. package/dist/packages/core/src/utilities/callOrReturn.d.ts +1 -1
  116. package/dist/packages/core/src/utilities/createStyleTag.d.ts +1 -1
  117. package/dist/packages/core/src/utilities/deleteProps.d.ts +1 -1
  118. package/dist/packages/core/src/utilities/elementFromString.d.ts +1 -1
  119. package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +1 -0
  120. package/dist/packages/core/src/utilities/findDuplicates.d.ts +1 -0
  121. package/dist/packages/core/src/utilities/fromString.d.ts +1 -1
  122. package/dist/packages/core/src/utilities/index.d.ts +20 -0
  123. package/dist/packages/core/src/utilities/isEmptyObject.d.ts +1 -1
  124. package/dist/packages/core/src/utilities/isFunction.d.ts +1 -0
  125. package/dist/packages/core/src/utilities/isMacOS.d.ts +1 -0
  126. package/dist/packages/core/src/utilities/isNumber.d.ts +1 -0
  127. package/dist/packages/core/src/utilities/isPlainObject.d.ts +1 -1
  128. package/dist/packages/core/src/utilities/isRegExp.d.ts +1 -0
  129. package/dist/packages/core/src/utilities/isString.d.ts +1 -0
  130. package/dist/packages/core/src/utilities/isiOS.d.ts +1 -1
  131. package/dist/packages/core/src/utilities/mergeAttributes.d.ts +1 -1
  132. package/dist/packages/core/src/utilities/mergeDeep.d.ts +1 -1
  133. package/dist/packages/core/src/utilities/minMax.d.ts +1 -1
  134. package/dist/packages/core/src/utilities/objectIncludes.d.ts +3 -1
  135. package/dist/packages/core/src/utilities/removeDuplicates.d.ts +8 -0
  136. package/package.json +25 -24
  137. package/src/CommandManager.ts +73 -83
  138. package/src/Editor.ts +101 -53
  139. package/src/EventEmitter.ts +14 -4
  140. package/src/Extension.ts +244 -138
  141. package/src/ExtensionManager.ts +153 -152
  142. package/src/InputRule.ts +260 -0
  143. package/src/Mark.ts +365 -204
  144. package/src/Node.ts +406 -253
  145. package/src/NodeView.ts +59 -38
  146. package/src/PasteRule.ts +240 -0
  147. package/src/Tracker.ts +4 -8
  148. package/src/commands/blur.ts +4 -0
  149. package/src/commands/clearNodes.ts +15 -9
  150. package/src/commands/createParagraphNear.ts +3 -2
  151. package/src/commands/deleteCurrentNode.ts +41 -0
  152. package/src/commands/deleteNode.ts +3 -2
  153. package/src/commands/deleteRange.ts +1 -1
  154. package/src/commands/deleteSelection.ts +3 -2
  155. package/src/commands/exitCode.ts +3 -2
  156. package/src/commands/extendMarkRange.ts +9 -5
  157. package/src/commands/focus.ts +31 -42
  158. package/src/commands/index.ts +50 -0
  159. package/src/commands/insertContent.ts +15 -4
  160. package/src/commands/insertContentAt.ts +71 -14
  161. package/src/commands/join.ts +53 -0
  162. package/src/commands/keyboardShortcut.ts +3 -3
  163. package/src/commands/lift.ts +6 -5
  164. package/src/commands/liftEmptyBlock.ts +2 -1
  165. package/src/commands/liftListItem.ts +5 -4
  166. package/src/commands/newlineInCode.ts +3 -2
  167. package/src/commands/resetAttributes.ts +16 -10
  168. package/src/commands/selectAll.ts +5 -3
  169. package/src/commands/selectNodeBackward.ts +3 -2
  170. package/src/commands/selectNodeForward.ts +3 -2
  171. package/src/commands/selectParentNode.ts +3 -2
  172. package/src/commands/selectTextblockEnd.ts +20 -0
  173. package/src/commands/selectTextblockStart.ts +20 -0
  174. package/src/commands/setContent.ts +6 -9
  175. package/src/commands/setMark.ts +66 -13
  176. package/src/commands/setNode.ts +30 -6
  177. package/src/commands/setNodeSelection.ts +6 -7
  178. package/src/commands/setTextSelection.ts +8 -9
  179. package/src/commands/sinkListItem.ts +5 -4
  180. package/src/commands/splitBlock.ts +23 -38
  181. package/src/commands/splitListItem.ts +30 -27
  182. package/src/commands/toggleList.ts +108 -19
  183. package/src/commands/toggleMark.ts +17 -6
  184. package/src/commands/toggleNode.ts +9 -4
  185. package/src/commands/toggleWrap.ts +8 -8
  186. package/src/commands/undoInputRule.ts +31 -2
  187. package/src/commands/unsetAllMarks.ts +4 -8
  188. package/src/commands/unsetMark.ts +34 -21
  189. package/src/commands/updateAttributes.ts +18 -12
  190. package/src/commands/wrapIn.ts +5 -10
  191. package/src/commands/wrapInList.ts +5 -4
  192. package/src/extensions/clipboardTextSerializer.ts +15 -36
  193. package/src/extensions/commands.ts +3 -144
  194. package/src/extensions/editable.ts +2 -1
  195. package/src/extensions/focusEvents.ts +4 -6
  196. package/src/extensions/index.ts +1 -0
  197. package/src/extensions/keymap.ts +111 -13
  198. package/src/extensions/tabindex.ts +18 -0
  199. package/src/helpers/combineTransactionSteps.ts +21 -0
  200. package/src/helpers/createChainableState.ts +38 -0
  201. package/src/helpers/createDocument.ts +4 -3
  202. package/src/helpers/createNodeFromContent.ts +10 -15
  203. package/src/helpers/defaultBlockAt.ts +13 -0
  204. package/src/helpers/findChildren.ts +4 -3
  205. package/src/helpers/findChildrenInRange.ts +8 -3
  206. package/src/helpers/findParentNode.ts +4 -3
  207. package/src/helpers/findParentNodeClosestToPos.ts +13 -7
  208. package/src/helpers/generateHTML.ts +6 -5
  209. package/src/helpers/generateJSON.ts +6 -7
  210. package/src/helpers/generateText.ts +27 -0
  211. package/src/helpers/getAttributes.ts +8 -9
  212. package/src/helpers/getAttributesFromExtensions.ts +25 -12
  213. package/src/helpers/getChangedRanges.ts +83 -0
  214. package/src/helpers/getDebugJSON.ts +42 -38
  215. package/src/helpers/getExtensionField.ts +3 -3
  216. package/src/helpers/getHTMLFromFragment.ts +5 -6
  217. package/src/helpers/getMarkAttributes.ts +18 -10
  218. package/src/helpers/getMarkRange.ts +13 -8
  219. package/src/helpers/getMarkType.ts +5 -3
  220. package/src/helpers/getMarksBetween.ts +34 -10
  221. package/src/helpers/getNodeAttributes.ts +14 -12
  222. package/src/helpers/getNodeType.ts +5 -3
  223. package/src/helpers/getRenderedAttributes.ts +8 -6
  224. package/src/helpers/getSchema.ts +5 -4
  225. package/src/helpers/getSchemaByResolvedExtensions.ts +165 -111
  226. package/src/helpers/getSchemaTypeByName.ts +3 -11
  227. package/src/helpers/getSchemaTypeNameByName.ts +2 -2
  228. package/src/helpers/getSplittedAttributes.ts +1 -1
  229. package/src/helpers/getText.ts +19 -0
  230. package/src/helpers/getTextBetween.ts +46 -0
  231. package/src/helpers/getTextContentFromNodes.ts +26 -0
  232. package/src/helpers/getTextSerializersFromSchema.ts +11 -0
  233. package/src/helpers/index.ts +47 -0
  234. package/src/helpers/injectExtensionAttributesToParseRule.ts +22 -23
  235. package/src/helpers/isActive.ts +10 -5
  236. package/src/helpers/isExtensionRulesEnabled.ts +15 -0
  237. package/src/helpers/isList.ts +6 -5
  238. package/src/helpers/isMarkActive.ts +32 -35
  239. package/src/helpers/isNodeActive.ts +27 -37
  240. package/src/helpers/isNodeEmpty.ts +2 -2
  241. package/src/helpers/isNodeSelection.ts +3 -4
  242. package/src/helpers/isTextSelection.ts +3 -4
  243. package/src/helpers/posToDOMRect.ts +10 -4
  244. package/src/helpers/resolveFocusPosition.ts +42 -0
  245. package/src/helpers/selectionToInsertionEnd.ts +3 -3
  246. package/src/helpers/splitExtensions.ts +3 -3
  247. package/src/index.ts +12 -37
  248. package/src/inputRules/index.ts +5 -0
  249. package/src/inputRules/markInputRule.ts +59 -40
  250. package/src/inputRules/nodeInputRule.ts +45 -12
  251. package/src/inputRules/textInputRule.ts +35 -0
  252. package/src/inputRules/textblockTypeInputRule.ts +37 -0
  253. package/src/inputRules/wrappingInputRule.ts +84 -0
  254. package/src/pasteRules/index.ts +3 -0
  255. package/src/pasteRules/markPasteRule.ts +49 -56
  256. package/src/pasteRules/nodePasteRule.ts +37 -0
  257. package/src/pasteRules/textPasteRule.ts +35 -0
  258. package/src/style.ts +12 -3
  259. package/src/types.ts +140 -106
  260. package/src/utilities/callOrReturn.ts +3 -2
  261. package/src/utilities/createStyleTag.ts +8 -4
  262. package/src/utilities/deleteProps.ts +1 -1
  263. package/src/utilities/elementFromString.ts +1 -1
  264. package/src/utilities/escapeForRegEx.ts +4 -0
  265. package/src/utilities/findDuplicates.ts +5 -0
  266. package/src/utilities/fromString.ts +2 -2
  267. package/src/utilities/index.ts +20 -0
  268. package/src/utilities/isEmptyObject.ts +2 -2
  269. package/src/utilities/isFunction.ts +3 -0
  270. package/src/utilities/isMacOS.ts +5 -0
  271. package/src/utilities/isNumber.ts +3 -0
  272. package/src/utilities/isPlainObject.ts +8 -5
  273. package/src/utilities/isRegExp.ts +3 -0
  274. package/src/utilities/isString.ts +3 -0
  275. package/src/utilities/isiOS.ts +1 -1
  276. package/src/utilities/mergeAttributes.ts +2 -1
  277. package/src/utilities/mergeDeep.ts +2 -2
  278. package/src/utilities/minMax.ts +1 -1
  279. package/src/utilities/objectIncludes.ts +18 -4
  280. package/src/utilities/removeDuplicates.ts +15 -0
  281. package/CHANGELOG.md +0 -1190
  282. package/LICENSE.md +0 -21
  283. package/dist/packages/core/src/commands/joinBackward.d.ts +0 -12
  284. package/dist/packages/core/src/commands/joinForward.d.ts +0 -12
  285. package/dist/packages/core/src/utilities/isClass.d.ts +0 -1
  286. package/dist/packages/core/src/utilities/isObject.d.ts +0 -1
  287. package/dist/packages/core/src/utilities/removeElement.d.ts +0 -1
  288. package/dist/tiptap-core.cjs.js +0 -3408
  289. package/dist/tiptap-core.cjs.js.map +0 -1
  290. package/dist/tiptap-core.esm.js.map +0 -1
  291. package/dist/tiptap-core.umd.js +0 -3405
  292. package/dist/tiptap-core.umd.js.map +0 -1
  293. package/src/commands/joinBackward.ts +0 -17
  294. package/src/commands/joinForward.ts +0 -17
  295. package/src/utilities/isClass.ts +0 -7
  296. package/src/utilities/isObject.ts +0 -10
  297. package/src/utilities/removeElement.ts +0 -5
@@ -1,7 +1,10 @@
1
- import { MarkType } from 'prosemirror-model'
1
+ import { MarkType, ResolvedPos } from '@tiptap/pm/model'
2
+ import { EditorState, Transaction } from '@tiptap/pm/state'
3
+
4
+ import { isTextSelection } from '../helpers'
5
+ import { getMarkAttributes } from '../helpers/getMarkAttributes'
6
+ import { getMarkType } from '../helpers/getMarkType'
2
7
  import { RawCommands } from '../types'
3
- import getMarkType from '../helpers/getMarkType'
4
- import getMarkAttributes from '../helpers/getMarkAttributes'
5
8
 
6
9
  declare module '@tiptap/core' {
7
10
  interface Commands<ReturnType> {
@@ -9,11 +12,55 @@ declare module '@tiptap/core' {
9
12
  /**
10
13
  * Add a mark with new attributes.
11
14
  */
12
- setMark: (typeOrName: string | MarkType, attributes?: Record<string, any>) => ReturnType,
15
+ setMark: (typeOrName: string | MarkType, attributes?: Record<string, any>) => ReturnType
13
16
  }
14
17
  }
15
18
  }
16
19
 
20
+ function canSetMark(state: EditorState, tr: Transaction, newMarkType: MarkType) {
21
+ const { selection } = tr
22
+ let cursor: ResolvedPos | null = null
23
+
24
+ if (isTextSelection(selection)) {
25
+ cursor = selection.$cursor
26
+ }
27
+
28
+ if (cursor) {
29
+ const currentMarks = state.storedMarks ?? cursor.marks()
30
+
31
+ // There can be no current marks that exclude the new mark
32
+ return (
33
+ !!newMarkType.isInSet(currentMarks)
34
+ || !currentMarks.some(mark => mark.type.excludes(newMarkType))
35
+ )
36
+ }
37
+
38
+ const { ranges } = selection
39
+
40
+ return ranges.some(({ $from, $to }) => {
41
+ let someNodeSupportsMark = $from.depth === 0
42
+ ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType)
43
+ : false
44
+
45
+ state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
46
+ // If we already found a mark that we can enable, return false to bypass the remaining search
47
+ if (someNodeSupportsMark) {
48
+ return false
49
+ }
50
+
51
+ if (node.isInline) {
52
+ const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType)
53
+ const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks)
54
+ || !node.marks.some(otherMark => otherMark.type.excludes(newMarkType))
55
+
56
+ someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType
57
+ }
58
+ return !someNodeSupportsMark
59
+ })
60
+
61
+ return someNodeSupportsMark
62
+ })
63
+ }
17
64
  export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
18
65
  const { selection } = tr
19
66
  const { empty, ranges } = selection
@@ -23,10 +70,12 @@ export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) =>
23
70
  if (empty) {
24
71
  const oldAttributes = getMarkAttributes(state, type)
25
72
 
26
- tr.addStoredMark(type.create({
27
- ...oldAttributes,
28
- ...attributes,
29
- }))
73
+ tr.addStoredMark(
74
+ type.create({
75
+ ...oldAttributes,
76
+ ...attributes,
77
+ }),
78
+ )
30
79
  } else {
31
80
  ranges.forEach(range => {
32
81
  const from = range.$from.pos
@@ -43,10 +92,14 @@ export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) =>
43
92
  if (someHasMark) {
44
93
  node.marks.forEach(mark => {
45
94
  if (type === mark.type) {
46
- tr.addMark(trimmedFrom, trimmedTo, type.create({
47
- ...mark.attrs,
48
- ...attributes,
49
- }))
95
+ tr.addMark(
96
+ trimmedFrom,
97
+ trimmedTo,
98
+ type.create({
99
+ ...mark.attrs,
100
+ ...attributes,
101
+ }),
102
+ )
50
103
  }
51
104
  })
52
105
  } else {
@@ -57,5 +110,5 @@ export const setMark: RawCommands['setMark'] = (typeOrName, attributes = {}) =>
57
110
  }
58
111
  }
59
112
 
60
- return true
113
+ return canSetMark(state, tr, type)
61
114
  }
@@ -1,7 +1,8 @@
1
- import { NodeType } from 'prosemirror-model'
2
- import { setBlockType } from 'prosemirror-commands'
1
+ import { setBlockType } from '@tiptap/pm/commands'
2
+ import { NodeType } from '@tiptap/pm/model'
3
+
4
+ import { getNodeType } from '../helpers/getNodeType'
3
5
  import { RawCommands } from '../types'
4
- import getNodeType from '../helpers/getNodeType'
5
6
 
6
7
  declare module '@tiptap/core' {
7
8
  interface Commands<ReturnType> {
@@ -9,13 +10,36 @@ declare module '@tiptap/core' {
9
10
  /**
10
11
  * Replace a given range with a node.
11
12
  */
12
- setNode: (typeOrName: string | NodeType, attributes?: Record<string, any>) => ReturnType,
13
+ setNode: (typeOrName: string | NodeType, attributes?: Record<string, any>) => ReturnType
13
14
  }
14
15
  }
15
16
  }
16
17
 
17
- export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
18
+ export const setNode: RawCommands['setNode'] = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
18
19
  const type = getNodeType(typeOrName, state.schema)
19
20
 
20
- return setBlockType(type, attributes)(state, dispatch)
21
+ // TODO: use a fallback like insertContent?
22
+ if (!type.isTextblock) {
23
+ console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.')
24
+
25
+ return false
26
+ }
27
+
28
+ return (
29
+ chain()
30
+ // try to convert node to default node if needed
31
+ .command(({ commands }) => {
32
+ const canSetBlock = setBlockType(type, attributes)(state)
33
+
34
+ if (canSetBlock) {
35
+ return true
36
+ }
37
+
38
+ return commands.clearNodes()
39
+ })
40
+ .command(({ state: updatedState }) => {
41
+ return setBlockType(type, attributes)(updatedState, dispatch)
42
+ })
43
+ .run()
44
+ )
21
45
  }
@@ -1,6 +1,7 @@
1
- import { Selection, NodeSelection } from 'prosemirror-state'
2
- import minMax from '../utilities/minMax'
1
+ import { NodeSelection } from '@tiptap/pm/state'
2
+
3
3
  import { RawCommands } from '../types'
4
+ import { minMax } from '../utilities/minMax'
4
5
 
5
6
  declare module '@tiptap/core' {
6
7
  interface Commands<ReturnType> {
@@ -8,7 +9,7 @@ declare module '@tiptap/core' {
8
9
  /**
9
10
  * Creates a NodeSelection.
10
11
  */
11
- setNodeSelection: (position: number) => ReturnType,
12
+ setNodeSelection: (position: number) => ReturnType
12
13
  }
13
14
  }
14
15
  }
@@ -16,10 +17,8 @@ declare module '@tiptap/core' {
16
17
  export const setNodeSelection: RawCommands['setNodeSelection'] = position => ({ tr, dispatch }) => {
17
18
  if (dispatch) {
18
19
  const { doc } = tr
19
- const minPos = Selection.atStart(doc).from
20
- const maxPos = Selection.atEnd(doc).to
21
- const resolvedPos = minMax(position, minPos, maxPos)
22
- const selection = NodeSelection.create(doc, resolvedPos)
20
+ const from = minMax(position, 0, doc.content.size)
21
+ const selection = NodeSelection.create(doc, from)
23
22
 
24
23
  tr.setSelection(selection)
25
24
  }
@@ -1,6 +1,7 @@
1
- import { Selection, TextSelection } from 'prosemirror-state'
2
- import minMax from '../utilities/minMax'
3
- import { RawCommands, Range } from '../types'
1
+ import { TextSelection } from '@tiptap/pm/state'
2
+
3
+ import { Range, RawCommands } from '../types'
4
+ import { minMax } from '../utilities/minMax'
4
5
 
5
6
  declare module '@tiptap/core' {
6
7
  interface Commands<ReturnType> {
@@ -8,7 +9,7 @@ declare module '@tiptap/core' {
8
9
  /**
9
10
  * Creates a TextSelection.
10
11
  */
11
- setTextSelection: (position: number | Range) => ReturnType,
12
+ setTextSelection: (position: number | Range) => ReturnType
12
13
  }
13
14
  }
14
15
  }
@@ -16,11 +17,9 @@ declare module '@tiptap/core' {
16
17
  export const setTextSelection: RawCommands['setTextSelection'] = position => ({ tr, dispatch }) => {
17
18
  if (dispatch) {
18
19
  const { doc } = tr
19
- const { from, to } = typeof position === 'number'
20
- ? { from: position, to: position }
21
- : position
22
- const minPos = Selection.atStart(doc).from
23
- const maxPos = Selection.atEnd(doc).to
20
+ const { from, to } = typeof position === 'number' ? { from: position, to: position } : position
21
+ const minPos = TextSelection.atStart(doc).from
22
+ const maxPos = TextSelection.atEnd(doc).to
24
23
  const resolvedFrom = minMax(from, minPos, maxPos)
25
24
  const resolvedEnd = minMax(to, minPos, maxPos)
26
25
  const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
@@ -1,7 +1,8 @@
1
- import { sinkListItem as originalSinkListItem } from 'prosemirror-schema-list'
2
- import { NodeType } from 'prosemirror-model'
1
+ import { NodeType } from '@tiptap/pm/model'
2
+ import { sinkListItem as originalSinkListItem } from '@tiptap/pm/schema-list'
3
+
4
+ import { getNodeType } from '../helpers/getNodeType'
3
5
  import { RawCommands } from '../types'
4
- import getNodeType from '../helpers/getNodeType'
5
6
 
6
7
  declare module '@tiptap/core' {
7
8
  interface Commands<ReturnType> {
@@ -9,7 +10,7 @@ declare module '@tiptap/core' {
9
10
  /**
10
11
  * Sink the list item down into an inner list.
11
12
  */
12
- sinkListItem: (typeOrName: string | NodeType) => ReturnType,
13
+ sinkListItem: (typeOrName: string | NodeType) => ReturnType
13
14
  }
14
15
  }
15
16
  }
@@ -1,23 +1,12 @@
1
- import { canSplit } from 'prosemirror-transform'
2
- import { ContentMatch } from 'prosemirror-model'
3
- import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state'
4
- import { RawCommands } from '../types'
5
- import getSplittedAttributes from '../helpers/getSplittedAttributes'
6
-
7
- function defaultBlockAt(match: ContentMatch) {
8
- for (let i = 0; i < match.edgeCount; i += 1) {
9
- const { type } = match.edge(i)
1
+ import { EditorState, NodeSelection, TextSelection } from '@tiptap/pm/state'
2
+ import { canSplit } from '@tiptap/pm/transform'
10
3
 
11
- if (type.isTextblock && !type.hasRequiredAttrs()) {
12
- return type
13
- }
14
- }
15
- return null
16
- }
4
+ import { defaultBlockAt } from '../helpers/defaultBlockAt'
5
+ import { getSplittedAttributes } from '../helpers/getSplittedAttributes'
6
+ import { RawCommands } from '../types'
17
7
 
18
8
  function ensureMarks(state: EditorState, splittableMarks?: string[]) {
19
- const marks = state.storedMarks
20
- || (state.selection.$to.parentOffset && state.selection.$from.marks())
9
+ const marks = state.storedMarks || (state.selection.$to.parentOffset && state.selection.$from.marks())
21
10
 
22
11
  if (marks) {
23
12
  const filteredMarks = marks.filter(mark => splittableMarks?.includes(mark.type.name))
@@ -32,16 +21,13 @@ declare module '@tiptap/core' {
32
21
  /**
33
22
  * Forks a new node from an existing node.
34
23
  */
35
- splitBlock: (options?: { keepMarks?: boolean }) => ReturnType,
24
+ splitBlock: (options?: { keepMarks?: boolean }) => ReturnType
36
25
  }
37
26
  }
38
27
  }
39
28
 
40
29
  export const splitBlock: RawCommands['splitBlock'] = ({ keepMarks = true } = {}) => ({
41
- tr,
42
- state,
43
- dispatch,
44
- editor,
30
+ tr, state, dispatch, editor,
45
31
  }) => {
46
32
  const { selection, doc } = tr
47
33
  const { $from, $to } = selection
@@ -84,37 +70,36 @@ export const splitBlock: RawCommands['splitBlock'] = ({ keepMarks = true } = {})
84
70
  : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)))
85
71
 
86
72
  let types = atEnd && deflt
87
- ? [{
88
- type: deflt,
89
- attrs: newAttributes,
90
- }]
73
+ ? [
74
+ {
75
+ type: deflt,
76
+ attrs: newAttributes,
77
+ },
78
+ ]
91
79
  : undefined
92
80
 
93
81
  let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types)
94
82
 
95
83
  if (
96
84
  !types
97
- && !can
98
- && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)
85
+ && !can
86
+ && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)
99
87
  ) {
100
88
  can = true
101
89
  types = deflt
102
- ? [{
103
- type: deflt,
104
- attrs: newAttributes,
105
- }]
90
+ ? [
91
+ {
92
+ type: deflt,
93
+ attrs: newAttributes,
94
+ },
95
+ ]
106
96
  : undefined
107
97
  }
108
98
 
109
99
  if (can) {
110
100
  tr.split(tr.mapping.map($from.pos), 1, types)
111
101
 
112
- if (
113
- deflt
114
- && !atEnd
115
- && !$from.parentOffset
116
- && $from.parent.type !== deflt
117
- ) {
102
+ if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
118
103
  const first = tr.mapping.map($from.before())
119
104
  const $first = tr.doc.resolve(first)
120
105
 
@@ -1,14 +1,12 @@
1
1
  import {
2
- NodeType,
3
- Node as ProseMirrorNode,
4
- Fragment,
5
- Slice,
6
- } from 'prosemirror-model'
7
- import { canSplit } from 'prosemirror-transform'
8
- import { TextSelection } from 'prosemirror-state'
2
+ Fragment, Node as ProseMirrorNode, NodeType, Slice,
3
+ } from '@tiptap/pm/model'
4
+ import { TextSelection } from '@tiptap/pm/state'
5
+ import { canSplit } from '@tiptap/pm/transform'
6
+
7
+ import { getNodeType } from '../helpers/getNodeType'
8
+ import { getSplittedAttributes } from '../helpers/getSplittedAttributes'
9
9
  import { RawCommands } from '../types'
10
- import getNodeType from '../helpers/getNodeType'
11
- import getSplittedAttributes from '../helpers/getSplittedAttributes'
12
10
 
13
11
  declare module '@tiptap/core' {
14
12
  interface Commands<ReturnType> {
@@ -16,7 +14,7 @@ declare module '@tiptap/core' {
16
14
  /**
17
15
  * Splits one list item into two list items.
18
16
  */
19
- splitListItem: (typeOrName: string | NodeType) => ReturnType,
17
+ splitListItem: (typeOrName: string | NodeType) => ReturnType
20
18
  }
21
19
  }
22
20
  }
@@ -29,7 +27,7 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
29
27
 
30
28
  // @ts-ignore
31
29
  // eslint-disable-next-line
32
- const node: ProseMirrorNode = state.selection.node
30
+ const node: ProseMirrorNode = state.selection.node
33
31
 
34
32
  if ((node && node.isBlock) || $from.depth < 2 || !$from.sameParent($to)) {
35
33
  return false
@@ -49,8 +47,8 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
49
47
  // command handle lifting.
50
48
  if (
51
49
  $from.depth === 2
52
- || $from.node(-3).type !== type
53
- || $from.index(-2) !== $from.node(-2).childCount - 1
50
+ || $from.node(-3).type !== type
51
+ || $from.index(-2) !== $from.node(-2).childCount - 1
54
52
  ) {
55
53
  return false
56
54
  }
@@ -58,11 +56,7 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
58
56
  if (dispatch) {
59
57
  let wrap = Fragment.empty
60
58
  // eslint-disable-next-line
61
- const depthBefore = $from.index(-1)
62
- ? 1
63
- : $from.index(-2)
64
- ? 2
65
- : 3
59
+ const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3
66
60
 
67
61
  // Build a fragment containing empty versions of the structure
68
62
  // from the outer list item to the parent node of the cursor
@@ -71,11 +65,7 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
71
65
  }
72
66
 
73
67
  // eslint-disable-next-line
74
- const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount
75
- ? 1
76
- : $from.indexAfter(-2) < $from.node(-3).childCount
77
- ? 2
78
- : 3
68
+ const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3
79
69
 
80
70
  // Add a second list item with an empty default start node
81
71
  const newNextTypeAttributes = getSplittedAttributes(
@@ -113,9 +103,7 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
113
103
  return true
114
104
  }
115
105
 
116
- const nextType = $to.pos === $from.end()
117
- ? grandParent.contentMatchAt(0).defaultType
118
- : null
106
+ const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null
119
107
 
120
108
  const newTypeAttributes = getSplittedAttributes(
121
109
  extensionAttributes,
@@ -131,7 +119,10 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
131
119
  tr.delete($from.pos, $to.pos)
132
120
 
133
121
  const types = nextType
134
- ? [{ type, attrs: newTypeAttributes }, { type: nextType, attrs: newNextTypeAttributes }]
122
+ ? [
123
+ { type, attrs: newTypeAttributes },
124
+ { type: nextType, attrs: newNextTypeAttributes },
125
+ ]
135
126
  : [{ type, attrs: newTypeAttributes }]
136
127
 
137
128
  if (!canSplit(tr.doc, $from.pos, 2)) {
@@ -139,7 +130,19 @@ export const splitListItem: RawCommands['splitListItem'] = typeOrName => ({
139
130
  }
140
131
 
141
132
  if (dispatch) {
133
+ const { selection, storedMarks } = state
134
+ const { splittableMarks } = editor.extensionManager
135
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
136
+
142
137
  tr.split($from.pos, 2, types).scrollIntoView()
138
+
139
+ if (!marks || !dispatch) {
140
+ return true
141
+ }
142
+
143
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
144
+
145
+ tr.ensureMarks(filteredMarks)
143
146
  }
144
147
 
145
148
  return true
@@ -1,8 +1,61 @@
1
- import { NodeType } from 'prosemirror-model'
1
+ import { NodeType } from '@tiptap/pm/model'
2
+ import { Transaction } from '@tiptap/pm/state'
3
+ import { canJoin } from '@tiptap/pm/transform'
4
+
5
+ import { findParentNode } from '../helpers/findParentNode'
6
+ import { getNodeType } from '../helpers/getNodeType'
7
+ import { isList } from '../helpers/isList'
2
8
  import { RawCommands } from '../types'
3
- import getNodeType from '../helpers/getNodeType'
4
- import findParentNode from '../helpers/findParentNode'
5
- import isList from '../helpers/isList'
9
+
10
+ const joinListBackwards = (tr: Transaction, listType: NodeType): boolean => {
11
+ const list = findParentNode(node => node.type === listType)(tr.selection)
12
+
13
+ if (!list) {
14
+ return true
15
+ }
16
+
17
+ const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth)
18
+
19
+ if (before === undefined) {
20
+ return true
21
+ }
22
+
23
+ const nodeBefore = tr.doc.nodeAt(before)
24
+ const canJoinBackwards = list.node.type === nodeBefore?.type && canJoin(tr.doc, list.pos)
25
+
26
+ if (!canJoinBackwards) {
27
+ return true
28
+ }
29
+
30
+ tr.join(list.pos)
31
+
32
+ return true
33
+ }
34
+
35
+ const joinListForwards = (tr: Transaction, listType: NodeType): boolean => {
36
+ const list = findParentNode(node => node.type === listType)(tr.selection)
37
+
38
+ if (!list) {
39
+ return true
40
+ }
41
+
42
+ const after = tr.doc.resolve(list.start).after(list.depth)
43
+
44
+ if (after === undefined) {
45
+ return true
46
+ }
47
+
48
+ const nodeAfter = tr.doc.nodeAt(after)
49
+ const canJoinForwards = list.node.type === nodeAfter?.type && canJoin(tr.doc, after)
50
+
51
+ if (!canJoinForwards) {
52
+ return true
53
+ }
54
+
55
+ tr.join(after)
56
+
57
+ return true
58
+ }
6
59
 
7
60
  declare module '@tiptap/core' {
8
61
  interface Commands<ReturnType> {
@@ -10,21 +63,23 @@ declare module '@tiptap/core' {
10
63
  /**
11
64
  * Toggle between different list types.
12
65
  */
13
- toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType) => ReturnType,
66
+ toggleList: (listTypeOrName: string | NodeType, itemTypeOrName: string | NodeType, keepMarks?: boolean, attributes?: Record<string, any>) => ReturnType;
14
67
  }
15
68
  }
16
69
  }
17
70
 
18
- export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOrName) => ({
71
+ export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOrName, keepMarks, attributes = {}) => ({
19
72
  editor, tr, state, dispatch, chain, commands, can,
20
73
  }) => {
21
- const { extensions } = editor.extensionManager
74
+ const { extensions, splittableMarks } = editor.extensionManager
22
75
  const listType = getNodeType(listTypeOrName, state.schema)
23
76
  const itemType = getNodeType(itemTypeOrName, state.schema)
24
- const { selection } = state
77
+ const { selection, storedMarks } = state
25
78
  const { $from, $to } = selection
26
79
  const range = $from.blockRange($to)
27
80
 
81
+ const marks = storedMarks || (selection.$to.parentOffset && selection.$from.marks())
82
+
28
83
  if (!range) {
29
84
  return false
30
85
  }
@@ -40,24 +95,58 @@ export const toggleList: RawCommands['toggleList'] = (listTypeOrName, itemTypeOr
40
95
  // change list type
41
96
  if (
42
97
  isList(parentList.node.type.name, extensions)
43
- && listType.validContent(parentList.node.content)
44
- && dispatch
98
+ && listType.validContent(parentList.node.content)
99
+ && dispatch
45
100
  ) {
46
- tr.setNodeMarkup(parentList.pos, listType)
101
+ return chain()
102
+ .command(() => {
103
+ tr.setNodeMarkup(parentList.pos, listType)
47
104
 
48
- return true
105
+ return true
106
+ })
107
+ .command(() => joinListBackwards(tr, listType))
108
+ .command(() => joinListForwards(tr, listType))
109
+ .run()
49
110
  }
50
111
  }
112
+ if (!keepMarks || !marks || !dispatch) {
51
113
 
52
- const canWrapInList = can().wrapInList(listType)
53
-
54
- // try to convert node to paragraph if needed
55
- if (!canWrapInList) {
56
114
  return chain()
57
- .clearNodes()
58
- .wrapInList(listType)
115
+ // try to convert node to default node if needed
116
+ .command(() => {
117
+ const canWrapInList = can().wrapInList(listType, attributes)
118
+
119
+ if (canWrapInList) {
120
+ return true
121
+ }
122
+
123
+ return commands.clearNodes()
124
+ })
125
+ .wrapInList(listType, attributes)
126
+ .command(() => joinListBackwards(tr, listType))
127
+ .command(() => joinListForwards(tr, listType))
59
128
  .run()
60
129
  }
61
130
 
62
- return commands.wrapInList(listType)
131
+ return (
132
+ chain()
133
+ // try to convert node to default node if needed
134
+ .command(() => {
135
+ const canWrapInList = can().wrapInList(listType, attributes)
136
+
137
+ const filteredMarks = marks.filter(mark => splittableMarks.includes(mark.type.name))
138
+
139
+ tr.ensureMarks(filteredMarks)
140
+
141
+ if (canWrapInList) {
142
+ return true
143
+ }
144
+
145
+ return commands.clearNodes()
146
+ })
147
+ .wrapInList(listType, attributes)
148
+ .command(() => joinListBackwards(tr, listType))
149
+ .command(() => joinListForwards(tr, listType))
150
+ .run()
151
+ )
63
152
  }
@@ -1,7 +1,8 @@
1
- import { MarkType } from 'prosemirror-model'
1
+ import { MarkType } from '@tiptap/pm/model'
2
+
3
+ import { getMarkType } from '../helpers/getMarkType'
4
+ import { isMarkActive } from '../helpers/isMarkActive'
2
5
  import { RawCommands } from '../types'
3
- import getMarkType from '../helpers/getMarkType'
4
- import isMarkActive from '../helpers/isMarkActive'
5
6
 
6
7
  declare module '@tiptap/core' {
7
8
  interface Commands<ReturnType> {
@@ -9,17 +10,27 @@ declare module '@tiptap/core' {
9
10
  /**
10
11
  * Toggle a mark on and off.
11
12
  */
12
- toggleMark: (typeOrName: string | MarkType, attributes?: Record<string, any>) => ReturnType,
13
+ toggleMark: (
14
+ typeOrName: string | MarkType,
15
+ attributes?: Record<string, any>,
16
+ options?: {
17
+ /**
18
+ * Removes the mark even across the current selection. Defaults to `false`.
19
+ */
20
+ extendEmptyMarkRange?: boolean
21
+ },
22
+ ) => ReturnType
13
23
  }
14
24
  }
15
25
  }
16
26
 
17
- export const toggleMark: RawCommands['toggleMark'] = (typeOrName, attributes = {}) => ({ state, commands }) => {
27
+ export const toggleMark: RawCommands['toggleMark'] = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
28
+ const { extendEmptyMarkRange = false } = options
18
29
  const type = getMarkType(typeOrName, state.schema)
19
30
  const isActive = isMarkActive(state, type, attributes)
20
31
 
21
32
  if (isActive) {
22
- return commands.unsetMark(type)
33
+ return commands.unsetMark(type, { extendEmptyMarkRange })
23
34
  }
24
35
 
25
36
  return commands.setMark(type, attributes)