@tiptap/core 2.5.5 → 2.5.7
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 +79 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +79 -40
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +79 -40
- package/dist/index.umd.js.map +1 -1
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +7 -1
- package/dist/packages/core/src/types.d.ts +1 -3
- package/package.json +3 -3
- package/src/Editor.ts +6 -0
- package/src/commands/insertContentAt.ts +7 -0
- package/src/commands/splitBlock.ts +31 -31
- package/src/helpers/createNodeFromContent.ts +21 -13
- package/src/helpers/isNodeEmpty.ts +34 -4
- package/src/types.ts +157 -156
package/dist/index.umd.js
CHANGED
|
@@ -1775,12 +1775,12 @@
|
|
|
1775
1775
|
}
|
|
1776
1776
|
}
|
|
1777
1777
|
if (isTextContent) {
|
|
1778
|
-
|
|
1779
|
-
let hasInvalidContent = false;
|
|
1780
|
-
let invalidContent = '';
|
|
1781
|
-
// Only ever check for invalid content if we're supposed to throw an error
|
|
1778
|
+
// Check for invalid content
|
|
1782
1779
|
if (options.errorOnInvalidContent) {
|
|
1783
|
-
|
|
1780
|
+
let hasInvalidContent = false;
|
|
1781
|
+
let invalidContent = '';
|
|
1782
|
+
// A copy of the current schema with a catch-all node at the end
|
|
1783
|
+
const contentCheckSchema = new model.Schema({
|
|
1784
1784
|
topNode: schema.spec.topNode,
|
|
1785
1785
|
marks: schema.spec.marks,
|
|
1786
1786
|
// Prosemirror's schemas are executed such that: the last to execute, matches last
|
|
@@ -1804,15 +1804,21 @@
|
|
|
1804
1804
|
},
|
|
1805
1805
|
}),
|
|
1806
1806
|
});
|
|
1807
|
+
if (options.slice) {
|
|
1808
|
+
model.DOMParser.fromSchema(contentCheckSchema).parseSlice(elementFromString(content), options.parseOptions);
|
|
1809
|
+
}
|
|
1810
|
+
else {
|
|
1811
|
+
model.DOMParser.fromSchema(contentCheckSchema).parse(elementFromString(content), options.parseOptions);
|
|
1812
|
+
}
|
|
1813
|
+
if (options.errorOnInvalidContent && hasInvalidContent) {
|
|
1814
|
+
throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
|
|
1815
|
+
}
|
|
1807
1816
|
}
|
|
1808
|
-
const parser = model.DOMParser.fromSchema(
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
: parser.parse(elementFromString(content), options.parseOptions);
|
|
1812
|
-
if (options.errorOnInvalidContent && hasInvalidContent) {
|
|
1813
|
-
throw new Error('[tiptap error]: Invalid HTML content', { cause: new Error(`Invalid element found: ${invalidContent}`) });
|
|
1817
|
+
const parser = model.DOMParser.fromSchema(schema);
|
|
1818
|
+
if (options.slice) {
|
|
1819
|
+
return parser.parseSlice(elementFromString(content), options.parseOptions).content;
|
|
1814
1820
|
}
|
|
1815
|
-
return
|
|
1821
|
+
return parser.parse(elementFromString(content), options.parseOptions);
|
|
1816
1822
|
}
|
|
1817
1823
|
return createNodeFromContent('', schema, options);
|
|
1818
1824
|
}
|
|
@@ -1861,6 +1867,13 @@
|
|
|
1861
1867
|
});
|
|
1862
1868
|
}
|
|
1863
1869
|
catch (e) {
|
|
1870
|
+
editor.emit('contentError', {
|
|
1871
|
+
editor,
|
|
1872
|
+
error: e,
|
|
1873
|
+
disableCollaboration: () => {
|
|
1874
|
+
console.error('[tiptap error]: Unable to disable collaboration at this point in time');
|
|
1875
|
+
},
|
|
1876
|
+
});
|
|
1864
1877
|
return false;
|
|
1865
1878
|
}
|
|
1866
1879
|
let { from, to } = typeof position === 'number' ? { from: position, to: position } : { from: position.from, to: position.to };
|
|
@@ -2811,12 +2824,34 @@
|
|
|
2811
2824
|
return group.split(' ').includes('list');
|
|
2812
2825
|
}
|
|
2813
2826
|
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2827
|
+
/**
|
|
2828
|
+
* Returns true if the given node is empty.
|
|
2829
|
+
* When `checkChildren` is true (default), it will also check if all children are empty.
|
|
2830
|
+
*/
|
|
2831
|
+
function isNodeEmpty(node, { checkChildren } = { checkChildren: true }) {
|
|
2832
|
+
if (node.isText) {
|
|
2833
|
+
return !node.text;
|
|
2834
|
+
}
|
|
2835
|
+
if (node.content.childCount === 0) {
|
|
2836
|
+
return true;
|
|
2837
|
+
}
|
|
2838
|
+
if (node.isLeaf) {
|
|
2817
2839
|
return false;
|
|
2818
2840
|
}
|
|
2819
|
-
|
|
2841
|
+
if (checkChildren) {
|
|
2842
|
+
let hasSameContent = true;
|
|
2843
|
+
node.content.forEach(childNode => {
|
|
2844
|
+
if (hasSameContent === false) {
|
|
2845
|
+
// Exit early for perf
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
if (!isNodeEmpty(childNode)) {
|
|
2849
|
+
hasSameContent = false;
|
|
2850
|
+
}
|
|
2851
|
+
});
|
|
2852
|
+
return hasSameContent;
|
|
2853
|
+
}
|
|
2854
|
+
return false;
|
|
2820
2855
|
}
|
|
2821
2856
|
|
|
2822
2857
|
function isNodeSelection(value) {
|
|
@@ -3014,15 +3049,24 @@
|
|
|
3014
3049
|
if (!$from.parent.isBlock) {
|
|
3015
3050
|
return false;
|
|
3016
3051
|
}
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3052
|
+
const atEnd = $to.parentOffset === $to.parent.content.size;
|
|
3053
|
+
const deflt = $from.depth === 0
|
|
3054
|
+
? undefined
|
|
3055
|
+
: defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
|
|
3056
|
+
let types = atEnd && deflt
|
|
3057
|
+
? [
|
|
3058
|
+
{
|
|
3059
|
+
type: deflt,
|
|
3060
|
+
attrs: newAttributes,
|
|
3061
|
+
},
|
|
3062
|
+
]
|
|
3063
|
+
: undefined;
|
|
3064
|
+
let can = transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
|
|
3065
|
+
if (!types
|
|
3066
|
+
&& !can
|
|
3067
|
+
&& transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
|
|
3068
|
+
can = true;
|
|
3069
|
+
types = deflt
|
|
3026
3070
|
? [
|
|
3027
3071
|
{
|
|
3028
3072
|
type: deflt,
|
|
@@ -3030,21 +3074,12 @@
|
|
|
3030
3074
|
},
|
|
3031
3075
|
]
|
|
3032
3076
|
: undefined;
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
&& !can
|
|
3036
|
-
&& transform.canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : undefined)) {
|
|
3037
|
-
can = true;
|
|
3038
|
-
types = deflt
|
|
3039
|
-
? [
|
|
3040
|
-
{
|
|
3041
|
-
type: deflt,
|
|
3042
|
-
attrs: newAttributes,
|
|
3043
|
-
},
|
|
3044
|
-
]
|
|
3045
|
-
: undefined;
|
|
3046
|
-
}
|
|
3077
|
+
}
|
|
3078
|
+
if (dispatch) {
|
|
3047
3079
|
if (can) {
|
|
3080
|
+
if (selection instanceof state.TextSelection) {
|
|
3081
|
+
tr.deleteSelection();
|
|
3082
|
+
}
|
|
3048
3083
|
tr.split(tr.mapping.map($from.pos), 1, types);
|
|
3049
3084
|
if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
|
|
3050
3085
|
const first = tr.mapping.map($from.before());
|
|
@@ -3059,7 +3094,7 @@
|
|
|
3059
3094
|
}
|
|
3060
3095
|
tr.scrollIntoView();
|
|
3061
3096
|
}
|
|
3062
|
-
return
|
|
3097
|
+
return can;
|
|
3063
3098
|
};
|
|
3064
3099
|
|
|
3065
3100
|
const splitListItem = typeOrName => ({ tr, state: state$1, dispatch, editor, }) => {
|
|
@@ -4158,6 +4193,7 @@ img.ProseMirror-separator {
|
|
|
4158
4193
|
this.prependClass();
|
|
4159
4194
|
// Let’s store the editor instance in the DOM element.
|
|
4160
4195
|
// So we’ll have access to it for tests.
|
|
4196
|
+
// @ts-ignore
|
|
4161
4197
|
const dom = this.view.dom;
|
|
4162
4198
|
dom.editor = this;
|
|
4163
4199
|
}
|
|
@@ -4165,6 +4201,9 @@ img.ProseMirror-separator {
|
|
|
4165
4201
|
* Creates all node views.
|
|
4166
4202
|
*/
|
|
4167
4203
|
createNodeViews() {
|
|
4204
|
+
if (this.view.isDestroyed) {
|
|
4205
|
+
return;
|
|
4206
|
+
}
|
|
4168
4207
|
this.view.setProps({
|
|
4169
4208
|
nodeViews: this.extensionManager.nodeViews,
|
|
4170
4209
|
});
|