@tiptap/core 2.10.4 → 2.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Plugin, PluginKey, TextSelection, Selection, NodeSelection, EditorState } from '@tiptap/pm/state';
1
+ import { Plugin, PluginKey, TextSelection, Selection, AllSelection, NodeSelection, EditorState } from '@tiptap/pm/state';
2
2
  import { EditorView } from '@tiptap/pm/view';
3
3
  import { keymap } from '@tiptap/pm/keymap';
4
4
  import { Schema, DOMSerializer, Fragment, Node as Node$1, DOMParser, Slice } from '@tiptap/pm/model';
@@ -320,7 +320,7 @@ function mergeAttributes(...objects) {
320
320
  return;
321
321
  }
322
322
  if (key === 'class') {
323
- const valueClasses = value ? value.split(' ') : [];
323
+ const valueClasses = value ? String(value).split(' ') : [];
324
324
  const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(' ') : [];
325
325
  const insertClasses = valueClasses.filter(valueClass => !existingClasses.includes(valueClass));
326
326
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
@@ -362,6 +362,7 @@ function getRenderedAttributes(nodeOrMark, extensionAttributes) {
362
362
  .reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
363
363
  }
364
364
 
365
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
365
366
  function isFunction(value) {
366
367
  return typeof value === 'function';
367
368
  }
@@ -996,6 +997,8 @@ function run(config) {
996
997
  const success = handlers.every(handler => handler !== null);
997
998
  return success;
998
999
  }
1000
+ // When dragging across editors, must get another editor instance to delete selection content.
1001
+ let tiptapDragFromOtherEditor = null;
999
1002
  const createClipboardPasteEvent = (text) => {
1000
1003
  var _a;
1001
1004
  const event = new ClipboardEvent('paste', {
@@ -1019,7 +1022,7 @@ function pasteRulesPlugin(props) {
1019
1022
  try {
1020
1023
  dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1021
1024
  }
1022
- catch (e) {
1025
+ catch {
1023
1026
  dropEvent = null;
1024
1027
  }
1025
1028
  const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
@@ -1043,7 +1046,7 @@ function pasteRulesPlugin(props) {
1043
1046
  try {
1044
1047
  dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1045
1048
  }
1046
- catch (e) {
1049
+ catch {
1047
1050
  dropEvent = null;
1048
1051
  }
1049
1052
  pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
@@ -1058,11 +1061,21 @@ function pasteRulesPlugin(props) {
1058
1061
  dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
1059
1062
  ? view.dom.parentElement
1060
1063
  : null;
1064
+ if (dragSourceElement) {
1065
+ tiptapDragFromOtherEditor = editor;
1066
+ }
1067
+ };
1068
+ const handleDragend = () => {
1069
+ if (tiptapDragFromOtherEditor) {
1070
+ tiptapDragFromOtherEditor = null;
1071
+ }
1061
1072
  };
1062
1073
  window.addEventListener('dragstart', handleDragstart);
1074
+ window.addEventListener('dragend', handleDragend);
1063
1075
  return {
1064
1076
  destroy() {
1065
1077
  window.removeEventListener('dragstart', handleDragstart);
1078
+ window.removeEventListener('dragend', handleDragend);
1066
1079
  },
1067
1080
  };
1068
1081
  },
@@ -1071,6 +1084,18 @@ function pasteRulesPlugin(props) {
1071
1084
  drop: (view, event) => {
1072
1085
  isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
1073
1086
  dropEvent = event;
1087
+ if (!isDroppedFromProseMirror) {
1088
+ const dragFromOtherEditor = tiptapDragFromOtherEditor;
1089
+ if (dragFromOtherEditor) {
1090
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
1091
+ setTimeout(() => {
1092
+ const selection = dragFromOtherEditor.state.selection;
1093
+ if (selection) {
1094
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
1095
+ }
1096
+ }, 10);
1097
+ }
1098
+ }
1074
1099
  return false;
1075
1100
  },
1076
1101
  paste: (_view, event) => {
@@ -1829,30 +1854,13 @@ function resolveFocusPosition(doc, position = null) {
1829
1854
  return TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1830
1855
  }
1831
1856
 
1832
- function isiOS() {
1833
- return [
1834
- 'iPad Simulator',
1835
- 'iPhone Simulator',
1836
- 'iPod Simulator',
1837
- 'iPad',
1838
- 'iPhone',
1839
- 'iPod',
1840
- ].includes(navigator.platform)
1841
- // iPad on iOS 13 detection
1842
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
1843
- }
1844
-
1845
1857
  const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
1846
1858
  options = {
1847
1859
  scrollIntoView: true,
1848
1860
  ...options,
1849
1861
  };
1850
1862
  const delayedFocus = () => {
1851
- // focus within `requestAnimationFrame` breaks focus on iOS
1852
- // so we have to call this
1853
- if (isiOS()) {
1854
- view.dom.focus();
1855
- }
1863
+ view.dom.focus();
1856
1864
  // For React we have to focus asynchronously. Otherwise wild things happen.
1857
1865
  // see: https://github.com/ueberdosis/tiptap/issues/1520
1858
1866
  requestAnimationFrame(() => {
@@ -2153,7 +2161,7 @@ const joinItemBackward = () => ({ state, dispatch, tr, }) => {
2153
2161
  }
2154
2162
  return true;
2155
2163
  }
2156
- catch (e) {
2164
+ catch {
2157
2165
  return false;
2158
2166
  }
2159
2167
  };
@@ -2170,7 +2178,7 @@ const joinItemForward = () => ({ state, dispatch, tr, }) => {
2170
2178
  }
2171
2179
  return true;
2172
2180
  }
2173
- catch (e) {
2181
+ catch {
2174
2182
  return false;
2175
2183
  }
2176
2184
  };
@@ -2183,6 +2191,19 @@ const joinTextblockForward = () => ({ state, dispatch }) => {
2183
2191
  return joinTextblockForward$1(state, dispatch);
2184
2192
  };
2185
2193
 
2194
+ function isiOS() {
2195
+ return [
2196
+ 'iPad Simulator',
2197
+ 'iPhone Simulator',
2198
+ 'iPod Simulator',
2199
+ 'iPad',
2200
+ 'iPhone',
2201
+ 'iPod',
2202
+ ].includes(navigator.platform)
2203
+ // iPad on iOS 13 detection
2204
+ || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
2205
+ }
2206
+
2186
2207
  function isMacOS() {
2187
2208
  return typeof navigator !== 'undefined'
2188
2209
  ? /Mac/.test(navigator.platform)
@@ -2393,11 +2414,12 @@ const scrollIntoView = () => ({ tr, dispatch }) => {
2393
2414
  return true;
2394
2415
  };
2395
2416
 
2396
- const selectAll = () => ({ tr, commands }) => {
2397
- return commands.setTextSelection({
2398
- from: 0,
2399
- to: tr.doc.content.size,
2400
- });
2417
+ const selectAll = () => ({ tr, dispatch }) => {
2418
+ if (dispatch) {
2419
+ const selection = new AllSelection(tr.doc);
2420
+ tr.setSelection(selection);
2421
+ }
2422
+ return true;
2401
2423
  };
2402
2424
 
2403
2425
  const selectNodeBackward = () => ({ state, dispatch }) => {
@@ -3084,6 +3106,81 @@ function posToDOMRect(view, from, to) {
3084
3106
  };
3085
3107
  }
3086
3108
 
3109
+ /**
3110
+ * The actual implementation of the rewriteUnknownContent function
3111
+ */
3112
+ function rewriteUnknownContentInner({ json, validMarks, validNodes, options, rewrittenContent = [], }) {
3113
+ if (json.marks && Array.isArray(json.marks)) {
3114
+ json.marks = json.marks.filter(mark => {
3115
+ const name = typeof mark === 'string' ? mark : mark.type;
3116
+ if (validMarks.has(name)) {
3117
+ return true;
3118
+ }
3119
+ rewrittenContent.push({
3120
+ original: JSON.parse(JSON.stringify(mark)),
3121
+ unsupported: name,
3122
+ });
3123
+ // Just ignore any unknown marks
3124
+ return false;
3125
+ });
3126
+ }
3127
+ if (json.content && Array.isArray(json.content)) {
3128
+ json.content = json.content
3129
+ .map(value => rewriteUnknownContentInner({
3130
+ json: value,
3131
+ validMarks,
3132
+ validNodes,
3133
+ options,
3134
+ rewrittenContent,
3135
+ }).json)
3136
+ .filter(a => a !== null && a !== undefined);
3137
+ }
3138
+ if (json.type && !validNodes.has(json.type)) {
3139
+ rewrittenContent.push({
3140
+ original: JSON.parse(JSON.stringify(json)),
3141
+ unsupported: json.type,
3142
+ });
3143
+ if (json.content && Array.isArray(json.content) && ((options === null || options === void 0 ? void 0 : options.fallbackToParagraph) !== false)) {
3144
+ // Just treat it like a paragraph and hope for the best
3145
+ json.type = 'paragraph';
3146
+ return {
3147
+ json,
3148
+ rewrittenContent,
3149
+ };
3150
+ }
3151
+ // or just omit it entirely
3152
+ return {
3153
+ json: null,
3154
+ rewrittenContent,
3155
+ };
3156
+ }
3157
+ return { json, rewrittenContent };
3158
+ }
3159
+ /**
3160
+ * Rewrite unknown nodes and marks within JSON content
3161
+ * Allowing for user within the editor
3162
+ */
3163
+ function rewriteUnknownContent(
3164
+ /**
3165
+ * The JSON content to clean of unknown nodes and marks
3166
+ */
3167
+ json,
3168
+ /**
3169
+ * The schema to use for validation
3170
+ */
3171
+ schema,
3172
+ /**
3173
+ * Options for the cleaning process
3174
+ */
3175
+ options) {
3176
+ return rewriteUnknownContentInner({
3177
+ json,
3178
+ validNodes: new Set(Object.keys(schema.nodes)),
3179
+ validMarks: new Set(Object.keys(schema.marks)),
3180
+ options,
3181
+ });
3182
+ }
3183
+
3087
3184
  function canSetMark(state, tr, newMarkType) {
3088
3185
  var _a;
3089
3186
  const { selection } = tr;
@@ -5079,10 +5176,10 @@ class NodeView {
5079
5176
  // ProseMirror tries to drag selectable nodes
5080
5177
  // even if `draggable` is set to `false`
5081
5178
  // this fix prevents that
5082
- if (!isDraggable && isSelectable && isDragEvent) {
5179
+ if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
5083
5180
  event.preventDefault();
5084
5181
  }
5085
- if (isDraggable && isDragEvent && !isDragging) {
5182
+ if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
5086
5183
  event.preventDefault();
5087
5184
  return false;
5088
5185
  }
@@ -5323,5 +5420,5 @@ class Tracker {
5323
5420
  }
5324
5421
  }
5325
5422
 
5326
- export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, index as extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
5423
+ export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, index as extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, rewriteUnknownContent, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
5327
5424
  //# sourceMappingURL=index.js.map