@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.umd.js CHANGED
@@ -318,7 +318,7 @@
318
318
  return;
319
319
  }
320
320
  if (key === 'class') {
321
- const valueClasses = value ? value.split(' ') : [];
321
+ const valueClasses = value ? String(value).split(' ') : [];
322
322
  const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(' ') : [];
323
323
  const insertClasses = valueClasses.filter(valueClass => !existingClasses.includes(valueClass));
324
324
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
@@ -360,6 +360,7 @@
360
360
  .reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
361
361
  }
362
362
 
363
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
363
364
  function isFunction(value) {
364
365
  return typeof value === 'function';
365
366
  }
@@ -994,6 +995,8 @@
994
995
  const success = handlers.every(handler => handler !== null);
995
996
  return success;
996
997
  }
998
+ // When dragging across editors, must get another editor instance to delete selection content.
999
+ let tiptapDragFromOtherEditor = null;
997
1000
  const createClipboardPasteEvent = (text) => {
998
1001
  var _a;
999
1002
  const event = new ClipboardEvent('paste', {
@@ -1017,7 +1020,7 @@
1017
1020
  try {
1018
1021
  dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1019
1022
  }
1020
- catch (e) {
1023
+ catch {
1021
1024
  dropEvent = null;
1022
1025
  }
1023
1026
  const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
@@ -1041,7 +1044,7 @@
1041
1044
  try {
1042
1045
  dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
1043
1046
  }
1044
- catch (e) {
1047
+ catch {
1045
1048
  dropEvent = null;
1046
1049
  }
1047
1050
  pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
@@ -1056,11 +1059,21 @@
1056
1059
  dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
1057
1060
  ? view.dom.parentElement
1058
1061
  : null;
1062
+ if (dragSourceElement) {
1063
+ tiptapDragFromOtherEditor = editor;
1064
+ }
1065
+ };
1066
+ const handleDragend = () => {
1067
+ if (tiptapDragFromOtherEditor) {
1068
+ tiptapDragFromOtherEditor = null;
1069
+ }
1059
1070
  };
1060
1071
  window.addEventListener('dragstart', handleDragstart);
1072
+ window.addEventListener('dragend', handleDragend);
1061
1073
  return {
1062
1074
  destroy() {
1063
1075
  window.removeEventListener('dragstart', handleDragstart);
1076
+ window.removeEventListener('dragend', handleDragend);
1064
1077
  },
1065
1078
  };
1066
1079
  },
@@ -1069,6 +1082,18 @@
1069
1082
  drop: (view, event) => {
1070
1083
  isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
1071
1084
  dropEvent = event;
1085
+ if (!isDroppedFromProseMirror) {
1086
+ const dragFromOtherEditor = tiptapDragFromOtherEditor;
1087
+ if (dragFromOtherEditor) {
1088
+ // setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
1089
+ setTimeout(() => {
1090
+ const selection = dragFromOtherEditor.state.selection;
1091
+ if (selection) {
1092
+ dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
1093
+ }
1094
+ }, 10);
1095
+ }
1096
+ }
1072
1097
  return false;
1073
1098
  },
1074
1099
  paste: (_view, event) => {
@@ -1827,30 +1852,13 @@
1827
1852
  return state.TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
1828
1853
  }
1829
1854
 
1830
- function isiOS() {
1831
- return [
1832
- 'iPad Simulator',
1833
- 'iPhone Simulator',
1834
- 'iPod Simulator',
1835
- 'iPad',
1836
- 'iPhone',
1837
- 'iPod',
1838
- ].includes(navigator.platform)
1839
- // iPad on iOS 13 detection
1840
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
1841
- }
1842
-
1843
1855
  const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
1844
1856
  options = {
1845
1857
  scrollIntoView: true,
1846
1858
  ...options,
1847
1859
  };
1848
1860
  const delayedFocus = () => {
1849
- // focus within `requestAnimationFrame` breaks focus on iOS
1850
- // so we have to call this
1851
- if (isiOS()) {
1852
- view.dom.focus();
1853
- }
1861
+ view.dom.focus();
1854
1862
  // For React we have to focus asynchronously. Otherwise wild things happen.
1855
1863
  // see: https://github.com/ueberdosis/tiptap/issues/1520
1856
1864
  requestAnimationFrame(() => {
@@ -2151,7 +2159,7 @@
2151
2159
  }
2152
2160
  return true;
2153
2161
  }
2154
- catch (e) {
2162
+ catch {
2155
2163
  return false;
2156
2164
  }
2157
2165
  };
@@ -2168,7 +2176,7 @@
2168
2176
  }
2169
2177
  return true;
2170
2178
  }
2171
- catch (e) {
2179
+ catch {
2172
2180
  return false;
2173
2181
  }
2174
2182
  };
@@ -2181,6 +2189,19 @@
2181
2189
  return commands$1.joinTextblockForward(state, dispatch);
2182
2190
  };
2183
2191
 
2192
+ function isiOS() {
2193
+ return [
2194
+ 'iPad Simulator',
2195
+ 'iPhone Simulator',
2196
+ 'iPod Simulator',
2197
+ 'iPad',
2198
+ 'iPhone',
2199
+ 'iPod',
2200
+ ].includes(navigator.platform)
2201
+ // iPad on iOS 13 detection
2202
+ || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
2203
+ }
2204
+
2184
2205
  function isMacOS() {
2185
2206
  return typeof navigator !== 'undefined'
2186
2207
  ? /Mac/.test(navigator.platform)
@@ -2391,11 +2412,12 @@
2391
2412
  return true;
2392
2413
  };
2393
2414
 
2394
- const selectAll = () => ({ tr, commands }) => {
2395
- return commands.setTextSelection({
2396
- from: 0,
2397
- to: tr.doc.content.size,
2398
- });
2415
+ const selectAll = () => ({ tr, dispatch }) => {
2416
+ if (dispatch) {
2417
+ const selection = new state.AllSelection(tr.doc);
2418
+ tr.setSelection(selection);
2419
+ }
2420
+ return true;
2399
2421
  };
2400
2422
 
2401
2423
  const selectNodeBackward = () => ({ state, dispatch }) => {
@@ -3082,6 +3104,81 @@
3082
3104
  };
3083
3105
  }
3084
3106
 
3107
+ /**
3108
+ * The actual implementation of the rewriteUnknownContent function
3109
+ */
3110
+ function rewriteUnknownContentInner({ json, validMarks, validNodes, options, rewrittenContent = [], }) {
3111
+ if (json.marks && Array.isArray(json.marks)) {
3112
+ json.marks = json.marks.filter(mark => {
3113
+ const name = typeof mark === 'string' ? mark : mark.type;
3114
+ if (validMarks.has(name)) {
3115
+ return true;
3116
+ }
3117
+ rewrittenContent.push({
3118
+ original: JSON.parse(JSON.stringify(mark)),
3119
+ unsupported: name,
3120
+ });
3121
+ // Just ignore any unknown marks
3122
+ return false;
3123
+ });
3124
+ }
3125
+ if (json.content && Array.isArray(json.content)) {
3126
+ json.content = json.content
3127
+ .map(value => rewriteUnknownContentInner({
3128
+ json: value,
3129
+ validMarks,
3130
+ validNodes,
3131
+ options,
3132
+ rewrittenContent,
3133
+ }).json)
3134
+ .filter(a => a !== null && a !== undefined);
3135
+ }
3136
+ if (json.type && !validNodes.has(json.type)) {
3137
+ rewrittenContent.push({
3138
+ original: JSON.parse(JSON.stringify(json)),
3139
+ unsupported: json.type,
3140
+ });
3141
+ if (json.content && Array.isArray(json.content) && ((options === null || options === void 0 ? void 0 : options.fallbackToParagraph) !== false)) {
3142
+ // Just treat it like a paragraph and hope for the best
3143
+ json.type = 'paragraph';
3144
+ return {
3145
+ json,
3146
+ rewrittenContent,
3147
+ };
3148
+ }
3149
+ // or just omit it entirely
3150
+ return {
3151
+ json: null,
3152
+ rewrittenContent,
3153
+ };
3154
+ }
3155
+ return { json, rewrittenContent };
3156
+ }
3157
+ /**
3158
+ * Rewrite unknown nodes and marks within JSON content
3159
+ * Allowing for user within the editor
3160
+ */
3161
+ function rewriteUnknownContent(
3162
+ /**
3163
+ * The JSON content to clean of unknown nodes and marks
3164
+ */
3165
+ json,
3166
+ /**
3167
+ * The schema to use for validation
3168
+ */
3169
+ schema,
3170
+ /**
3171
+ * Options for the cleaning process
3172
+ */
3173
+ options) {
3174
+ return rewriteUnknownContentInner({
3175
+ json,
3176
+ validNodes: new Set(Object.keys(schema.nodes)),
3177
+ validMarks: new Set(Object.keys(schema.marks)),
3178
+ options,
3179
+ });
3180
+ }
3181
+
3085
3182
  function canSetMark(state, tr, newMarkType) {
3086
3183
  var _a;
3087
3184
  const { selection } = tr;
@@ -5077,10 +5174,10 @@ img.ProseMirror-separator {
5077
5174
  // ProseMirror tries to drag selectable nodes
5078
5175
  // even if `draggable` is set to `false`
5079
5176
  // this fix prevents that
5080
- if (!isDraggable && isSelectable && isDragEvent) {
5177
+ if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
5081
5178
  event.preventDefault();
5082
5179
  }
5083
- if (isDraggable && isDragEvent && !isDragging) {
5180
+ if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
5084
5181
  event.preventDefault();
5085
5182
  return false;
5086
5183
  }
@@ -5406,6 +5503,7 @@ img.ProseMirror-separator {
5406
5503
  exports.posToDOMRect = posToDOMRect;
5407
5504
  exports.removeDuplicates = removeDuplicates;
5408
5505
  exports.resolveFocusPosition = resolveFocusPosition;
5506
+ exports.rewriteUnknownContent = rewriteUnknownContent;
5409
5507
  exports.selectionToInsertionEnd = selectionToInsertionEnd;
5410
5508
  exports.splitExtensions = splitExtensions;
5411
5509
  exports.textInputRule = textInputRule;