@tiptap/core 2.10.4 → 2.11.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/Editor.d.ts +1 -1
- package/dist/Editor.d.ts.map +1 -1
- package/dist/EventEmitter.d.ts.map +1 -1
- package/dist/Mark.d.ts.map +1 -1
- package/dist/Node.d.ts.map +1 -1
- package/dist/PasteRule.d.ts.map +1 -1
- package/dist/commands/focus.d.ts.map +1 -1
- package/dist/commands/selectAll.d.ts.map +1 -1
- package/dist/helpers/index.d.ts +1 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/rewriteUnknownContent.d.ts +46 -0
- package/dist/helpers/rewriteUnknownContent.d.ts.map +1 -0
- package/dist/index.cjs +128 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +129 -32
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +128 -30
- package/dist/index.umd.js.map +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities/isFunction.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/Editor.ts +2 -1
- package/src/EventEmitter.ts +1 -1
- package/src/Mark.ts +1 -0
- package/src/Node.ts +1 -0
- package/src/NodeView.ts +2 -2
- package/src/PasteRule.ts +31 -2
- package/src/commands/focus.ts +1 -6
- package/src/commands/joinItemBackward.ts +1 -1
- package/src/commands/joinItemForward.ts +1 -1
- package/src/commands/selectAll.ts +10 -5
- package/src/helpers/getSchemaByResolvedExtensions.ts +1 -1
- package/src/helpers/index.ts +1 -0
- package/src/helpers/rewriteUnknownContent.ts +148 -0
- package/src/types.ts +1 -1
- package/src/utilities/isFunction.ts +1 -0
- package/src/utilities/mergeAttributes.ts +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plugin, PluginKey, TextSelection, Selection, NodeSelection, EditorState } from '@tiptap/pm/state';
|
|
1
|
+
import { Plugin, PluginKey, TextSelection, Selection, AllSelection, NodeSelection, EditorState } from '@tiptap/pm/state';
|
|
2
2
|
import { EditorView } from '@tiptap/pm/view';
|
|
3
3
|
import { keymap } from '@tiptap/pm/keymap';
|
|
4
4
|
import { Schema, DOMSerializer, Fragment, Node as Node$1, DOMParser, Slice } from '@tiptap/pm/model';
|
|
@@ -320,7 +320,7 @@ function mergeAttributes(...objects) {
|
|
|
320
320
|
return;
|
|
321
321
|
}
|
|
322
322
|
if (key === 'class') {
|
|
323
|
-
const valueClasses = value ? value.split(' ') : [];
|
|
323
|
+
const valueClasses = value ? String(value).split(' ') : [];
|
|
324
324
|
const existingClasses = mergedAttributes[key] ? mergedAttributes[key].split(' ') : [];
|
|
325
325
|
const insertClasses = valueClasses.filter(valueClass => !existingClasses.includes(valueClass));
|
|
326
326
|
mergedAttributes[key] = [...existingClasses, ...insertClasses].join(' ');
|
|
@@ -362,6 +362,7 @@ function getRenderedAttributes(nodeOrMark, extensionAttributes) {
|
|
|
362
362
|
.reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
|
365
366
|
function isFunction(value) {
|
|
366
367
|
return typeof value === 'function';
|
|
367
368
|
}
|
|
@@ -996,6 +997,8 @@ function run(config) {
|
|
|
996
997
|
const success = handlers.every(handler => handler !== null);
|
|
997
998
|
return success;
|
|
998
999
|
}
|
|
1000
|
+
// When dragging across editors, must get another editor instance to delete selection content.
|
|
1001
|
+
let tiptapDragFromOtherEditor = null;
|
|
999
1002
|
const createClipboardPasteEvent = (text) => {
|
|
1000
1003
|
var _a;
|
|
1001
1004
|
const event = new ClipboardEvent('paste', {
|
|
@@ -1019,7 +1022,7 @@ function pasteRulesPlugin(props) {
|
|
|
1019
1022
|
try {
|
|
1020
1023
|
dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
|
|
1021
1024
|
}
|
|
1022
|
-
catch
|
|
1025
|
+
catch {
|
|
1023
1026
|
dropEvent = null;
|
|
1024
1027
|
}
|
|
1025
1028
|
const processEvent = ({ state, from, to, rule, pasteEvt, }) => {
|
|
@@ -1043,7 +1046,7 @@ function pasteRulesPlugin(props) {
|
|
|
1043
1046
|
try {
|
|
1044
1047
|
dropEvent = typeof DragEvent !== 'undefined' ? new DragEvent('drop') : null;
|
|
1045
1048
|
}
|
|
1046
|
-
catch
|
|
1049
|
+
catch {
|
|
1047
1050
|
dropEvent = null;
|
|
1048
1051
|
}
|
|
1049
1052
|
pasteEvent = typeof ClipboardEvent !== 'undefined' ? new ClipboardEvent('paste') : null;
|
|
@@ -1058,11 +1061,21 @@ function pasteRulesPlugin(props) {
|
|
|
1058
1061
|
dragSourceElement = ((_a = view.dom.parentElement) === null || _a === void 0 ? void 0 : _a.contains(event.target))
|
|
1059
1062
|
? view.dom.parentElement
|
|
1060
1063
|
: null;
|
|
1064
|
+
if (dragSourceElement) {
|
|
1065
|
+
tiptapDragFromOtherEditor = editor;
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
const handleDragend = () => {
|
|
1069
|
+
if (tiptapDragFromOtherEditor) {
|
|
1070
|
+
tiptapDragFromOtherEditor = null;
|
|
1071
|
+
}
|
|
1061
1072
|
};
|
|
1062
1073
|
window.addEventListener('dragstart', handleDragstart);
|
|
1074
|
+
window.addEventListener('dragend', handleDragend);
|
|
1063
1075
|
return {
|
|
1064
1076
|
destroy() {
|
|
1065
1077
|
window.removeEventListener('dragstart', handleDragstart);
|
|
1078
|
+
window.removeEventListener('dragend', handleDragend);
|
|
1066
1079
|
},
|
|
1067
1080
|
};
|
|
1068
1081
|
},
|
|
@@ -1071,6 +1084,18 @@ function pasteRulesPlugin(props) {
|
|
|
1071
1084
|
drop: (view, event) => {
|
|
1072
1085
|
isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
|
|
1073
1086
|
dropEvent = event;
|
|
1087
|
+
if (!isDroppedFromProseMirror) {
|
|
1088
|
+
const dragFromOtherEditor = tiptapDragFromOtherEditor;
|
|
1089
|
+
if (dragFromOtherEditor) {
|
|
1090
|
+
// setTimeout to avoid the wrong content after drop, timeout arg can't be empty or 0
|
|
1091
|
+
setTimeout(() => {
|
|
1092
|
+
const selection = dragFromOtherEditor.state.selection;
|
|
1093
|
+
if (selection) {
|
|
1094
|
+
dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
|
|
1095
|
+
}
|
|
1096
|
+
}, 10);
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1074
1099
|
return false;
|
|
1075
1100
|
},
|
|
1076
1101
|
paste: (_view, event) => {
|
|
@@ -1829,30 +1854,13 @@ function resolveFocusPosition(doc, position = null) {
|
|
|
1829
1854
|
return TextSelection.create(doc, minMax(position, minPos, maxPos), minMax(position, minPos, maxPos));
|
|
1830
1855
|
}
|
|
1831
1856
|
|
|
1832
|
-
function isiOS() {
|
|
1833
|
-
return [
|
|
1834
|
-
'iPad Simulator',
|
|
1835
|
-
'iPhone Simulator',
|
|
1836
|
-
'iPod Simulator',
|
|
1837
|
-
'iPad',
|
|
1838
|
-
'iPhone',
|
|
1839
|
-
'iPod',
|
|
1840
|
-
].includes(navigator.platform)
|
|
1841
|
-
// iPad on iOS 13 detection
|
|
1842
|
-
|| (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
|
|
1843
|
-
}
|
|
1844
|
-
|
|
1845
1857
|
const focus = (position = null, options = {}) => ({ editor, view, tr, dispatch, }) => {
|
|
1846
1858
|
options = {
|
|
1847
1859
|
scrollIntoView: true,
|
|
1848
1860
|
...options,
|
|
1849
1861
|
};
|
|
1850
1862
|
const delayedFocus = () => {
|
|
1851
|
-
|
|
1852
|
-
// so we have to call this
|
|
1853
|
-
if (isiOS()) {
|
|
1854
|
-
view.dom.focus();
|
|
1855
|
-
}
|
|
1863
|
+
view.dom.focus();
|
|
1856
1864
|
// For React we have to focus asynchronously. Otherwise wild things happen.
|
|
1857
1865
|
// see: https://github.com/ueberdosis/tiptap/issues/1520
|
|
1858
1866
|
requestAnimationFrame(() => {
|
|
@@ -2153,7 +2161,7 @@ const joinItemBackward = () => ({ state, dispatch, tr, }) => {
|
|
|
2153
2161
|
}
|
|
2154
2162
|
return true;
|
|
2155
2163
|
}
|
|
2156
|
-
catch
|
|
2164
|
+
catch {
|
|
2157
2165
|
return false;
|
|
2158
2166
|
}
|
|
2159
2167
|
};
|
|
@@ -2170,7 +2178,7 @@ const joinItemForward = () => ({ state, dispatch, tr, }) => {
|
|
|
2170
2178
|
}
|
|
2171
2179
|
return true;
|
|
2172
2180
|
}
|
|
2173
|
-
catch
|
|
2181
|
+
catch {
|
|
2174
2182
|
return false;
|
|
2175
2183
|
}
|
|
2176
2184
|
};
|
|
@@ -2183,6 +2191,19 @@ const joinTextblockForward = () => ({ state, dispatch }) => {
|
|
|
2183
2191
|
return joinTextblockForward$1(state, dispatch);
|
|
2184
2192
|
};
|
|
2185
2193
|
|
|
2194
|
+
function isiOS() {
|
|
2195
|
+
return [
|
|
2196
|
+
'iPad Simulator',
|
|
2197
|
+
'iPhone Simulator',
|
|
2198
|
+
'iPod Simulator',
|
|
2199
|
+
'iPad',
|
|
2200
|
+
'iPhone',
|
|
2201
|
+
'iPod',
|
|
2202
|
+
].includes(navigator.platform)
|
|
2203
|
+
// iPad on iOS 13 detection
|
|
2204
|
+
|| (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2186
2207
|
function isMacOS() {
|
|
2187
2208
|
return typeof navigator !== 'undefined'
|
|
2188
2209
|
? /Mac/.test(navigator.platform)
|
|
@@ -2393,11 +2414,12 @@ const scrollIntoView = () => ({ tr, dispatch }) => {
|
|
|
2393
2414
|
return true;
|
|
2394
2415
|
};
|
|
2395
2416
|
|
|
2396
|
-
const selectAll = () => ({ tr,
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
}
|
|
2417
|
+
const selectAll = () => ({ tr, dispatch }) => {
|
|
2418
|
+
if (dispatch) {
|
|
2419
|
+
const selection = new AllSelection(tr.doc);
|
|
2420
|
+
tr.setSelection(selection);
|
|
2421
|
+
}
|
|
2422
|
+
return true;
|
|
2401
2423
|
};
|
|
2402
2424
|
|
|
2403
2425
|
const selectNodeBackward = () => ({ state, dispatch }) => {
|
|
@@ -3084,6 +3106,81 @@ function posToDOMRect(view, from, to) {
|
|
|
3084
3106
|
};
|
|
3085
3107
|
}
|
|
3086
3108
|
|
|
3109
|
+
/**
|
|
3110
|
+
* The actual implementation of the rewriteUnknownContent function
|
|
3111
|
+
*/
|
|
3112
|
+
function rewriteUnknownContentInner({ json, validMarks, validNodes, options, rewrittenContent = [], }) {
|
|
3113
|
+
if (json.marks && Array.isArray(json.marks)) {
|
|
3114
|
+
json.marks = json.marks.filter(mark => {
|
|
3115
|
+
const name = typeof mark === 'string' ? mark : mark.type;
|
|
3116
|
+
if (validMarks.has(name)) {
|
|
3117
|
+
return true;
|
|
3118
|
+
}
|
|
3119
|
+
rewrittenContent.push({
|
|
3120
|
+
original: JSON.parse(JSON.stringify(mark)),
|
|
3121
|
+
unsupported: name,
|
|
3122
|
+
});
|
|
3123
|
+
// Just ignore any unknown marks
|
|
3124
|
+
return false;
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
if (json.content && Array.isArray(json.content)) {
|
|
3128
|
+
json.content = json.content
|
|
3129
|
+
.map(value => rewriteUnknownContentInner({
|
|
3130
|
+
json: value,
|
|
3131
|
+
validMarks,
|
|
3132
|
+
validNodes,
|
|
3133
|
+
options,
|
|
3134
|
+
rewrittenContent,
|
|
3135
|
+
}).json)
|
|
3136
|
+
.filter(a => a !== null && a !== undefined);
|
|
3137
|
+
}
|
|
3138
|
+
if (json.type && !validNodes.has(json.type)) {
|
|
3139
|
+
rewrittenContent.push({
|
|
3140
|
+
original: JSON.parse(JSON.stringify(json)),
|
|
3141
|
+
unsupported: json.type,
|
|
3142
|
+
});
|
|
3143
|
+
if (json.content && Array.isArray(json.content) && ((options === null || options === void 0 ? void 0 : options.fallbackToParagraph) !== false)) {
|
|
3144
|
+
// Just treat it like a paragraph and hope for the best
|
|
3145
|
+
json.type = 'paragraph';
|
|
3146
|
+
return {
|
|
3147
|
+
json,
|
|
3148
|
+
rewrittenContent,
|
|
3149
|
+
};
|
|
3150
|
+
}
|
|
3151
|
+
// or just omit it entirely
|
|
3152
|
+
return {
|
|
3153
|
+
json: null,
|
|
3154
|
+
rewrittenContent,
|
|
3155
|
+
};
|
|
3156
|
+
}
|
|
3157
|
+
return { json, rewrittenContent };
|
|
3158
|
+
}
|
|
3159
|
+
/**
|
|
3160
|
+
* Rewrite unknown nodes and marks within JSON content
|
|
3161
|
+
* Allowing for user within the editor
|
|
3162
|
+
*/
|
|
3163
|
+
function rewriteUnknownContent(
|
|
3164
|
+
/**
|
|
3165
|
+
* The JSON content to clean of unknown nodes and marks
|
|
3166
|
+
*/
|
|
3167
|
+
json,
|
|
3168
|
+
/**
|
|
3169
|
+
* The schema to use for validation
|
|
3170
|
+
*/
|
|
3171
|
+
schema,
|
|
3172
|
+
/**
|
|
3173
|
+
* Options for the cleaning process
|
|
3174
|
+
*/
|
|
3175
|
+
options) {
|
|
3176
|
+
return rewriteUnknownContentInner({
|
|
3177
|
+
json,
|
|
3178
|
+
validNodes: new Set(Object.keys(schema.nodes)),
|
|
3179
|
+
validMarks: new Set(Object.keys(schema.marks)),
|
|
3180
|
+
options,
|
|
3181
|
+
});
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3087
3184
|
function canSetMark(state, tr, newMarkType) {
|
|
3088
3185
|
var _a;
|
|
3089
3186
|
const { selection } = tr;
|
|
@@ -5079,10 +5176,10 @@ class NodeView {
|
|
|
5079
5176
|
// ProseMirror tries to drag selectable nodes
|
|
5080
5177
|
// even if `draggable` is set to `false`
|
|
5081
5178
|
// this fix prevents that
|
|
5082
|
-
if (!isDraggable && isSelectable && isDragEvent) {
|
|
5179
|
+
if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
|
|
5083
5180
|
event.preventDefault();
|
|
5084
5181
|
}
|
|
5085
|
-
if (isDraggable && isDragEvent && !isDragging) {
|
|
5182
|
+
if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
|
|
5086
5183
|
event.preventDefault();
|
|
5087
5184
|
return false;
|
|
5088
5185
|
}
|
|
@@ -5323,5 +5420,5 @@ class Tracker {
|
|
|
5323
5420
|
}
|
|
5324
5421
|
}
|
|
5325
5422
|
|
|
5326
|
-
export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, index as extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
|
|
5423
|
+
export { CommandManager, Editor, Extension, InputRule, Mark, Node, NodePos, NodeView, PasteRule, Tracker, callOrReturn, combineTransactionSteps, createChainableState, createDocument, createNodeFromContent, createStyleTag, defaultBlockAt, deleteProps, elementFromString, escapeForRegEx, index as extensions, findChildren, findChildrenInRange, findDuplicates, findParentNode, findParentNodeClosestToPos, fromString, generateHTML, generateJSON, generateText, getAttributes, getAttributesFromExtensions, getChangedRanges, getDebugJSON, getExtensionField, getHTMLFromFragment, getMarkAttributes, getMarkRange, getMarkType, getMarksBetween, getNodeAtPosition, getNodeAttributes, getNodeType, getRenderedAttributes, getSchema, getSchemaByResolvedExtensions, getSchemaTypeByName, getSchemaTypeNameByName, getSplittedAttributes, getText, getTextBetween, getTextContentFromNodes, getTextSerializersFromSchema, injectExtensionAttributesToParseRule, inputRulesPlugin, isActive, isAtEndOfNode, isAtStartOfNode, isEmptyObject, isExtensionRulesEnabled, isFunction, isList, isMacOS, isMarkActive, isNodeActive, isNodeEmpty, isNodeSelection, isNumber, isPlainObject, isRegExp, isString, isTextSelection, isiOS, markInputRule, markPasteRule, mergeAttributes, mergeDeep, minMax, nodeInputRule, nodePasteRule, objectIncludes, pasteRulesPlugin, posToDOMRect, removeDuplicates, resolveFocusPosition, rewriteUnknownContent, selectionToInsertionEnd, splitExtensions, textInputRule, textPasteRule, textblockTypeInputRule, wrappingInputRule };
|
|
5327
5424
|
//# sourceMappingURL=index.js.map
|