@tiptap/core 2.0.0-beta.17 → 2.0.0-beta.173

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 (318) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +2 -2
  3. package/dist/packages/core/src/CommandManager.d.ts +13 -6
  4. package/dist/packages/core/src/Editor.d.ts +23 -18
  5. package/dist/packages/core/src/EventEmitter.d.ts +8 -4
  6. package/dist/packages/core/src/Extension.d.ts +102 -26
  7. package/dist/packages/core/src/ExtensionManager.d.ts +7 -12
  8. package/dist/packages/core/src/InputRule.d.ts +42 -0
  9. package/dist/packages/core/src/Mark.d.ts +134 -30
  10. package/dist/packages/core/src/Node.d.ts +160 -32
  11. package/dist/packages/core/src/NodeView.d.ts +5 -9
  12. package/dist/packages/core/src/PasteRule.d.ts +42 -0
  13. package/dist/packages/core/src/Tracker.d.ts +11 -0
  14. package/dist/packages/core/src/commands/blur.d.ts +3 -3
  15. package/dist/packages/core/src/commands/clearContent.d.ts +3 -3
  16. package/dist/packages/core/src/commands/clearNodes.d.ts +3 -3
  17. package/dist/packages/core/src/commands/command.d.ts +2 -2
  18. package/dist/packages/core/src/commands/createParagraphNear.d.ts +3 -3
  19. package/dist/packages/core/src/commands/deleteNode.d.ts +13 -0
  20. package/dist/packages/core/src/commands/deleteRange.d.ts +3 -3
  21. package/dist/packages/core/src/commands/deleteSelection.d.ts +3 -3
  22. package/dist/packages/core/src/commands/enter.d.ts +3 -3
  23. package/dist/packages/core/src/commands/exitCode.d.ts +3 -3
  24. package/dist/packages/core/src/commands/extendMarkRange.d.ts +3 -3
  25. package/dist/packages/core/src/commands/first.d.ts +3 -3
  26. package/dist/packages/core/src/commands/focus.d.ts +5 -3
  27. package/dist/packages/core/src/commands/forEach.d.ts +14 -0
  28. package/dist/packages/core/src/commands/insertContent.d.ts +7 -3
  29. package/dist/packages/core/src/commands/insertContentAt.d.ts +16 -0
  30. package/dist/packages/core/src/commands/joinBackward.d.ts +3 -3
  31. package/dist/packages/core/src/commands/joinForward.d.ts +3 -3
  32. package/dist/packages/core/src/commands/keyboardShortcut.d.ts +3 -3
  33. package/dist/packages/core/src/commands/lift.d.ts +3 -3
  34. package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +3 -3
  35. package/dist/packages/core/src/commands/liftListItem.d.ts +3 -3
  36. package/dist/packages/core/src/commands/newlineInCode.d.ts +3 -3
  37. package/dist/packages/core/src/commands/resetAttributes.d.ts +13 -0
  38. package/dist/packages/core/src/commands/scrollIntoView.d.ts +3 -3
  39. package/dist/packages/core/src/commands/selectAll.d.ts +3 -3
  40. package/dist/packages/core/src/commands/selectNodeBackward.d.ts +3 -3
  41. package/dist/packages/core/src/commands/selectNodeForward.d.ts +3 -3
  42. package/dist/packages/core/src/commands/selectParentNode.d.ts +3 -3
  43. package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +12 -0
  44. package/dist/packages/core/src/commands/selectTextblockStart.d.ts +12 -0
  45. package/dist/packages/core/src/commands/setContent.d.ts +4 -3
  46. package/dist/packages/core/src/commands/setMark.d.ts +3 -3
  47. package/dist/packages/core/src/commands/setMeta.d.ts +12 -0
  48. package/dist/packages/core/src/commands/setNode.d.ts +3 -3
  49. package/dist/packages/core/src/commands/setNodeSelection.d.ts +12 -0
  50. package/dist/packages/core/src/commands/setTextSelection.d.ts +12 -0
  51. package/dist/packages/core/src/commands/sinkListItem.d.ts +3 -3
  52. package/dist/packages/core/src/commands/splitBlock.d.ts +3 -3
  53. package/dist/packages/core/src/commands/splitListItem.d.ts +3 -3
  54. package/dist/packages/core/src/commands/toggleList.d.ts +3 -3
  55. package/dist/packages/core/src/commands/toggleMark.d.ts +8 -3
  56. package/dist/packages/core/src/commands/toggleNode.d.ts +3 -3
  57. package/dist/packages/core/src/commands/toggleWrap.d.ts +3 -3
  58. package/dist/packages/core/src/commands/undoInputRule.d.ts +3 -3
  59. package/dist/packages/core/src/commands/unsetAllMarks.d.ts +3 -3
  60. package/dist/packages/core/src/commands/unsetMark.d.ts +8 -3
  61. package/dist/packages/core/src/commands/updateAttributes.d.ts +13 -0
  62. package/dist/packages/core/src/commands/wrapIn.d.ts +3 -3
  63. package/dist/packages/core/src/commands/wrapInList.d.ts +3 -3
  64. package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +1 -1
  65. package/dist/packages/core/src/extensions/commands.d.ts +21 -15
  66. package/dist/packages/core/src/extensions/editable.d.ts +1 -1
  67. package/dist/packages/core/src/extensions/focusEvents.d.ts +1 -1
  68. package/dist/packages/core/src/extensions/index.d.ts +1 -0
  69. package/dist/packages/core/src/extensions/keymap.d.ts +1 -1
  70. package/dist/packages/core/src/extensions/tabindex.d.ts +2 -0
  71. package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +7 -0
  72. package/dist/packages/core/src/helpers/createChainableState.d.ts +5 -0
  73. package/dist/packages/core/src/helpers/createDocument.d.ts +3 -4
  74. package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +4 -5
  75. package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +2 -0
  76. package/dist/packages/core/src/helpers/findChildren.d.ts +3 -0
  77. package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +6 -0
  78. package/dist/packages/core/src/helpers/findParentNode.d.ts +1 -1
  79. package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +1 -1
  80. package/dist/packages/core/src/helpers/generateHTML.d.ts +2 -2
  81. package/dist/packages/core/src/helpers/generateJSON.d.ts +2 -0
  82. package/dist/packages/core/src/helpers/generateText.d.ts +5 -0
  83. package/dist/packages/core/src/helpers/getAttributes.d.ts +3 -0
  84. package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +1 -1
  85. package/dist/packages/core/src/helpers/getChangedRanges.d.ts +11 -0
  86. package/dist/packages/core/src/helpers/getDebugJSON.d.ts +8 -0
  87. package/dist/packages/core/src/helpers/getExtensionField.d.ts +2 -0
  88. package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +2 -2
  89. package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +1 -2
  90. package/dist/packages/core/src/helpers/getMarkRange.d.ts +1 -1
  91. package/dist/packages/core/src/helpers/getMarkType.d.ts +1 -1
  92. package/dist/packages/core/src/helpers/getMarksBetween.d.ts +2 -2
  93. package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +1 -2
  94. package/dist/packages/core/src/helpers/getNodeType.d.ts +1 -1
  95. package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +2 -2
  96. package/dist/packages/core/src/helpers/getSchema.d.ts +1 -1
  97. package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +3 -0
  98. package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +1 -1
  99. package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +1 -1
  100. package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +2 -2
  101. package/dist/packages/core/src/helpers/getText.d.ts +6 -0
  102. package/dist/packages/core/src/helpers/getTextBetween.d.ts +6 -0
  103. package/dist/packages/core/src/helpers/getTextSeralizersFromSchema.d.ts +3 -0
  104. package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +1 -1
  105. package/dist/packages/core/src/helpers/isActive.d.ts +1 -2
  106. package/dist/packages/core/src/helpers/isExtensionRulesEnabled.d.ts +2 -0
  107. package/dist/packages/core/src/helpers/isList.d.ts +1 -1
  108. package/dist/packages/core/src/helpers/isMarkActive.d.ts +1 -2
  109. package/dist/packages/core/src/helpers/isNodeActive.d.ts +1 -2
  110. package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +1 -1
  111. package/dist/packages/core/src/helpers/isNodeSelection.d.ts +1 -1
  112. package/dist/packages/core/src/helpers/isTextSelection.d.ts +1 -1
  113. package/dist/packages/core/src/helpers/posToDOMRect.d.ts +2 -0
  114. package/dist/packages/core/src/helpers/resolveFocusPosition.d.ts +4 -0
  115. package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +1 -1
  116. package/dist/packages/core/src/helpers/splitExtensions.d.ts +4 -4
  117. package/dist/packages/core/src/index.d.ts +51 -20
  118. package/dist/packages/core/src/inputRules/markInputRule.d.ts +11 -2
  119. package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +11 -2
  120. package/dist/packages/core/src/inputRules/textInputRule.d.ts +9 -0
  121. package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +14 -0
  122. package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +23 -0
  123. package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +11 -2
  124. package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +9 -0
  125. package/dist/packages/core/src/style.d.ts +1 -2
  126. package/dist/packages/core/src/types.d.ts +105 -52
  127. package/dist/packages/core/src/utilities/callOrReturn.d.ts +2 -1
  128. package/dist/packages/core/src/utilities/createStyleTag.d.ts +1 -1
  129. package/dist/packages/core/src/utilities/deleteProps.d.ts +1 -2
  130. package/dist/packages/core/src/utilities/elementFromString.d.ts +1 -1
  131. package/dist/packages/core/src/utilities/escapeForRegEx.d.ts +1 -0
  132. package/dist/packages/core/src/utilities/findDuplicates.d.ts +1 -0
  133. package/dist/packages/core/src/utilities/fromString.d.ts +1 -1
  134. package/dist/packages/core/src/utilities/isClass.d.ts +1 -1
  135. package/dist/packages/core/src/utilities/isEmptyObject.d.ts +1 -1
  136. package/dist/packages/core/src/utilities/isFunction.d.ts +1 -0
  137. package/dist/packages/core/src/utilities/isMacOS.d.ts +1 -0
  138. package/dist/packages/core/src/utilities/isNumber.d.ts +1 -0
  139. package/dist/packages/core/src/utilities/isObject.d.ts +1 -1
  140. package/dist/packages/core/src/utilities/isPlainObject.d.ts +1 -1
  141. package/dist/packages/core/src/utilities/isRegExp.d.ts +1 -0
  142. package/dist/packages/core/src/utilities/isiOS.d.ts +1 -0
  143. package/dist/packages/core/src/utilities/mergeAttributes.d.ts +1 -2
  144. package/dist/packages/core/src/utilities/mergeDeep.d.ts +1 -2
  145. package/dist/packages/core/src/utilities/minMax.d.ts +1 -1
  146. package/dist/packages/core/src/utilities/objectIncludes.d.ts +3 -2
  147. package/dist/packages/core/src/utilities/removeDuplicates.d.ts +8 -0
  148. package/dist/tiptap-core.cjs.js +3576 -2041
  149. package/dist/tiptap-core.cjs.js.map +1 -1
  150. package/dist/tiptap-core.esm.js +3548 -2044
  151. package/dist/tiptap-core.esm.js.map +1 -1
  152. package/dist/tiptap-core.umd.js +3434 -1898
  153. package/dist/tiptap-core.umd.js.map +1 -1
  154. package/package.json +20 -16
  155. package/src/CommandManager.ts +60 -62
  156. package/src/Editor.ts +109 -74
  157. package/src/EventEmitter.ts +14 -4
  158. package/src/Extension.ts +196 -41
  159. package/src/ExtensionManager.ts +242 -78
  160. package/src/InputRule.ts +268 -0
  161. package/src/Mark.ts +242 -47
  162. package/src/Node.ts +279 -52
  163. package/src/NodeView.ts +105 -42
  164. package/src/PasteRule.ts +246 -0
  165. package/src/Tracker.ts +42 -0
  166. package/src/commands/blur.ts +12 -6
  167. package/src/commands/clearContent.ts +3 -3
  168. package/src/commands/clearNodes.ts +29 -18
  169. package/src/commands/command.ts +2 -2
  170. package/src/commands/createParagraphNear.ts +3 -3
  171. package/src/commands/deleteNode.ts +36 -0
  172. package/src/commands/deleteRange.ts +3 -3
  173. package/src/commands/deleteSelection.ts +3 -3
  174. package/src/commands/enter.ts +3 -3
  175. package/src/commands/exitCode.ts +3 -3
  176. package/src/commands/extendMarkRange.ts +10 -10
  177. package/src/commands/first.ts +3 -3
  178. package/src/commands/focus.ts +45 -44
  179. package/src/commands/forEach.ts +24 -0
  180. package/src/commands/insertContent.ts +12 -24
  181. package/src/commands/insertContentAt.ts +107 -0
  182. package/src/commands/joinBackward.ts +3 -3
  183. package/src/commands/joinForward.ts +3 -3
  184. package/src/commands/keyboardShortcut.ts +6 -6
  185. package/src/commands/lift.ts +5 -5
  186. package/src/commands/liftEmptyBlock.ts +3 -3
  187. package/src/commands/liftListItem.ts +4 -4
  188. package/src/commands/newlineInCode.ts +3 -3
  189. package/src/commands/resetAttributes.ts +61 -0
  190. package/src/commands/scrollIntoView.ts +3 -3
  191. package/src/commands/selectAll.ts +8 -6
  192. package/src/commands/selectNodeBackward.ts +3 -3
  193. package/src/commands/selectNodeForward.ts +3 -3
  194. package/src/commands/selectParentNode.ts +3 -3
  195. package/src/commands/selectTextblockEnd.ts +19 -0
  196. package/src/commands/selectTextblockStart.ts +19 -0
  197. package/src/commands/setContent.ts +7 -11
  198. package/src/commands/setMark.ts +35 -12
  199. package/src/commands/setMeta.ts +18 -0
  200. package/src/commands/setNode.ts +27 -6
  201. package/src/commands/setNodeSelection.ts +28 -0
  202. package/src/commands/setTextSelection.ts +32 -0
  203. package/src/commands/sinkListItem.ts +4 -4
  204. package/src/commands/splitBlock.ts +14 -9
  205. package/src/commands/splitListItem.ts +41 -15
  206. package/src/commands/toggleList.ts +82 -18
  207. package/src/commands/toggleMark.ts +17 -7
  208. package/src/commands/toggleNode.ts +5 -5
  209. package/src/commands/toggleWrap.ts +8 -9
  210. package/src/commands/undoInputRule.ts +34 -5
  211. package/src/commands/unsetAllMarks.ts +7 -11
  212. package/src/commands/unsetMark.ts +34 -22
  213. package/src/commands/updateAttributes.ts +72 -0
  214. package/src/commands/wrapIn.ts +4 -10
  215. package/src/commands/wrapInList.ts +4 -4
  216. package/src/extensions/clipboardTextSerializer.ts +13 -35
  217. package/src/extensions/commands.ts +30 -21
  218. package/src/extensions/focusEvents.ts +0 -3
  219. package/src/extensions/index.ts +1 -0
  220. package/src/extensions/keymap.ts +111 -13
  221. package/src/extensions/tabindex.ts +23 -0
  222. package/src/helpers/combineTransactionSteps.ts +18 -0
  223. package/src/helpers/createChainableState.ts +37 -0
  224. package/src/helpers/createDocument.ts +5 -7
  225. package/src/helpers/createNodeFromContent.ts +15 -18
  226. package/src/helpers/defaultBlockAt.ts +13 -0
  227. package/src/helpers/findChildren.ts +17 -0
  228. package/src/helpers/findChildrenInRange.ts +31 -0
  229. package/src/helpers/findParentNode.ts +2 -2
  230. package/src/helpers/findParentNodeClosestToPos.ts +1 -1
  231. package/src/helpers/generateHTML.ts +5 -5
  232. package/src/helpers/generateJSON.ts +13 -0
  233. package/src/helpers/generateText.ts +29 -0
  234. package/src/helpers/getAttributes.ts +27 -0
  235. package/src/helpers/getAttributesFromExtensions.ts +28 -7
  236. package/src/helpers/getChangedRanges.ts +82 -0
  237. package/src/helpers/getDebugJSON.ts +53 -0
  238. package/src/helpers/getExtensionField.ts +25 -0
  239. package/src/helpers/getHTMLFromFragment.ts +6 -5
  240. package/src/helpers/getMarkAttributes.ts +12 -9
  241. package/src/helpers/getMarkRange.ts +34 -6
  242. package/src/helpers/getMarkType.ts +5 -1
  243. package/src/helpers/getMarksBetween.ts +31 -10
  244. package/src/helpers/getNodeAttributes.ts +7 -8
  245. package/src/helpers/getNodeType.ts +5 -1
  246. package/src/helpers/getRenderedAttributes.ts +4 -6
  247. package/src/helpers/getSchema.ts +6 -133
  248. package/src/helpers/getSchemaByResolvedExtensions.ts +147 -0
  249. package/src/helpers/getSchemaTypeByName.ts +2 -10
  250. package/src/helpers/getSchemaTypeNameByName.ts +1 -1
  251. package/src/helpers/getSplittedAttributes.ts +4 -4
  252. package/src/helpers/getText.ts +18 -0
  253. package/src/helpers/getTextBetween.ts +45 -0
  254. package/src/helpers/getTextSeralizersFromSchema.ts +9 -0
  255. package/src/helpers/injectExtensionAttributesToParseRule.ts +14 -17
  256. package/src/helpers/isActive.ts +4 -5
  257. package/src/helpers/isExtensionRulesEnabled.ts +15 -0
  258. package/src/helpers/isList.ts +14 -7
  259. package/src/helpers/isMarkActive.ts +43 -19
  260. package/src/helpers/isNodeActive.ts +26 -34
  261. package/src/helpers/isNodeEmpty.ts +1 -1
  262. package/src/helpers/isNodeSelection.ts +2 -2
  263. package/src/helpers/isTextSelection.ts +2 -2
  264. package/src/helpers/posToDOMRect.ts +34 -0
  265. package/src/helpers/resolveFocusPosition.ts +34 -0
  266. package/src/helpers/selectionToInsertionEnd.ts +1 -1
  267. package/src/helpers/splitExtensions.ts +1 -1
  268. package/src/index.ts +53 -20
  269. package/src/inputRules/markInputRule.ts +58 -39
  270. package/src/inputRules/nodeInputRule.ts +44 -11
  271. package/src/inputRules/textInputRule.ts +35 -0
  272. package/src/inputRules/textblockTypeInputRule.ts +37 -0
  273. package/src/inputRules/wrappingInputRule.ts +59 -0
  274. package/src/pasteRules/markPasteRule.ts +61 -53
  275. package/src/pasteRules/textPasteRule.ts +35 -0
  276. package/src/style.ts +16 -3
  277. package/src/types.ts +119 -37
  278. package/src/utilities/callOrReturn.ts +6 -3
  279. package/src/utilities/createStyleTag.ts +8 -1
  280. package/src/utilities/deleteProps.ts +2 -4
  281. package/src/utilities/elementFromString.ts +4 -5
  282. package/src/utilities/escapeForRegEx.ts +4 -0
  283. package/src/utilities/findDuplicates.ts +5 -0
  284. package/src/utilities/fromString.ts +2 -2
  285. package/src/utilities/isClass.ts +2 -2
  286. package/src/utilities/isEmptyObject.ts +2 -2
  287. package/src/utilities/isFunction.ts +3 -0
  288. package/src/utilities/isMacOS.ts +5 -0
  289. package/src/utilities/isNumber.ts +3 -0
  290. package/src/utilities/isObject.ts +6 -6
  291. package/src/utilities/isPlainObject.ts +8 -5
  292. package/src/utilities/isRegExp.ts +3 -0
  293. package/src/utilities/isString.ts +3 -0
  294. package/src/utilities/isiOS.ts +12 -0
  295. package/src/utilities/mergeAttributes.ts +2 -3
  296. package/src/utilities/mergeDeep.ts +2 -3
  297. package/src/utilities/minMax.ts +1 -1
  298. package/src/utilities/objectIncludes.ts +17 -5
  299. package/src/utilities/removeDuplicates.ts +15 -0
  300. package/CHANGELOG.md +0 -324
  301. package/dist/packages/core/src/commands/insertHTML.d.ts +0 -12
  302. package/dist/packages/core/src/commands/insertNode.d.ts +0 -13
  303. package/dist/packages/core/src/commands/insertText.d.ts +0 -12
  304. package/dist/packages/core/src/commands/replace.d.ts +0 -13
  305. package/dist/packages/core/src/commands/replaceRange.d.ts +0 -13
  306. package/dist/packages/core/src/commands/resetNodeAttributes.d.ts +0 -13
  307. package/dist/packages/core/src/commands/updateNodeAttributes.d.ts +0 -13
  308. package/dist/packages/core/src/utilities/removeElement.d.ts +0 -1
  309. package/dist/tiptap-core.bundle.umd.min.js +0 -17
  310. package/dist/tiptap-core.bundle.umd.min.js.map +0 -1
  311. package/src/commands/insertHTML.ts +0 -30
  312. package/src/commands/insertNode.ts +0 -33
  313. package/src/commands/insertText.ts +0 -22
  314. package/src/commands/replace.ts +0 -20
  315. package/src/commands/replaceRange.ts +0 -36
  316. package/src/commands/resetNodeAttributes.ts +0 -31
  317. package/src/commands/updateNodeAttributes.ts +0 -33
  318. package/src/utilities/removeElement.ts +0 -5
@@ -1,19 +1,24 @@
1
1
  import { keymap } from 'prosemirror-keymap'
2
2
  import { Schema, Node as ProsemirrorNode } from 'prosemirror-model'
3
- import { inputRules as inputRulesPlugin } from 'prosemirror-inputrules'
3
+ import { inputRulesPlugin } from './InputRule'
4
+ import { pasteRulesPlugin } from './PasteRule'
4
5
  import { EditorView, Decoration } from 'prosemirror-view'
5
6
  import { Plugin } from 'prosemirror-state'
6
7
  import { Editor } from './Editor'
7
- import { Extensions, NodeViewRenderer, RawCommands } from './types'
8
- import getSchema from './helpers/getSchema'
9
- import getSchemaTypeByName from './helpers/getSchemaTypeByName'
10
- import getNodeType from './helpers/getNodeType'
11
- import splitExtensions from './helpers/splitExtensions'
12
- import getAttributesFromExtensions from './helpers/getAttributesFromExtensions'
13
- import getRenderedAttributes from './helpers/getRenderedAttributes'
14
- import callOrReturn from './utilities/callOrReturn'
15
-
16
- export default class ExtensionManager {
8
+ import { Extensions, RawCommands, AnyConfig } from './types'
9
+ import { getExtensionField } from './helpers/getExtensionField'
10
+ import { getSchemaByResolvedExtensions } from './helpers/getSchemaByResolvedExtensions'
11
+ import { getSchemaTypeByName } from './helpers/getSchemaTypeByName'
12
+ import { getNodeType } from './helpers/getNodeType'
13
+ import { splitExtensions } from './helpers/splitExtensions'
14
+ import { getAttributesFromExtensions } from './helpers/getAttributesFromExtensions'
15
+ import { getRenderedAttributes } from './helpers/getRenderedAttributes'
16
+ import { isExtensionRulesEnabled } from './helpers/isExtensionRulesEnabled'
17
+ import { callOrReturn } from './utilities/callOrReturn'
18
+ import { findDuplicates } from './utilities/findDuplicates'
19
+ import { NodeConfig } from '.'
20
+
21
+ export class ExtensionManager {
17
22
 
18
23
  editor: Editor
19
24
 
@@ -25,112 +30,269 @@ export default class ExtensionManager {
25
30
 
26
31
  constructor(extensions: Extensions, editor: Editor) {
27
32
  this.editor = editor
28
- this.extensions = extensions
29
- this.schema = getSchema(this.extensions)
33
+ this.extensions = ExtensionManager.resolve(extensions)
34
+ this.schema = getSchemaByResolvedExtensions(this.extensions)
30
35
 
31
36
  this.extensions.forEach(extension => {
37
+ // store extension storage in editor
38
+ this.editor.extensionStorage[extension.name] = extension.storage
39
+
32
40
  const context = {
41
+ name: extension.name,
33
42
  options: extension.options,
43
+ storage: extension.storage,
34
44
  editor: this.editor,
35
- type: getSchemaTypeByName(extension.config.name, this.schema),
45
+ type: getSchemaTypeByName(extension.name, this.schema),
36
46
  }
37
47
 
38
48
  if (extension.type === 'mark') {
39
- const keepOnSplit = callOrReturn(extension.config.keepOnSplit, context) ?? true
49
+ const keepOnSplit = callOrReturn(getExtensionField(extension, 'keepOnSplit', context)) ?? true
40
50
 
41
51
  if (keepOnSplit) {
42
- this.splittableMarks.push(extension.config.name)
52
+ this.splittableMarks.push(extension.name)
43
53
  }
44
54
  }
45
55
 
46
- if (typeof extension.config.onCreate === 'function') {
47
- this.editor.on('create', extension.config.onCreate.bind(context))
56
+ const onBeforeCreate = getExtensionField<AnyConfig['onBeforeCreate']>(
57
+ extension,
58
+ 'onBeforeCreate',
59
+ context,
60
+ )
61
+
62
+ if (onBeforeCreate) {
63
+ this.editor.on('beforeCreate', onBeforeCreate)
48
64
  }
49
65
 
50
- if (typeof extension.config.onUpdate === 'function') {
51
- this.editor.on('update', extension.config.onUpdate.bind(context))
66
+ const onCreate = getExtensionField<AnyConfig['onCreate']>(
67
+ extension,
68
+ 'onCreate',
69
+ context,
70
+ )
71
+
72
+ if (onCreate) {
73
+ this.editor.on('create', onCreate)
52
74
  }
53
75
 
54
- if (typeof extension.config.onSelectionUpdate === 'function') {
55
- this.editor.on('selectionUpdate', extension.config.onSelectionUpdate.bind(context))
76
+ const onUpdate = getExtensionField<AnyConfig['onUpdate']>(
77
+ extension,
78
+ 'onUpdate',
79
+ context,
80
+ )
81
+
82
+ if (onUpdate) {
83
+ this.editor.on('update', onUpdate)
56
84
  }
57
85
 
58
- if (typeof extension.config.onViewUpdate === 'function') {
59
- this.editor.on('viewUpdate', extension.config.onViewUpdate.bind(context))
86
+ const onSelectionUpdate = getExtensionField<AnyConfig['onSelectionUpdate']>(
87
+ extension,
88
+ 'onSelectionUpdate',
89
+ context,
90
+ )
91
+
92
+ if (onSelectionUpdate) {
93
+ this.editor.on('selectionUpdate', onSelectionUpdate)
60
94
  }
61
95
 
62
- if (typeof extension.config.onTransaction === 'function') {
63
- this.editor.on('transaction', extension.config.onTransaction.bind(context))
96
+ const onTransaction = getExtensionField<AnyConfig['onTransaction']>(
97
+ extension,
98
+ 'onTransaction',
99
+ context,
100
+ )
101
+
102
+ if (onTransaction) {
103
+ this.editor.on('transaction', onTransaction)
64
104
  }
65
105
 
66
- if (typeof extension.config.onFocus === 'function') {
67
- this.editor.on('focus', extension.config.onFocus.bind(context))
106
+ const onFocus = getExtensionField<AnyConfig['onFocus']>(
107
+ extension,
108
+ 'onFocus',
109
+ context,
110
+ )
111
+
112
+ if (onFocus) {
113
+ this.editor.on('focus', onFocus)
68
114
  }
69
115
 
70
- if (typeof extension.config.onBlur === 'function') {
71
- this.editor.on('blur', extension.config.onBlur.bind(context))
116
+ const onBlur = getExtensionField<AnyConfig['onBlur']>(
117
+ extension,
118
+ 'onBlur',
119
+ context,
120
+ )
121
+
122
+ if (onBlur) {
123
+ this.editor.on('blur', onBlur)
72
124
  }
73
125
 
74
- if (typeof extension.config.onDestroy === 'function') {
75
- this.editor.on('destroy', extension.config.onDestroy.bind(context))
126
+ const onDestroy = getExtensionField<AnyConfig['onDestroy']>(
127
+ extension,
128
+ 'onDestroy',
129
+ context,
130
+ )
131
+
132
+ if (onDestroy) {
133
+ this.editor.on('destroy', onDestroy)
76
134
  }
77
135
  })
78
136
  }
79
137
 
138
+ static resolve(extensions: Extensions): Extensions {
139
+ const resolvedExtensions = ExtensionManager.sort(ExtensionManager.flatten(extensions))
140
+ const duplicatedNames = findDuplicates(resolvedExtensions.map(extension => extension.name))
141
+
142
+ if (duplicatedNames.length) {
143
+ console.warn(`[tiptap warn]: Duplicate extension names found: [${duplicatedNames.map(item => `'${item}'`).join(', ')}]. This can lead to issues.`)
144
+ }
145
+
146
+ return resolvedExtensions
147
+ }
148
+
149
+ static flatten(extensions: Extensions): Extensions {
150
+ return extensions
151
+ .map(extension => {
152
+ const context = {
153
+ name: extension.name,
154
+ options: extension.options,
155
+ storage: extension.storage,
156
+ }
157
+
158
+ const addExtensions = getExtensionField<AnyConfig['addExtensions']>(
159
+ extension,
160
+ 'addExtensions',
161
+ context,
162
+ )
163
+
164
+ if (addExtensions) {
165
+ return [
166
+ extension,
167
+ ...this.flatten(addExtensions()),
168
+ ]
169
+ }
170
+
171
+ return extension
172
+ })
173
+ // `Infinity` will break TypeScript so we set a number that is probably high enough
174
+ .flat(10)
175
+ }
176
+
177
+ static sort(extensions: Extensions): Extensions {
178
+ const defaultPriority = 100
179
+
180
+ return extensions.sort((a, b) => {
181
+ const priorityA = getExtensionField<AnyConfig['priority']>(a, 'priority') || defaultPriority
182
+ const priorityB = getExtensionField<AnyConfig['priority']>(b, 'priority') || defaultPriority
183
+
184
+ if (priorityA > priorityB) {
185
+ return -1
186
+ }
187
+
188
+ if (priorityA < priorityB) {
189
+ return 1
190
+ }
191
+
192
+ return 0
193
+ })
194
+ }
195
+
80
196
  get commands(): RawCommands {
81
197
  return this.extensions.reduce((commands, extension) => {
82
198
  const context = {
199
+ name: extension.name,
83
200
  options: extension.options,
201
+ storage: extension.storage,
84
202
  editor: this.editor,
85
- type: getSchemaTypeByName(extension.config.name, this.schema),
203
+ type: getSchemaTypeByName(extension.name, this.schema),
86
204
  }
87
205
 
88
- if (!extension.config.addCommands) {
206
+ const addCommands = getExtensionField<AnyConfig['addCommands']>(
207
+ extension,
208
+ 'addCommands',
209
+ context,
210
+ )
211
+
212
+ if (!addCommands) {
89
213
  return commands
90
214
  }
91
215
 
92
216
  return {
93
217
  ...commands,
94
- ...extension.config.addCommands.bind(context)(),
218
+ ...addCommands(),
95
219
  }
96
220
  }, {} as RawCommands)
97
221
  }
98
222
 
99
223
  get plugins(): Plugin[] {
100
- return [...this.extensions]
101
- .reverse()
224
+ const { editor } = this
225
+
226
+ // With ProseMirror, first plugins within an array are executed first.
227
+ // In tiptap, we provide the ability to override plugins,
228
+ // so it feels more natural to run plugins at the end of an array first.
229
+ // That’s why we have to reverse the `extensions` array and sort again
230
+ // based on the `priority` option.
231
+ const extensions = ExtensionManager.sort([...this.extensions].reverse())
232
+
233
+ const inputRules: any[] = []
234
+ const pasteRules: any[] = []
235
+
236
+ const allPlugins = extensions
102
237
  .map(extension => {
103
238
  const context = {
239
+ name: extension.name,
104
240
  options: extension.options,
105
- editor: this.editor,
106
- type: getSchemaTypeByName(extension.config.name, this.schema),
241
+ storage: extension.storage,
242
+ editor,
243
+ type: getSchemaTypeByName(extension.name, this.schema),
107
244
  }
108
245
 
109
246
  const plugins: Plugin[] = []
110
247
 
111
- if (extension.config.addKeyboardShortcuts) {
112
- const keyMapPlugin = keymap(extension.config.addKeyboardShortcuts.bind(context)())
248
+ const addKeyboardShortcuts = getExtensionField<AnyConfig['addKeyboardShortcuts']>(
249
+ extension,
250
+ 'addKeyboardShortcuts',
251
+ context,
252
+ )
253
+
254
+ if (addKeyboardShortcuts) {
255
+ const bindings = Object.fromEntries(
256
+ Object
257
+ .entries(addKeyboardShortcuts())
258
+ .map(([shortcut, method]) => {
259
+ return [shortcut, () => method({ editor })]
260
+ }),
261
+ )
262
+
263
+ const keyMapPlugin = keymap(bindings)
113
264
 
114
265
  plugins.push(keyMapPlugin)
115
266
  }
116
267
 
117
- if (this.editor.options.enableInputRules && extension.config.addInputRules) {
118
- const inputRules = extension.config.addInputRules.bind(context)()
119
- const inputRulePlugins = inputRules.length
120
- ? [inputRulesPlugin({ rules: inputRules })]
121
- : []
268
+ const addInputRules = getExtensionField<AnyConfig['addInputRules']>(
269
+ extension,
270
+ 'addInputRules',
271
+ context,
272
+ )
122
273
 
123
- plugins.push(...inputRulePlugins)
274
+ if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
275
+ inputRules.push(...addInputRules())
124
276
  }
125
277
 
126
- if (this.editor.options.enablePasteRules && extension.config.addPasteRules) {
127
- const pasteRulePlugins = extension.config.addPasteRules.bind(context)()
278
+ const addPasteRules = getExtensionField<AnyConfig['addPasteRules']>(
279
+ extension,
280
+ 'addPasteRules',
281
+ context,
282
+ )
128
283
 
129
- plugins.push(...pasteRulePlugins)
284
+ if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
285
+ pasteRules.push(...addPasteRules())
130
286
  }
131
287
 
132
- if (extension.config.addProseMirrorPlugins) {
133
- const proseMirrorPlugins = extension.config.addProseMirrorPlugins.bind(context)()
288
+ const addProseMirrorPlugins = getExtensionField<AnyConfig['addProseMirrorPlugins']>(
289
+ extension,
290
+ 'addProseMirrorPlugins',
291
+ context,
292
+ )
293
+
294
+ if (addProseMirrorPlugins) {
295
+ const proseMirrorPlugins = addProseMirrorPlugins()
134
296
 
135
297
  plugins.push(...proseMirrorPlugins)
136
298
  }
@@ -138,6 +300,18 @@ export default class ExtensionManager {
138
300
  return plugins
139
301
  })
140
302
  .flat()
303
+
304
+ return [
305
+ inputRulesPlugin({
306
+ editor,
307
+ rules: inputRules,
308
+ }),
309
+ ...pasteRulesPlugin({
310
+ editor,
311
+ rules: pasteRules,
312
+ }),
313
+ ...allPlugins,
314
+ ]
141
315
  }
142
316
 
143
317
  get attributes() {
@@ -149,15 +323,25 @@ export default class ExtensionManager {
149
323
  const { nodeExtensions } = splitExtensions(this.extensions)
150
324
 
151
325
  return Object.fromEntries(nodeExtensions
152
- .filter(extension => !!extension.config.addNodeView)
326
+ .filter(extension => !!getExtensionField(extension, 'addNodeView'))
153
327
  .map(extension => {
154
- const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.config.name)
328
+ const extensionAttributes = this.attributes.filter(attribute => attribute.type === extension.name)
155
329
  const context = {
330
+ name: extension.name,
156
331
  options: extension.options,
332
+ storage: extension.storage,
157
333
  editor,
158
- type: getNodeType(extension.config.name, this.schema),
334
+ type: getNodeType(extension.name, this.schema),
335
+ }
336
+ const addNodeView = getExtensionField<NodeConfig['addNodeView']>(
337
+ extension,
338
+ 'addNodeView',
339
+ context,
340
+ )
341
+
342
+ if (!addNodeView) {
343
+ return []
159
344
  }
160
- const renderer = extension.config.addNodeView?.call(context) as NodeViewRenderer
161
345
 
162
346
  const nodeview = (
163
347
  node: ProsemirrorNode,
@@ -167,7 +351,7 @@ export default class ExtensionManager {
167
351
  ) => {
168
352
  const HTMLAttributes = getRenderedAttributes(node, extensionAttributes)
169
353
 
170
- return renderer({
354
+ return addNodeView()({
171
355
  editor,
172
356
  node,
173
357
  getPos,
@@ -177,27 +361,7 @@ export default class ExtensionManager {
177
361
  })
178
362
  }
179
363
 
180
- return [extension.config.name, nodeview]
364
+ return [extension.name, nodeview]
181
365
  }))
182
366
  }
183
-
184
- get textSerializers() {
185
- const { editor } = this
186
- const { nodeExtensions } = splitExtensions(this.extensions)
187
-
188
- return Object.fromEntries(nodeExtensions
189
- .filter(extension => !!extension.config.renderText)
190
- .map(extension => {
191
- const context = {
192
- options: extension.options,
193
- editor,
194
- type: getNodeType(extension.config.name, this.schema),
195
- }
196
-
197
- const textSerializer = (props: { node: ProsemirrorNode }) => extension.config.renderText?.call(context, props)
198
-
199
- return [extension.config.name, textSerializer]
200
- }))
201
- }
202
-
203
367
  }
@@ -0,0 +1,268 @@
1
+ import { EditorState, Plugin, TextSelection } from 'prosemirror-state'
2
+ import { Editor } from './Editor'
3
+ import { CommandManager } from './CommandManager'
4
+ import { createChainableState } from './helpers/createChainableState'
5
+ import { isRegExp } from './utilities/isRegExp'
6
+ import {
7
+ Range,
8
+ ExtendedRegExpMatchArray,
9
+ SingleCommands,
10
+ ChainedCommands,
11
+ CanCommands,
12
+ } from './types'
13
+
14
+ export type InputRuleMatch = {
15
+ index: number,
16
+ text: string,
17
+ replaceWith?: string,
18
+ match?: RegExpMatchArray,
19
+ data?: Record<string, any>,
20
+ }
21
+
22
+ export type InputRuleFinder =
23
+ | RegExp
24
+ | ((text: string) => InputRuleMatch | null)
25
+
26
+ export class InputRule {
27
+ find: InputRuleFinder
28
+
29
+ handler: (props: {
30
+ state: EditorState,
31
+ range: Range,
32
+ match: ExtendedRegExpMatchArray,
33
+ commands: SingleCommands,
34
+ chain: () => ChainedCommands,
35
+ can: () => CanCommands,
36
+ }) => void | null
37
+
38
+ constructor(config: {
39
+ find: InputRuleFinder,
40
+ handler: (props: {
41
+ state: EditorState,
42
+ range: Range,
43
+ match: ExtendedRegExpMatchArray,
44
+ commands: SingleCommands,
45
+ chain: () => ChainedCommands,
46
+ can: () => CanCommands,
47
+ }) => void | null,
48
+ }) {
49
+ this.find = config.find
50
+ this.handler = config.handler
51
+ }
52
+ }
53
+
54
+ const inputRuleMatcherHandler = (text: string, find: InputRuleFinder): ExtendedRegExpMatchArray | null => {
55
+ if (isRegExp(find)) {
56
+ return find.exec(text)
57
+ }
58
+
59
+ const inputRuleMatch = find(text)
60
+
61
+ if (!inputRuleMatch) {
62
+ return null
63
+ }
64
+
65
+ const result: ExtendedRegExpMatchArray = []
66
+
67
+ result.push(inputRuleMatch.text)
68
+ result.index = inputRuleMatch.index
69
+ result.input = text
70
+ result.data = inputRuleMatch.data
71
+
72
+ if (inputRuleMatch.replaceWith) {
73
+ if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
74
+ console.warn('[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".')
75
+ }
76
+
77
+ result.push(inputRuleMatch.replaceWith)
78
+ }
79
+
80
+ return result
81
+ }
82
+
83
+ function run(config: {
84
+ editor: Editor,
85
+ from: number,
86
+ to: number,
87
+ text: string,
88
+ rules: InputRule[],
89
+ plugin: Plugin,
90
+ }): boolean {
91
+ const {
92
+ editor,
93
+ from,
94
+ to,
95
+ text,
96
+ rules,
97
+ plugin,
98
+ } = config
99
+ const { view } = editor
100
+
101
+ if (view.composing) {
102
+ return false
103
+ }
104
+
105
+ const $from = view.state.doc.resolve(from)
106
+
107
+ if (
108
+ // check for code node
109
+ $from.parent.type.spec.code
110
+ // check for code mark
111
+ || !!($from.nodeBefore || $from.nodeAfter)?.marks.find(mark => mark.type.spec.code)
112
+ ) {
113
+ return false
114
+ }
115
+
116
+ let matched = false
117
+ const maxMatch = 500
118
+ const textBefore = $from.parent.textBetween(
119
+ Math.max(0, $from.parentOffset - maxMatch),
120
+ $from.parentOffset,
121
+ undefined,
122
+ ' ',
123
+ ) + text
124
+
125
+ rules.forEach(rule => {
126
+ if (matched) {
127
+ return
128
+ }
129
+
130
+ const match = inputRuleMatcherHandler(textBefore, rule.find)
131
+
132
+ if (!match) {
133
+ return
134
+ }
135
+
136
+ const tr = view.state.tr
137
+ const state = createChainableState({
138
+ state: view.state,
139
+ transaction: tr,
140
+ })
141
+ const range = {
142
+ from: from - (match[0].length - text.length),
143
+ to,
144
+ }
145
+
146
+ const { commands, chain, can } = new CommandManager({
147
+ editor,
148
+ state,
149
+ })
150
+
151
+ const handler = rule.handler({
152
+ state,
153
+ range,
154
+ match,
155
+ commands,
156
+ chain,
157
+ can,
158
+ })
159
+
160
+ // stop if there are no changes
161
+ if (handler === null || !tr.steps.length) {
162
+ return
163
+ }
164
+
165
+ // store transform as meta data
166
+ // so we can undo input rules within the `undoInputRules` command
167
+ tr.setMeta(plugin, {
168
+ transform: tr,
169
+ from,
170
+ to,
171
+ text,
172
+ })
173
+
174
+ view.dispatch(tr)
175
+ matched = true
176
+ })
177
+
178
+ return matched
179
+ }
180
+
181
+ /**
182
+ * Create an input rules plugin. When enabled, it will cause text
183
+ * input that matches any of the given rules to trigger the rule’s
184
+ * action.
185
+ */
186
+ export function inputRulesPlugin(props: { editor: Editor, rules: InputRule[] }): Plugin {
187
+ const { editor, rules } = props
188
+ const plugin = new Plugin({
189
+ state: {
190
+ init() {
191
+ return null
192
+ },
193
+ apply(tr, prev) {
194
+ const stored = tr.getMeta(this)
195
+
196
+ if (stored) {
197
+ return stored
198
+ }
199
+
200
+ return tr.selectionSet || tr.docChanged
201
+ ? null
202
+ : prev
203
+ },
204
+ },
205
+
206
+ props: {
207
+ handleTextInput(view, from, to, text) {
208
+ return run({
209
+ editor,
210
+ from,
211
+ to,
212
+ text,
213
+ rules,
214
+ plugin,
215
+ })
216
+ },
217
+
218
+ handleDOMEvents: {
219
+ compositionend: view => {
220
+ setTimeout(() => {
221
+ const { $cursor } = view.state.selection as TextSelection
222
+
223
+ if ($cursor) {
224
+ run({
225
+ editor,
226
+ from: $cursor.pos,
227
+ to: $cursor.pos,
228
+ text: '',
229
+ rules,
230
+ plugin,
231
+ })
232
+ }
233
+ })
234
+
235
+ return false
236
+ },
237
+ },
238
+
239
+ // add support for input rules to trigger on enter
240
+ // this is useful for example for code blocks
241
+ handleKeyDown(view, event) {
242
+ if (event.key !== 'Enter') {
243
+ return false
244
+ }
245
+
246
+ const { $cursor } = view.state.selection as TextSelection
247
+
248
+ if ($cursor) {
249
+ return run({
250
+ editor,
251
+ from: $cursor.pos,
252
+ to: $cursor.pos,
253
+ text: '\n',
254
+ rules,
255
+ plugin,
256
+ })
257
+ }
258
+
259
+ return false
260
+ },
261
+ },
262
+
263
+ // @ts-ignore
264
+ isInputRules: true,
265
+ }) as Plugin
266
+
267
+ return plugin
268
+ }