@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 +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.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
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
871
|
-
|
|
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
|
-
|
|
1767
|
+
newContent = value.map(v => v.text || '').join('');
|
|
1709
1768
|
}
|
|
1710
1769
|
else if (typeof value === 'object' && !!value && !!value.text) {
|
|
1711
|
-
|
|
1770
|
+
newContent = value.text;
|
|
1712
1771
|
}
|
|
1713
1772
|
else {
|
|
1714
|
-
|
|
1773
|
+
newContent = value;
|
|
1715
1774
|
}
|
|
1775
|
+
tr.insertText(newContent, from, to);
|
|
1716
1776
|
}
|
|
1717
1777
|
else {
|
|
1718
|
-
|
|
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
|
|
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 +
|
|
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 (
|
|
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
|
-
|
|
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 =
|
|
4718
|
+
exports.extensions = index;
|
|
4641
4719
|
exports.findChildren = findChildren;
|
|
4642
4720
|
exports.findChildrenInRange = findChildrenInRange;
|
|
4643
4721
|
exports.findDuplicates = findDuplicates;
|