@tiptap/core 2.6.6 → 2.7.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;
@@ -1148,15 +1159,19 @@
1148
1159
  if (!addNodeView) {
1149
1160
  return [];
1150
1161
  }
1151
- const nodeview = (node, view, getPos, decorations) => {
1162
+ const nodeview = (node, view, getPos, decorations, innerDecorations) => {
1152
1163
  const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
1153
1164
  return addNodeView()({
1154
- editor,
1165
+ // pass-through
1155
1166
  node,
1156
- getPos,
1167
+ view,
1168
+ getPos: getPos,
1157
1169
  decorations,
1158
- HTMLAttributes,
1170
+ innerDecorations,
1171
+ // tiptap-specific
1172
+ editor,
1159
1173
  extension,
1174
+ HTMLAttributes,
1160
1175
  });
1161
1176
  };
1162
1177
  return [extension.name, nodeview];
@@ -3314,10 +3329,17 @@
3314
3329
  const type = getNodeType(typeOrName, state.schema);
3315
3330
  const toggleType = getNodeType(toggleTypeOrName, state.schema);
3316
3331
  const isActive = isNodeActive(state, type, attributes);
3332
+ let attributesToCopy;
3333
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3334
+ // only copy attributes if the selection is pointing to a node of the same type
3335
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3336
+ }
3317
3337
  if (isActive) {
3318
- return commands.setNode(toggleType);
3338
+ return commands.setNode(toggleType, attributesToCopy);
3319
3339
  }
3320
- return commands.setNode(type, attributes);
3340
+ // If the node is not active, we want to set the new node type with the given attributes
3341
+ // Copying over the attributes from the current node if the selection is pointing to a node of the same type
3342
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
3321
3343
  };
3322
3344
 
3323
3345
  const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
@@ -3651,7 +3673,8 @@
3651
3673
  appendTransaction: (transactions, oldState, newState) => {
3652
3674
  const docChanges = transactions.some(transaction => transaction.docChanged)
3653
3675
  && !oldState.doc.eq(newState.doc);
3654
- if (!docChanges) {
3676
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3677
+ if (!docChanges || ignoreTr) {
3655
3678
  return;
3656
3679
  }
3657
3680
  const { empty, from, to } = oldState.selection;
@@ -3661,7 +3684,7 @@
3661
3684
  if (empty || !allWasSelected) {
3662
3685
  return;
3663
3686
  }
3664
- const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
3687
+ const isEmpty = isNodeEmpty(newState.doc);
3665
3688
  if (!isEmpty) {
3666
3689
  return;
3667
3690
  }
@@ -3885,6 +3908,28 @@
3885
3908
  }
3886
3909
  }
3887
3910
 
3911
+ const DropPlugin = (onDrop) => {
3912
+ return new state.Plugin({
3913
+ key: new state.PluginKey('tiptapDrop'),
3914
+ props: {
3915
+ handleDrop: (_, e, slice, moved) => {
3916
+ onDrop(e, slice, moved);
3917
+ },
3918
+ },
3919
+ });
3920
+ };
3921
+
3922
+ const PastePlugin = (onPaste) => {
3923
+ return new state.Plugin({
3924
+ key: new state.PluginKey('tiptapPaste'),
3925
+ props: {
3926
+ handlePaste: (_view, e, slice) => {
3927
+ onPaste(e, slice);
3928
+ },
3929
+ },
3930
+ });
3931
+ };
3932
+
3888
3933
  const style = `.ProseMirror {
3889
3934
  position: relative;
3890
3935
  }
@@ -4009,6 +4054,8 @@ img.ProseMirror-separator {
4009
4054
  onBlur: () => null,
4010
4055
  onDestroy: () => null,
4011
4056
  onContentError: ({ error }) => { throw error; },
4057
+ onPaste: () => null,
4058
+ onDrop: () => null,
4012
4059
  };
4013
4060
  this.isCapturingTransaction = false;
4014
4061
  this.capturedTransaction = null;
@@ -4028,6 +4075,12 @@ img.ProseMirror-separator {
4028
4075
  this.on('focus', this.options.onFocus);
4029
4076
  this.on('blur', this.options.onBlur);
4030
4077
  this.on('destroy', this.options.onDestroy);
4078
+ if (this.options.onPaste) {
4079
+ this.registerPlugin(PastePlugin(this.options.onPaste));
4080
+ }
4081
+ if (this.options.onDrop) {
4082
+ this.registerPlugin(DropPlugin(this.options.onDrop));
4083
+ }
4031
4084
  window.setTimeout(() => {
4032
4085
  if (this.isDestroyed) {
4033
4086
  return;
@@ -4155,7 +4208,12 @@ img.ProseMirror-separator {
4155
4208
  FocusEvents,
4156
4209
  Keymap,
4157
4210
  Tabindex,
4158
- ] : [];
4211
+ ].filter(ext => {
4212
+ if (typeof this.options.enableCoreExtensions === 'object') {
4213
+ return this.options.enableCoreExtensions[ext.name] !== false;
4214
+ }
4215
+ return true;
4216
+ }) : [];
4159
4217
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4160
4218
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4161
4219
  });
@@ -4764,6 +4822,9 @@ img.ProseMirror-separator {
4764
4822
  this.extension = props.extension;
4765
4823
  this.node = props.node;
4766
4824
  this.decorations = props.decorations;
4825
+ this.innerDecorations = props.innerDecorations;
4826
+ this.view = props.view;
4827
+ this.HTMLAttributes = props.HTMLAttributes;
4767
4828
  this.getPos = props.getPos;
4768
4829
  this.mount();
4769
4830
  }
@@ -4802,9 +4863,13 @@ img.ProseMirror-separator {
4802
4863
  y = handleBox.y - domBox.y + offsetY;
4803
4864
  }
4804
4865
  (_g = event.dataTransfer) === null || _g === void 0 ? void 0 : _g.setDragImage(this.dom, x, y);
4866
+ const pos = this.getPos();
4867
+ if (typeof pos !== 'number') {
4868
+ return;
4869
+ }
4805
4870
  // we need to tell ProseMirror that we want to move the whole node
4806
4871
  // so we create a NodeSelection
4807
- const selection = state.NodeSelection.create(view.state.doc, this.getPos());
4872
+ const selection = state.NodeSelection.create(view.state.doc, pos);
4808
4873
  const transaction = view.state.tr.setSelection(selection);
4809
4874
  view.dispatch(transaction);
4810
4875
  }
@@ -4875,6 +4940,11 @@ img.ProseMirror-separator {
4875
4940
  }
4876
4941
  return true;
4877
4942
  }
4943
+ /**
4944
+ * Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
4945
+ * @return `false` if the editor should re-read the selection or re-parse the range around the mutation
4946
+ * @return `true` if it can safely be ignored.
4947
+ */
4878
4948
  ignoreMutation(mutation) {
4879
4949
  if (!this.dom || !this.contentDOM) {
4880
4950
  return true;
@@ -4921,9 +4991,15 @@ img.ProseMirror-separator {
4921
4991
  }
4922
4992
  return true;
4923
4993
  }
4994
+ /**
4995
+ * Update the attributes of the prosemirror node.
4996
+ */
4924
4997
  updateAttributes(attributes) {
4925
4998
  this.editor.commands.command(({ tr }) => {
4926
4999
  const pos = this.getPos();
5000
+ if (typeof pos !== 'number') {
5001
+ return false;
5002
+ }
4927
5003
  tr.setNodeMarkup(pos, undefined, {
4928
5004
  ...this.node.attrs,
4929
5005
  ...attributes,
@@ -4931,8 +5007,14 @@ img.ProseMirror-separator {
4931
5007
  return true;
4932
5008
  });
4933
5009
  }
5010
+ /**
5011
+ * Delete the node.
5012
+ */
4934
5013
  deleteNode() {
4935
5014
  const from = this.getPos();
5015
+ if (typeof from !== 'number') {
5016
+ return;
5017
+ }
4936
5018
  const to = from + this.node.nodeSize;
4937
5019
  this.editor.commands.deleteRange({ from, to });
4938
5020
  }
@@ -5068,6 +5150,7 @@ img.ProseMirror-separator {
5068
5150
  }
5069
5151
 
5070
5152
  exports.CommandManager = CommandManager;
5153
+ exports.DropPlugin = DropPlugin;
5071
5154
  exports.Editor = Editor;
5072
5155
  exports.Extension = Extension;
5073
5156
  exports.InputRule = InputRule;
@@ -5075,6 +5158,7 @@ img.ProseMirror-separator {
5075
5158
  exports.Node = Node;
5076
5159
  exports.NodePos = NodePos;
5077
5160
  exports.NodeView = NodeView;
5161
+ exports.PastePlugin = PastePlugin;
5078
5162
  exports.PasteRule = PasteRule;
5079
5163
  exports.Tracker = Tracker;
5080
5164
  exports.callOrReturn = callOrReturn;