@tiptap/core 2.3.1 → 2.4.0

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 (185) hide show
  1. package/dist/index.cjs +290 -79
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +290 -79
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.umd.js +290 -79
  6. package/dist/index.umd.js.map +1 -1
  7. package/dist/packages/core/src/Extension.d.ts +129 -14
  8. package/dist/packages/core/src/ExtensionManager.d.ts +37 -0
  9. package/dist/packages/core/src/Mark.d.ts +129 -14
  10. package/dist/packages/core/src/Node.d.ts +226 -30
  11. package/dist/packages/core/src/NodeView.d.ts +4 -0
  12. package/dist/packages/core/src/PasteRule.d.ts +4 -0
  13. package/dist/packages/core/src/commands/blur.d.ts +1 -0
  14. package/dist/packages/core/src/commands/clearContent.d.ts +2 -0
  15. package/dist/packages/core/src/commands/clearNodes.d.ts +1 -0
  16. package/dist/packages/core/src/commands/command.d.ts +6 -0
  17. package/dist/packages/core/src/commands/createParagraphNear.d.ts +1 -0
  18. package/dist/packages/core/src/commands/cut.d.ts +5 -0
  19. package/dist/packages/core/src/commands/deleteCurrentNode.d.ts +1 -0
  20. package/dist/packages/core/src/commands/deleteNode.d.ts +3 -1
  21. package/dist/packages/core/src/commands/deleteRange.d.ts +2 -0
  22. package/dist/packages/core/src/commands/deleteSelection.d.ts +1 -0
  23. package/dist/packages/core/src/commands/enter.d.ts +1 -0
  24. package/dist/packages/core/src/commands/exitCode.d.ts +1 -0
  25. package/dist/packages/core/src/commands/extendMarkRange.d.ts +14 -2
  26. package/dist/packages/core/src/commands/first.d.ts +2 -0
  27. package/dist/packages/core/src/commands/focus.d.ts +14 -1
  28. package/dist/packages/core/src/commands/insertContent.d.ts +17 -1
  29. package/dist/packages/core/src/commands/insertContentAt.d.ts +20 -1
  30. package/dist/packages/core/src/commands/join.d.ts +12 -4
  31. package/dist/packages/core/src/commands/joinItemBackward.d.ts +2 -1
  32. package/dist/packages/core/src/commands/joinItemForward.d.ts +2 -1
  33. package/dist/packages/core/src/commands/keyboardShortcut.d.ts +2 -0
  34. package/dist/packages/core/src/commands/lift.d.ts +5 -1
  35. package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +2 -1
  36. package/dist/packages/core/src/commands/liftListItem.d.ts +3 -1
  37. package/dist/packages/core/src/commands/newlineInCode.d.ts +1 -0
  38. package/dist/packages/core/src/commands/resetAttributes.d.ts +3 -0
  39. package/dist/packages/core/src/commands/scrollIntoView.d.ts +1 -0
  40. package/dist/packages/core/src/commands/selectAll.d.ts +1 -0
  41. package/dist/packages/core/src/commands/selectNodeBackward.d.ts +1 -0
  42. package/dist/packages/core/src/commands/selectNodeForward.d.ts +1 -0
  43. package/dist/packages/core/src/commands/selectParentNode.d.ts +1 -0
  44. package/dist/packages/core/src/commands/selectTextblockEnd.d.ts +1 -0
  45. package/dist/packages/core/src/commands/selectTextblockStart.d.ts +1 -0
  46. package/dist/packages/core/src/commands/setContent.d.ts +19 -1
  47. package/dist/packages/core/src/commands/setMark.d.ts +2 -0
  48. package/dist/packages/core/src/commands/setMeta.d.ts +3 -0
  49. package/dist/packages/core/src/commands/setNode.d.ts +3 -0
  50. package/dist/packages/core/src/commands/setNodeSelection.d.ts +2 -0
  51. package/dist/packages/core/src/commands/setTextSelection.d.ts +2 -0
  52. package/dist/packages/core/src/commands/sinkListItem.d.ts +2 -0
  53. package/dist/packages/core/src/commands/splitBlock.d.ts +3 -0
  54. package/dist/packages/core/src/commands/splitListItem.d.ts +2 -0
  55. package/dist/packages/core/src/commands/toggleList.d.ts +5 -0
  56. package/dist/packages/core/src/commands/toggleMark.d.ts +13 -1
  57. package/dist/packages/core/src/commands/toggleNode.d.ts +4 -0
  58. package/dist/packages/core/src/commands/toggleWrap.d.ts +3 -0
  59. package/dist/packages/core/src/commands/undoInputRule.d.ts +1 -0
  60. package/dist/packages/core/src/commands/unsetAllMarks.d.ts +1 -0
  61. package/dist/packages/core/src/commands/unsetMark.d.ts +8 -1
  62. package/dist/packages/core/src/commands/updateAttributes.d.ts +12 -1
  63. package/dist/packages/core/src/commands/wrapIn.d.ts +3 -0
  64. package/dist/packages/core/src/commands/wrapInList.d.ts +3 -0
  65. package/dist/packages/core/src/helpers/combineTransactionSteps.d.ts +3 -0
  66. package/dist/packages/core/src/helpers/createChainableState.d.ts +5 -0
  67. package/dist/packages/core/src/helpers/createDocument.d.ts +7 -0
  68. package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +7 -0
  69. package/dist/packages/core/src/helpers/defaultBlockAt.d.ts +5 -0
  70. package/dist/packages/core/src/helpers/findChildren.d.ts +6 -0
  71. package/dist/packages/core/src/helpers/findChildrenInRange.d.ts +4 -0
  72. package/dist/packages/core/src/helpers/findParentNode.d.ts +8 -0
  73. package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +9 -0
  74. package/dist/packages/core/src/helpers/generateHTML.d.ts +6 -0
  75. package/dist/packages/core/src/helpers/generateJSON.d.ts +6 -0
  76. package/dist/packages/core/src/helpers/generateText.d.ts +7 -0
  77. package/dist/packages/core/src/helpers/getAttributes.d.ts +6 -0
  78. package/dist/packages/core/src/helpers/getExtensionField.d.ts +7 -0
  79. package/dist/packages/core/src/helpers/getSchemaByResolvedExtensions.d.ts +6 -0
  80. package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +6 -0
  81. package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +6 -0
  82. package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +7 -0
  83. package/dist/packages/core/src/helpers/getText.d.ts +9 -0
  84. package/dist/packages/core/src/helpers/getTextBetween.d.ts +8 -0
  85. package/dist/packages/core/src/helpers/getTextContentFromNodes.d.ts +6 -0
  86. package/dist/packages/core/src/helpers/getTextSerializersFromSchema.d.ts +5 -0
  87. package/dist/packages/core/src/inputRules/markInputRule.d.ts +1 -0
  88. package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +1 -0
  89. package/dist/packages/core/src/inputRules/textInputRule.d.ts +1 -0
  90. package/dist/packages/core/src/inputRules/textblockTypeInputRule.d.ts +1 -0
  91. package/dist/packages/core/src/inputRules/wrappingInputRule.d.ts +1 -0
  92. package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +1 -0
  93. package/dist/packages/core/src/pasteRules/nodePasteRule.d.ts +1 -0
  94. package/dist/packages/core/src/pasteRules/textPasteRule.d.ts +1 -0
  95. package/package.json +2 -2
  96. package/src/Extension.ts +130 -14
  97. package/src/ExtensionManager.ts +117 -85
  98. package/src/Mark.ts +129 -14
  99. package/src/Node.ts +226 -30
  100. package/src/NodePos.ts +19 -18
  101. package/src/NodeView.ts +4 -0
  102. package/src/PasteRule.ts +4 -0
  103. package/src/commands/blur.ts +1 -0
  104. package/src/commands/clearContent.ts +2 -0
  105. package/src/commands/clearNodes.ts +1 -0
  106. package/src/commands/command.ts +6 -0
  107. package/src/commands/createParagraphNear.ts +1 -0
  108. package/src/commands/cut.ts +5 -0
  109. package/src/commands/deleteCurrentNode.ts +1 -0
  110. package/src/commands/deleteNode.ts +3 -1
  111. package/src/commands/deleteRange.ts +2 -0
  112. package/src/commands/deleteSelection.ts +1 -0
  113. package/src/commands/enter.ts +1 -0
  114. package/src/commands/exitCode.ts +1 -0
  115. package/src/commands/extendMarkRange.ts +12 -1
  116. package/src/commands/first.ts +2 -0
  117. package/src/commands/focus.ts +12 -0
  118. package/src/commands/insertContent.ts +16 -0
  119. package/src/commands/insertContentAt.ts +19 -0
  120. package/src/commands/join.ts +12 -4
  121. package/src/commands/joinItemBackward.ts +2 -1
  122. package/src/commands/joinItemForward.ts +2 -1
  123. package/src/commands/keyboardShortcut.ts +2 -0
  124. package/src/commands/lift.ts +5 -1
  125. package/src/commands/liftEmptyBlock.ts +2 -1
  126. package/src/commands/liftListItem.ts +3 -1
  127. package/src/commands/newlineInCode.ts +1 -0
  128. package/src/commands/resetAttributes.ts +3 -0
  129. package/src/commands/scrollIntoView.ts +1 -0
  130. package/src/commands/selectAll.ts +1 -0
  131. package/src/commands/selectNodeBackward.ts +1 -0
  132. package/src/commands/selectNodeForward.ts +1 -0
  133. package/src/commands/selectParentNode.ts +1 -0
  134. package/src/commands/selectTextblockEnd.ts +1 -0
  135. package/src/commands/selectTextblockStart.ts +1 -0
  136. package/src/commands/setContent.ts +17 -0
  137. package/src/commands/setMark.ts +2 -0
  138. package/src/commands/setMeta.ts +3 -0
  139. package/src/commands/setNode.ts +3 -0
  140. package/src/commands/setNodeSelection.ts +2 -0
  141. package/src/commands/setTextSelection.ts +2 -0
  142. package/src/commands/sinkListItem.ts +2 -0
  143. package/src/commands/splitBlock.ts +3 -0
  144. package/src/commands/splitListItem.ts +2 -0
  145. package/src/commands/toggleList.ts +5 -0
  146. package/src/commands/toggleMark.ts +12 -0
  147. package/src/commands/toggleNode.ts +4 -0
  148. package/src/commands/toggleWrap.ts +3 -0
  149. package/src/commands/undoInputRule.ts +1 -0
  150. package/src/commands/unsetAllMarks.ts +1 -0
  151. package/src/commands/unsetMark.ts +7 -0
  152. package/src/commands/updateAttributes.ts +10 -0
  153. package/src/commands/wrapIn.ts +3 -0
  154. package/src/commands/wrapInList.ts +3 -0
  155. package/src/extensions/keymap.ts +7 -1
  156. package/src/helpers/combineTransactionSteps.ts +3 -0
  157. package/src/helpers/createChainableState.ts +5 -0
  158. package/src/helpers/createDocument.ts +7 -0
  159. package/src/helpers/createNodeFromContent.ts +16 -3
  160. package/src/helpers/defaultBlockAt.ts +5 -0
  161. package/src/helpers/findChildren.ts +6 -0
  162. package/src/helpers/findChildrenInRange.ts +4 -0
  163. package/src/helpers/findParentNode.ts +8 -0
  164. package/src/helpers/findParentNodeClosestToPos.ts +9 -0
  165. package/src/helpers/generateHTML.ts +6 -0
  166. package/src/helpers/generateJSON.ts +6 -0
  167. package/src/helpers/generateText.ts +7 -0
  168. package/src/helpers/getAttributes.ts +6 -0
  169. package/src/helpers/getExtensionField.ts +7 -0
  170. package/src/helpers/getSchemaByResolvedExtensions.ts +6 -0
  171. package/src/helpers/getSchemaTypeByName.ts +6 -0
  172. package/src/helpers/getSchemaTypeNameByName.ts +6 -0
  173. package/src/helpers/getSplittedAttributes.ts +7 -0
  174. package/src/helpers/getText.ts +9 -0
  175. package/src/helpers/getTextBetween.ts +12 -10
  176. package/src/helpers/getTextContentFromNodes.ts +6 -0
  177. package/src/helpers/getTextSerializersFromSchema.ts +5 -0
  178. package/src/inputRules/markInputRule.ts +1 -0
  179. package/src/inputRules/nodeInputRule.ts +1 -0
  180. package/src/inputRules/textInputRule.ts +1 -0
  181. package/src/inputRules/textblockTypeInputRule.ts +1 -0
  182. package/src/inputRules/wrappingInputRule.ts +1 -0
  183. package/src/pasteRules/markPasteRule.ts +1 -0
  184. package/src/pasteRules/nodePasteRule.ts +1 -0
  185. package/src/pasteRules/textPasteRule.ts +1 -0
package/dist/index.umd.js CHANGED
@@ -4,6 +4,11 @@
4
4
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@tiptap/core"] = {}, global.state, global.view, global.keymap, global.model, global.transform, global.commands$1, global.schemaList));
5
5
  })(this, (function (exports, state, view, keymap, model, transform, commands$1, schemaList) { 'use strict';
6
6
 
7
+ /**
8
+ * Takes a Transaction & Editor State and turns it into a chainable state object
9
+ * @param config The transaction and state to create the chainable state from
10
+ * @returns A chainable Editor state object
11
+ */
7
12
  function createChainableState(config) {
8
13
  const { state, transaction } = config;
9
14
  let { selection } = transaction;
@@ -170,6 +175,13 @@
170
175
  }
171
176
  }
172
177
 
178
+ /**
179
+ * Returns a field from an extension
180
+ * @param extension The Tiptap extension
181
+ * @param field The field, for example `renderHTML` or `priority`
182
+ * @param context The context object that should be passed as `this` into the function
183
+ * @returns The field value
184
+ */
173
185
  function getExtensionField(extension, field, context) {
174
186
  if (extension.config[field] === undefined && extension.parent) {
175
187
  return getExtensionField(extension.parent, field, context);
@@ -414,6 +426,12 @@
414
426
  return value !== null && value !== undefined;
415
427
  }));
416
428
  }
429
+ /**
430
+ * Creates a new Prosemirror schema based on the given extensions.
431
+ * @param extensions An array of Tiptap extensions
432
+ * @param editor The editor instance
433
+ * @returns A Prosemirror schema
434
+ */
417
435
  function getSchemaByResolvedExtensions(extensions, editor) {
418
436
  var _a;
419
437
  const allAttributes = getAttributesFromExtensions(extensions);
@@ -515,6 +533,12 @@
515
533
  });
516
534
  }
517
535
 
536
+ /**
537
+ * Tries to get a node or mark type by its name.
538
+ * @param name The name of the node or mark type
539
+ * @param schema The Prosemiror schema to search in
540
+ * @returns The node or mark type, or null if it doesn't exist
541
+ */
518
542
  function getSchemaTypeByName(name, schema) {
519
543
  return schema.nodes[name] || schema.marks[name] || null;
520
544
  }
@@ -531,6 +555,12 @@
531
555
  return enabled;
532
556
  }
533
557
 
558
+ /**
559
+ * Returns the text content of a resolved prosemirror position
560
+ * @param $from The resolved position to get the text content from
561
+ * @param maxMatch The maximum number of characters to match
562
+ * @returns The text content
563
+ */
534
564
  const getTextContentFromNodes = ($from, maxMatch = 500) => {
535
565
  let textBefore = '';
536
566
  const sliceEndPos = $from.parentOffset;
@@ -738,6 +768,10 @@
738
768
  return typeof value === 'number';
739
769
  }
740
770
 
771
+ /**
772
+ * Paste rules are used to react to pasted content.
773
+ * @see https://tiptap.dev/guide/custom-extensions/#paste-rules
774
+ */
741
775
  class PasteRule {
742
776
  constructor(config) {
743
777
  this.find = config.find;
@@ -936,57 +970,14 @@
936
970
  this.editor = editor;
937
971
  this.extensions = ExtensionManager.resolve(extensions);
938
972
  this.schema = getSchemaByResolvedExtensions(this.extensions, editor);
939
- this.extensions.forEach(extension => {
940
- var _a;
941
- // store extension storage in editor
942
- this.editor.extensionStorage[extension.name] = extension.storage;
943
- const context = {
944
- name: extension.name,
945
- options: extension.options,
946
- storage: extension.storage,
947
- editor: this.editor,
948
- type: getSchemaTypeByName(extension.name, this.schema),
949
- };
950
- if (extension.type === 'mark') {
951
- const keepOnSplit = (_a = callOrReturn(getExtensionField(extension, 'keepOnSplit', context))) !== null && _a !== void 0 ? _a : true;
952
- if (keepOnSplit) {
953
- this.splittableMarks.push(extension.name);
954
- }
955
- }
956
- const onBeforeCreate = getExtensionField(extension, 'onBeforeCreate', context);
957
- if (onBeforeCreate) {
958
- this.editor.on('beforeCreate', onBeforeCreate);
959
- }
960
- const onCreate = getExtensionField(extension, 'onCreate', context);
961
- if (onCreate) {
962
- this.editor.on('create', onCreate);
963
- }
964
- const onUpdate = getExtensionField(extension, 'onUpdate', context);
965
- if (onUpdate) {
966
- this.editor.on('update', onUpdate);
967
- }
968
- const onSelectionUpdate = getExtensionField(extension, 'onSelectionUpdate', context);
969
- if (onSelectionUpdate) {
970
- this.editor.on('selectionUpdate', onSelectionUpdate);
971
- }
972
- const onTransaction = getExtensionField(extension, 'onTransaction', context);
973
- if (onTransaction) {
974
- this.editor.on('transaction', onTransaction);
975
- }
976
- const onFocus = getExtensionField(extension, 'onFocus', context);
977
- if (onFocus) {
978
- this.editor.on('focus', onFocus);
979
- }
980
- const onBlur = getExtensionField(extension, 'onBlur', context);
981
- if (onBlur) {
982
- this.editor.on('blur', onBlur);
983
- }
984
- const onDestroy = getExtensionField(extension, 'onDestroy', context);
985
- if (onDestroy) {
986
- this.editor.on('destroy', onDestroy);
987
- }
988
- });
973
+ this.setupExtensions();
989
974
  }
975
+ /**
976
+ * Returns a flattened and sorted extension list while
977
+ * also checking for duplicated extensions and warns the user.
978
+ * @param extensions An array of Tiptap extensions
979
+ * @returns An flattened and sorted array of Tiptap extensions
980
+ */
990
981
  static resolve(extensions) {
991
982
  const resolvedExtensions = ExtensionManager.sort(ExtensionManager.flatten(extensions));
992
983
  const duplicatedNames = findDuplicates(resolvedExtensions.map(extension => extension.name));
@@ -997,6 +988,11 @@
997
988
  }
998
989
  return resolvedExtensions;
999
990
  }
991
+ /**
992
+ * Create a flattened array of extensions by traversing the `addExtensions` field.
993
+ * @param extensions An array of Tiptap extensions
994
+ * @returns A flattened array of Tiptap extensions
995
+ */
1000
996
  static flatten(extensions) {
1001
997
  return (extensions
1002
998
  .map(extension => {
@@ -1014,6 +1010,11 @@
1014
1010
  // `Infinity` will break TypeScript so we set a number that is probably high enough
1015
1011
  .flat(10));
1016
1012
  }
1013
+ /**
1014
+ * Sort extensions by priority.
1015
+ * @param extensions An array of Tiptap extensions
1016
+ * @returns A sorted array of Tiptap extensions by priority
1017
+ */
1017
1018
  static sort(extensions) {
1018
1019
  const defaultPriority = 100;
1019
1020
  return extensions.sort((a, b) => {
@@ -1028,6 +1029,10 @@
1028
1029
  return 0;
1029
1030
  });
1030
1031
  }
1032
+ /**
1033
+ * Get all commands from the extensions.
1034
+ * @returns An object with all commands where the key is the command name and the value is the command function
1035
+ */
1031
1036
  get commands() {
1032
1037
  return this.extensions.reduce((commands, extension) => {
1033
1038
  const context = {
@@ -1047,6 +1052,10 @@
1047
1052
  };
1048
1053
  }, {});
1049
1054
  }
1055
+ /**
1056
+ * Get all registered Prosemirror plugins from the extensions.
1057
+ * @returns An array of Prosemirror plugins
1058
+ */
1050
1059
  get plugins() {
1051
1060
  const { editor } = this;
1052
1061
  // With ProseMirror, first plugins within an array are executed first.
@@ -1109,9 +1118,17 @@
1109
1118
  ...allPlugins,
1110
1119
  ];
1111
1120
  }
1121
+ /**
1122
+ * Get all attributes from the extensions.
1123
+ * @returns An array of attributes
1124
+ */
1112
1125
  get attributes() {
1113
1126
  return getAttributesFromExtensions(this.extensions);
1114
1127
  }
1128
+ /**
1129
+ * Get all node views from the extensions.
1130
+ * @returns An object with all node views where the key is the node name and the value is the node view function
1131
+ */
1115
1132
  get nodeViews() {
1116
1133
  const { editor } = this;
1117
1134
  const { nodeExtensions } = splitExtensions(this.extensions);
@@ -1144,6 +1161,62 @@
1144
1161
  return [extension.name, nodeview];
1145
1162
  }));
1146
1163
  }
1164
+ /**
1165
+ * Go through all extensions, create extension storages & setup marks
1166
+ * & bind editor event listener.
1167
+ */
1168
+ setupExtensions() {
1169
+ this.extensions.forEach(extension => {
1170
+ var _a;
1171
+ // store extension storage in editor
1172
+ this.editor.extensionStorage[extension.name] = extension.storage;
1173
+ const context = {
1174
+ name: extension.name,
1175
+ options: extension.options,
1176
+ storage: extension.storage,
1177
+ editor: this.editor,
1178
+ type: getSchemaTypeByName(extension.name, this.schema),
1179
+ };
1180
+ if (extension.type === 'mark') {
1181
+ const keepOnSplit = (_a = callOrReturn(getExtensionField(extension, 'keepOnSplit', context))) !== null && _a !== void 0 ? _a : true;
1182
+ if (keepOnSplit) {
1183
+ this.splittableMarks.push(extension.name);
1184
+ }
1185
+ }
1186
+ const onBeforeCreate = getExtensionField(extension, 'onBeforeCreate', context);
1187
+ const onCreate = getExtensionField(extension, 'onCreate', context);
1188
+ const onUpdate = getExtensionField(extension, 'onUpdate', context);
1189
+ const onSelectionUpdate = getExtensionField(extension, 'onSelectionUpdate', context);
1190
+ const onTransaction = getExtensionField(extension, 'onTransaction', context);
1191
+ const onFocus = getExtensionField(extension, 'onFocus', context);
1192
+ const onBlur = getExtensionField(extension, 'onBlur', context);
1193
+ const onDestroy = getExtensionField(extension, 'onDestroy', context);
1194
+ if (onBeforeCreate) {
1195
+ this.editor.on('beforeCreate', onBeforeCreate);
1196
+ }
1197
+ if (onCreate) {
1198
+ this.editor.on('create', onCreate);
1199
+ }
1200
+ if (onUpdate) {
1201
+ this.editor.on('update', onUpdate);
1202
+ }
1203
+ if (onSelectionUpdate) {
1204
+ this.editor.on('selectionUpdate', onSelectionUpdate);
1205
+ }
1206
+ if (onTransaction) {
1207
+ this.editor.on('transaction', onTransaction);
1208
+ }
1209
+ if (onFocus) {
1210
+ this.editor.on('focus', onFocus);
1211
+ }
1212
+ if (onBlur) {
1213
+ this.editor.on('blur', onBlur);
1214
+ }
1215
+ if (onDestroy) {
1216
+ this.editor.on('destroy', onDestroy);
1217
+ }
1218
+ });
1219
+ }
1147
1220
  }
1148
1221
 
1149
1222
  // see: https://github.com/mesqueeb/is-what/blob/88d6e4ca92fb2baab6003c54e02eedf4e729e5ab/src/index.ts
@@ -1177,6 +1250,10 @@
1177
1250
  return output;
1178
1251
  }
1179
1252
 
1253
+ /**
1254
+ * The Extension class is the base class for all extensions.
1255
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
1256
+ */
1180
1257
  class Extension {
1181
1258
  constructor(config = {}) {
1182
1259
  this.type = 'extension';
@@ -1214,6 +1291,7 @@
1214
1291
  // return a new instance so we can use the same extension
1215
1292
  // with different calls of `configure`
1216
1293
  const extension = this.extend();
1294
+ extension.parent = this.parent;
1217
1295
  extension.options = mergeDeep(this.options, options);
1218
1296
  extension.storage = callOrReturn(getExtensionField(extension, 'addStorage', {
1219
1297
  name: extension.name,
@@ -1240,19 +1318,25 @@
1240
1318
  }
1241
1319
  }
1242
1320
 
1321
+ /**
1322
+ * Gets the text between two positions in a Prosemirror node
1323
+ * and serializes it using the given text serializers and block separator (see getText)
1324
+ * @param startNode The Prosemirror node to start from
1325
+ * @param range The range of the text to get
1326
+ * @param options Options for the text serializer & block separator
1327
+ * @returns The text between the two positions
1328
+ */
1243
1329
  function getTextBetween(startNode, range, options) {
1244
1330
  const { from, to } = range;
1245
1331
  const { blockSeparator = '\n\n', textSerializers = {} } = options || {};
1246
1332
  let text = '';
1247
- let separated = true;
1248
1333
  startNode.nodesBetween(from, to, (node, pos, parent, index) => {
1249
1334
  var _a;
1335
+ if (node.isBlock && pos > from) {
1336
+ text += blockSeparator;
1337
+ }
1250
1338
  const textSerializer = textSerializers === null || textSerializers === void 0 ? void 0 : textSerializers[node.type.name];
1251
1339
  if (textSerializer) {
1252
- if (node.isBlock && !separated) {
1253
- text += blockSeparator;
1254
- separated = true;
1255
- }
1256
1340
  if (parent) {
1257
1341
  text += textSerializer({
1258
1342
  node,
@@ -1267,16 +1351,16 @@
1267
1351
  }
1268
1352
  if (node.isText) {
1269
1353
  text += (_a = node === null || node === void 0 ? void 0 : node.text) === null || _a === void 0 ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos); // eslint-disable-line
1270
- separated = false;
1271
- }
1272
- else if (node.isBlock && !separated) {
1273
- text += blockSeparator;
1274
- separated = true;
1275
1354
  }
1276
1355
  });
1277
1356
  return text;
1278
1357
  }
1279
1358
 
1359
+ /**
1360
+ * Find text serializers `toText` in a Prosemirror schema
1361
+ * @param schema The Prosemirror schema to search in
1362
+ * @returns A record of text serializers by node name
1363
+ */
1280
1364
  function getTextSerializersFromSchema(schema) {
1281
1365
  return Object.fromEntries(Object.entries(schema.nodes)
1282
1366
  .filter(([, node]) => node.spec.toText)
@@ -1659,15 +1743,26 @@
1659
1743
  return removeWhitespaces(html);
1660
1744
  }
1661
1745
 
1746
+ /**
1747
+ * Takes a JSON or HTML content and creates a Prosemirror node or fragment from it.
1748
+ * @param content The JSON or HTML content to create the node from
1749
+ * @param schema The Prosemirror schema to use for the node
1750
+ * @param options Options for the parser
1751
+ * @returns The created Prosemirror node or fragment
1752
+ */
1662
1753
  function createNodeFromContent(content, schema, options) {
1663
1754
  options = {
1664
1755
  slice: true,
1665
1756
  parseOptions: {},
1666
1757
  ...options,
1667
1758
  };
1668
- if (typeof content === 'object' && content !== null) {
1759
+ const isJSONContent = typeof content === 'object' && content !== null;
1760
+ const isTextContent = typeof content === 'string';
1761
+ if (isJSONContent) {
1669
1762
  try {
1670
- if (Array.isArray(content) && content.length > 0) {
1763
+ const isArrayContent = Array.isArray(content) && content.length > 0;
1764
+ // if the JSON Content is an array of nodes, create a fragment for each node
1765
+ if (isArrayContent) {
1671
1766
  return model.Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)));
1672
1767
  }
1673
1768
  return schema.nodeFromJSON(content);
@@ -1677,7 +1772,7 @@
1677
1772
  return createNodeFromContent('', schema, options);
1678
1773
  }
1679
1774
  }
1680
- if (typeof content === 'string') {
1775
+ if (isTextContent) {
1681
1776
  const parser = model.DOMParser.fromSchema(schema);
1682
1777
  return options.slice
1683
1778
  ? parser.parseSlice(elementFromString(content), options.parseOptions).content
@@ -1977,6 +2072,12 @@
1977
2072
  return commands$1.newlineInCode(state, dispatch);
1978
2073
  };
1979
2074
 
2075
+ /**
2076
+ * Get the type of a schema item by its name.
2077
+ * @param name The name of the schema item
2078
+ * @param schema The Prosemiror schema to search in
2079
+ * @returns The type of the schema item (`node` or `mark`), or null if it doesn't exist
2080
+ */
1980
2081
  function getSchemaTypeNameByName(name, schema) {
1981
2082
  if (schema.nodes[name]) {
1982
2083
  return 'node';
@@ -2074,6 +2175,13 @@
2074
2175
  return commands$1.selectTextblockStart(state, dispatch);
2075
2176
  };
2076
2177
 
2178
+ /**
2179
+ * Create a new Prosemirror document node from content.
2180
+ * @param content The JSON or HTML content to create the document from
2181
+ * @param schema The Prosemirror schema to use for the document
2182
+ * @param parseOptions Options for the parser
2183
+ * @returns The created Prosemirror document node
2184
+ */
2077
2185
  function createDocument(content, schema, parseOptions = {}) {
2078
2186
  return createNodeFromContent(content, schema, { slice: false, parseOptions });
2079
2187
  }
@@ -2111,6 +2219,9 @@
2111
2219
 
2112
2220
  /**
2113
2221
  * Returns a new `Transform` based on all steps of the passed transactions.
2222
+ * @param oldDoc The Prosemirror node to start from
2223
+ * @param transactions The transactions to combine
2224
+ * @returns A new `Transform` with all steps of the passed transactions
2114
2225
  */
2115
2226
  function combineTransactionSteps(oldDoc, transactions) {
2116
2227
  const transform$1 = new transform.Transform(oldDoc);
@@ -2122,6 +2233,11 @@
2122
2233
  return transform$1;
2123
2234
  }
2124
2235
 
2236
+ /**
2237
+ * Gets the default block type at a given match
2238
+ * @param match The content match to get the default block type from
2239
+ * @returns The default block type or null
2240
+ */
2125
2241
  function defaultBlockAt(match) {
2126
2242
  for (let i = 0; i < match.edgeCount; i += 1) {
2127
2243
  const { type } = match.edge(i);
@@ -2132,6 +2248,12 @@
2132
2248
  return null;
2133
2249
  }
2134
2250
 
2251
+ /**
2252
+ * Find children inside a Prosemirror node that match a predicate.
2253
+ * @param node The Prosemirror node to search in
2254
+ * @param predicate The predicate to match
2255
+ * @returns An array of nodes with their positions
2256
+ */
2135
2257
  function findChildren(node, predicate) {
2136
2258
  const nodesWithPos = [];
2137
2259
  node.descendants((child, pos) => {
@@ -2147,6 +2269,10 @@
2147
2269
 
2148
2270
  /**
2149
2271
  * Same as `findChildren` but searches only within a `range`.
2272
+ * @param node The Prosemirror node to search in
2273
+ * @param range The range to search in
2274
+ * @param predicate The predicate to match
2275
+ * @returns An array of nodes with their positions
2150
2276
  */
2151
2277
  function findChildrenInRange(node, range, predicate) {
2152
2278
  const nodesWithPos = [];
@@ -2170,6 +2296,15 @@
2170
2296
  return nodesWithPos;
2171
2297
  }
2172
2298
 
2299
+ /**
2300
+ * Finds the closest parent node to a resolved position that matches a predicate.
2301
+ * @param $pos The resolved position to search from
2302
+ * @param predicate The predicate to match
2303
+ * @returns The closest parent node to the resolved position that matches the predicate
2304
+ * @example ```js
2305
+ * findParentNodeClosestToPos($from, node => node.type.name === 'paragraph')
2306
+ * ```
2307
+ */
2173
2308
  function findParentNodeClosestToPos($pos, predicate) {
2174
2309
  for (let i = $pos.depth; i > 0; i -= 1) {
2175
2310
  const node = $pos.node(i);
@@ -2184,6 +2319,14 @@
2184
2319
  }
2185
2320
  }
2186
2321
 
2322
+ /**
2323
+ * Finds the closest parent node to the current selection that matches a predicate.
2324
+ * @param predicate The predicate to match
2325
+ * @returns A command that finds the closest parent node to the current selection that matches the predicate
2326
+ * @example ```js
2327
+ * findParentNode(node => node.type.name === 'paragraph')
2328
+ * ```
2329
+ */
2187
2330
  function findParentNode(predicate) {
2188
2331
  return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
2189
2332
  }
@@ -2201,18 +2344,39 @@
2201
2344
  return getSchemaByResolvedExtensions(resolvedExtensions, editor);
2202
2345
  }
2203
2346
 
2347
+ /**
2348
+ * Generate HTML from a JSONContent
2349
+ * @param doc The JSONContent to generate HTML from
2350
+ * @param extensions The extensions to use for the schema
2351
+ * @returns The generated HTML
2352
+ */
2204
2353
  function generateHTML(doc, extensions) {
2205
2354
  const schema = getSchema(extensions);
2206
2355
  const contentNode = model.Node.fromJSON(schema, doc);
2207
2356
  return getHTMLFromFragment(contentNode.content, schema);
2208
2357
  }
2209
2358
 
2359
+ /**
2360
+ * Generate JSONContent from HTML
2361
+ * @param html The HTML to generate JSONContent from
2362
+ * @param extensions The extensions to use for the schema
2363
+ * @returns The generated JSONContent
2364
+ */
2210
2365
  function generateJSON(html, extensions) {
2211
2366
  const schema = getSchema(extensions);
2212
2367
  const dom = elementFromString(html);
2213
2368
  return model.DOMParser.fromSchema(schema).parse(dom).toJSON();
2214
2369
  }
2215
2370
 
2371
+ /**
2372
+ * Gets the text of a Prosemirror node
2373
+ * @param node The Prosemirror node
2374
+ * @param options Options for the text serializer & block separator
2375
+ * @returns The text of the node
2376
+ * @example ```js
2377
+ * const text = getText(node, { blockSeparator: '\n' })
2378
+ * ```
2379
+ */
2216
2380
  function getText(node, options) {
2217
2381
  const range = {
2218
2382
  from: 0,
@@ -2221,6 +2385,13 @@
2221
2385
  return getTextBetween(node, range, options);
2222
2386
  }
2223
2387
 
2388
+ /**
2389
+ * Generate raw text from a JSONContent
2390
+ * @param doc The JSONContent to generate text from
2391
+ * @param extensions The extensions to use for the schema
2392
+ * @param options Options for the text generation f.e. blockSeparator or textSerializers
2393
+ * @returns The generated text
2394
+ */
2224
2395
  function generateText(doc, extensions, options) {
2225
2396
  const { blockSeparator = '\n\n', textSerializers = {} } = options || {};
2226
2397
  const schema = getSchema(extensions);
@@ -2248,6 +2419,12 @@
2248
2419
  return { ...node.attrs };
2249
2420
  }
2250
2421
 
2422
+ /**
2423
+ * Get node or mark attributes by type or name on the current editor state
2424
+ * @param state The current editor state
2425
+ * @param typeOrName The node or mark type or name
2426
+ * @returns The attributes of the node or mark or an empty object
2427
+ */
2251
2428
  function getAttributes(state, typeOrName) {
2252
2429
  const schemaType = getSchemaTypeNameByName(typeof typeOrName === 'string' ? typeOrName : typeOrName.name, state.schema);
2253
2430
  if (schemaType === 'node') {
@@ -2432,6 +2609,13 @@
2432
2609
  return [node, currentDepth];
2433
2610
  };
2434
2611
 
2612
+ /**
2613
+ * Return attributes of an extension that should be splitted by keepOnSplit flag
2614
+ * @param extensionAttributes Array of extension attributes
2615
+ * @param typeName The type of the extension
2616
+ * @param attributes The attributes of the extension
2617
+ * @returns The splitted attributes
2618
+ */
2435
2619
  function getSplittedAttributes(extensionAttributes, typeName, attributes) {
2436
2620
  return Object.fromEntries(Object
2437
2621
  .entries(attributes)
@@ -3282,7 +3466,12 @@
3282
3466
  const isAtStart = (parentIsIsolating && $parentPos.parent.childCount === 1)
3283
3467
  ? parentPos === $anchor.pos
3284
3468
  : state.Selection.atStart(doc).from === pos;
3285
- if (!empty || !isAtStart || !parent.type.isTextblock || parent.textContent.length) {
3469
+ if (!empty
3470
+ || !parent.type.isTextblock
3471
+ || parent.textContent.length
3472
+ || !isAtStart
3473
+ || (isAtStart && $anchor.parent.type.name === 'paragraph') // prevent clearNodes when no nodes to clear, otherwise history stack is appended
3474
+ ) {
3286
3475
  return false;
3287
3476
  }
3288
3477
  return commands.clearNodes();
@@ -3544,28 +3733,30 @@
3544
3733
  }
3545
3734
  querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
3546
3735
  let nodes = [];
3547
- // iterate through children recursively finding all nodes which match the selector with the node name
3548
3736
  if (!this.children || this.children.length === 0) {
3549
3737
  return nodes;
3550
3738
  }
3739
+ const attrKeys = Object.keys(attributes);
3740
+ /**
3741
+ * Finds all children recursively that match the selector and attributes
3742
+ * If firstItemOnly is true, it will return the first item found
3743
+ */
3551
3744
  this.children.forEach(childPos => {
3745
+ // If we already found a node and we only want the first item, we dont need to keep going
3746
+ if (firstItemOnly && nodes.length > 0) {
3747
+ return;
3748
+ }
3552
3749
  if (childPos.node.type.name === selector) {
3553
- if (Object.keys(attributes).length > 0) {
3554
- const nodeAttributes = childPos.node.attrs;
3555
- const attrKeys = Object.keys(attributes);
3556
- for (let index = 0; index < attrKeys.length; index += 1) {
3557
- const key = attrKeys[index];
3558
- if (nodeAttributes[key] !== attributes[key]) {
3559
- return;
3560
- }
3561
- }
3562
- }
3563
- nodes.push(childPos);
3564
- if (firstItemOnly) {
3565
- return;
3750
+ const doesAllAttributesMatch = attrKeys.every(key => attributes[key] === childPos.node.attrs[key]);
3751
+ if (doesAllAttributesMatch) {
3752
+ nodes.push(childPos);
3566
3753
  }
3567
3754
  }
3568
- nodes = nodes.concat(childPos.querySelectorAll(selector));
3755
+ // If we already found a node and we only want the first item, we can stop here and skip the recursion
3756
+ if (firstItemOnly && nodes.length > 0) {
3757
+ return;
3758
+ }
3759
+ nodes = nodes.concat(childPos.querySelectorAll(selector, attributes, firstItemOnly));
3569
3760
  });
3570
3761
  return nodes;
3571
3762
  }
@@ -4052,6 +4243,7 @@ img.ProseMirror-separator {
4052
4243
  /**
4053
4244
  * Build an input rule that adds a mark when the
4054
4245
  * matched text is typed into it.
4246
+ * @see https://tiptap.dev/guide/custom-extensions/#input-rules
4055
4247
  */
4056
4248
  function markInputRule(config) {
4057
4249
  return new InputRule({
@@ -4095,6 +4287,7 @@ img.ProseMirror-separator {
4095
4287
  /**
4096
4288
  * Build an input rule that adds a node when the
4097
4289
  * matched text is typed into it.
4290
+ * @see https://tiptap.dev/guide/custom-extensions/#input-rules
4098
4291
  */
4099
4292
  function nodeInputRule(config) {
4100
4293
  return new InputRule({
@@ -4133,6 +4326,7 @@ img.ProseMirror-separator {
4133
4326
  * matched text is typed into it. When using a regular expresion you’ll
4134
4327
  * probably want the regexp to start with `^`, so that the pattern can
4135
4328
  * only occur at the start of a textblock.
4329
+ * @see https://tiptap.dev/guide/custom-extensions/#input-rules
4136
4330
  */
4137
4331
  function textblockTypeInputRule(config) {
4138
4332
  return new InputRule({
@@ -4153,6 +4347,7 @@ img.ProseMirror-separator {
4153
4347
  /**
4154
4348
  * Build an input rule that replaces text when the
4155
4349
  * matched text is typed into it.
4350
+ * @see https://tiptap.dev/guide/custom-extensions/#input-rules
4156
4351
  */
4157
4352
  function textInputRule(config) {
4158
4353
  return new InputRule({
@@ -4189,6 +4384,7 @@ img.ProseMirror-separator {
4189
4384
  * two nodes. You can pass a join predicate, which takes a regular
4190
4385
  * expression match and the node before the wrapped node, and can
4191
4386
  * return a boolean to indicate whether a join should happen.
4387
+ * @see https://tiptap.dev/guide/custom-extensions/#input-rules
4192
4388
  */
4193
4389
  function wrappingInputRule(config) {
4194
4390
  return new InputRule({
@@ -4228,6 +4424,10 @@ img.ProseMirror-separator {
4228
4424
  });
4229
4425
  }
4230
4426
 
4427
+ /**
4428
+ * The Mark class is used to create custom mark extensions.
4429
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
4430
+ */
4231
4431
  class Mark {
4232
4432
  constructor(config = {}) {
4233
4433
  this.type = 'mark';
@@ -4311,6 +4511,10 @@ img.ProseMirror-separator {
4311
4511
  }
4312
4512
  }
4313
4513
 
4514
+ /**
4515
+ * The Node class is used to create custom node extensions.
4516
+ * @see https://tiptap.dev/api/extensions#create-a-new-extension
4517
+ */
4314
4518
  class Node {
4315
4519
  constructor(config = {}) {
4316
4520
  this.type = 'node';
@@ -4378,6 +4582,10 @@ img.ProseMirror-separator {
4378
4582
  return navigator.platform === 'Android' || /android/i.test(navigator.userAgent);
4379
4583
  }
4380
4584
 
4585
+ /**
4586
+ * Node views are used to customize the rendered DOM structure of a node.
4587
+ * @see https://tiptap.dev/guide/node-views
4588
+ */
4381
4589
  class NodeView {
4382
4590
  constructor(component, props, options) {
4383
4591
  this.isDragging = false;
@@ -4568,6 +4776,7 @@ img.ProseMirror-separator {
4568
4776
  /**
4569
4777
  * Build an paste rule that adds a mark when the
4570
4778
  * matched text is pasted into it.
4779
+ * @see https://tiptap.dev/guide/custom-extensions/#paste-rules
4571
4780
  */
4572
4781
  function markPasteRule(config) {
4573
4782
  return new PasteRule({
@@ -4621,6 +4830,7 @@ img.ProseMirror-separator {
4621
4830
  /**
4622
4831
  * Build an paste rule that adds a node when the
4623
4832
  * matched text is pasted into it.
4833
+ * @see https://tiptap.dev/guide/custom-extensions/#paste-rules
4624
4834
  */
4625
4835
  function nodePasteRule(config) {
4626
4836
  return new PasteRule({
@@ -4643,6 +4853,7 @@ img.ProseMirror-separator {
4643
4853
  /**
4644
4854
  * Build an paste rule that replaces text when the
4645
4855
  * matched text is pasted into it.
4856
+ * @see https://tiptap.dev/guide/custom-extensions/#paste-rules
4646
4857
  */
4647
4858
  function textPasteRule(config) {
4648
4859
  return new PasteRule({