@tiptap/core 2.5.5 → 2.5.7

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
@@ -1775,12 +1775,12 @@
1775
1775
  }
1776
1776
  }
1777
1777
  if (isTextContent) {
1778
- let schemaToUse = schema;
1779
- let hasInvalidContent = false;
1780
- let invalidContent = '';
1781
- // Only ever check for invalid content if we're supposed to throw an error
1778
+ // Check for invalid content
1782
1779
  if (options.errorOnInvalidContent) {
1783
- schemaToUse = new model.Schema({
1780
+ let hasInvalidContent = false;
1781
+ let invalidContent = '';
1782
+ // A copy of the current schema with a catch-all node at the end
1783
+ const contentCheckSchema = new model.Schema({
1784
1784
  topNode: schema.spec.topNode,
1785
1785
  marks: schema.spec.marks,
1786
1786
  // Prosemirror's schemas are executed such that: the last to execute, matches last
@@ -1804,15 +1804,21 @@
1804
1804
  },
1805
1805
  }),
1806
1806
  });
1807
+ if (options.slice) {
1808
+ model.DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
1809
+ }
1810
+ else {
1811
+ model.DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
1812
+ }
1813
+ if (options.errorOnInvalidContent && hasInvalidContent) {
1814
+ throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
1815
+ }
1807
1816
  }
1808
- const parser = model.DOMParser.fromSchema(schemaToUse);
1809
- const response = options.slice
1810
- ? parser.parseSlice(elementFromString(content), options.parseOptions).content
1811
- : parser.parse(elementFromString(content), options.parseOptions);
1812
- if (options.errorOnInvalidContent && hasInvalidContent) {
1813
- throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
1817
+ const parser = model.DOMParser.fromSchema(schema);
1818
+ if (options.slice) {
1819
+ return parser.parseSlice(elementFromString(content), options.parseOptions).content;
1814
1820
  }
1815
- return response;
1821
+ return parser.parse(elementFromString(content), options.parseOptions);
1816
1822
  }
1817
1823
  return createNodeFromContent('', schema, options);
1818
1824
  }
@@ -1861,6 +1867,13 @@
1861
1867
  });
1862
1868
  }
1863
1869
  catch (e) {
1870
+ editor.emit('contentError', {
1871
+ editor,
1872
+ error: e,
1873
+ disableCollaboration: () => {
1874
+ console.error('[tiptap error]: Unable to disable collaboration at this point in time');
1875
+ },
1876
+ });
1864
1877
  return false;
1865
1878
  }
1866
1879
  let { from, to } = typeof position === 'number' ? { from: position, to: position } : { from: position.from, to: position.to };
@@ -2811,12 +2824,34 @@
2811
2824
  return group.split(' ').includes('list');
2812
2825
  }
2813
2826
 
2814
- function isNodeEmpty(node) {
2815
- const defaultContent = node.type.createAndFill();
2816
- if (!defaultContent) {
2827
+ /**
2828
+ * Returns true if the given node is empty.
2829
+ * When `checkChildren` is true (default), it will also check if all children are empty.
2830
+ */
2831
+ function isNodeEmpty(node, { checkChildren } = { checkChildren: true }) {
2832
+ if (node.isText) {
2833
+ return !node.text;
2834
+ }
2835
+ if (node.content.childCount === 0) {
2836
+ return true;
2837
+ }
2838
+ if (node.isLeaf) {
2817
2839
  return false;
2818
2840
  }
2819
- return node.eq(defaultContent);
2841
+ if (checkChildren) {
2842
+ let hasSameContent = true;
2843
+ node.content.forEach(childNode => {
2844
+ if (hasSameContent === false) {
2845
+ // Exit early for perf
2846
+ return;
2847
+ }
2848
+ if (!isNodeEmpty(childNode)) {
2849
+ hasSameContent = false;
2850
+ }
2851
+ });
2852
+ return hasSameContent;
2853
+ }
2854
+ return false;
2820
2855
  }
2821
2856
 
2822
2857
  function isNodeSelection(value) {
@@ -3014,15 +3049,24 @@
3014
3049
  if (!$from.parent.isBlock) {
3015
3050
  return false;
3016
3051
  }
3017
- if (dispatch) {
3018
- const atEnd = $to.parentOffset === $to.parent.content.size;
3019
- if (selection instanceof state.TextSelection) {
3020
- tr.deleteSelection();
3021
- }
3022
- const deflt = $from.depth === 0
3023
- ? undefined
3024
- : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
3025
- let types = atEnd && deflt
3052
+ const atEnd = $to.parentOffset === $to.parent.content.size;
3053
+ const deflt = $from.depth === 0
3054
+ ? undefined
3055
+ : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
3056
+ let types = atEnd && deflt
3057
+ ? [
3058
+ {
3059
+ type: deflt,
3060
+ attrs: newAttributes,
3061
+ },
3062
+ ]
3063
+ : undefined;
3064
+ let can = transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
3065
+ if (!types
3066
+ && !can
3067
+ && transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
3068
+ can = true;
3069
+ types = deflt
3026
3070
  ? [
3027
3071
  {
3028
3072
  type: deflt,
@@ -3030,21 +3074,12 @@
3030
3074
  },
3031
3075
  ]
3032
3076
  : undefined;
3033
- let can = transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
3034
- if (!types
3035
- && !can
3036
- && transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
3037
- can = true;
3038
- types = deflt
3039
- ? [
3040
- {
3041
- type: deflt,
3042
- attrs: newAttributes,
3043
- },
3044
- ]
3045
- : undefined;
3046
- }
3077
+ }
3078
+ if (dispatch) {
3047
3079
  if (can) {
3080
+ if (selection instanceof state.TextSelection) {
3081
+ tr.deleteSelection();
3082
+ }
3048
3083
  tr.split(tr.mapping.map($from.pos), 1, types);
3049
3084
  if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
3050
3085
  const first = tr.mapping.map($from.before());
@@ -3059,7 +3094,7 @@
3059
3094
  }
3060
3095
  tr.scrollIntoView();
3061
3096
  }
3062
- return true;
3097
+ return can;
3063
3098
  };
3064
3099
 
3065
3100
  const splitListItem = typeOrName => ({ tr, state: state$1, dispatch, editor, }) => {
@@ -4158,6 +4193,7 @@ img.ProseMirror-separator {
4158
4193
  this.prependClass();
4159
4194
  // Let’s store the editor instance in the DOM element.
4160
4195
  // So we’ll have access to it for tests.
4196
+ // @ts-ignore
4161
4197
  const dom = this.view.dom;
4162
4198
  dom.editor = this;
4163
4199
  }
@@ -4165,6 +4201,9 @@ img.ProseMirror-separator {
4165
4201
  * Creates all node views.
4166
4202
  */
4167
4203
  createNodeViews() {
4204
+ if (this.view.isDestroyed) {
4205
+ return;
4206
+ }
4168
4207
  this.view.setProps({
4169
4208
  nodeViews: this.extensionManager.nodeViews,
4170
4209
  });