@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.cjs CHANGED
@@ -321,7 +321,18 @@ function mergeAttributes(...objects) {
321
321
  mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
322
322
  }
323
323
  else if (key === 'style') {
324
- mergedAttributes[key] = [mergedAttributes[key], value].join('; ');
324
+ const newStyles = value ? value.split(';').map((style) => style.trim()).filter(Boolean) : [];
325
+ const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(';').map((style) => style.trim()).filter(Boolean) : [];
326
+ const styleMap = new Map();
327
+ existingStyles.forEach(style => {
328
+ const [property, val] = style.split(':').map(part => part.trim());
329
+ styleMap.set(property, val);
330
+ });
331
+ newStyles.forEach(style => {
332
+ const [property, val] = style.split(':').map(part => part.trim());
333
+ styleMap.set(property, val);
334
+ });
335
+ mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join('; ');
325
336
  }
326
337
  else {
327
338
  mergedAttributes[key] = value;
@@ -715,16 +726,6 @@ function inputRulesPlugin(props) {
715
726
  },
716
727
  },
717
728
  props: {
718
- handleTextInput(view, from, to, text) {
719
- return run$1({
720
- editor,
721
- from,
722
- to,
723
- text,
724
- rules,
725
- plugin,
726
- });
727
- },
728
729
  handleDOMEvents: {
729
730
  compositionend: view => {
730
731
  setTimeout(() => {
@@ -742,6 +743,19 @@ function inputRulesPlugin(props) {
742
743
  });
743
744
  return false;
744
745
  },
746
+ keyup(view, event) {
747
+ if (event.key.length === 1) {
748
+ return run$1({
749
+ editor,
750
+ from: view.state.selection.from,
751
+ to: view.state.selection.from,
752
+ text: '',
753
+ rules,
754
+ plugin,
755
+ });
756
+ }
757
+ return false;
758
+ },
745
759
  },
746
760
  // add support for input rules to trigger on enter
747
761
  // this is useful for example for code blocks
@@ -1152,15 +1166,19 @@ class ExtensionManager {
1152
1166
  if (!addNodeView) {
1153
1167
  return [];
1154
1168
  }
1155
- const nodeview = (node, view, getPos, decorations) => {
1169
+ const nodeview = (node, view, getPos, decorations, innerDecorations) => {
1156
1170
  const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
1157
1171
  return addNodeView()({
1158
- editor,
1172
+ // pass-through
1159
1173
  node,
1160
- getPos,
1174
+ view,
1175
+ getPos: getPos,
1161
1176
  decorations,
1162
- HTMLAttributes,
1177
+ innerDecorations,
1178
+ // tiptap-specific
1179
+ editor,
1163
1180
  extension,
1181
+ HTMLAttributes,
1164
1182
  });
1165
1183
  };
1166
1184
  return [extension.name, nodeview];
@@ -3318,10 +3336,17 @@ const toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state,
3318
3336
  const type = getNodeType(typeOrName, state.schema);
3319
3337
  const toggleType = getNodeType(toggleTypeOrName, state.schema);
3320
3338
  const isActive = isNodeActive(state, type, attributes);
3339
+ let attributesToCopy;
3340
+ if (state.selection.$anchor.sameParent(state.selection.$head)) {
3341
+ // only copy attributes if the selection is pointing to a node of the same type
3342
+ attributesToCopy = state.selection.$anchor.parent.attrs;
3343
+ }
3321
3344
  if (isActive) {
3322
- return commands.setNode(toggleType);
3345
+ return commands.setNode(toggleType, attributesToCopy);
3323
3346
  }
3324
- return commands.setNode(type, attributes);
3347
+ // If the node is not active, we want to set the new node type with the given attributes
3348
+ // Copying over the attributes from the current node if the selection is pointing to a node of the same type
3349
+ return commands.setNode(type, { ...attributesToCopy, ...attributes });
3325
3350
  };
3326
3351
 
3327
3352
  const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
@@ -3655,7 +3680,8 @@ const Keymap = Extension.create({
3655
3680
  appendTransaction: (transactions, oldState, newState) => {
3656
3681
  const docChanges = transactions.some(transaction => transaction.docChanged)
3657
3682
  && !oldState.doc.eq(newState.doc);
3658
- if (!docChanges) {
3683
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3684
+ if (!docChanges || ignoreTr) {
3659
3685
  return;
3660
3686
  }
3661
3687
  const { empty, from, to } = oldState.selection;
@@ -3665,7 +3691,7 @@ const Keymap = Extension.create({
3665
3691
  if (empty || !allWasSelected) {
3666
3692
  return;
3667
3693
  }
3668
- const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
3694
+ const isEmpty = isNodeEmpty(newState.doc);
3669
3695
  if (!isEmpty) {
3670
3696
  return;
3671
3697
  }
@@ -3889,6 +3915,28 @@ class NodePos {
3889
3915
  }
3890
3916
  }
3891
3917
 
3918
+ const DropPlugin = (onDrop) => {
3919
+ return new state.Plugin({
3920
+ key: new state.PluginKey('tiptapDrop'),
3921
+ props: {
3922
+ handleDrop: (_, e, slice, moved) => {
3923
+ onDrop(e, slice, moved);
3924
+ },
3925
+ },
3926
+ });
3927
+ };
3928
+
3929
+ const PastePlugin = (onPaste) => {
3930
+ return new state.Plugin({
3931
+ key: new state.PluginKey('tiptapPaste'),
3932
+ props: {
3933
+ handlePaste: (_view, e, slice) => {
3934
+ onPaste(e, slice);
3935
+ },
3936
+ },
3937
+ });
3938
+ };
3939
+
3892
3940
  const style = `.ProseMirror {
3893
3941
  position: relative;
3894
3942
  }
@@ -4013,6 +4061,8 @@ class Editor extends EventEmitter {
4013
4061
  onBlur: () => null,
4014
4062
  onDestroy: () => null,
4015
4063
  onContentError: ({ error }) => { throw error; },
4064
+ onPaste: () => null,
4065
+ onDrop: () => null,
4016
4066
  };
4017
4067
  this.isCapturingTransaction = false;
4018
4068
  this.capturedTransaction = null;
@@ -4032,6 +4082,12 @@ class Editor extends EventEmitter {
4032
4082
  this.on('focus', this.options.onFocus);
4033
4083
  this.on('blur', this.options.onBlur);
4034
4084
  this.on('destroy', this.options.onDestroy);
4085
+ if (this.options.onPaste) {
4086
+ this.registerPlugin(PastePlugin(this.options.onPaste));
4087
+ }
4088
+ if (this.options.onDrop) {
4089
+ this.registerPlugin(DropPlugin(this.options.onDrop));
4090
+ }
4035
4091
  window.setTimeout(() => {
4036
4092
  if (this.isDestroyed) {
4037
4093
  return;
@@ -4159,7 +4215,12 @@ class Editor extends EventEmitter {
4159
4215
  FocusEvents,
4160
4216
  Keymap,
4161
4217
  Tabindex,
4162
- ] : [];
4218
+ ].filter(ext => {
4219
+ if (typeof this.options.enableCoreExtensions === 'object') {
4220
+ return this.options.enableCoreExtensions[ext.name] !== false;
4221
+ }
4222
+ return true;
4223
+ }) : [];
4163
4224
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4164
4225
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4165
4226
  });
@@ -4768,6 +4829,9 @@ class NodeView {
4768
4829
  this.extension = props.extension;
4769
4830
  this.node = props.node;
4770
4831
  this.decorations = props.decorations;
4832
+ this.innerDecorations = props.innerDecorations;
4833
+ this.view = props.view;
4834
+ this.HTMLAttributes = props.HTMLAttributes;
4771
4835
  this.getPos = props.getPos;
4772
4836
  this.mount();
4773
4837
  }
@@ -4806,9 +4870,13 @@ class NodeView {
4806
4870
  y = handleBox.y - domBox.y + offsetY;
4807
4871
  }
4808
4872
  (_g = event.dataTransfer) === null || _g === void 0 ? void 0 : _g.setDragImage(this.dom, x, y);
4873
+ const pos = this.getPos();
4874
+ if (typeof pos !== 'number') {
4875
+ return;
4876
+ }
4809
4877
  // we need to tell ProseMirror that we want to move the whole node
4810
4878
  // so we create a NodeSelection
4811
- const selection = state.NodeSelection.create(view.state.doc, this.getPos());
4879
+ const selection = state.NodeSelection.create(view.state.doc, pos);
4812
4880
  const transaction = view.state.tr.setSelection(selection);
4813
4881
  view.dispatch(transaction);
4814
4882
  }
@@ -4879,6 +4947,11 @@ class NodeView {
4879
4947
  }
4880
4948
  return true;
4881
4949
  }
4950
+ /**
4951
+ * Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
4952
+ * @return `false` if the editor should re-read the selection or re-parse the range around the mutation
4953
+ * @return `true` if it can safely be ignored.
4954
+ */
4882
4955
  ignoreMutation(mutation) {
4883
4956
  if (!this.dom || !this.contentDOM) {
4884
4957
  return true;
@@ -4925,9 +4998,15 @@ class NodeView {
4925
4998
  }
4926
4999
  return true;
4927
5000
  }
5001
+ /**
5002
+ * Update the attributes of the prosemirror node.
5003
+ */
4928
5004
  updateAttributes(attributes) {
4929
5005
  this.editor.commands.command(({ tr }) => {
4930
5006
  const pos = this.getPos();
5007
+ if (typeof pos !== 'number') {
5008
+ return false;
5009
+ }
4931
5010
  tr.setNodeMarkup(pos, undefined, {
4932
5011
  ...this.node.attrs,
4933
5012
  ...attributes,
@@ -4935,8 +5014,14 @@ class NodeView {
4935
5014
  return true;
4936
5015
  });
4937
5016
  }
5017
+ /**
5018
+ * Delete the node.
5019
+ */
4938
5020
  deleteNode() {
4939
5021
  const from = this.getPos();
5022
+ if (typeof from !== 'number') {
5023
+ return;
5024
+ }
4940
5025
  const to = from + this.node.nodeSize;
4941
5026
  this.editor.commands.deleteRange({ from, to });
4942
5027
  }
@@ -5072,6 +5157,7 @@ class Tracker {
5072
5157
  }
5073
5158
 
5074
5159
  exports.CommandManager = CommandManager;
5160
+ exports.DropPlugin = DropPlugin;
5075
5161
  exports.Editor = Editor;
5076
5162
  exports.Extension = Extension;
5077
5163
  exports.InputRule = InputRule;
@@ -5079,6 +5165,7 @@ exports.Mark = Mark;
5079
5165
  exports.Node = Node;
5080
5166
  exports.NodePos = NodePos;
5081
5167
  exports.NodeView = NodeView;
5168
+ exports.PastePlugin = PastePlugin;
5082
5169
  exports.PasteRule = PasteRule;
5083
5170
  exports.Tracker = Tracker;
5084
5171
  exports.callOrReturn = callOrReturn;