@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.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];
@@ -1768,7 +1786,11 @@ function createNodeFromContent(content, schema, options) {
1768
1786
  if (isArrayContent) {
1769
1787
  return model.Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)));
1770
1788
  }
1771
- return schema.nodeFromJSON(content);
1789
+ const node = schema.nodeFromJSON(content);
1790
+ if (options.errorOnInvalidContent) {
1791
+ node.check();
1792
+ }
1793
+ return node;
1772
1794
  }
1773
1795
  catch (error) {
1774
1796
  if (options.errorOnInvalidContent) {
@@ -3314,10 +3336,17 @@ const toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state,
3314
3336
  const type = getNodeType(typeOrName, state.schema);
3315
3337
  const toggleType = getNodeType(toggleTypeOrName, state.schema);
3316
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
+ }
3317
3344
  if (isActive) {
3318
- return commands.setNode(toggleType);
3345
+ return commands.setNode(toggleType, attributesToCopy);
3319
3346
  }
3320
- 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 });
3321
3350
  };
3322
3351
 
3323
3352
  const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
@@ -3651,7 +3680,8 @@ const Keymap = Extension.create({
3651
3680
  appendTransaction: (transactions, oldState, newState) => {
3652
3681
  const docChanges = transactions.some(transaction => transaction.docChanged)
3653
3682
  && !oldState.doc.eq(newState.doc);
3654
- if (!docChanges) {
3683
+ const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
3684
+ if (!docChanges || ignoreTr) {
3655
3685
  return;
3656
3686
  }
3657
3687
  const { empty, from, to } = oldState.selection;
@@ -3661,7 +3691,7 @@ const Keymap = Extension.create({
3661
3691
  if (empty || !allWasSelected) {
3662
3692
  return;
3663
3693
  }
3664
- const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, ' ', ' ').length === 0;
3694
+ const isEmpty = isNodeEmpty(newState.doc);
3665
3695
  if (!isEmpty) {
3666
3696
  return;
3667
3697
  }
@@ -3885,6 +3915,28 @@ class NodePos {
3885
3915
  }
3886
3916
  }
3887
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
+
3888
3940
  const style = `.ProseMirror {
3889
3941
  position: relative;
3890
3942
  }
@@ -4009,6 +4061,8 @@ class Editor extends EventEmitter {
4009
4061
  onBlur: () => null,
4010
4062
  onDestroy: () => null,
4011
4063
  onContentError: ({ error }) => { throw error; },
4064
+ onPaste: () => null,
4065
+ onDrop: () => null,
4012
4066
  };
4013
4067
  this.isCapturingTransaction = false;
4014
4068
  this.capturedTransaction = null;
@@ -4028,6 +4082,12 @@ class Editor extends EventEmitter {
4028
4082
  this.on('focus', this.options.onFocus);
4029
4083
  this.on('blur', this.options.onBlur);
4030
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
+ }
4031
4091
  window.setTimeout(() => {
4032
4092
  if (this.isDestroyed) {
4033
4093
  return;
@@ -4155,7 +4215,12 @@ class Editor extends EventEmitter {
4155
4215
  FocusEvents,
4156
4216
  Keymap,
4157
4217
  Tabindex,
4158
- ] : [];
4218
+ ].filter(ext => {
4219
+ if (typeof this.options.enableCoreExtensions === 'object') {
4220
+ return this.options.enableCoreExtensions[ext.name] !== false;
4221
+ }
4222
+ return true;
4223
+ }) : [];
4159
4224
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
4160
4225
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
4161
4226
  });
@@ -4764,6 +4829,9 @@ class NodeView {
4764
4829
  this.extension = props.extension;
4765
4830
  this.node = props.node;
4766
4831
  this.decorations = props.decorations;
4832
+ this.innerDecorations = props.innerDecorations;
4833
+ this.view = props.view;
4834
+ this.HTMLAttributes = props.HTMLAttributes;
4767
4835
  this.getPos = props.getPos;
4768
4836
  this.mount();
4769
4837
  }
@@ -4802,9 +4870,13 @@ class NodeView {
4802
4870
  y = handleBox.y - domBox.y + offsetY;
4803
4871
  }
4804
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
+ }
4805
4877
  // we need to tell ProseMirror that we want to move the whole node
4806
4878
  // so we create a NodeSelection
4807
- const selection = state.NodeSelection.create(view.state.doc, this.getPos());
4879
+ const selection = state.NodeSelection.create(view.state.doc, pos);
4808
4880
  const transaction = view.state.tr.setSelection(selection);
4809
4881
  view.dispatch(transaction);
4810
4882
  }
@@ -4875,6 +4947,11 @@ class NodeView {
4875
4947
  }
4876
4948
  return true;
4877
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
+ */
4878
4955
  ignoreMutation(mutation) {
4879
4956
  if (!this.dom || !this.contentDOM) {
4880
4957
  return true;
@@ -4921,9 +4998,15 @@ class NodeView {
4921
4998
  }
4922
4999
  return true;
4923
5000
  }
5001
+ /**
5002
+ * Update the attributes of the prosemirror node.
5003
+ */
4924
5004
  updateAttributes(attributes) {
4925
5005
  this.editor.commands.command(({ tr }) => {
4926
5006
  const pos = this.getPos();
5007
+ if (typeof pos !== 'number') {
5008
+ return false;
5009
+ }
4927
5010
  tr.setNodeMarkup(pos, undefined, {
4928
5011
  ...this.node.attrs,
4929
5012
  ...attributes,
@@ -4931,8 +5014,14 @@ class NodeView {
4931
5014
  return true;
4932
5015
  });
4933
5016
  }
5017
+ /**
5018
+ * Delete the node.
5019
+ */
4934
5020
  deleteNode() {
4935
5021
  const from = this.getPos();
5022
+ if (typeof from !== 'number') {
5023
+ return;
5024
+ }
4936
5025
  const to = from + this.node.nodeSize;
4937
5026
  this.editor.commands.deleteRange({ from, to });
4938
5027
  }
@@ -5068,6 +5157,7 @@ class Tracker {
5068
5157
  }
5069
5158
 
5070
5159
  exports.CommandManager = CommandManager;
5160
+ exports.DropPlugin = DropPlugin;
5071
5161
  exports.Editor = Editor;
5072
5162
  exports.Extension = Extension;
5073
5163
  exports.InputRule = InputRule;
@@ -5075,6 +5165,7 @@ exports.Mark = Mark;
5075
5165
  exports.Node = Node;
5076
5166
  exports.NodePos = NodePos;
5077
5167
  exports.NodeView = NodeView;
5168
+ exports.PastePlugin = PastePlugin;
5078
5169
  exports.PasteRule = PasteRule;
5079
5170
  exports.Tracker = Tracker;
5080
5171
  exports.callOrReturn = callOrReturn;