@tiptap/core 2.2.6 → 2.3.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
@@ -659,6 +659,23 @@
659
659
  if (stored) {
660
660
  return stored;
661
661
  }
662
+ // if InputRule is triggered by insertContent()
663
+ const simulatedInputMeta = tr.getMeta('applyInputRules');
664
+ const isSimulatedInput = !!simulatedInputMeta;
665
+ if (isSimulatedInput) {
666
+ setTimeout(() => {
667
+ const { from, text } = simulatedInputMeta;
668
+ const to = from + text.length;
669
+ run$1({
670
+ editor,
671
+ from,
672
+ to,
673
+ text,
674
+ rules,
675
+ plugin,
676
+ });
677
+ });
678
+ }
662
679
  return tr.selectionSet || tr.docChanged ? null : prev;
663
680
  },
664
681
  },
@@ -790,6 +807,14 @@
790
807
  const success = handlers.every(handler => handler !== null);
791
808
  return success;
792
809
  }
810
+ const createClipboardPasteEvent = (text) => {
811
+ var _a;
812
+ const event = new ClipboardEvent('paste', {
813
+ clipboardData: new DataTransfer(),
814
+ });
815
+ (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.setData('text/html', text);
816
+ return event;
817
+ };
793
818
  /**
794
819
  * Create an paste rules plugin. When enabled, it will cause pasted
795
820
  * text that matches any of the given rules to trigger the rule’s
@@ -802,6 +827,28 @@
802
827
  let isDroppedFromProseMirror = false;
803
828
  let pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
804
829
  let dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
830
+ const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
831
+ const tr = state.tr;
832
+ const chainableState = createChainableState({
833
+ state,
834
+ transaction: tr,
835
+ });
836
+ const handler = run({
837
+ editor,
838
+ state: chainableState,
839
+ from: Math.max(from - 1, 0),
840
+ to: to.b - 1,
841
+ rule,
842
+ pasteEvent: pasteEvt,
843
+ dropEvent,
844
+ });
845
+ if (!handler || !tr.steps.length) {
846
+ return;
847
+ }
848
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
849
+ pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
850
+ return tr;
851
+ };
805
852
  const plugins = rules.map(rule => {
806
853
  return new state.Plugin({
807
854
  // we register a global drag handler to track the current drag source element
@@ -839,38 +886,39 @@
839
886
  const transaction = transactions[0];
840
887
  const isPaste = transaction.getMeta('uiEvent') === 'paste' && !isPastedFromProseMirror;
841
888
  const isDrop = transaction.getMeta('uiEvent') === 'drop' && !isDroppedFromProseMirror;
842
- if (!isPaste && !isDrop) {
889
+ // if PasteRule is triggered by insertContent()
890
+ const simulatedPasteMeta = transaction.getMeta('applyPasteRules');
891
+ const isSimulatedPaste = !!simulatedPasteMeta;
892
+ if (!isPaste && !isDrop && !isSimulatedPaste) {
843
893
  return;
844
894
  }
845
- // stop if there is no changed range
895
+ // Handle simulated paste
896
+ if (isSimulatedPaste) {
897
+ const { from, text } = simulatedPasteMeta;
898
+ const to = from + text.length;
899
+ const pasteEvt = createClipboardPasteEvent(text);
900
+ return processEvent({
901
+ rule,
902
+ state,
903
+ from,
904
+ to: { b: to },
905
+ pasteEvt,
906
+ });
907
+ }
908
+ // handle actual paste/drop
846
909
  const from = oldState.doc.content.findDiffStart(state.doc.content);
847
910
  const to = oldState.doc.content.findDiffEnd(state.doc.content);
911
+ // stop if there is no changed range
848
912
  if (!isNumber(from) || !to || from === to.b) {
849
913
  return;
850
914
  }
851
- // build a chainable state
852
- // so we can use a single transaction for all paste rules
853
- const tr = state.tr;
854
- const chainableState = createChainableState({
855
- state,
856
- transaction: tr,
857
- });
858
- const handler = run({
859
- editor,
860
- state: chainableState,
861
- from: Math.max(from - 1, 0),
862
- to: to.b - 1,
915
+ return processEvent({
863
916
  rule,
864
- pasteEvent,
865
- dropEvent,
917
+ state,
918
+ from,
919
+ to,
920
+ pasteEvt: pasteEvent,
866
921
  });
867
- // stop if there are no changes
868
- if (!handler || !tr.steps.length) {
869
- return;
870
- }
871
- dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
872
- pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
873
- return tr;
874
922
  },
875
923
  });
876
924
  });
@@ -1237,6 +1285,11 @@
1237
1285
 
1238
1286
  const ClipboardTextSerializer = Extension.create({
1239
1287
  name: 'clipboardTextSerializer',
1288
+ addOptions() {
1289
+ return {
1290
+ blockSeparator: undefined,
1291
+ };
1292
+ },
1240
1293
  addProseMirrorPlugins() {
1241
1294
  return [
1242
1295
  new state.Plugin({
@@ -1252,6 +1305,9 @@
1252
1305
  const textSerializers = getTextSerializersFromSchema(schema);
1253
1306
  const range = { from, to };
1254
1307
  return getTextBetween(doc, range, {
1308
+ ...(this.options.blockSeparator !== undefined
1309
+ ? { blockSeparator: this.options.blockSeparator }
1310
+ : {}),
1255
1311
  textSerializers,
1256
1312
  });
1257
1313
  },
@@ -1658,6 +1714,8 @@
1658
1714
  options = {
1659
1715
  parseOptions: {},
1660
1716
  updateSelection: true,
1717
+ applyInputRules: false,
1718
+ applyPasteRules: false,
1661
1719
  ...options,
1662
1720
  };
1663
1721
  const content = createNodeFromContent(value, editor.schema, {
@@ -1693,28 +1751,37 @@
1693
1751
  to += 1;
1694
1752
  }
1695
1753
  }
1754
+ let newContent;
1696
1755
  // if there is only plain text we have to use `insertText`
1697
1756
  // because this will keep the current marks
1698
1757
  if (isOnlyTextContent) {
1699
1758
  // if value is string, we can use it directly
1700
1759
  // otherwise if it is an array, we have to join it
1701
1760
  if (Array.isArray(value)) {
1702
- tr.insertText(value.map(v => v.text || '').join(''), from, to);
1761
+ newContent = value.map(v => v.text || '').join('');
1703
1762
  }
1704
1763
  else if (typeof value === 'object' && !!value && !!value.text) {
1705
- tr.insertText(value.text, from, to);
1764
+ newContent = value.text;
1706
1765
  }
1707
1766
  else {
1708
- tr.insertText(value, from, to);
1767
+ newContent = value;
1709
1768
  }
1769
+ tr.insertText(newContent, from, to);
1710
1770
  }
1711
1771
  else {
1712
- tr.replaceWith(from, to, content);
1772
+ newContent = content;
1773
+ tr.replaceWith(from, to, newContent);
1713
1774
  }
1714
1775
  // set cursor at end of inserted content
1715
1776
  if (options.updateSelection) {
1716
1777
  selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1717
1778
  }
1779
+ if (options.applyInputRules) {
1780
+ tr.setMeta('applyInputRules', { from, text: newContent });
1781
+ }
1782
+ if (options.applyPasteRules) {
1783
+ tr.setMeta('applyPasteRules', { from, text: newContent });
1784
+ }
1718
1785
  }
1719
1786
  return true;
1720
1787
  };
@@ -3325,7 +3392,7 @@
3325
3392
  },
3326
3393
  });
3327
3394
 
3328
- var extensions = /*#__PURE__*/Object.freeze({
3395
+ var index = /*#__PURE__*/Object.freeze({
3329
3396
  __proto__: null,
3330
3397
  ClipboardTextSerializer: ClipboardTextSerializer,
3331
3398
  Commands: Commands,
@@ -3429,7 +3496,7 @@
3429
3496
  const children = [];
3430
3497
  this.node.content.forEach((node, offset) => {
3431
3498
  const isBlock = node.isBlock && !node.isTextblock;
3432
- const targetPos = this.pos + offset + (isBlock ? 0 : 1);
3499
+ const targetPos = this.pos + offset + 1;
3433
3500
  const $pos = this.resolvedPos.doc.resolve(targetPos);
3434
3501
  if (!isBlock && $pos.depth <= this.depth) {
3435
3502
  return;
@@ -3478,7 +3545,7 @@
3478
3545
  querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
3479
3546
  let nodes = [];
3480
3547
  // iterate through children recursively finding all nodes which match the selector with the node name
3481
- if (this.isBlock || !this.children || this.children.length === 0) {
3548
+ if (!this.children || this.children.length === 0) {
3482
3549
  return nodes;
3483
3550
  }
3484
3551
  this.children.forEach(childPos => {
@@ -3615,6 +3682,7 @@ img.ProseMirror-separator {
3615
3682
  editable: true,
3616
3683
  editorProps: {},
3617
3684
  parseOptions: {},
3685
+ coreExtensionOptions: {},
3618
3686
  enableInputRules: true,
3619
3687
  enablePasteRules: true,
3620
3688
  enableCoreExtensions: true,
@@ -3760,7 +3828,17 @@ img.ProseMirror-separator {
3760
3828
  * Creates an extension manager.
3761
3829
  */
3762
3830
  createExtensionManager() {
3763
- const coreExtensions = this.options.enableCoreExtensions ? Object.values(extensions) : [];
3831
+ var _a, _b;
3832
+ const coreExtensions = this.options.enableCoreExtensions ? [
3833
+ Editable,
3834
+ ClipboardTextSerializer.configure({
3835
+ blockSeparator: (_b = (_a = this.options.coreExtensionOptions) === null || _a === void 0 ? void 0 : _a.clipboardTextSerializer) === null || _b === void 0 ? void 0 : _b.blockSeparator,
3836
+ }),
3837
+ Commands,
3838
+ FocusEvents,
3839
+ Keymap,
3840
+ Tabindex,
3841
+ ] : [];
3764
3842
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
3765
3843
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
3766
3844
  });
@@ -4631,7 +4709,7 @@ img.ProseMirror-separator {
4631
4709
  exports.deleteProps = deleteProps;
4632
4710
  exports.elementFromString = elementFromString;
4633
4711
  exports.escapeForRegEx = escapeForRegEx;
4634
- exports.extensions = extensions;
4712
+ exports.extensions = index;
4635
4713
  exports.findChildren = findChildren;
4636
4714
  exports.findChildrenInRange = findChildrenInRange;
4637
4715
  exports.findDuplicates = findDuplicates;