@tiptap/core 2.6.5 → 2.7.0-pre.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 +113 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +112 -23
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +113 -22
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/NodeView.d.ts +20 -8
- package/dist/packages/core/src/index.d.ts +2 -0
- package/dist/packages/core/src/plugins/DropPlugin.d.ts +3 -0
- package/dist/packages/core/src/plugins/PastePlugin.d.ts +3 -0
- package/dist/packages/core/src/types.d.ts +35 -15
- package/package.json +3 -3
- package/src/Editor.ts +18 -1
- package/src/ExtensionManager.ts +15 -10
- package/src/InputRule.ts +14 -11
- package/src/NodeView.ts +39 -8
- package/src/commands/toggleNode.ts +11 -2
- package/src/extensions/keymap.ts +5 -2
- package/src/helpers/createNodeFromContent.ts +7 -1
- package/src/index.ts +2 -0
- package/src/plugins/DropPlugin.ts +14 -0
- package/src/plugins/PastePlugin.ts +14 -0
- package/src/types.ts +46 -17
- package/src/utilities/mergeAttributes.ts +18 -1
package/dist/index.cjs
CHANGED
|
@@ -321,7 +321,18 @@ function mergeAttributes(...objects) {
|
|
|
321
321
|
mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
|
|
322
322
|
}
|
|
323
323
|
else if (key === 'style') {
|
|
324
|
-
|
|
324
|
+
const newStyles = value ? value.split(';').map((style) => style.trim()).filter(Boolean) : [];
|
|
325
|
+
const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(';').map((style) => style.trim()).filter(Boolean) : [];
|
|
326
|
+
const styleMap = new Map();
|
|
327
|
+
existingStyles.forEach(style => {
|
|
328
|
+
const [property, val] = style.split(':').map(part => part.trim());
|
|
329
|
+
styleMap.set(property, val);
|
|
330
|
+
});
|
|
331
|
+
newStyles.forEach(style => {
|
|
332
|
+
const [property, val] = style.split(':').map(part => part.trim());
|
|
333
|
+
styleMap.set(property, val);
|
|
334
|
+
});
|
|
335
|
+
mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join('; ');
|
|
325
336
|
}
|
|
326
337
|
else {
|
|
327
338
|
mergedAttributes[key] = value;
|
|
@@ -715,16 +726,6 @@ function inputRulesPlugin(props) {
|
|
|
715
726
|
},
|
|
716
727
|
},
|
|
717
728
|
props: {
|
|
718
|
-
handleTextInput(view, from, to, text) {
|
|
719
|
-
return run$1({
|
|
720
|
-
editor,
|
|
721
|
-
from,
|
|
722
|
-
to,
|
|
723
|
-
text,
|
|
724
|
-
rules,
|
|
725
|
-
plugin,
|
|
726
|
-
});
|
|
727
|
-
},
|
|
728
729
|
handleDOMEvents: {
|
|
729
730
|
compositionend: view => {
|
|
730
731
|
setTimeout(() => {
|
|
@@ -742,6 +743,19 @@ function inputRulesPlugin(props) {
|
|
|
742
743
|
});
|
|
743
744
|
return false;
|
|
744
745
|
},
|
|
746
|
+
keyup(view, event) {
|
|
747
|
+
if (event.key.length === 1) {
|
|
748
|
+
return run$1({
|
|
749
|
+
editor,
|
|
750
|
+
from: view.state.selection.from,
|
|
751
|
+
to: view.state.selection.from,
|
|
752
|
+
text: '',
|
|
753
|
+
rules,
|
|
754
|
+
plugin,
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
return false;
|
|
758
|
+
},
|
|
745
759
|
},
|
|
746
760
|
// add support for input rules to trigger on enter
|
|
747
761
|
// this is useful for example for code blocks
|
|
@@ -1152,15 +1166,19 @@ class ExtensionManager {
|
|
|
1152
1166
|
if (!addNodeView) {
|
|
1153
1167
|
return [];
|
|
1154
1168
|
}
|
|
1155
|
-
const nodeview = (node, view, getPos, decorations) => {
|
|
1169
|
+
const nodeview = (node, view, getPos, decorations, innerDecorations) => {
|
|
1156
1170
|
const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
|
|
1157
1171
|
return addNodeView()({
|
|
1158
|
-
|
|
1172
|
+
// pass-through
|
|
1159
1173
|
node,
|
|
1160
|
-
|
|
1174
|
+
view,
|
|
1175
|
+
getPos: getPos,
|
|
1161
1176
|
decorations,
|
|
1162
|
-
|
|
1177
|
+
innerDecorations,
|
|
1178
|
+
// tiptap-specific
|
|
1179
|
+
editor,
|
|
1163
1180
|
extension,
|
|
1181
|
+
HTMLAttributes,
|
|
1164
1182
|
});
|
|
1165
1183
|
};
|
|
1166
1184
|
return [extension.name, nodeview];
|
|
@@ -1768,7 +1786,11 @@ function createNodeFromContent(content, schema, options) {
|
|
|
1768
1786
|
if (isArrayContent) {
|
|
1769
1787
|
return model.Fragment.fromArray(content.map(item => schema.nodeFromJSON(item)));
|
|
1770
1788
|
}
|
|
1771
|
-
|
|
1789
|
+
const node = schema.nodeFromJSON(content);
|
|
1790
|
+
if (options.errorOnInvalidContent) {
|
|
1791
|
+
node.check();
|
|
1792
|
+
}
|
|
1793
|
+
return node;
|
|
1772
1794
|
}
|
|
1773
1795
|
catch (error) {
|
|
1774
1796
|
if (options.errorOnInvalidContent) {
|
|
@@ -3314,10 +3336,17 @@ const toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state,
|
|
|
3314
3336
|
const type = getNodeType(typeOrName, state.schema);
|
|
3315
3337
|
const toggleType = getNodeType(toggleTypeOrName, state.schema);
|
|
3316
3338
|
const isActive = isNodeActive(state, type, attributes);
|
|
3339
|
+
let attributesToCopy;
|
|
3340
|
+
if (state.selection.$anchor.sameParent(state.selection.$head)) {
|
|
3341
|
+
// only copy attributes if the selection is pointing to a node of the same type
|
|
3342
|
+
attributesToCopy = state.selection.$anchor.parent.attrs;
|
|
3343
|
+
}
|
|
3317
3344
|
if (isActive) {
|
|
3318
|
-
return commands.setNode(toggleType);
|
|
3345
|
+
return commands.setNode(toggleType, attributesToCopy);
|
|
3319
3346
|
}
|
|
3320
|
-
|
|
3347
|
+
// If the node is not active, we want to set the new node type with the given attributes
|
|
3348
|
+
// Copying over the attributes from the current node if the selection is pointing to a node of the same type
|
|
3349
|
+
return commands.setNode(type, { ...attributesToCopy, ...attributes });
|
|
3321
3350
|
};
|
|
3322
3351
|
|
|
3323
3352
|
const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
|
|
@@ -3651,7 +3680,8 @@ const Keymap = Extension.create({
|
|
|
3651
3680
|
appendTransaction: (transactions, oldState, newState) => {
|
|
3652
3681
|
const docChanges = transactions.some(transaction => transaction.docChanged)
|
|
3653
3682
|
&& !oldState.doc.eq(newState.doc);
|
|
3654
|
-
|
|
3683
|
+
const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
|
|
3684
|
+
if (!docChanges || ignoreTr) {
|
|
3655
3685
|
return;
|
|
3656
3686
|
}
|
|
3657
3687
|
const { empty, from, to } = oldState.selection;
|
|
@@ -3661,7 +3691,7 @@ const Keymap = Extension.create({
|
|
|
3661
3691
|
if (empty || !allWasSelected) {
|
|
3662
3692
|
return;
|
|
3663
3693
|
}
|
|
3664
|
-
const isEmpty =
|
|
3694
|
+
const isEmpty = isNodeEmpty(newState.doc);
|
|
3665
3695
|
if (!isEmpty) {
|
|
3666
3696
|
return;
|
|
3667
3697
|
}
|
|
@@ -3885,6 +3915,28 @@ class NodePos {
|
|
|
3885
3915
|
}
|
|
3886
3916
|
}
|
|
3887
3917
|
|
|
3918
|
+
const DropPlugin = (onDrop) => {
|
|
3919
|
+
return new state.Plugin({
|
|
3920
|
+
key: new state.PluginKey('tiptapDrop'),
|
|
3921
|
+
props: {
|
|
3922
|
+
handleDrop: (_, e, slice, moved) => {
|
|
3923
|
+
onDrop(e, slice, moved);
|
|
3924
|
+
},
|
|
3925
|
+
},
|
|
3926
|
+
});
|
|
3927
|
+
};
|
|
3928
|
+
|
|
3929
|
+
const PastePlugin = (onPaste) => {
|
|
3930
|
+
return new state.Plugin({
|
|
3931
|
+
key: new state.PluginKey('tiptapPaste'),
|
|
3932
|
+
props: {
|
|
3933
|
+
handlePaste: (_view, e, slice) => {
|
|
3934
|
+
onPaste(e, slice);
|
|
3935
|
+
},
|
|
3936
|
+
},
|
|
3937
|
+
});
|
|
3938
|
+
};
|
|
3939
|
+
|
|
3888
3940
|
const style = `.ProseMirror {
|
|
3889
3941
|
position: relative;
|
|
3890
3942
|
}
|
|
@@ -4009,6 +4061,8 @@ class Editor extends EventEmitter {
|
|
|
4009
4061
|
onBlur: () => null,
|
|
4010
4062
|
onDestroy: () => null,
|
|
4011
4063
|
onContentError: ({ error }) => { throw error; },
|
|
4064
|
+
onPaste: () => null,
|
|
4065
|
+
onDrop: () => null,
|
|
4012
4066
|
};
|
|
4013
4067
|
this.isCapturingTransaction = false;
|
|
4014
4068
|
this.capturedTransaction = null;
|
|
@@ -4028,6 +4082,12 @@ class Editor extends EventEmitter {
|
|
|
4028
4082
|
this.on('focus', this.options.onFocus);
|
|
4029
4083
|
this.on('blur', this.options.onBlur);
|
|
4030
4084
|
this.on('destroy', this.options.onDestroy);
|
|
4085
|
+
if (this.options.onPaste) {
|
|
4086
|
+
this.registerPlugin(PastePlugin(this.options.onPaste));
|
|
4087
|
+
}
|
|
4088
|
+
if (this.options.onDrop) {
|
|
4089
|
+
this.registerPlugin(DropPlugin(this.options.onDrop));
|
|
4090
|
+
}
|
|
4031
4091
|
window.setTimeout(() => {
|
|
4032
4092
|
if (this.isDestroyed) {
|
|
4033
4093
|
return;
|
|
@@ -4155,7 +4215,12 @@ class Editor extends EventEmitter {
|
|
|
4155
4215
|
FocusEvents,
|
|
4156
4216
|
Keymap,
|
|
4157
4217
|
Tabindex,
|
|
4158
|
-
]
|
|
4218
|
+
].filter(ext => {
|
|
4219
|
+
if (typeof this.options.enableCoreExtensions === 'object') {
|
|
4220
|
+
return this.options.enableCoreExtensions[ext.name] !== false;
|
|
4221
|
+
}
|
|
4222
|
+
return true;
|
|
4223
|
+
}) : [];
|
|
4159
4224
|
const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
|
|
4160
4225
|
return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
|
|
4161
4226
|
});
|
|
@@ -4764,6 +4829,9 @@ class NodeView {
|
|
|
4764
4829
|
this.extension = props.extension;
|
|
4765
4830
|
this.node = props.node;
|
|
4766
4831
|
this.decorations = props.decorations;
|
|
4832
|
+
this.innerDecorations = props.innerDecorations;
|
|
4833
|
+
this.view = props.view;
|
|
4834
|
+
this.HTMLAttributes = props.HTMLAttributes;
|
|
4767
4835
|
this.getPos = props.getPos;
|
|
4768
4836
|
this.mount();
|
|
4769
4837
|
}
|
|
@@ -4802,9 +4870,13 @@ class NodeView {
|
|
|
4802
4870
|
y = handleBox.y - domBox.y + offsetY;
|
|
4803
4871
|
}
|
|
4804
4872
|
(_g = event.dataTransfer) === null || _g === void 0 ? void 0 : _g.setDragImage(this.dom, x, y);
|
|
4873
|
+
const pos = this.getPos();
|
|
4874
|
+
if (typeof pos !== 'number') {
|
|
4875
|
+
return;
|
|
4876
|
+
}
|
|
4805
4877
|
// we need to tell ProseMirror that we want to move the whole node
|
|
4806
4878
|
// so we create a NodeSelection
|
|
4807
|
-
const selection = state.NodeSelection.create(view.state.doc,
|
|
4879
|
+
const selection = state.NodeSelection.create(view.state.doc, pos);
|
|
4808
4880
|
const transaction = view.state.tr.setSelection(selection);
|
|
4809
4881
|
view.dispatch(transaction);
|
|
4810
4882
|
}
|
|
@@ -4875,6 +4947,11 @@ class NodeView {
|
|
|
4875
4947
|
}
|
|
4876
4948
|
return true;
|
|
4877
4949
|
}
|
|
4950
|
+
/**
|
|
4951
|
+
* Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
|
|
4952
|
+
* @return `false` if the editor should re-read the selection or re-parse the range around the mutation
|
|
4953
|
+
* @return `true` if it can safely be ignored.
|
|
4954
|
+
*/
|
|
4878
4955
|
ignoreMutation(mutation) {
|
|
4879
4956
|
if (!this.dom || !this.contentDOM) {
|
|
4880
4957
|
return true;
|
|
@@ -4921,9 +4998,15 @@ class NodeView {
|
|
|
4921
4998
|
}
|
|
4922
4999
|
return true;
|
|
4923
5000
|
}
|
|
5001
|
+
/**
|
|
5002
|
+
* Update the attributes of the prosemirror node.
|
|
5003
|
+
*/
|
|
4924
5004
|
updateAttributes(attributes) {
|
|
4925
5005
|
this.editor.commands.command(({ tr }) => {
|
|
4926
5006
|
const pos = this.getPos();
|
|
5007
|
+
if (typeof pos !== 'number') {
|
|
5008
|
+
return false;
|
|
5009
|
+
}
|
|
4927
5010
|
tr.setNodeMarkup(pos, undefined, {
|
|
4928
5011
|
...this.node.attrs,
|
|
4929
5012
|
...attributes,
|
|
@@ -4931,8 +5014,14 @@ class NodeView {
|
|
|
4931
5014
|
return true;
|
|
4932
5015
|
});
|
|
4933
5016
|
}
|
|
5017
|
+
/**
|
|
5018
|
+
* Delete the node.
|
|
5019
|
+
*/
|
|
4934
5020
|
deleteNode() {
|
|
4935
5021
|
const from = this.getPos();
|
|
5022
|
+
if (typeof from !== 'number') {
|
|
5023
|
+
return;
|
|
5024
|
+
}
|
|
4936
5025
|
const to = from + this.node.nodeSize;
|
|
4937
5026
|
this.editor.commands.deleteRange({ from, to });
|
|
4938
5027
|
}
|
|
@@ -5068,6 +5157,7 @@ class Tracker {
|
|
|
5068
5157
|
}
|
|
5069
5158
|
|
|
5070
5159
|
exports.CommandManager = CommandManager;
|
|
5160
|
+
exports.DropPlugin = DropPlugin;
|
|
5071
5161
|
exports.Editor = Editor;
|
|
5072
5162
|
exports.Extension = Extension;
|
|
5073
5163
|
exports.InputRule = InputRule;
|
|
@@ -5075,6 +5165,7 @@ exports.Mark = Mark;
|
|
|
5075
5165
|
exports.Node = Node;
|
|
5076
5166
|
exports.NodePos = NodePos;
|
|
5077
5167
|
exports.NodeView = NodeView;
|
|
5168
|
+
exports.PastePlugin = PastePlugin;
|
|
5078
5169
|
exports.PasteRule = PasteRule;
|
|
5079
5170
|
exports.Tracker = Tracker;
|
|
5080
5171
|
exports.callOrReturn = callOrReturn;
|