@tiptap/core 2.2.5 → 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 +114 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +114 -34
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +114 -34
- 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/extensions/keymap.ts +1 -1
- package/src/helpers/getTextBetween.ts +5 -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
|
});
|
|
@@ -1214,8 +1262,10 @@
|
|
|
1214
1262
|
range,
|
|
1215
1263
|
});
|
|
1216
1264
|
}
|
|
1265
|
+
// do not descend into child nodes when there exists a serializer
|
|
1266
|
+
return false;
|
|
1217
1267
|
}
|
|
1218
|
-
|
|
1268
|
+
if (node.isText) {
|
|
1219
1269
|
text += (_a = node === null || node === void 0 ? void 0 : node.text) === null || _a === void 0 ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos); // eslint-disable-line
|
|
1220
1270
|
separated = false;
|
|
1221
1271
|
}
|
|
@@ -1235,6 +1285,11 @@
|
|
|
1235
1285
|
|
|
1236
1286
|
const ClipboardTextSerializer = Extension.create({
|
|
1237
1287
|
name: 'clipboardTextSerializer',
|
|
1288
|
+
addOptions() {
|
|
1289
|
+
return {
|
|
1290
|
+
blockSeparator: undefined,
|
|
1291
|
+
};
|
|
1292
|
+
},
|
|
1238
1293
|
addProseMirrorPlugins() {
|
|
1239
1294
|
return [
|
|
1240
1295
|
new state.Plugin({
|
|
@@ -1250,6 +1305,9 @@
|
|
|
1250
1305
|
const textSerializers = getTextSerializersFromSchema(schema);
|
|
1251
1306
|
const range = { from, to };
|
|
1252
1307
|
return getTextBetween(doc, range, {
|
|
1308
|
+
...(this.options.blockSeparator !== undefined
|
|
1309
|
+
? { blockSeparator: this.options.blockSeparator }
|
|
1310
|
+
: {}),
|
|
1253
1311
|
textSerializers,
|
|
1254
1312
|
});
|
|
1255
1313
|
},
|
|
@@ -1656,6 +1714,8 @@
|
|
|
1656
1714
|
options = {
|
|
1657
1715
|
parseOptions: {},
|
|
1658
1716
|
updateSelection: true,
|
|
1717
|
+
applyInputRules: false,
|
|
1718
|
+
applyPasteRules: false,
|
|
1659
1719
|
...options,
|
|
1660
1720
|
};
|
|
1661
1721
|
const content = createNodeFromContent(value, editor.schema, {
|
|
@@ -1691,28 +1751,37 @@
|
|
|
1691
1751
|
to += 1;
|
|
1692
1752
|
}
|
|
1693
1753
|
}
|
|
1754
|
+
let newContent;
|
|
1694
1755
|
// if there is only plain text we have to use `insertText`
|
|
1695
1756
|
// because this will keep the current marks
|
|
1696
1757
|
if (isOnlyTextContent) {
|
|
1697
1758
|
// if value is string, we can use it directly
|
|
1698
1759
|
// otherwise if it is an array, we have to join it
|
|
1699
1760
|
if (Array.isArray(value)) {
|
|
1700
|
-
|
|
1761
|
+
newContent = value.map(v => v.text || '').join('');
|
|
1701
1762
|
}
|
|
1702
1763
|
else if (typeof value === 'object' && !!value && !!value.text) {
|
|
1703
|
-
|
|
1764
|
+
newContent = value.text;
|
|
1704
1765
|
}
|
|
1705
1766
|
else {
|
|
1706
|
-
|
|
1767
|
+
newContent = value;
|
|
1707
1768
|
}
|
|
1769
|
+
tr.insertText(newContent, from, to);
|
|
1708
1770
|
}
|
|
1709
1771
|
else {
|
|
1710
|
-
|
|
1772
|
+
newContent = content;
|
|
1773
|
+
tr.replaceWith(from, to, newContent);
|
|
1711
1774
|
}
|
|
1712
1775
|
// set cursor at end of inserted content
|
|
1713
1776
|
if (options.updateSelection) {
|
|
1714
1777
|
selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
|
|
1715
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
|
+
}
|
|
1716
1785
|
}
|
|
1717
1786
|
return true;
|
|
1718
1787
|
};
|
|
@@ -3207,7 +3276,7 @@
|
|
|
3207
3276
|
const { selection, doc } = tr;
|
|
3208
3277
|
const { empty, $anchor } = selection;
|
|
3209
3278
|
const { pos, parent } = $anchor;
|
|
3210
|
-
const $parentPos = $anchor.parent.isTextblock ? tr.doc.resolve(pos - 1) : $anchor;
|
|
3279
|
+
const $parentPos = $anchor.parent.isTextblock && pos > 0 ? tr.doc.resolve(pos - 1) : $anchor;
|
|
3211
3280
|
const parentIsIsolating = $parentPos.parent.type.spec.isolating;
|
|
3212
3281
|
const parentPos = $anchor.pos - $anchor.parentOffset;
|
|
3213
3282
|
const isAtStart = (parentIsIsolating && $parentPos.parent.childCount === 1)
|
|
@@ -3323,7 +3392,7 @@
|
|
|
3323
3392
|
},
|
|
3324
3393
|
});
|
|
3325
3394
|
|
|
3326
|
-
var
|
|
3395
|
+
var index = /*#__PURE__*/Object.freeze({
|
|
3327
3396
|
__proto__: null,
|
|
3328
3397
|
ClipboardTextSerializer: ClipboardTextSerializer,
|
|
3329
3398
|
Commands: Commands,
|
|
@@ -3427,7 +3496,7 @@
|
|
|
3427
3496
|
const children = [];
|
|
3428
3497
|
this.node.content.forEach((node, offset) => {
|
|
3429
3498
|
const isBlock = node.isBlock && !node.isTextblock;
|
|
3430
|
-
const targetPos = this.pos + offset +
|
|
3499
|
+
const targetPos = this.pos + offset + 1;
|
|
3431
3500
|
const $pos = this.resolvedPos.doc.resolve(targetPos);
|
|
3432
3501
|
if (!isBlock && $pos.depth <= this.depth) {
|
|
3433
3502
|
return;
|
|
@@ -3476,7 +3545,7 @@
|
|
|
3476
3545
|
querySelectorAll(selector, attributes = {}, firstItemOnly = false) {
|
|
3477
3546
|
let nodes = [];
|
|
3478
3547
|
// iterate through children recursively finding all nodes which match the selector with the node name
|
|
3479
|
-
if (
|
|
3548
|
+
if (!this.children || this.children.length === 0) {
|
|
3480
3549
|
return nodes;
|
|
3481
3550
|
}
|
|
3482
3551
|
this.children.forEach(childPos => {
|
|
@@ -3613,6 +3682,7 @@ img.ProseMirror-separator {
|
|
|
3613
3682
|
editable: true,
|
|
3614
3683
|
editorProps: {},
|
|
3615
3684
|
parseOptions: {},
|
|
3685
|
+
coreExtensionOptions: {},
|
|
3616
3686
|
enableInputRules: true,
|
|
3617
3687
|
enablePasteRules: true,
|
|
3618
3688
|
enableCoreExtensions: true,
|
|
@@ -3758,7 +3828,17 @@ img.ProseMirror-separator {
|
|
|
3758
3828
|
* Creates an extension manager.
|
|
3759
3829
|
*/
|
|
3760
3830
|
createExtensionManager() {
|
|
3761
|
-
|
|
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
|
+
] : [];
|
|
3762
3842
|
const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
|
|
3763
3843
|
return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
|
|
3764
3844
|
});
|
|
@@ -4629,7 +4709,7 @@ img.ProseMirror-separator {
|
|
|
4629
4709
|
exports.deleteProps = deleteProps;
|
|
4630
4710
|
exports.elementFromString = elementFromString;
|
|
4631
4711
|
exports.escapeForRegEx = escapeForRegEx;
|
|
4632
|
-
exports.extensions =
|
|
4712
|
+
exports.extensions = index;
|
|
4633
4713
|
exports.findChildren = findChildren;
|
|
4634
4714
|
exports.findChildrenInRange = findChildrenInRange;
|
|
4635
4715
|
exports.findDuplicates = findDuplicates;
|