@tiptap/core 2.6.5 → 2.7.0-pre.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.
package/dist/index.umd.js CHANGED
@@ -317,7 +317,18 @@
317
317
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
318
318
  }
319
319
  else if (key === 'style') {
320
- mergedAttributes[key] = [mergedAttributes[key], value].join('; ');
320
+ const newStyles = value ? value.split(';').map((style) => style.trim()).filter(Boolean) : [];
321
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(';').map((style) => style.trim()).filter(Boolean) : [];
322
+ const styleMap = new Map();
323
+ existingStyles.forEach(style => {
324
+ const [property, val] = style.split(':').map(part => part.trim());
325
+ styleMap.set(property, val);
326
+ });
327
+ newStyles.forEach(style => {
328
+ const [property, val] = style.split(':').map(part => part.trim());
329
+ styleMap.set(property, val);
330
+ });
331
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join('; ');
321
332
  }
322
333
  else {
323
334
  mergedAttributes[key] = value;
@@ -711,16 +722,6 @@
711
722
  },
712
723
  },
713
724
  props: {
714
- handleTextInput(view, from, to, text) {
715
- return run$1({
716
- editor,
717
- from,
718
- to,
719
- text,
720
- rules,
721
- plugin,
722
- });
723
- },
724
725
  handleDOMEvents: {
725
726
  compositionend: view => {
726
727
  setTimeout(() => {
@@ -738,6 +739,19 @@
738
739
  });
739
740
  return false;
740
741
  },
742
+ keyup(view, event) {
743
+ if (event.key.length === 1) {
744
+ return run$1({
745
+ editor,
746
+ from: view.state.selection.from,
747
+ to: view.state.selection.from,
748
+ text: '',
749
+ rules,
750
+ plugin,
751
+ });
752
+ }
753
+ return false;
754
+ },
741
755
  },
742
756
  // add support for input rules to trigger on enter
743
757
  // this is useful for example for code blocks
@@ -1148,15 +1162,19 @@
1148
1162
  if (!addNodeView) {
1149
1163
  return [];
1150
1164
  }
1151
- const nodeview = (node, view, getPos, decorations) => {
1165
+ const nodeview = (node, view, getPos, decorations, innerDecorations) => {
1152
1166
  const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
1153
1167
  return addNodeView()({
1154
- editor,
1168
+ // pass-through
1155
1169
  node,
1156
- getPos,
1170
+ view,
1171
+ getPos: getPos,
1157
1172
  decorations,
1158
- HTMLAttributes,
1173
+ innerDecorations,
1174
+ // tiptap-specific
1175
+ editor,
1159
1176
  extension,
1177
+ HTMLAttributes,
1160
1178
  });
1161
1179
  };
1162
1180
  return [extension.name, nodeview];
@@ -1764,7 +1782,11 @@
1764
1782
  if (isArrayContent) {
1765
1783
  return model.Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)));
1766
1784
  }
1767
- return schema.nodeFromJSON(content);
1785
+ const node = schema.nodeFromJSON(content);
1786
+ if (options.errorOnInvalidContent) {
1787
+ node.check();
1788
+ }
1789
+ return node;
1768
1790
  }
1769
1791
  catch (error) {
1770
1792
  if (options.errorOnInvalidContent) {
@@ -3310,10 +3332,17 @@
3310
3332
  const type = getNodeType(typeOrName, state.schema);
3311
3333
  const toggleType = getNodeType(toggleTypeOrName, state.schema);
3312
3334
  const isActive = isNodeActive(state, type, attributes);
3335
+ let attributesToCopy;
3336
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3337
+ // only copy attributes if the selection is pointing to a node of the same type
3338
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3339
+ }
3313
3340
  if (isActive) {
3314
- return commands.setNode(toggleType);
3341
+ return commands.setNode(toggleType, attributesToCopy);
3315
3342
  }
3316
- return commands.setNode(type, attributes);
3343
+ // If the node is not active, we want to set the new node type with the given attributes
3344
+ // Copying over the attributes from the current node if the selection is pointing to a node of the same type
3345
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
3317
3346
  };
3318
3347
 
3319
3348
  const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
@@ -3647,7 +3676,8 @@
3647
3676
  appendTransaction: (transactions, oldState, newState) => {
3648
3677
  const docChanges = transactions.some(transaction => transaction.docChanged)
3649
3678
  && !oldState.doc.eq(newState.doc);
3650
- if (!docChanges) {
3679
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3680
+ if (!docChanges || ignoreTr) {
3651
3681
  return;
3652
3682
  }
3653
3683
  const { empty, from, to } = oldState.selection;
@@ -3657,7 +3687,7 @@
3657
3687
  if (empty || !allWasSelected) {
3658
3688
  return;
3659
3689
  }
3660
- const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
3690
+ const isEmpty = isNodeEmpty(newState.doc);
3661
3691
  if (!isEmpty) {
3662
3692
  return;
3663
3693
  }
@@ -3881,6 +3911,28 @@
3881
3911
  }
3882
3912
  }
3883
3913
 
3914
+ const DropPlugin = (onDrop) => {
3915
+ return new state.Plugin({
3916
+ key: new state.PluginKey('tiptapDrop'),
3917
+ props: {
3918
+ handleDrop: (_, e, slice, moved) => {
3919
+ onDrop(e, slice, moved);
3920
+ },
3921
+ },
3922
+ });
3923
+ };
3924
+
3925
+ const PastePlugin = (onPaste) => {
3926
+ return new state.Plugin({
3927
+ key: new state.PluginKey('tiptapPaste'),
3928
+ props: {
3929
+ handlePaste: (_view, e, slice) => {
3930
+ onPaste(e, slice);
3931
+ },
3932
+ },
3933
+ });
3934
+ };
3935
+
3884
3936
  const style = `.ProseMirror {
3885
3937
  position: relative;
3886
3938
  }
@@ -4005,6 +4057,8 @@ img.ProseMirror-separator {
4005
4057
  onBlur: () => null,
4006
4058
  onDestroy: () => null,
4007
4059
  onContentError: ({ error }) => { throw error; },
4060
+ onPaste: () => null,
4061
+ onDrop: () => null,
4008
4062
  };
4009
4063
  this.isCapturingTransaction = false;
4010
4064
  this.capturedTransaction = null;
@@ -4024,6 +4078,12 @@ img.ProseMirror-separator {
4024
4078
  this.on('focus', this.options.onFocus);
4025
4079
  this.on('blur', this.options.onBlur);
4026
4080
  this.on('destroy', this.options.onDestroy);
4081
+ if (this.options.onPaste) {
4082
+ this.registerPlugin(PastePlugin(this.options.onPaste));
4083
+ }
4084
+ if (this.options.onDrop) {
4085
+ this.registerPlugin(DropPlugin(this.options.onDrop));
4086
+ }
4027
4087
  window.setTimeout(() => {
4028
4088
  if (this.isDestroyed) {
4029
4089
  return;
@@ -4151,7 +4211,12 @@ img.ProseMirror-separator {
4151
4211
  FocusEvents,
4152
4212
  Keymap,
4153
4213
  Tabindex,
4154
- ] : [];
4214
+ ].filter(ext => {
4215
+ if (typeof this.options.enableCoreExtensions === 'object') {
4216
+ return this.options.enableCoreExtensions[ext.name] !== false;
4217
+ }
4218
+ return true;
4219
+ }) : [];
4155
4220
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4156
4221
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4157
4222
  });
@@ -4760,6 +4825,9 @@ img.ProseMirror-separator {
4760
4825
  this.extension = props.extension;
4761
4826
  this.node = props.node;
4762
4827
  this.decorations = props.decorations;
4828
+ this.innerDecorations = props.innerDecorations;
4829
+ this.view = props.view;
4830
+ this.HTMLAttributes = props.HTMLAttributes;
4763
4831
  this.getPos = props.getPos;
4764
4832
  this.mount();
4765
4833
  }
@@ -4798,9 +4866,13 @@ img.ProseMirror-separator {
4798
4866
  y = handleBox.y - domBox.y + offsetY;
4799
4867
  }
4800
4868
  (_g = event.dataTransfer) === null || _g === void 0 ? void 0 : _g.setDragImage(this.dom, x, y);
4869
+ const pos = this.getPos();
4870
+ if (typeof pos !== 'number') {
4871
+ return;
4872
+ }
4801
4873
  // we need to tell ProseMirror that we want to move the whole node
4802
4874
  // so we create a NodeSelection
4803
- const selection = state.NodeSelection.create(view.state.doc, this.getPos());
4875
+ const selection = state.NodeSelection.create(view.state.doc, pos);
4804
4876
  const transaction = view.state.tr.setSelection(selection);
4805
4877
  view.dispatch(transaction);
4806
4878
  }
@@ -4871,6 +4943,11 @@ img.ProseMirror-separator {
4871
4943
  }
4872
4944
  return true;
4873
4945
  }
4946
+ /**
4947
+ * Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
4948
+ * @return `false` if the editor should re-read the selection or re-parse the range around the mutation
4949
+ * @return `true` if it can safely be ignored.
4950
+ */
4874
4951
  ignoreMutation(mutation) {
4875
4952
  if (!this.dom || !this.contentDOM) {
4876
4953
  return true;
@@ -4917,9 +4994,15 @@ img.ProseMirror-separator {
4917
4994
  }
4918
4995
  return true;
4919
4996
  }
4997
+ /**
4998
+ * Update the attributes of the prosemirror node.
4999
+ */
4920
5000
  updateAttributes(attributes) {
4921
5001
  this.editor.commands.command(({ tr }) => {
4922
5002
  const pos = this.getPos();
5003
+ if (typeof pos !== 'number') {
5004
+ return false;
5005
+ }
4923
5006
  tr.setNodeMarkup(pos, undefined, {
4924
5007
  ...this.node.attrs,
4925
5008
  ...attributes,
@@ -4927,8 +5010,14 @@ img.ProseMirror-separator {
4927
5010
  return true;
4928
5011
  });
4929
5012
  }
5013
+ /**
5014
+ * Delete the node.
5015
+ */
4930
5016
  deleteNode() {
4931
5017
  const from = this.getPos();
5018
+ if (typeof from !== 'number') {
5019
+ return;
5020
+ }
4932
5021
  const to = from + this.node.nodeSize;
4933
5022
  this.editor.commands.deleteRange({ from, to });
4934
5023
  }
@@ -5064,6 +5153,7 @@ img.ProseMirror-separator {
5064
5153
  }
5065
5154
 
5066
5155
  exports.CommandManager = CommandManager;
5156
+ exports.DropPlugin = DropPlugin;
5067
5157
  exports.Editor = Editor;
5068
5158
  exports.Extension = Extension;
5069
5159
  exports.InputRule = InputRule;
@@ -5071,6 +5161,7 @@ img.ProseMirror-separator {
5071
5161
  exports.Node = Node;
5072
5162
  exports.NodePos = NodePos;
5073
5163
  exports.NodeView = NodeView;
5164
+ exports.PastePlugin = PastePlugin;
5074
5165
  exports.PasteRule = PasteRule;
5075
5166
  exports.Tracker = Tracker;
5076
5167
  exports.callOrReturn = callOrReturn;