@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.cjs +110 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +110 -32
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +110 -32
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/Editor.d.ts +1 -2
- package/dist/packages/core/src/commands/insertContent.d.ts +2 -0
- package/dist/packages/core/src/commands/insertContentAt.d.ts +2 -0
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +4 -1
- package/dist/packages/core/src/types.d.ts +5 -0
- package/package.json +2 -2
- package/src/Editor.ts +16 -3
- package/src/InputRule.ts +20 -0
- package/src/NodePos.ts +2 -2
- package/src/PasteRule.ts +76 -27
- package/src/commands/insertContent.ts +2 -0
- package/src/commands/insertContentAt.ts +22 -4
- package/src/extensions/clipboardTextSerializer.ts +14 -1
- package/src/types.ts +5 -0
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
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
865
|
-
|
|
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
|
-
|
|
1761
|
+
newContent = value.map(v => v.text || '').join('');
|
|
1703
1762
|
}
|
|
1704
1763
|
else if (typeof value === 'object' && !!value && !!value.text) {
|
|
1705
|
-
|
|
1764
|
+
newContent = value.text;
|
|
1706
1765
|
}
|
|
1707
1766
|
else {
|
|
1708
|
-
|
|
1767
|
+
newContent = value;
|
|
1709
1768
|
}
|
|
1769
|
+
tr.insertText(newContent, from, to);
|
|
1710
1770
|
}
|
|
1711
1771
|
else {
|
|
1712
|
-
|
|
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
|
|
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 +
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
4712
|
+
exports.extensions = index;
|
|
4635
4713
|
exports.findChildren = findChildren;
|
|
4636
4714
|
exports.findChildrenInRange = findChildrenInRange;
|
|
4637
4715
|
exports.findDuplicates = findDuplicates;
|