@tiptap/core 2.6.6 → 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];
@@ -3314,10 +3332,17 @@
3314
3332
  const type = getNodeType(typeOrName, state.schema);
3315
3333
  const toggleType = getNodeType(toggleTypeOrName, state.schema);
3316
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
+ }
3317
3340
  if (isActive) {
3318
- return commands.setNode(toggleType);
3341
+ return commands.setNode(toggleType, attributesToCopy);
3319
3342
  }
3320
- 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 });
3321
3346
  };
3322
3347
 
3323
3348
  const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
@@ -3651,7 +3676,8 @@
3651
3676
  appendTransaction: (transactions, oldState, newState) => {
3652
3677
  const docChanges = transactions.some(transaction => transaction.docChanged)
3653
3678
  && !oldState.doc.eq(newState.doc);
3654
- if (!docChanges) {
3679
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3680
+ if (!docChanges || ignoreTr) {
3655
3681
  return;
3656
3682
  }
3657
3683
  const { empty, from, to } = oldState.selection;
@@ -3661,7 +3687,7 @@
3661
3687
  if (empty || !allWasSelected) {
3662
3688
  return;
3663
3689
  }
3664
- const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
3690
+ const isEmpty = isNodeEmpty(newState.doc);
3665
3691
  if (!isEmpty) {
3666
3692
  return;
3667
3693
  }
@@ -3885,6 +3911,28 @@
3885
3911
  }
3886
3912
  }
3887
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
+
3888
3936
  const style = `.ProseMirror {
3889
3937
  position: relative;
3890
3938
  }
@@ -4009,6 +4057,8 @@ img.ProseMirror-separator {
4009
4057
  onBlur: () => null,
4010
4058
  onDestroy: () => null,
4011
4059
  onContentError: ({ error }) => { throw error; },
4060
+ onPaste: () => null,
4061
+ onDrop: () => null,
4012
4062
  };
4013
4063
  this.isCapturingTransaction = false;
4014
4064
  this.capturedTransaction = null;
@@ -4028,6 +4078,12 @@ img.ProseMirror-separator {
4028
4078
  this.on('focus', this.options.onFocus);
4029
4079
  this.on('blur', this.options.onBlur);
4030
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
+ }
4031
4087
  window.setTimeout(() => {
4032
4088
  if (this.isDestroyed) {
4033
4089
  return;
@@ -4155,7 +4211,12 @@ img.ProseMirror-separator {
4155
4211
  FocusEvents,
4156
4212
  Keymap,
4157
4213
  Tabindex,
4158
- ] : [];
4214
+ ].filter(ext => {
4215
+ if (typeof this.options.enableCoreExtensions === 'object') {
4216
+ return this.options.enableCoreExtensions[ext.name] !== false;
4217
+ }
4218
+ return true;
4219
+ }) : [];
4159
4220
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4160
4221
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4161
4222
  });
@@ -4764,6 +4825,9 @@ img.ProseMirror-separator {
4764
4825
  this.extension = props.extension;
4765
4826
  this.node = props.node;
4766
4827
  this.decorations = props.decorations;
4828
+ this.innerDecorations = props.innerDecorations;
4829
+ this.view = props.view;
4830
+ this.HTMLAttributes = props.HTMLAttributes;
4767
4831
  this.getPos = props.getPos;
4768
4832
  this.mount();
4769
4833
  }
@@ -4802,9 +4866,13 @@ img.ProseMirror-separator {
4802
4866
  y = handleBox.y - domBox.y + offsetY;
4803
4867
  }
4804
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
+ }
4805
4873
  // we need to tell ProseMirror that we want to move the whole node
4806
4874
  // so we create a NodeSelection
4807
- const selection = state.NodeSelection.create(view.state.doc, this.getPos());
4875
+ const selection = state.NodeSelection.create(view.state.doc, pos);
4808
4876
  const transaction = view.state.tr.setSelection(selection);
4809
4877
  view.dispatch(transaction);
4810
4878
  }
@@ -4875,6 +4943,11 @@ img.ProseMirror-separator {
4875
4943
  }
4876
4944
  return true;
4877
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
+ */
4878
4951
  ignoreMutation(mutation) {
4879
4952
  if (!this.dom || !this.contentDOM) {
4880
4953
  return true;
@@ -4921,9 +4994,15 @@ img.ProseMirror-separator {
4921
4994
  }
4922
4995
  return true;
4923
4996
  }
4997
+ /**
4998
+ * Update the attributes of the prosemirror node.
4999
+ */
4924
5000
  updateAttributes(attributes) {
4925
5001
  this.editor.commands.command(({ tr }) => {
4926
5002
  const pos = this.getPos();
5003
+ if (typeof pos !== 'number') {
5004
+ return false;
5005
+ }
4927
5006
  tr.setNodeMarkup(pos, undefined, {
4928
5007
  ...this.node.attrs,
4929
5008
  ...attributes,
@@ -4931,8 +5010,14 @@ img.ProseMirror-separator {
4931
5010
  return true;
4932
5011
  });
4933
5012
  }
5013
+ /**
5014
+ * Delete the node.
5015
+ */
4934
5016
  deleteNode() {
4935
5017
  const from = this.getPos();
5018
+ if (typeof from !== 'number') {
5019
+ return;
5020
+ }
4936
5021
  const to = from + this.node.nodeSize;
4937
5022
  this.editor.commands.deleteRange({ from, to });
4938
5023
  }
@@ -5068,6 +5153,7 @@ img.ProseMirror-separator {
5068
5153
  }
5069
5154
 
5070
5155
  exports.CommandManager = CommandManager;
5156
+ exports.DropPlugin = DropPlugin;
5071
5157
  exports.Editor = Editor;
5072
5158
  exports.Extension = Extension;
5073
5159
  exports.InputRule = InputRule;
@@ -5075,6 +5161,7 @@ img.ProseMirror-separator {
5075
5161
  exports.Node = Node;
5076
5162
  exports.NodePos = NodePos;
5077
5163
  exports.NodeView = NodeView;
5164
+ exports.PastePlugin = PastePlugin;
5078
5165
  exports.PasteRule = PasteRule;
5079
5166
  exports.Tracker = Tracker;
5080
5167
  exports.callOrReturn = callOrReturn;