@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.js CHANGED
@@ -661,6 +661,23 @@ function inputRulesPlugin(props) {
661
661
  if (stored) {
662
662
  return stored;
663
663
  }
664
+ // if InputRule is triggered by insertContent()
665
+ const simulatedInputMeta = tr.getMeta('applyInputRules');
666
+ const isSimulatedInput = !!simulatedInputMeta;
667
+ if (isSimulatedInput) {
668
+ setTimeout(() => {
669
+ const { from, text } = simulatedInputMeta;
670
+ const to = from + text.length;
671
+ run$1({
672
+ editor,
673
+ from,
674
+ to,
675
+ text,
676
+ rules,
677
+ plugin,
678
+ });
679
+ });
680
+ }
664
681
  return tr.selectionSet || tr.docChanged ? null : prev;
665
682
  },
666
683
  },
@@ -792,6 +809,14 @@ function run(config) {
792
809
  const success = handlers.every(handler => handler !== null);
793
810
  return success;
794
811
  }
812
+ const createClipboardPasteEvent = (text) => {
813
+ var _a;
814
+ const event = new ClipboardEvent('paste', {
815
+ clipboardData: new DataTransfer(),
816
+ });
817
+ (_a = event.clipboardData) === null || _a === void 0 ? void 0 : _a.setData('text/html', text);
818
+ return event;
819
+ };
795
820
  /**
796
821
  * Create an paste rules plugin. When enabled, it will cause pasted
797
822
  * text that matches any of the given rules to trigger the rule’s
@@ -804,6 +829,28 @@ function pasteRulesPlugin(props) {
804
829
  let isDroppedFromProseMirror = false;
805
830
  let pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
806
831
  let dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
832
+ const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
833
+ const tr = state.tr;
834
+ const chainableState = createChainableState({
835
+ state,
836
+ transaction: tr,
837
+ });
838
+ const handler = run({
839
+ editor,
840
+ state: chainableState,
841
+ from: Math.max(from - 1, 0),
842
+ to: to.b - 1,
843
+ rule,
844
+ pasteEvent: pasteEvt,
845
+ dropEvent,
846
+ });
847
+ if (!handler || !tr.steps.length) {
848
+ return;
849
+ }
850
+ dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
851
+ pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
852
+ return tr;
853
+ };
807
854
  const plugins = rules.map(rule => {
808
855
  return new Plugin({
809
856
  // we register a global drag handler to track the current drag source element
@@ -841,38 +888,39 @@ function pasteRulesPlugin(props) {
841
888
  const transaction = transactions[0];
842
889
  const isPaste = transaction.getMeta('uiEvent') === 'paste' && !isPastedFromProseMirror;
843
890
  const isDrop = transaction.getMeta('uiEvent') === 'drop' && !isDroppedFromProseMirror;
844
- if (!isPaste && !isDrop) {
891
+ // if PasteRule is triggered by insertContent()
892
+ const simulatedPasteMeta = transaction.getMeta('applyPasteRules');
893
+ const isSimulatedPaste = !!simulatedPasteMeta;
894
+ if (!isPaste && !isDrop && !isSimulatedPaste) {
845
895
  return;
846
896
  }
847
- // stop if there is no changed range
897
+ // Handle simulated paste
898
+ if (isSimulatedPaste) {
899
+ const { from, text } = simulatedPasteMeta;
900
+ const to = from + text.length;
901
+ const pasteEvt = createClipboardPasteEvent(text);
902
+ return processEvent({
903
+ rule,
904
+ state,
905
+ from,
906
+ to: { b: to },
907
+ pasteEvt,
908
+ });
909
+ }
910
+ // handle actual paste/drop
848
911
  const from = oldState.doc.content.findDiffStart(state.doc.content);
849
912
  const to = oldState.doc.content.findDiffEnd(state.doc.content);
913
+ // stop if there is no changed range
850
914
  if (!isNumber(from) || !to || from === to.b) {
851
915
  return;
852
916
  }
853
- // build a chainable state
854
- // so we can use a single transaction for all paste rules
855
- const tr = state.tr;
856
- const chainableState = createChainableState({
857
- state,
858
- transaction: tr,
859
- });
860
- const handler = run({
861
- editor,
862
- state: chainableState,
863
- from: Math.max(from - 1, 0),
864
- to: to.b - 1,
917
+ return processEvent({
865
918
  rule,
866
- pasteEvent,
867
- dropEvent,
919
+ state,
920
+ from,
921
+ to,
922
+ pasteEvt: pasteEvent,
868
923
  });
869
- // stop if there are no changes
870
- if (!handler || !tr.steps.length) {
871
- return;
872
- }
873
- dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
874
- pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
875
- return tr;
876
924
  },
877
925
  });
878
926
  });
@@ -1239,6 +1287,11 @@ function getTextSerializersFromSchema(schema) {
1239
1287
 
1240
1288
  const ClipboardTextSerializer = Extension.create({
1241
1289
  name: 'clipboardTextSerializer',
1290
+ addOptions() {
1291
+ return {
1292
+ blockSeparator: undefined,
1293
+ };
1294
+ },
1242
1295
  addProseMirrorPlugins() {
1243
1296
  return [
1244
1297
  new Plugin({
@@ -1254,6 +1307,9 @@ const ClipboardTextSerializer = Extension.create({
1254
1307
  const textSerializers = getTextSerializersFromSchema(schema);
1255
1308
  const range = { from, to };
1256
1309
  return getTextBetween(doc, range, {
1310
+ ...(this.options.blockSeparator !== undefined
1311
+ ? { blockSeparator: this.options.blockSeparator }
1312
+ : {}),
1257
1313
  textSerializers,
1258
1314
  });
1259
1315
  },
@@ -1660,6 +1716,8 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1660
1716
  options = {
1661
1717
  parseOptions: {},
1662
1718
  updateSelection: true,
1719
+ applyInputRules: false,
1720
+ applyPasteRules: false,
1663
1721
  ...options,
1664
1722
  };
1665
1723
  const content = createNodeFromContent(value, editor.schema, {
@@ -1695,28 +1753,37 @@ const insertContentAt = (position, value, options) => ({ tr, dispatch, editor })
1695
1753
  to += 1;
1696
1754
  }
1697
1755
  }
1756
+ let newContent;
1698
1757
  // if there is only plain text we have to use `insertText`
1699
1758
  // because this will keep the current marks
1700
1759
  if (isOnlyTextContent) {
1701
1760
  // if value is string, we can use it directly
1702
1761
  // otherwise if it is an array, we have to join it
1703
1762
  if (Array.isArray(value)) {
1704
- tr.insertText(value.map(v => v.text || '').join(''), from, to);
1763
+ newContent = value.map(v => v.text || '').join('');
1705
1764
  }
1706
1765
  else if (typeof value === 'object' && !!value && !!value.text) {
1707
- tr.insertText(value.text, from, to);
1766
+ newContent = value.text;
1708
1767
  }
1709
1768
  else {
1710
- tr.insertText(value, from, to);
1769
+ newContent = value;
1711
1770
  }
1771
+ tr.insertText(newContent, from, to);
1712
1772
  }
1713
1773
  else {
1714
- tr.replaceWith(from, to, content);
1774
+ newContent = content;
1775
+ tr.replaceWith(from, to, newContent);
1715
1776
  }
1716
1777
  // set cursor at end of inserted content
1717
1778
  if (options.updateSelection) {
1718
1779
  selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
1719
1780
  }
1781
+ if (options.applyInputRules) {
1782
+ tr.setMeta('applyInputRules', { from, text: newContent });
1783
+ }
1784
+ if (options.applyPasteRules) {
1785
+ tr.setMeta('applyPasteRules', { from, text: newContent });
1786
+ }
1720
1787
  }
1721
1788
  return true;
1722
1789
  };
@@ -3327,7 +3394,7 @@ const Tabindex = Extension.create({
3327
3394
  },
3328
3395
  });
3329
3396
 
3330
- var extensions = /*#__PURE__*/Object.freeze({
3397
+ var index = /*#__PURE__*/Object.freeze({
3331
3398
  __proto__: null,
3332
3399
  ClipboardTextSerializer: ClipboardTextSerializer,
3333
3400
  Commands: Commands,
@@ -3431,7 +3498,7 @@ class NodePos {
3431
3498
  const children = [];
3432
3499
  this.node.content.forEach((node, offset) => {
3433
3500
  const isBlock = node.isBlock && !node.isTextblock;
3434
- const targetPos = this.pos + offset + (isBlock ? 0 : 1);
3501
+ const targetPos = this.pos + offset + 1;
3435
3502
  const $pos = this.resolvedPos.doc.resolve(targetPos);
3436
3503
  if (!isBlock && $pos.depth <= this.depth) {
3437
3504
  return;
@@ -3480,7 +3547,7 @@ class NodePos {
3480
3547
  querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
3481
3548
  let nodes = [];
3482
3549
  // iterate through children recursively finding all nodes which match the selector with the node name
3483
- if (this.isBlock || !this.children || this.children.length === 0) {
3550
+ if (!this.children || this.children.length === 0) {
3484
3551
  return nodes;
3485
3552
  }
3486
3553
  this.children.forEach(childPos => {
@@ -3617,6 +3684,7 @@ class Editor extends EventEmitter {
3617
3684
  editable: true,
3618
3685
  editorProps: {},
3619
3686
  parseOptions: {},
3687
+ coreExtensionOptions: {},
3620
3688
  enableInputRules: true,
3621
3689
  enablePasteRules: true,
3622
3690
  enableCoreExtensions: true,
@@ -3762,7 +3830,17 @@ class Editor extends EventEmitter {
3762
3830
  * Creates an extension manager.
3763
3831
  */
3764
3832
  createExtensionManager() {
3765
- const coreExtensions = this.options.enableCoreExtensions ? Object.values(extensions) : [];
3833
+ var _a, _b;
3834
+ const coreExtensions = this.options.enableCoreExtensions ? [
3835
+ Editable,
3836
+ ClipboardTextSerializer.configure({
3837
+ blockSeparator: (_b = (_a = this.options.coreExtensionOptions) === null || _a === void 0 ? void 0 : _a.clipboardTextSerializer) === null || _b === void 0 ? void 0 : _b.blockSeparator,
3838
+ }),
3839
+ Commands,
3840
+ FocusEvents,
3841
+ Keymap,
3842
+ Tabindex,
3843
+ ] : [];
3766
3844
  const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
3767
3845
  return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
3768
3846
  });
@@ -4613,5 +4691,5 @@ class Tracker {
4613
4691
  }
4614
4692
  }
4615
4693
 
4616
- export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4694
+ export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, index as extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
4617
4695
  //# sourceMappingURL=index.js.map