@tiptap/core 2.2.6 → 2.3.1

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
@@ -665,6 +665,23 @@ function inputRulesPlugin(props) {
665
665
  if (stored) {
666
666
  return stored;
667
667
  }
668
+ // if InputRule is triggered by insertContent()
669
+ const simulatedInputMeta = tr.getMeta('applyInputRules');
670
+ const isSimulatedInput = !!simulatedInputMeta;
671
+ if (isSimulatedInput) {
672
+ setTimeout(() => {
673
+ const { from, text } = simulatedInputMeta;
674
+ const to = from + text.length;
675
+ run$1({
676
+ editor,
677
+ from,
678
+ to,
679
+ text,
680
+ rules,
681
+ plugin,
682
+ });
683
+ });
684
+ }
668
685
  return tr.selectionSet || tr.docChanged ? null : prev;
669
686
  },
670
687
  },
@@ -796,6 +813,14 @@ function run(config) {
796
813
  const success = handlers.every(handler => handler !== null);
797
814
  return success;
798
815
  }
816
+ const createClipboardPasteEvent = (text) => {
817
+ var _a;
818
+ const event = new ClipboardEvent('paste', {
819
+ clipboardData: new DataTransfer(),
820
+ });
821
+ (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.setData('text/html', text);
822
+ return event;
823
+ };
799
824
  /**
800
825
  * Create an paste rules plugin. When enabled, it will cause pasted
801
826
  * text that matches any of the given rules to trigger the rule’s
@@ -808,6 +833,28 @@ function pasteRulesPlugin(props) {
808
833
  let isDroppedFromProseMirror = false;
809
834
  let pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
810
835
  let dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
836
+ const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
837
+ const tr = state.tr;
838
+ const chainableState = createChainableState({
839
+ state,
840
+ transaction: tr,
841
+ });
842
+ const handler = run({
843
+ editor,
844
+ state: chainableState,
845
+ from: Math.max(from - 1, 0),
846
+ to: to.b - 1,
847
+ rule,
848
+ pasteEvent: pasteEvt,
849
+ dropEvent,
850
+ });
851
+ if (!handler || !tr.steps.length) {
852
+ return;
853
+ }
854
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
855
+ pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
856
+ return tr;
857
+ };
811
858
  const plugins = rules.map(rule => {
812
859
  return new state.Plugin({
813
860
  // we register a global drag handler to track the current drag source element
@@ -845,38 +892,39 @@ function pasteRulesPlugin(props) {
845
892
  const transaction = transactions[0];
846
893
  const isPaste = transaction.getMeta('uiEvent') === 'paste' && !isPastedFromProseMirror;
847
894
  const isDrop = transaction.getMeta('uiEvent') === 'drop' && !isDroppedFromProseMirror;
848
- if (!isPaste && !isDrop) {
895
+ // if PasteRule is triggered by insertContent()
896
+ const simulatedPasteMeta = transaction.getMeta('applyPasteRules');
897
+ const isSimulatedPaste = !!simulatedPasteMeta;
898
+ if (!isPaste && !isDrop && !isSimulatedPaste) {
849
899
  return;
850
900
  }
851
- // stop if there is no changed range
901
+ // Handle simulated paste
902
+ if (isSimulatedPaste) {
903
+ const { from, text } = simulatedPasteMeta;
904
+ const to = from + text.length;
905
+ const pasteEvt = createClipboardPasteEvent(text);
906
+ return processEvent({
907
+ rule,
908
+ state,
909
+ from,
910
+ to: { b: to },
911
+ pasteEvt,
912
+ });
913
+ }
914
+ // handle actual paste/drop
852
915
  const from = oldState.doc.content.findDiffStart(state.doc.content);
853
916
  const to = oldState.doc.content.findDiffEnd(state.doc.content);
917
+ // stop if there is no changed range
854
918
  if (!isNumber(from) || !to || from === to.b) {
855
919
  return;
856
920
  }
857
- // build a chainable state
858
- // so we can use a single transaction for all paste rules
859
- const tr = state.tr;
860
- const chainableState = createChainableState({
861
- state,
862
- transaction: tr,
863
- });
864
- const handler = run({
865
- editor,
866
- state: chainableState,
867
- from: Math.max(from - 1, 0),
868
- to: to.b - 1,
921
+ return processEvent({
869
922
  rule,
870
- pasteEvent,
871
- dropEvent,
923
+ state,
924
+ from,
925
+ to,
926
+ pasteEvt: pasteEvent,
872
927
  });
873
- // stop if there are no changes
874
- if (!handler || !tr.steps.length) {
875
- return;
876
- }
877
- dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
878
- pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
879
- return tr;
880
928
  },
881
929
  });
882
930
  });
@@ -1243,6 +1291,11 @@ function getTextSerializersFromSchema(schema) {
1243
1291
 
1244
1292
  const ClipboardTextSerializer = Extension.create({
1245
1293
  name: 'clipboardTextSerializer',
1294
+ addOptions() {
1295
+ return {
1296
+ blockSeparator: undefined,
1297
+ };
1298
+ },
1246
1299
  addProseMirrorPlugins() {
1247
1300
  return [
1248
1301
  new state.Plugin({
@@ -1258,6 +1311,9 @@ const ClipboardTextSerializer = Extension.create({
1258
1311
  const textSerializers = getTextSerializersFromSchema(schema);
1259
1312
  const range = { from, to };
1260
1313
  return getTextBetween(doc, range, {
1314
+ ...(this.options.blockSeparator !== undefined
1315
+ ? { blockSeparator: this.options.blockSeparator }
1316
+ : {}),
1261
1317
  textSerializers,
1262
1318
  });
1263
1319
  },
@@ -1664,6 +1720,8 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1664
1720
  options = {
1665
1721
  parseOptions: {},
1666
1722
  updateSelection: true,
1723
+ applyInputRules: false,
1724
+ applyPasteRules: false,
1667
1725
  ...options,
1668
1726
  };
1669
1727
  const content = createNodeFromContent(value, editor.schema, {
@@ -1699,28 +1757,37 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1699
1757
  to += 1;
1700
1758
  }
1701
1759
  }
1760
+ let newContent;
1702
1761
  // if there is only plain text we have to use `insertText`
1703
1762
  // because this will keep the current marks
1704
1763
  if (isOnlyTextContent) {
1705
1764
  // if value is string, we can use it directly
1706
1765
  // otherwise if it is an array, we have to join it
1707
1766
  if (Array.isArray(value)) {
1708
- tr.insertText(value.map(v => v.text || '').join(''), from, to);
1767
+ newContent = value.map(v => v.text || '').join('');
1709
1768
  }
1710
1769
  else if (typeof value === 'object' && !!value && !!value.text) {
1711
- tr.insertText(value.text, from, to);
1770
+ newContent = value.text;
1712
1771
  }
1713
1772
  else {
1714
- tr.insertText(value, from, to);
1773
+ newContent = value;
1715
1774
  }
1775
+ tr.insertText(newContent, from, to);
1716
1776
  }
1717
1777
  else {
1718
- tr.replaceWith(from, to, content);
1778
+ newContent = content;
1779
+ tr.replaceWith(from, to, newContent);
1719
1780
  }
1720
1781
  // set cursor at end of inserted content
1721
1782
  if (options.updateSelection) {
1722
1783
  selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1723
1784
  }
1785
+ if (options.applyInputRules) {
1786
+ tr.setMeta('applyInputRules', { from, text: newContent });
1787
+ }
1788
+ if (options.applyPasteRules) {
1789
+ tr.setMeta('applyPasteRules', { from, text: newContent });
1790
+ }
1724
1791
  }
1725
1792
  return true;
1726
1793
  };
@@ -3331,7 +3398,7 @@ const Tabindex = Extension.create({
3331
3398
  },
3332
3399
  });
3333
3400
 
3334
- var extensions = /*#__PURE__*/Object.freeze({
3401
+ var index = /*#__PURE__*/Object.freeze({
3335
3402
  __proto__: null,
3336
3403
  ClipboardTextSerializer: ClipboardTextSerializer,
3337
3404
  Commands: Commands,
@@ -3435,7 +3502,7 @@ class NodePos {
3435
3502
  const children = [];
3436
3503
  this.node.content.forEach((node, offset) => {
3437
3504
  const isBlock = node.isBlock && !node.isTextblock;
3438
- const targetPos = this.pos + offset + (isBlock ? 0 : 1);
3505
+ const targetPos = this.pos + offset + 1;
3439
3506
  const $pos = this.resolvedPos.doc.resolve(targetPos);
3440
3507
  if (!isBlock && $pos.depth <= this.depth) {
3441
3508
  return;
@@ -3484,7 +3551,7 @@ class NodePos {
3484
3551
  querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
3485
3552
  let nodes = [];
3486
3553
  // iterate through children recursively finding all nodes which match the selector with the node name
3487
- if (this.isBlock || !this.children || this.children.length === 0) {
3554
+ if (!this.children || this.children.length === 0) {
3488
3555
  return nodes;
3489
3556
  }
3490
3557
  this.children.forEach(childPos => {
@@ -3621,6 +3688,7 @@ class Editor extends EventEmitter {
3621
3688
  editable: true,
3622
3689
  editorProps: {},
3623
3690
  parseOptions: {},
3691
+ coreExtensionOptions: {},
3624
3692
  enableInputRules: true,
3625
3693
  enablePasteRules: true,
3626
3694
  enableCoreExtensions: true,
@@ -3766,7 +3834,17 @@ class Editor extends EventEmitter {
3766
3834
  * Creates an extension manager.
3767
3835
  */
3768
3836
  createExtensionManager() {
3769
- const coreExtensions = this.options.enableCoreExtensions ? Object.values(extensions) : [];
3837
+ var _a, _b;
3838
+ const coreExtensions = this.options.enableCoreExtensions ? [
3839
+ Editable,
3840
+ ClipboardTextSerializer.configure({
3841
+ blockSeparator: (_b = (_a = this.options.coreExtensionOptions) === null || _a === void 0 ? void 0 : _a.clipboardTextSerializer) === null || _b === void 0 ? void 0 : _b.blockSeparator,
3842
+ }),
3843
+ Commands,
3844
+ FocusEvents,
3845
+ Keymap,
3846
+ Tabindex,
3847
+ ] : [];
3770
3848
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
3771
3849
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
3772
3850
  });
@@ -4637,7 +4715,7 @@ exports.defaultBlockAt = defaultBlockAt;
4637
4715
  exports.deleteProps = deleteProps;
4638
4716
  exports.elementFromString = elementFromString;
4639
4717
  exports.escapeForRegEx = escapeForRegEx;
4640
- exports.extensions = extensions;
4718
+ exports.extensions = index;
4641
4719
  exports.findChildren = findChildren;
4642
4720
  exports.findChildrenInRange = findChildrenInRange;
4643
4721
  exports.findDuplicates = findDuplicates;