@tiptap/core 2.6.6 → 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 +108 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +107 -22
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +108 -21
- 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/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.umd.js
CHANGED
|
@@ -317,7 +317,18 @@
|
|
|
317
317
|
mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
|
|
318
318
|
}
|
|
319
319
|
else if (key === 'style') {
|
|
320
|
-
|
|
320
|
+
const newStyles = value ? value.split(';').map((style) => style.trim()).filter(Boolean) : [];
|
|
321
|
+
const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(';').map((style) => style.trim()).filter(Boolean) : [];
|
|
322
|
+
const styleMap = new Map();
|
|
323
|
+
existingStyles.forEach(style => {
|
|
324
|
+
const [property, val] = style.split(':').map(part => part.trim());
|
|
325
|
+
styleMap.set(property, val);
|
|
326
|
+
});
|
|
327
|
+
newStyles.forEach(style => {
|
|
328
|
+
const [property, val] = style.split(':').map(part => part.trim());
|
|
329
|
+
styleMap.set(property, val);
|
|
330
|
+
});
|
|
331
|
+
mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join('; ');
|
|
321
332
|
}
|
|
322
333
|
else {
|
|
323
334
|
mergedAttributes[key] = value;
|
|
@@ -711,16 +722,6 @@
|
|
|
711
722
|
},
|
|
712
723
|
},
|
|
713
724
|
props: {
|
|
714
|
-
handleTextInput(view, from, to, text) {
|
|
715
|
-
return run$1({
|
|
716
|
-
editor,
|
|
717
|
-
from,
|
|
718
|
-
to,
|
|
719
|
-
text,
|
|
720
|
-
rules,
|
|
721
|
-
plugin,
|
|
722
|
-
});
|
|
723
|
-
},
|
|
724
725
|
handleDOMEvents: {
|
|
725
726
|
compositionend: view => {
|
|
726
727
|
setTimeout(() => {
|
|
@@ -738,6 +739,19 @@
|
|
|
738
739
|
});
|
|
739
740
|
return false;
|
|
740
741
|
},
|
|
742
|
+
keyup(view, event) {
|
|
743
|
+
if (event.key.length === 1) {
|
|
744
|
+
return run$1({
|
|
745
|
+
editor,
|
|
746
|
+
from: view.state.selection.from,
|
|
747
|
+
to: view.state.selection.from,
|
|
748
|
+
text: '',
|
|
749
|
+
rules,
|
|
750
|
+
plugin,
|
|
751
|
+
});
|
|
752
|
+
}
|
|
753
|
+
return false;
|
|
754
|
+
},
|
|
741
755
|
},
|
|
742
756
|
// add support for input rules to trigger on enter
|
|
743
757
|
// this is useful for example for code blocks
|
|
@@ -1148,15 +1162,19 @@
|
|
|
1148
1162
|
if (!addNodeView) {
|
|
1149
1163
|
return [];
|
|
1150
1164
|
}
|
|
1151
|
-
const nodeview = (node, view, getPos, decorations) => {
|
|
1165
|
+
const nodeview = (node, view, getPos, decorations, innerDecorations) => {
|
|
1152
1166
|
const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
|
|
1153
1167
|
return addNodeView()({
|
|
1154
|
-
|
|
1168
|
+
// pass-through
|
|
1155
1169
|
node,
|
|
1156
|
-
|
|
1170
|
+
view,
|
|
1171
|
+
getPos: getPos,
|
|
1157
1172
|
decorations,
|
|
1158
|
-
|
|
1173
|
+
innerDecorations,
|
|
1174
|
+
// tiptap-specific
|
|
1175
|
+
editor,
|
|
1159
1176
|
extension,
|
|
1177
|
+
HTMLAttributes,
|
|
1160
1178
|
});
|
|
1161
1179
|
};
|
|
1162
1180
|
return [extension.name, nodeview];
|
|
@@ -3314,10 +3332,17 @@
|
|
|
3314
3332
|
const type = getNodeType(typeOrName, state.schema);
|
|
3315
3333
|
const toggleType = getNodeType(toggleTypeOrName, state.schema);
|
|
3316
3334
|
const isActive = isNodeActive(state, type, attributes);
|
|
3335
|
+
let attributesToCopy;
|
|
3336
|
+
if (state.selection.$anchor.sameParent(state.selection.$head)) {
|
|
3337
|
+
// only copy attributes if the selection is pointing to a node of the same type
|
|
3338
|
+
attributesToCopy = state.selection.$anchor.parent.attrs;
|
|
3339
|
+
}
|
|
3317
3340
|
if (isActive) {
|
|
3318
|
-
return commands.setNode(toggleType);
|
|
3341
|
+
return commands.setNode(toggleType, attributesToCopy);
|
|
3319
3342
|
}
|
|
3320
|
-
|
|
3343
|
+
// If the node is not active, we want to set the new node type with the given attributes
|
|
3344
|
+
// Copying over the attributes from the current node if the selection is pointing to a node of the same type
|
|
3345
|
+
return commands.setNode(type, { ...attributesToCopy, ...attributes });
|
|
3321
3346
|
};
|
|
3322
3347
|
|
|
3323
3348
|
const toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
|
|
@@ -3651,7 +3676,8 @@
|
|
|
3651
3676
|
appendTransaction: (transactions, oldState, newState) => {
|
|
3652
3677
|
const docChanges = transactions.some(transaction => transaction.docChanged)
|
|
3653
3678
|
&& !oldState.doc.eq(newState.doc);
|
|
3654
|
-
|
|
3679
|
+
const ignoreTr = transactions.some(transaction => transaction.getMeta('preventClearDocument'));
|
|
3680
|
+
if (!docChanges || ignoreTr) {
|
|
3655
3681
|
return;
|
|
3656
3682
|
}
|
|
3657
3683
|
const { empty, from, to } = oldState.selection;
|
|
@@ -3661,7 +3687,7 @@
|
|
|
3661
3687
|
if (empty || !allWasSelected) {
|
|
3662
3688
|
return;
|
|
3663
3689
|
}
|
|
3664
|
-
const isEmpty =
|
|
3690
|
+
const isEmpty = isNodeEmpty(newState.doc);
|
|
3665
3691
|
if (!isEmpty) {
|
|
3666
3692
|
return;
|
|
3667
3693
|
}
|
|
@@ -3885,6 +3911,28 @@
|
|
|
3885
3911
|
}
|
|
3886
3912
|
}
|
|
3887
3913
|
|
|
3914
|
+
const DropPlugin = (onDrop) => {
|
|
3915
|
+
return new state.Plugin({
|
|
3916
|
+
key: new state.PluginKey('tiptapDrop'),
|
|
3917
|
+
props: {
|
|
3918
|
+
handleDrop: (_, e, slice, moved) => {
|
|
3919
|
+
onDrop(e, slice, moved);
|
|
3920
|
+
},
|
|
3921
|
+
},
|
|
3922
|
+
});
|
|
3923
|
+
};
|
|
3924
|
+
|
|
3925
|
+
const PastePlugin = (onPaste) => {
|
|
3926
|
+
return new state.Plugin({
|
|
3927
|
+
key: new state.PluginKey('tiptapPaste'),
|
|
3928
|
+
props: {
|
|
3929
|
+
handlePaste: (_view, e, slice) => {
|
|
3930
|
+
onPaste(e, slice);
|
|
3931
|
+
},
|
|
3932
|
+
},
|
|
3933
|
+
});
|
|
3934
|
+
};
|
|
3935
|
+
|
|
3888
3936
|
const style = `.ProseMirror {
|
|
3889
3937
|
position: relative;
|
|
3890
3938
|
}
|
|
@@ -4009,6 +4057,8 @@ img.ProseMirror-separator {
|
|
|
4009
4057
|
onBlur: () => null,
|
|
4010
4058
|
onDestroy: () => null,
|
|
4011
4059
|
onContentError: ({ error }) => { throw error; },
|
|
4060
|
+
onPaste: () => null,
|
|
4061
|
+
onDrop: () => null,
|
|
4012
4062
|
};
|
|
4013
4063
|
this.isCapturingTransaction = false;
|
|
4014
4064
|
this.capturedTransaction = null;
|
|
@@ -4028,6 +4078,12 @@ img.ProseMirror-separator {
|
|
|
4028
4078
|
this.on('focus', this.options.onFocus);
|
|
4029
4079
|
this.on('blur', this.options.onBlur);
|
|
4030
4080
|
this.on('destroy', this.options.onDestroy);
|
|
4081
|
+
if (this.options.onPaste) {
|
|
4082
|
+
this.registerPlugin(PastePlugin(this.options.onPaste));
|
|
4083
|
+
}
|
|
4084
|
+
if (this.options.onDrop) {
|
|
4085
|
+
this.registerPlugin(DropPlugin(this.options.onDrop));
|
|
4086
|
+
}
|
|
4031
4087
|
window.setTimeout(() => {
|
|
4032
4088
|
if (this.isDestroyed) {
|
|
4033
4089
|
return;
|
|
@@ -4155,7 +4211,12 @@ img.ProseMirror-separator {
|
|
|
4155
4211
|
FocusEvents,
|
|
4156
4212
|
Keymap,
|
|
4157
4213
|
Tabindex,
|
|
4158
|
-
]
|
|
4214
|
+
].filter(ext => {
|
|
4215
|
+
if (typeof this.options.enableCoreExtensions === 'object') {
|
|
4216
|
+
return this.options.enableCoreExtensions[ext.name] !== false;
|
|
4217
|
+
}
|
|
4218
|
+
return true;
|
|
4219
|
+
}) : [];
|
|
4159
4220
|
const allExtensions = [...coreExtensions, ...this.options.extensions].filter(extension => {
|
|
4160
4221
|
return ['extension', 'node', 'mark'].includes(extension === null || extension === void 0 ? void 0 : extension.type);
|
|
4161
4222
|
});
|
|
@@ -4764,6 +4825,9 @@ img.ProseMirror-separator {
|
|
|
4764
4825
|
this.extension = props.extension;
|
|
4765
4826
|
this.node = props.node;
|
|
4766
4827
|
this.decorations = props.decorations;
|
|
4828
|
+
this.innerDecorations = props.innerDecorations;
|
|
4829
|
+
this.view = props.view;
|
|
4830
|
+
this.HTMLAttributes = props.HTMLAttributes;
|
|
4767
4831
|
this.getPos = props.getPos;
|
|
4768
4832
|
this.mount();
|
|
4769
4833
|
}
|
|
@@ -4802,9 +4866,13 @@ img.ProseMirror-separator {
|
|
|
4802
4866
|
y = handleBox.y - domBox.y + offsetY;
|
|
4803
4867
|
}
|
|
4804
4868
|
(_g = event.dataTransfer) === null || _g === void 0 ? void 0 : _g.setDragImage(this.dom, x, y);
|
|
4869
|
+
const pos = this.getPos();
|
|
4870
|
+
if (typeof pos !== 'number') {
|
|
4871
|
+
return;
|
|
4872
|
+
}
|
|
4805
4873
|
// we need to tell ProseMirror that we want to move the whole node
|
|
4806
4874
|
// so we create a NodeSelection
|
|
4807
|
-
const selection = state.NodeSelection.create(view.state.doc,
|
|
4875
|
+
const selection = state.NodeSelection.create(view.state.doc, pos);
|
|
4808
4876
|
const transaction = view.state.tr.setSelection(selection);
|
|
4809
4877
|
view.dispatch(transaction);
|
|
4810
4878
|
}
|
|
@@ -4875,6 +4943,11 @@ img.ProseMirror-separator {
|
|
|
4875
4943
|
}
|
|
4876
4944
|
return true;
|
|
4877
4945
|
}
|
|
4946
|
+
/**
|
|
4947
|
+
* Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
|
|
4948
|
+
* @return `false` if the editor should re-read the selection or re-parse the range around the mutation
|
|
4949
|
+
* @return `true` if it can safely be ignored.
|
|
4950
|
+
*/
|
|
4878
4951
|
ignoreMutation(mutation) {
|
|
4879
4952
|
if (!this.dom || !this.contentDOM) {
|
|
4880
4953
|
return true;
|
|
@@ -4921,9 +4994,15 @@ img.ProseMirror-separator {
|
|
|
4921
4994
|
}
|
|
4922
4995
|
return true;
|
|
4923
4996
|
}
|
|
4997
|
+
/**
|
|
4998
|
+
* Update the attributes of the prosemirror node.
|
|
4999
|
+
*/
|
|
4924
5000
|
updateAttributes(attributes) {
|
|
4925
5001
|
this.editor.commands.command(({ tr }) => {
|
|
4926
5002
|
const pos = this.getPos();
|
|
5003
|
+
if (typeof pos !== 'number') {
|
|
5004
|
+
return false;
|
|
5005
|
+
}
|
|
4927
5006
|
tr.setNodeMarkup(pos, undefined, {
|
|
4928
5007
|
...this.node.attrs,
|
|
4929
5008
|
...attributes,
|
|
@@ -4931,8 +5010,14 @@ img.ProseMirror-separator {
|
|
|
4931
5010
|
return true;
|
|
4932
5011
|
});
|
|
4933
5012
|
}
|
|
5013
|
+
/**
|
|
5014
|
+
* Delete the node.
|
|
5015
|
+
*/
|
|
4934
5016
|
deleteNode() {
|
|
4935
5017
|
const from = this.getPos();
|
|
5018
|
+
if (typeof from !== 'number') {
|
|
5019
|
+
return;
|
|
5020
|
+
}
|
|
4936
5021
|
const to = from + this.node.nodeSize;
|
|
4937
5022
|
this.editor.commands.deleteRange({ from, to });
|
|
4938
5023
|
}
|
|
@@ -5068,6 +5153,7 @@ img.ProseMirror-separator {
|
|
|
5068
5153
|
}
|
|
5069
5154
|
|
|
5070
5155
|
exports.CommandManager = CommandManager;
|
|
5156
|
+
exports.DropPlugin = DropPlugin;
|
|
5071
5157
|
exports.Editor = Editor;
|
|
5072
5158
|
exports.Extension = Extension;
|
|
5073
5159
|
exports.InputRule = InputRule;
|
|
@@ -5075,6 +5161,7 @@ img.ProseMirror-separator {
|
|
|
5075
5161
|
exports.Node = Node;
|
|
5076
5162
|
exports.NodePos = NodePos;
|
|
5077
5163
|
exports.NodeView = NodeView;
|
|
5164
|
+
exports.PastePlugin = PastePlugin;
|
|
5078
5165
|
exports.PasteRule = PasteRule;
|
|
5079
5166
|
exports.Tracker = Tracker;
|
|
5080
5167
|
exports.callOrReturn = callOrReturn;
|