@tiptap/core 3.0.0-next.1 → 3.0.0-next.2
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 +403 -137
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +177 -53
- package/dist/index.d.ts +177 -53
- package/dist/index.js +375 -108
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Editor.ts +60 -10
- package/src/EventEmitter.ts +9 -0
- package/src/ExtensionManager.ts +16 -11
- package/src/InputRule.ts +45 -30
- package/src/Node.ts +19 -0
- package/src/NodePos.ts +9 -4
- package/src/NodeView.ts +43 -12
- package/src/PasteRule.ts +96 -42
- package/src/commands/focus.ts +1 -6
- package/src/commands/insertContent.ts +9 -9
- package/src/commands/insertContentAt.ts +23 -3
- package/src/commands/selectAll.ts +10 -5
- package/src/commands/setContent.ts +10 -14
- package/src/commands/setNode.ts +9 -2
- package/src/commands/toggleNode.ts +11 -2
- package/src/commands/updateAttributes.ts +72 -12
- package/src/extensions/drop.ts +26 -0
- package/src/extensions/index.ts +2 -0
- package/src/extensions/keymap.ts +5 -2
- package/src/extensions/paste.ts +26 -0
- package/src/helpers/createDocument.ts +4 -2
- package/src/helpers/createNodeFromContent.ts +11 -2
- package/src/helpers/getMarkRange.ts +35 -8
- package/src/helpers/getRenderedAttributes.ts +3 -0
- package/src/helpers/getSchemaByResolvedExtensions.ts +2 -1
- package/src/inputRules/markInputRule.ts +1 -1
- package/src/inputRules/nodeInputRule.ts +1 -1
- package/src/inputRules/textInputRule.ts +1 -1
- package/src/inputRules/textblockTypeInputRule.ts +1 -1
- package/src/inputRules/wrappingInputRule.ts +1 -1
- package/src/pasteRules/markPasteRule.ts +1 -1
- package/src/pasteRules/nodePasteRule.ts +1 -1
- package/src/pasteRules/textPasteRule.ts +1 -1
- package/src/types.ts +107 -19
- package/src/utilities/mergeAttributes.ts +18 -1
package/dist/index.js
CHANGED
|
@@ -178,6 +178,13 @@ var EventEmitter = class {
|
|
|
178
178
|
}
|
|
179
179
|
return this;
|
|
180
180
|
}
|
|
181
|
+
once(event, fn) {
|
|
182
|
+
const onceFn = (...args) => {
|
|
183
|
+
this.off(event, onceFn);
|
|
184
|
+
fn.apply(this, args);
|
|
185
|
+
};
|
|
186
|
+
return this.on(event, onceFn);
|
|
187
|
+
}
|
|
181
188
|
removeAllListeners() {
|
|
182
189
|
this.callbacks = {};
|
|
183
190
|
}
|
|
@@ -324,7 +331,18 @@ function mergeAttributes(...objects) {
|
|
|
324
331
|
);
|
|
325
332
|
mergedAttributes[key] = [...existingClasses, ...insertClasses].join(" ");
|
|
326
333
|
} else if (key === "style") {
|
|
327
|
-
|
|
334
|
+
const newStyles = value ? value.split(";").map((style2) => style2.trim()).filter(Boolean) : [];
|
|
335
|
+
const existingStyles = mergedAttributes[key] ? mergedAttributes[key].split(";").map((style2) => style2.trim()).filter(Boolean) : [];
|
|
336
|
+
const styleMap = /* @__PURE__ */ new Map();
|
|
337
|
+
existingStyles.forEach((style2) => {
|
|
338
|
+
const [property, val] = style2.split(":").map((part) => part.trim());
|
|
339
|
+
styleMap.set(property, val);
|
|
340
|
+
});
|
|
341
|
+
newStyles.forEach((style2) => {
|
|
342
|
+
const [property, val] = style2.split(":").map((part) => part.trim());
|
|
343
|
+
styleMap.set(property, val);
|
|
344
|
+
});
|
|
345
|
+
mergedAttributes[key] = Array.from(styleMap.entries()).map(([property, val]) => `${property}: ${val}`).join("; ");
|
|
328
346
|
} else {
|
|
329
347
|
mergedAttributes[key] = value;
|
|
330
348
|
}
|
|
@@ -335,7 +353,9 @@ function mergeAttributes(...objects) {
|
|
|
335
353
|
|
|
336
354
|
// src/helpers/getRenderedAttributes.ts
|
|
337
355
|
function getRenderedAttributes(nodeOrMark, extensionAttributes) {
|
|
338
|
-
return extensionAttributes.filter(
|
|
356
|
+
return extensionAttributes.filter(
|
|
357
|
+
(attribute) => attribute.type === nodeOrMark.type.name
|
|
358
|
+
).filter((item) => item.attribute.rendered).map((item) => {
|
|
339
359
|
if (!item.attribute.renderHTML) {
|
|
340
360
|
return {
|
|
341
361
|
[item.name]: nodeOrMark.attrs[item.name]
|
|
@@ -471,6 +491,7 @@ function getSchemaByResolvedExtensions(extensions, editor) {
|
|
|
471
491
|
),
|
|
472
492
|
code: callOrReturn(getExtensionField(extension, "code", context)),
|
|
473
493
|
whitespace: callOrReturn(getExtensionField(extension, "whitespace", context)),
|
|
494
|
+
linebreakReplacement: callOrReturn(getExtensionField(extension, "linebreakReplacement", context)),
|
|
474
495
|
defining: callOrReturn(
|
|
475
496
|
getExtensionField(extension, "defining", context)
|
|
476
497
|
),
|
|
@@ -598,8 +619,19 @@ function isExtensionRulesEnabled(extension, enabled) {
|
|
|
598
619
|
}
|
|
599
620
|
|
|
600
621
|
// src/InputRule.ts
|
|
622
|
+
import { Fragment as Fragment2 } from "@tiptap/pm/model";
|
|
601
623
|
import { Plugin } from "@tiptap/pm/state";
|
|
602
624
|
|
|
625
|
+
// src/helpers/getHTMLFromFragment.ts
|
|
626
|
+
import { DOMSerializer } from "@tiptap/pm/model";
|
|
627
|
+
function getHTMLFromFragment(fragment, schema) {
|
|
628
|
+
const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
629
|
+
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
630
|
+
const container = temporaryDocument.createElement("div");
|
|
631
|
+
container.appendChild(documentFragment);
|
|
632
|
+
return container.innerHTML;
|
|
633
|
+
}
|
|
634
|
+
|
|
603
635
|
// src/helpers/getTextContentFromNodes.ts
|
|
604
636
|
var getTextContentFromNodes = ($from, maxMatch = 500) => {
|
|
605
637
|
let textBefore = "";
|
|
@@ -728,7 +760,7 @@ function inputRulesPlugin(props) {
|
|
|
728
760
|
init() {
|
|
729
761
|
return null;
|
|
730
762
|
},
|
|
731
|
-
apply(tr, prev) {
|
|
763
|
+
apply(tr, prev, state) {
|
|
732
764
|
const stored = tr.getMeta(plugin);
|
|
733
765
|
if (stored) {
|
|
734
766
|
return stored;
|
|
@@ -737,7 +769,13 @@ function inputRulesPlugin(props) {
|
|
|
737
769
|
const isSimulatedInput = !!simulatedInputMeta;
|
|
738
770
|
if (isSimulatedInput) {
|
|
739
771
|
setTimeout(() => {
|
|
740
|
-
|
|
772
|
+
let { text } = simulatedInputMeta;
|
|
773
|
+
if (typeof text === "string") {
|
|
774
|
+
text = text;
|
|
775
|
+
} else {
|
|
776
|
+
text = getHTMLFromFragment(Fragment2.from(text), state.schema);
|
|
777
|
+
}
|
|
778
|
+
const { from } = simulatedInputMeta;
|
|
741
779
|
const to = from + text.length;
|
|
742
780
|
run({
|
|
743
781
|
editor,
|
|
@@ -929,6 +967,7 @@ var Mark = class _Mark {
|
|
|
929
967
|
};
|
|
930
968
|
|
|
931
969
|
// src/PasteRule.ts
|
|
970
|
+
import { Fragment as Fragment3 } from "@tiptap/pm/model";
|
|
932
971
|
import { Plugin as Plugin2 } from "@tiptap/pm/state";
|
|
933
972
|
|
|
934
973
|
// src/utilities/isNumber.ts
|
|
@@ -1016,6 +1055,7 @@ function run2(config) {
|
|
|
1016
1055
|
const success = handlers.every((handler) => handler !== null);
|
|
1017
1056
|
return success;
|
|
1018
1057
|
}
|
|
1058
|
+
var tiptapDragFromOtherEditor = null;
|
|
1019
1059
|
var createClipboardPasteEvent = (text) => {
|
|
1020
1060
|
var _a;
|
|
1021
1061
|
const event = new ClipboardEvent("paste", {
|
|
@@ -1030,7 +1070,12 @@ function pasteRulesPlugin(props) {
|
|
|
1030
1070
|
let isPastedFromProseMirror = false;
|
|
1031
1071
|
let isDroppedFromProseMirror = false;
|
|
1032
1072
|
let pasteEvent = typeof ClipboardEvent !== "undefined" ? new ClipboardEvent("paste") : null;
|
|
1033
|
-
let dropEvent
|
|
1073
|
+
let dropEvent;
|
|
1074
|
+
try {
|
|
1075
|
+
dropEvent = typeof DragEvent !== "undefined" ? new DragEvent("drop") : null;
|
|
1076
|
+
} catch (e) {
|
|
1077
|
+
dropEvent = null;
|
|
1078
|
+
}
|
|
1034
1079
|
const processEvent = ({
|
|
1035
1080
|
state,
|
|
1036
1081
|
from,
|
|
@@ -1055,7 +1100,11 @@ function pasteRulesPlugin(props) {
|
|
|
1055
1100
|
if (!handler || !tr.steps.length) {
|
|
1056
1101
|
return;
|
|
1057
1102
|
}
|
|
1058
|
-
|
|
1103
|
+
try {
|
|
1104
|
+
dropEvent = typeof DragEvent !== "undefined" ? new DragEvent("drop") : null;
|
|
1105
|
+
} catch (e) {
|
|
1106
|
+
dropEvent = null;
|
|
1107
|
+
}
|
|
1059
1108
|
pasteEvent = typeof ClipboardEvent !== "undefined" ? new ClipboardEvent("paste") : null;
|
|
1060
1109
|
return tr;
|
|
1061
1110
|
};
|
|
@@ -1066,11 +1115,21 @@ function pasteRulesPlugin(props) {
|
|
|
1066
1115
|
const handleDragstart = (event) => {
|
|
1067
1116
|
var _a;
|
|
1068
1117
|
dragSourceElement = ((_a = view.dom.parentElement) == null ? void 0 : _a.contains(event.target)) ? view.dom.parentElement : null;
|
|
1118
|
+
if (dragSourceElement) {
|
|
1119
|
+
tiptapDragFromOtherEditor = editor;
|
|
1120
|
+
}
|
|
1121
|
+
};
|
|
1122
|
+
const handleDragend = () => {
|
|
1123
|
+
if (tiptapDragFromOtherEditor) {
|
|
1124
|
+
tiptapDragFromOtherEditor = null;
|
|
1125
|
+
}
|
|
1069
1126
|
};
|
|
1070
1127
|
window.addEventListener("dragstart", handleDragstart);
|
|
1128
|
+
window.addEventListener("dragend", handleDragend);
|
|
1071
1129
|
return {
|
|
1072
1130
|
destroy() {
|
|
1073
1131
|
window.removeEventListener("dragstart", handleDragstart);
|
|
1132
|
+
window.removeEventListener("dragend", handleDragend);
|
|
1074
1133
|
}
|
|
1075
1134
|
};
|
|
1076
1135
|
},
|
|
@@ -1079,6 +1138,17 @@ function pasteRulesPlugin(props) {
|
|
|
1079
1138
|
drop: (view, event) => {
|
|
1080
1139
|
isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
|
|
1081
1140
|
dropEvent = event;
|
|
1141
|
+
if (!isDroppedFromProseMirror) {
|
|
1142
|
+
const dragFromOtherEditor = tiptapDragFromOtherEditor;
|
|
1143
|
+
if (dragFromOtherEditor) {
|
|
1144
|
+
setTimeout(() => {
|
|
1145
|
+
const selection = dragFromOtherEditor.state.selection;
|
|
1146
|
+
if (selection) {
|
|
1147
|
+
dragFromOtherEditor.commands.deleteRange({ from: selection.from, to: selection.to });
|
|
1148
|
+
}
|
|
1149
|
+
}, 10);
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1082
1152
|
return false;
|
|
1083
1153
|
},
|
|
1084
1154
|
paste: (_view, event) => {
|
|
@@ -1100,7 +1170,13 @@ function pasteRulesPlugin(props) {
|
|
|
1100
1170
|
return;
|
|
1101
1171
|
}
|
|
1102
1172
|
if (isSimulatedPaste) {
|
|
1103
|
-
|
|
1173
|
+
let { text } = simulatedPasteMeta;
|
|
1174
|
+
if (typeof text === "string") {
|
|
1175
|
+
text = text;
|
|
1176
|
+
} else {
|
|
1177
|
+
text = getHTMLFromFragment(Fragment3.from(text), state.schema);
|
|
1178
|
+
}
|
|
1179
|
+
const { from: from2 } = simulatedPasteMeta;
|
|
1104
1180
|
const to2 = from2 + text.length;
|
|
1105
1181
|
const pasteEvt = createClipboardPasteEvent(text);
|
|
1106
1182
|
return processEvent({
|
|
@@ -1339,15 +1415,19 @@ var ExtensionManager = class _ExtensionManager {
|
|
|
1339
1415
|
if (!addNodeView) {
|
|
1340
1416
|
return [];
|
|
1341
1417
|
}
|
|
1342
|
-
const nodeview = (node, view, getPos, decorations) => {
|
|
1418
|
+
const nodeview = (node, view, getPos, decorations, innerDecorations) => {
|
|
1343
1419
|
const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
|
|
1344
1420
|
return addNodeView()({
|
|
1345
|
-
|
|
1421
|
+
// pass-through
|
|
1346
1422
|
node,
|
|
1423
|
+
view,
|
|
1347
1424
|
getPos,
|
|
1348
1425
|
decorations,
|
|
1349
|
-
|
|
1350
|
-
|
|
1426
|
+
innerDecorations,
|
|
1427
|
+
// tiptap-specific
|
|
1428
|
+
editor,
|
|
1429
|
+
extension,
|
|
1430
|
+
HTMLAttributes
|
|
1351
1431
|
});
|
|
1352
1432
|
};
|
|
1353
1433
|
return [extension.name, nodeview];
|
|
@@ -1428,9 +1508,11 @@ var extensions_exports = {};
|
|
|
1428
1508
|
__export(extensions_exports, {
|
|
1429
1509
|
ClipboardTextSerializer: () => ClipboardTextSerializer,
|
|
1430
1510
|
Commands: () => Commands,
|
|
1511
|
+
Drop: () => Drop,
|
|
1431
1512
|
Editable: () => Editable,
|
|
1432
1513
|
FocusEvents: () => FocusEvents,
|
|
1433
1514
|
Keymap: () => Keymap,
|
|
1515
|
+
Paste: () => Paste,
|
|
1434
1516
|
Tabindex: () => Tabindex
|
|
1435
1517
|
});
|
|
1436
1518
|
|
|
@@ -1807,23 +1889,29 @@ function objectIncludes(object1, object2, options = { strict: true }) {
|
|
|
1807
1889
|
// src/helpers/getMarkRange.ts
|
|
1808
1890
|
function findMarkInSet(marks, type, attributes = {}) {
|
|
1809
1891
|
return marks.find((item) => {
|
|
1810
|
-
return item.type === type && objectIncludes(
|
|
1892
|
+
return item.type === type && objectIncludes(
|
|
1893
|
+
// Only check equality for the attributes that are provided
|
|
1894
|
+
Object.fromEntries(Object.keys(attributes).map((k) => [k, item.attrs[k]])),
|
|
1895
|
+
attributes
|
|
1896
|
+
);
|
|
1811
1897
|
});
|
|
1812
1898
|
}
|
|
1813
1899
|
function isMarkInSet(marks, type, attributes = {}) {
|
|
1814
1900
|
return !!findMarkInSet(marks, type, attributes);
|
|
1815
1901
|
}
|
|
1816
|
-
function getMarkRange($pos, type, attributes
|
|
1902
|
+
function getMarkRange($pos, type, attributes) {
|
|
1903
|
+
var _a;
|
|
1817
1904
|
if (!$pos || !type) {
|
|
1818
1905
|
return;
|
|
1819
1906
|
}
|
|
1820
1907
|
let start = $pos.parent.childAfter($pos.parentOffset);
|
|
1821
|
-
if (
|
|
1908
|
+
if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
|
|
1822
1909
|
start = $pos.parent.childBefore($pos.parentOffset);
|
|
1823
1910
|
}
|
|
1824
|
-
if (!start.node) {
|
|
1911
|
+
if (!start.node || !start.node.marks.some((mark2) => mark2.type === type)) {
|
|
1825
1912
|
return;
|
|
1826
1913
|
}
|
|
1914
|
+
attributes = attributes || ((_a = start.node.marks[0]) == null ? void 0 : _a.attrs);
|
|
1827
1915
|
const mark = findMarkInSet([...start.node.marks], type, attributes);
|
|
1828
1916
|
if (!mark) {
|
|
1829
1917
|
return;
|
|
@@ -1832,8 +1920,7 @@ function getMarkRange($pos, type, attributes = {}) {
|
|
|
1832
1920
|
let startPos = $pos.start() + start.offset;
|
|
1833
1921
|
let endIndex = startIndex + 1;
|
|
1834
1922
|
let endPos = startPos + start.node.nodeSize;
|
|
1835
|
-
|
|
1836
|
-
while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
|
|
1923
|
+
while (startIndex > 0 && isMarkInSet([...$pos.parent.child(startIndex - 1).marks], type, attributes)) {
|
|
1837
1924
|
startIndex -= 1;
|
|
1838
1925
|
startPos -= $pos.parent.child(startIndex).nodeSize;
|
|
1839
1926
|
}
|
|
@@ -1929,18 +2016,6 @@ function resolveFocusPosition(doc, position = null) {
|
|
|
1929
2016
|
);
|
|
1930
2017
|
}
|
|
1931
2018
|
|
|
1932
|
-
// src/utilities/isiOS.ts
|
|
1933
|
-
function isiOS() {
|
|
1934
|
-
return [
|
|
1935
|
-
"iPad Simulator",
|
|
1936
|
-
"iPhone Simulator",
|
|
1937
|
-
"iPod Simulator",
|
|
1938
|
-
"iPad",
|
|
1939
|
-
"iPhone",
|
|
1940
|
-
"iPod"
|
|
1941
|
-
].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1944
2019
|
// src/commands/focus.ts
|
|
1945
2020
|
var focus = (position = null, options = {}) => ({
|
|
1946
2021
|
editor,
|
|
@@ -1953,9 +2028,7 @@ var focus = (position = null, options = {}) => ({
|
|
|
1953
2028
|
...options
|
|
1954
2029
|
};
|
|
1955
2030
|
const delayedFocus = () => {
|
|
1956
|
-
|
|
1957
|
-
view.dom.focus();
|
|
1958
|
-
}
|
|
2031
|
+
view.dom.focus();
|
|
1959
2032
|
requestAnimationFrame(() => {
|
|
1960
2033
|
if (!editor.isDestroyed) {
|
|
1961
2034
|
view.focus();
|
|
@@ -2000,11 +2073,15 @@ var insertContent = (value, options) => ({ tr, commands }) => {
|
|
|
2000
2073
|
);
|
|
2001
2074
|
};
|
|
2002
2075
|
|
|
2076
|
+
// src/commands/insertContentAt.ts
|
|
2077
|
+
import { Fragment as Fragment5 } from "@tiptap/pm/model";
|
|
2078
|
+
|
|
2003
2079
|
// src/helpers/createNodeFromContent.ts
|
|
2004
2080
|
import {
|
|
2005
2081
|
DOMParser,
|
|
2006
|
-
Fragment,
|
|
2007
|
-
|
|
2082
|
+
Fragment as Fragment4,
|
|
2083
|
+
Node as ProseMirrorNode3,
|
|
2084
|
+
Schema as Schema3
|
|
2008
2085
|
} from "@tiptap/pm/model";
|
|
2009
2086
|
|
|
2010
2087
|
// src/utilities/elementFromString.ts
|
|
@@ -2028,6 +2105,9 @@ function elementFromString(value) {
|
|
|
2028
2105
|
|
|
2029
2106
|
// src/helpers/createNodeFromContent.ts
|
|
2030
2107
|
function createNodeFromContent(content, schema, options) {
|
|
2108
|
+
if (content instanceof ProseMirrorNode3 || content instanceof Fragment4) {
|
|
2109
|
+
return content;
|
|
2110
|
+
}
|
|
2031
2111
|
options = {
|
|
2032
2112
|
slice: true,
|
|
2033
2113
|
parseOptions: {},
|
|
@@ -2039,9 +2119,13 @@ function createNodeFromContent(content, schema, options) {
|
|
|
2039
2119
|
try {
|
|
2040
2120
|
const isArrayContent = Array.isArray(content) && content.length > 0;
|
|
2041
2121
|
if (isArrayContent) {
|
|
2042
|
-
return
|
|
2122
|
+
return Fragment4.fromArray(content.map((item) => schema.nodeFromJSON(item)));
|
|
2123
|
+
}
|
|
2124
|
+
const node = schema.nodeFromJSON(content);
|
|
2125
|
+
if (options.errorOnInvalidContent) {
|
|
2126
|
+
node.check();
|
|
2043
2127
|
}
|
|
2044
|
-
return
|
|
2128
|
+
return node;
|
|
2045
2129
|
} catch (error) {
|
|
2046
2130
|
if (options.errorOnInvalidContent) {
|
|
2047
2131
|
throw new Error("[tiptap error]: Invalid JSON content", { cause: error });
|
|
@@ -2054,7 +2138,7 @@ function createNodeFromContent(content, schema, options) {
|
|
|
2054
2138
|
if (options.errorOnInvalidContent) {
|
|
2055
2139
|
let hasInvalidContent = false;
|
|
2056
2140
|
let invalidContent = "";
|
|
2057
|
-
const contentCheckSchema = new
|
|
2141
|
+
const contentCheckSchema = new Schema3({
|
|
2058
2142
|
topNode: schema.spec.topNode,
|
|
2059
2143
|
marks: schema.spec.marks,
|
|
2060
2144
|
// Prosemirror's schemas are executed such that: the last to execute, matches last
|
|
@@ -2124,13 +2208,14 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
|
|
|
2124
2208
|
var _a;
|
|
2125
2209
|
if (dispatch) {
|
|
2126
2210
|
options = {
|
|
2127
|
-
parseOptions:
|
|
2211
|
+
parseOptions: editor.options.parseOptions,
|
|
2128
2212
|
updateSelection: true,
|
|
2129
2213
|
applyInputRules: false,
|
|
2130
2214
|
applyPasteRules: false,
|
|
2131
2215
|
...options
|
|
2132
2216
|
};
|
|
2133
2217
|
let content;
|
|
2218
|
+
const { selection } = editor.state;
|
|
2134
2219
|
try {
|
|
2135
2220
|
content = createNodeFromContent(value, editor.schema, {
|
|
2136
2221
|
parseOptions: {
|
|
@@ -2144,7 +2229,9 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
|
|
|
2144
2229
|
editor,
|
|
2145
2230
|
error: e,
|
|
2146
2231
|
disableCollaboration: () => {
|
|
2147
|
-
|
|
2232
|
+
if (editor.storage.collaboration) {
|
|
2233
|
+
editor.storage.collaboration.isDisabled = true;
|
|
2234
|
+
}
|
|
2148
2235
|
}
|
|
2149
2236
|
});
|
|
2150
2237
|
return false;
|
|
@@ -2170,6 +2257,14 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
|
|
|
2170
2257
|
if (isOnlyTextContent) {
|
|
2171
2258
|
if (Array.isArray(value)) {
|
|
2172
2259
|
newContent = value.map((v) => v.text || "").join("");
|
|
2260
|
+
} else if (value instanceof Fragment5) {
|
|
2261
|
+
let text = "";
|
|
2262
|
+
value.forEach((node) => {
|
|
2263
|
+
if (node.text) {
|
|
2264
|
+
text += node.text;
|
|
2265
|
+
}
|
|
2266
|
+
});
|
|
2267
|
+
newContent = text;
|
|
2173
2268
|
} else if (typeof value === "object" && !!value && !!value.text) {
|
|
2174
2269
|
newContent = value.text;
|
|
2175
2270
|
} else {
|
|
@@ -2178,6 +2273,11 @@ var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) =
|
|
|
2178
2273
|
tr.insertText(newContent, from, to);
|
|
2179
2274
|
} else {
|
|
2180
2275
|
newContent = content;
|
|
2276
|
+
const fromSelectionAtStart = selection.$from.parentOffset === 0;
|
|
2277
|
+
const isTextSelection2 = selection.$from.node().isText || selection.$from.node().isTextblock;
|
|
2278
|
+
if (fromSelectionAtStart && isTextSelection2) {
|
|
2279
|
+
from = Math.max(0, from - 1);
|
|
2280
|
+
}
|
|
2181
2281
|
tr.replaceWith(from, to, newContent);
|
|
2182
2282
|
}
|
|
2183
2283
|
if (options.updateSelection) {
|
|
@@ -2269,6 +2369,18 @@ var joinTextblockForward = () => ({ state, dispatch }) => {
|
|
|
2269
2369
|
return originalCommand2(state, dispatch);
|
|
2270
2370
|
};
|
|
2271
2371
|
|
|
2372
|
+
// src/utilities/isiOS.ts
|
|
2373
|
+
function isiOS() {
|
|
2374
|
+
return [
|
|
2375
|
+
"iPad Simulator",
|
|
2376
|
+
"iPhone Simulator",
|
|
2377
|
+
"iPod Simulator",
|
|
2378
|
+
"iPad",
|
|
2379
|
+
"iPhone",
|
|
2380
|
+
"iPod"
|
|
2381
|
+
].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2272
2384
|
// src/utilities/isMacOS.ts
|
|
2273
2385
|
function isMacOS() {
|
|
2274
2386
|
return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
|
|
@@ -2482,11 +2594,13 @@ var scrollIntoView = () => ({ tr, dispatch }) => {
|
|
|
2482
2594
|
};
|
|
2483
2595
|
|
|
2484
2596
|
// src/commands/selectAll.ts
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2597
|
+
import { AllSelection } from "@tiptap/pm/state";
|
|
2598
|
+
var selectAll = () => ({ tr, dispatch }) => {
|
|
2599
|
+
if (dispatch) {
|
|
2600
|
+
const selection = new AllSelection(tr.doc);
|
|
2601
|
+
tr.setSelection(selection);
|
|
2602
|
+
}
|
|
2603
|
+
return true;
|
|
2490
2604
|
};
|
|
2491
2605
|
|
|
2492
2606
|
// src/commands/selectNodeBackward.ts
|
|
@@ -2549,14 +2663,10 @@ var setContent = (content, emitUpdate = false, parseOptions = {}, options = {})
|
|
|
2549
2663
|
if (dispatch) {
|
|
2550
2664
|
tr.setMeta("preventUpdate", !emitUpdate);
|
|
2551
2665
|
}
|
|
2552
|
-
return commands.insertContentAt(
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
parseOptions,
|
|
2557
|
-
errorOnInvalidContent: (_b = options.errorOnInvalidContent) != null ? _b : editor.options.enableContentCheck
|
|
2558
|
-
}
|
|
2559
|
-
);
|
|
2666
|
+
return commands.insertContentAt({ from: 0, to: doc.content.size }, content, {
|
|
2667
|
+
parseOptions,
|
|
2668
|
+
errorOnInvalidContent: (_b = options.errorOnInvalidContent) != null ? _b : editor.options.enableContentCheck
|
|
2669
|
+
});
|
|
2560
2670
|
};
|
|
2561
2671
|
|
|
2562
2672
|
// src/helpers/getMarkAttributes.ts
|
|
@@ -2655,16 +2765,6 @@ function findParentNode(predicate) {
|
|
|
2655
2765
|
// src/helpers/generateHTML.ts
|
|
2656
2766
|
import { Node } from "@tiptap/pm/model";
|
|
2657
2767
|
|
|
2658
|
-
// src/helpers/getHTMLFromFragment.ts
|
|
2659
|
-
import { DOMSerializer } from "@tiptap/pm/model";
|
|
2660
|
-
function getHTMLFromFragment(fragment, schema) {
|
|
2661
|
-
const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
2662
|
-
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
2663
|
-
const container = temporaryDocument.createElement("div");
|
|
2664
|
-
container.appendChild(documentFragment);
|
|
2665
|
-
return container.innerHTML;
|
|
2666
|
-
}
|
|
2667
|
-
|
|
2668
2768
|
// src/helpers/getSchema.ts
|
|
2669
2769
|
function getSchema(extensions, editor) {
|
|
2670
2770
|
const resolvedExtensions = ExtensionManager.resolve(extensions);
|
|
@@ -3173,18 +3273,22 @@ var setMeta = (key, value) => ({ tr }) => {
|
|
|
3173
3273
|
import { setBlockType } from "@tiptap/pm/commands";
|
|
3174
3274
|
var setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
|
|
3175
3275
|
const type = getNodeType(typeOrName, state.schema);
|
|
3276
|
+
let attributesToCopy;
|
|
3277
|
+
if (state.selection.$anchor.sameParent(state.selection.$head)) {
|
|
3278
|
+
attributesToCopy = state.selection.$anchor.parent.attrs;
|
|
3279
|
+
}
|
|
3176
3280
|
if (!type.isTextblock) {
|
|
3177
3281
|
console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
|
|
3178
3282
|
return false;
|
|
3179
3283
|
}
|
|
3180
3284
|
return chain().command(({ commands }) => {
|
|
3181
|
-
const canSetBlock = setBlockType(type, attributes)(state);
|
|
3285
|
+
const canSetBlock = setBlockType(type, { ...attributesToCopy, ...attributes })(state);
|
|
3182
3286
|
if (canSetBlock) {
|
|
3183
3287
|
return true;
|
|
3184
3288
|
}
|
|
3185
3289
|
return commands.clearNodes();
|
|
3186
3290
|
}).command(({ state: updatedState }) => {
|
|
3187
|
-
return setBlockType(type, attributes)(updatedState, dispatch);
|
|
3291
|
+
return setBlockType(type, { ...attributesToCopy, ...attributes })(updatedState, dispatch);
|
|
3188
3292
|
}).run();
|
|
3189
3293
|
};
|
|
3190
3294
|
|
|
@@ -3304,7 +3408,7 @@ var splitBlock = ({ keepMarks = true } = {}) => ({
|
|
|
3304
3408
|
|
|
3305
3409
|
// src/commands/splitListItem.ts
|
|
3306
3410
|
import {
|
|
3307
|
-
Fragment as
|
|
3411
|
+
Fragment as Fragment6,
|
|
3308
3412
|
Slice
|
|
3309
3413
|
} from "@tiptap/pm/model";
|
|
3310
3414
|
import { TextSelection as TextSelection8 } from "@tiptap/pm/state";
|
|
@@ -3332,10 +3436,10 @@ var splitListItem = (typeOrName, overrideAttrs = {}) => ({
|
|
|
3332
3436
|
return false;
|
|
3333
3437
|
}
|
|
3334
3438
|
if (dispatch) {
|
|
3335
|
-
let wrap =
|
|
3439
|
+
let wrap = Fragment6.empty;
|
|
3336
3440
|
const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
|
|
3337
3441
|
for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
|
|
3338
|
-
wrap =
|
|
3442
|
+
wrap = Fragment6.from($from.node(d).copy(wrap));
|
|
3339
3443
|
}
|
|
3340
3444
|
const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
|
|
3341
3445
|
const newNextTypeAttributes2 = {
|
|
@@ -3347,7 +3451,7 @@ var splitListItem = (typeOrName, overrideAttrs = {}) => ({
|
|
|
3347
3451
|
...overrideAttrs
|
|
3348
3452
|
};
|
|
3349
3453
|
const nextType2 = ((_a = type.contentMatch.defaultType) == null ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
|
|
3350
|
-
wrap = wrap.append(
|
|
3454
|
+
wrap = wrap.append(Fragment6.from(type.createAndFill(null, nextType2) || void 0));
|
|
3351
3455
|
const start = $from.before($from.depth - (depthBefore - 1));
|
|
3352
3456
|
tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
|
|
3353
3457
|
let sel = -1;
|
|
@@ -3508,10 +3612,14 @@ var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, co
|
|
|
3508
3612
|
const type = getNodeType(typeOrName, state.schema);
|
|
3509
3613
|
const toggleType = getNodeType(toggleTypeOrName, state.schema);
|
|
3510
3614
|
const isActive2 = isNodeActive(state, type, attributes);
|
|
3615
|
+
let attributesToCopy;
|
|
3616
|
+
if (state.selection.$anchor.sameParent(state.selection.$head)) {
|
|
3617
|
+
attributesToCopy = state.selection.$anchor.parent.attrs;
|
|
3618
|
+
}
|
|
3511
3619
|
if (isActive2) {
|
|
3512
|
-
return commands.setNode(toggleType);
|
|
3620
|
+
return commands.setNode(toggleType, attributesToCopy);
|
|
3513
3621
|
}
|
|
3514
|
-
return commands.setNode(type, attributes);
|
|
3622
|
+
return commands.setNode(type, { ...attributesToCopy, ...attributes });
|
|
3515
3623
|
};
|
|
3516
3624
|
|
|
3517
3625
|
// src/commands/toggleWrap.ts
|
|
@@ -3614,18 +3722,63 @@ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }
|
|
|
3614
3722
|
tr.selection.ranges.forEach((range) => {
|
|
3615
3723
|
const from = range.$from.pos;
|
|
3616
3724
|
const to = range.$to.pos;
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3725
|
+
let lastPos;
|
|
3726
|
+
let lastNode;
|
|
3727
|
+
let trimmedFrom;
|
|
3728
|
+
let trimmedTo;
|
|
3729
|
+
if (tr.selection.empty) {
|
|
3730
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
3731
|
+
if (nodeType && nodeType === node.type) {
|
|
3732
|
+
trimmedFrom = Math.max(pos, from);
|
|
3733
|
+
trimmedTo = Math.min(pos + node.nodeSize, to);
|
|
3734
|
+
lastPos = pos;
|
|
3735
|
+
lastNode = node;
|
|
3736
|
+
}
|
|
3737
|
+
});
|
|
3738
|
+
} else {
|
|
3739
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
3740
|
+
if (pos < from && nodeType && nodeType === node.type) {
|
|
3741
|
+
trimmedFrom = Math.max(pos, from);
|
|
3742
|
+
trimmedTo = Math.min(pos + node.nodeSize, to);
|
|
3743
|
+
lastPos = pos;
|
|
3744
|
+
lastNode = node;
|
|
3745
|
+
}
|
|
3746
|
+
if (pos >= from && pos <= to) {
|
|
3747
|
+
if (nodeType && nodeType === node.type) {
|
|
3748
|
+
tr.setNodeMarkup(pos, void 0, {
|
|
3749
|
+
...node.attrs,
|
|
3750
|
+
...attributes
|
|
3751
|
+
});
|
|
3752
|
+
}
|
|
3753
|
+
if (markType && node.marks.length) {
|
|
3754
|
+
node.marks.forEach((mark) => {
|
|
3755
|
+
if (markType === mark.type) {
|
|
3756
|
+
const trimmedFrom2 = Math.max(pos, from);
|
|
3757
|
+
const trimmedTo2 = Math.min(pos + node.nodeSize, to);
|
|
3758
|
+
tr.addMark(
|
|
3759
|
+
trimmedFrom2,
|
|
3760
|
+
trimmedTo2,
|
|
3761
|
+
markType.create({
|
|
3762
|
+
...mark.attrs,
|
|
3763
|
+
...attributes
|
|
3764
|
+
})
|
|
3765
|
+
);
|
|
3766
|
+
}
|
|
3767
|
+
});
|
|
3768
|
+
}
|
|
3769
|
+
}
|
|
3770
|
+
});
|
|
3771
|
+
}
|
|
3772
|
+
if (lastNode) {
|
|
3773
|
+
if (lastPos !== void 0) {
|
|
3774
|
+
tr.setNodeMarkup(lastPos, void 0, {
|
|
3775
|
+
...lastNode.attrs,
|
|
3621
3776
|
...attributes
|
|
3622
3777
|
});
|
|
3623
3778
|
}
|
|
3624
|
-
if (markType &&
|
|
3625
|
-
|
|
3779
|
+
if (markType && lastNode.marks.length) {
|
|
3780
|
+
lastNode.marks.forEach((mark) => {
|
|
3626
3781
|
if (markType === mark.type) {
|
|
3627
|
-
const trimmedFrom = Math.max(pos, from);
|
|
3628
|
-
const trimmedTo = Math.min(pos + node.nodeSize, to);
|
|
3629
3782
|
tr.addMark(
|
|
3630
3783
|
trimmedFrom,
|
|
3631
3784
|
trimmedTo,
|
|
@@ -3637,7 +3790,7 @@ var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }
|
|
|
3637
3790
|
}
|
|
3638
3791
|
});
|
|
3639
3792
|
}
|
|
3640
|
-
}
|
|
3793
|
+
}
|
|
3641
3794
|
});
|
|
3642
3795
|
}
|
|
3643
3796
|
return true;
|
|
@@ -3667,14 +3820,37 @@ var Commands = Extension.create({
|
|
|
3667
3820
|
}
|
|
3668
3821
|
});
|
|
3669
3822
|
|
|
3670
|
-
// src/extensions/
|
|
3823
|
+
// src/extensions/drop.ts
|
|
3671
3824
|
import { Plugin as Plugin4, PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
3825
|
+
var Drop = Extension.create({
|
|
3826
|
+
name: "drop",
|
|
3827
|
+
addProseMirrorPlugins() {
|
|
3828
|
+
return [
|
|
3829
|
+
new Plugin4({
|
|
3830
|
+
key: new PluginKey2("tiptapDrop"),
|
|
3831
|
+
props: {
|
|
3832
|
+
handleDrop: (_, e, slice, moved) => {
|
|
3833
|
+
this.editor.emit("drop", {
|
|
3834
|
+
editor: this.editor,
|
|
3835
|
+
event: e,
|
|
3836
|
+
slice,
|
|
3837
|
+
moved
|
|
3838
|
+
});
|
|
3839
|
+
}
|
|
3840
|
+
}
|
|
3841
|
+
})
|
|
3842
|
+
];
|
|
3843
|
+
}
|
|
3844
|
+
});
|
|
3845
|
+
|
|
3846
|
+
// src/extensions/editable.ts
|
|
3847
|
+
import { Plugin as Plugin5, PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
3672
3848
|
var Editable = Extension.create({
|
|
3673
3849
|
name: "editable",
|
|
3674
3850
|
addProseMirrorPlugins() {
|
|
3675
3851
|
return [
|
|
3676
|
-
new
|
|
3677
|
-
key: new
|
|
3852
|
+
new Plugin5({
|
|
3853
|
+
key: new PluginKey3("editable"),
|
|
3678
3854
|
props: {
|
|
3679
3855
|
editable: () => this.editor.options.editable
|
|
3680
3856
|
}
|
|
@@ -3684,14 +3860,14 @@ var Editable = Extension.create({
|
|
|
3684
3860
|
});
|
|
3685
3861
|
|
|
3686
3862
|
// src/extensions/focusEvents.ts
|
|
3687
|
-
import { Plugin as
|
|
3863
|
+
import { Plugin as Plugin6, PluginKey as PluginKey4 } from "@tiptap/pm/state";
|
|
3688
3864
|
var FocusEvents = Extension.create({
|
|
3689
3865
|
name: "focusEvents",
|
|
3690
3866
|
addProseMirrorPlugins() {
|
|
3691
3867
|
const { editor } = this;
|
|
3692
3868
|
return [
|
|
3693
|
-
new
|
|
3694
|
-
key: new
|
|
3869
|
+
new Plugin6({
|
|
3870
|
+
key: new PluginKey4("focusEvents"),
|
|
3695
3871
|
props: {
|
|
3696
3872
|
handleDOMEvents: {
|
|
3697
3873
|
focus: (view, event) => {
|
|
@@ -3714,7 +3890,7 @@ var FocusEvents = Extension.create({
|
|
|
3714
3890
|
});
|
|
3715
3891
|
|
|
3716
3892
|
// src/extensions/keymap.ts
|
|
3717
|
-
import { Plugin as
|
|
3893
|
+
import { Plugin as Plugin7, PluginKey as PluginKey5, Selection as Selection3 } from "@tiptap/pm/state";
|
|
3718
3894
|
var Keymap = Extension.create({
|
|
3719
3895
|
name: "keymap",
|
|
3720
3896
|
addKeyboardShortcuts() {
|
|
@@ -3786,11 +3962,12 @@ var Keymap = Extension.create({
|
|
|
3786
3962
|
// to a paragraph if necessary.
|
|
3787
3963
|
// This is an alternative to ProseMirror's `AllSelection`, which doesn’t work well
|
|
3788
3964
|
// with many other commands.
|
|
3789
|
-
new
|
|
3790
|
-
key: new
|
|
3965
|
+
new Plugin7({
|
|
3966
|
+
key: new PluginKey5("clearDocument"),
|
|
3791
3967
|
appendTransaction: (transactions, oldState, newState) => {
|
|
3792
3968
|
const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
|
|
3793
|
-
|
|
3969
|
+
const ignoreTr = transactions.some((transaction) => transaction.getMeta("preventClearDocument"));
|
|
3970
|
+
if (!docChanges || ignoreTr) {
|
|
3794
3971
|
return;
|
|
3795
3972
|
}
|
|
3796
3973
|
const { empty, from, to } = oldState.selection;
|
|
@@ -3800,7 +3977,7 @@ var Keymap = Extension.create({
|
|
|
3800
3977
|
if (empty || !allWasSelected) {
|
|
3801
3978
|
return;
|
|
3802
3979
|
}
|
|
3803
|
-
const isEmpty =
|
|
3980
|
+
const isEmpty = isNodeEmpty(newState.doc);
|
|
3804
3981
|
if (!isEmpty) {
|
|
3805
3982
|
return;
|
|
3806
3983
|
}
|
|
@@ -3824,14 +4001,36 @@ var Keymap = Extension.create({
|
|
|
3824
4001
|
}
|
|
3825
4002
|
});
|
|
3826
4003
|
|
|
4004
|
+
// src/extensions/paste.ts
|
|
4005
|
+
import { Plugin as Plugin8, PluginKey as PluginKey6 } from "@tiptap/pm/state";
|
|
4006
|
+
var Paste = Extension.create({
|
|
4007
|
+
name: "paste",
|
|
4008
|
+
addProseMirrorPlugins() {
|
|
4009
|
+
return [
|
|
4010
|
+
new Plugin8({
|
|
4011
|
+
key: new PluginKey6("tiptapPaste"),
|
|
4012
|
+
props: {
|
|
4013
|
+
handlePaste: (_view, e, slice) => {
|
|
4014
|
+
this.editor.emit("paste", {
|
|
4015
|
+
editor: this.editor,
|
|
4016
|
+
event: e,
|
|
4017
|
+
slice
|
|
4018
|
+
});
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
})
|
|
4022
|
+
];
|
|
4023
|
+
}
|
|
4024
|
+
});
|
|
4025
|
+
|
|
3827
4026
|
// src/extensions/tabindex.ts
|
|
3828
|
-
import { Plugin as
|
|
4027
|
+
import { Plugin as Plugin9, PluginKey as PluginKey7 } from "@tiptap/pm/state";
|
|
3829
4028
|
var Tabindex = Extension.create({
|
|
3830
4029
|
name: "tabindex",
|
|
3831
4030
|
addProseMirrorPlugins() {
|
|
3832
4031
|
return [
|
|
3833
|
-
new
|
|
3834
|
-
key: new
|
|
4032
|
+
new Plugin9({
|
|
4033
|
+
key: new PluginKey7("tabindex"),
|
|
3835
4034
|
props: {
|
|
3836
4035
|
attributes: () => this.editor.isEditable ? { tabindex: "0" } : {}
|
|
3837
4036
|
}
|
|
@@ -3935,7 +4134,8 @@ var NodePos = class _NodePos {
|
|
|
3935
4134
|
const children = [];
|
|
3936
4135
|
this.node.content.forEach((node, offset) => {
|
|
3937
4136
|
const isBlock = node.isBlock && !node.isTextblock;
|
|
3938
|
-
const
|
|
4137
|
+
const isNonTextAtom = node.isAtom && !node.isText;
|
|
4138
|
+
const targetPos = this.pos + offset + (isNonTextAtom ? 0 : 1);
|
|
3939
4139
|
const $pos = this.resolvedPos.doc.resolve(targetPos);
|
|
3940
4140
|
if (!isBlock && $pos.depth <= this.depth) {
|
|
3941
4141
|
return;
|
|
@@ -4004,8 +4204,12 @@ var NodePos = class _NodePos {
|
|
|
4004
4204
|
return nodes;
|
|
4005
4205
|
}
|
|
4006
4206
|
setAttribute(attributes) {
|
|
4007
|
-
const
|
|
4008
|
-
|
|
4207
|
+
const { tr } = this.editor.state;
|
|
4208
|
+
tr.setNodeMarkup(this.from, void 0, {
|
|
4209
|
+
...this.node.attrs,
|
|
4210
|
+
...attributes
|
|
4211
|
+
});
|
|
4212
|
+
this.editor.view.dispatch(tr);
|
|
4009
4213
|
}
|
|
4010
4214
|
};
|
|
4011
4215
|
|
|
@@ -4108,6 +4312,10 @@ var Editor = class extends EventEmitter {
|
|
|
4108
4312
|
*/
|
|
4109
4313
|
this.isInitialized = false;
|
|
4110
4314
|
this.extensionStorage = {};
|
|
4315
|
+
/**
|
|
4316
|
+
* A unique ID for this editor instance.
|
|
4317
|
+
*/
|
|
4318
|
+
this.instanceId = Math.random().toString(36).slice(2, 9);
|
|
4111
4319
|
this.options = {
|
|
4112
4320
|
element: document.createElement("div"),
|
|
4113
4321
|
content: "",
|
|
@@ -4133,7 +4341,9 @@ var Editor = class extends EventEmitter {
|
|
|
4133
4341
|
onDestroy: () => null,
|
|
4134
4342
|
onContentError: ({ error }) => {
|
|
4135
4343
|
throw error;
|
|
4136
|
-
}
|
|
4344
|
+
},
|
|
4345
|
+
onPaste: () => null,
|
|
4346
|
+
onDrop: () => null
|
|
4137
4347
|
};
|
|
4138
4348
|
this.isCapturingTransaction = false;
|
|
4139
4349
|
this.capturedTransaction = null;
|
|
@@ -4153,6 +4363,8 @@ var Editor = class extends EventEmitter {
|
|
|
4153
4363
|
this.on("focus", this.options.onFocus);
|
|
4154
4364
|
this.on("blur", this.options.onBlur);
|
|
4155
4365
|
this.on("destroy", this.options.onDestroy);
|
|
4366
|
+
this.on("drop", ({ event, slice, moved }) => this.options.onDrop(event, slice, moved));
|
|
4367
|
+
this.on("paste", ({ event, slice }) => this.options.onPaste(event, slice));
|
|
4156
4368
|
window.setTimeout(() => {
|
|
4157
4369
|
if (this.isDestroyed) {
|
|
4158
4370
|
return;
|
|
@@ -4238,27 +4450,38 @@ var Editor = class extends EventEmitter {
|
|
|
4238
4450
|
*
|
|
4239
4451
|
* @param plugin A ProseMirror plugin
|
|
4240
4452
|
* @param handlePlugins Control how to merge the plugin into the existing plugins.
|
|
4453
|
+
* @returns The new editor state
|
|
4241
4454
|
*/
|
|
4242
4455
|
registerPlugin(plugin, handlePlugins) {
|
|
4243
4456
|
const plugins = isFunction(handlePlugins) ? handlePlugins(plugin, [...this.state.plugins]) : [...this.state.plugins, plugin];
|
|
4244
4457
|
const state = this.state.reconfigure({ plugins });
|
|
4245
4458
|
this.view.updateState(state);
|
|
4459
|
+
return state;
|
|
4246
4460
|
}
|
|
4247
4461
|
/**
|
|
4248
4462
|
* Unregister a ProseMirror plugin.
|
|
4249
4463
|
*
|
|
4250
|
-
* @param
|
|
4464
|
+
* @param nameOrPluginKeyToRemove The plugins name
|
|
4465
|
+
* @returns The new editor state or undefined if the editor is destroyed
|
|
4251
4466
|
*/
|
|
4252
|
-
unregisterPlugin(
|
|
4467
|
+
unregisterPlugin(nameOrPluginKeyToRemove) {
|
|
4253
4468
|
if (this.isDestroyed) {
|
|
4254
|
-
return;
|
|
4469
|
+
return void 0;
|
|
4470
|
+
}
|
|
4471
|
+
const prevPlugins = this.state.plugins;
|
|
4472
|
+
let plugins = prevPlugins;
|
|
4473
|
+
[].concat(nameOrPluginKeyToRemove).forEach((nameOrPluginKey) => {
|
|
4474
|
+
const name = typeof nameOrPluginKey === "string" ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
|
|
4475
|
+
plugins = prevPlugins.filter((plugin) => !plugin.key.startsWith(name));
|
|
4476
|
+
});
|
|
4477
|
+
if (prevPlugins.length === plugins.length) {
|
|
4478
|
+
return void 0;
|
|
4255
4479
|
}
|
|
4256
|
-
const name = typeof nameOrPluginKey === "string" ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
|
|
4257
4480
|
const state = this.state.reconfigure({
|
|
4258
|
-
|
|
4259
|
-
plugins: this.state.plugins.filter((plugin) => !plugin.key.startsWith(name))
|
|
4481
|
+
plugins
|
|
4260
4482
|
});
|
|
4261
4483
|
this.view.updateState(state);
|
|
4484
|
+
return state;
|
|
4262
4485
|
}
|
|
4263
4486
|
/**
|
|
4264
4487
|
* Creates an extension manager.
|
|
@@ -4273,8 +4496,15 @@ var Editor = class extends EventEmitter {
|
|
|
4273
4496
|
Commands,
|
|
4274
4497
|
FocusEvents,
|
|
4275
4498
|
Keymap,
|
|
4276
|
-
Tabindex
|
|
4277
|
-
|
|
4499
|
+
Tabindex,
|
|
4500
|
+
Drop,
|
|
4501
|
+
Paste
|
|
4502
|
+
].filter((ext) => {
|
|
4503
|
+
if (typeof this.options.enableCoreExtensions === "object") {
|
|
4504
|
+
return this.options.enableCoreExtensions[ext.name] !== false;
|
|
4505
|
+
}
|
|
4506
|
+
return true;
|
|
4507
|
+
}) : [];
|
|
4278
4508
|
const allExtensions = [...coreExtensions, ...this.options.extensions].filter((extension) => {
|
|
4279
4509
|
return ["extension", "node", "mark"].includes(extension == null ? void 0 : extension.type);
|
|
4280
4510
|
});
|
|
@@ -4298,6 +4528,7 @@ var Editor = class extends EventEmitter {
|
|
|
4298
4528
|
* Creates a ProseMirror view.
|
|
4299
4529
|
*/
|
|
4300
4530
|
createView() {
|
|
4531
|
+
var _a;
|
|
4301
4532
|
let doc;
|
|
4302
4533
|
try {
|
|
4303
4534
|
doc = createDocument(
|
|
@@ -4314,6 +4545,9 @@ var Editor = class extends EventEmitter {
|
|
|
4314
4545
|
editor: this,
|
|
4315
4546
|
error: e,
|
|
4316
4547
|
disableCollaboration: () => {
|
|
4548
|
+
if (this.storage.collaboration) {
|
|
4549
|
+
this.storage.collaboration.isDisabled = true;
|
|
4550
|
+
}
|
|
4317
4551
|
this.options.extensions = this.options.extensions.filter((extension) => extension.name !== "collaboration");
|
|
4318
4552
|
this.createExtensionManager();
|
|
4319
4553
|
}
|
|
@@ -4328,6 +4562,11 @@ var Editor = class extends EventEmitter {
|
|
|
4328
4562
|
const selection = resolveFocusPosition(doc, this.options.autofocus);
|
|
4329
4563
|
this.view = new EditorView(this.options.element, {
|
|
4330
4564
|
...this.options.editorProps,
|
|
4565
|
+
attributes: {
|
|
4566
|
+
// add `role="textbox"` to the editor element
|
|
4567
|
+
role: "textbox",
|
|
4568
|
+
...(_a = this.options.editorProps) == null ? void 0 : _a.attributes
|
|
4569
|
+
},
|
|
4331
4570
|
dispatchTransaction: this.dispatchTransaction.bind(this),
|
|
4332
4571
|
state: EditorState4.create({
|
|
4333
4572
|
doc,
|
|
@@ -4489,6 +4728,10 @@ var Editor = class extends EventEmitter {
|
|
|
4489
4728
|
destroy() {
|
|
4490
4729
|
this.emit("destroy");
|
|
4491
4730
|
if (this.view) {
|
|
4731
|
+
const dom = this.view.dom;
|
|
4732
|
+
if (dom && dom.editor) {
|
|
4733
|
+
delete dom.editor;
|
|
4734
|
+
}
|
|
4492
4735
|
this.view.destroy();
|
|
4493
4736
|
}
|
|
4494
4737
|
this.removeAllListeners();
|
|
@@ -4763,6 +5006,9 @@ var NodeView = class {
|
|
|
4763
5006
|
this.extension = props.extension;
|
|
4764
5007
|
this.node = props.node;
|
|
4765
5008
|
this.decorations = props.decorations;
|
|
5009
|
+
this.innerDecorations = props.innerDecorations;
|
|
5010
|
+
this.view = props.view;
|
|
5011
|
+
this.HTMLAttributes = props.HTMLAttributes;
|
|
4766
5012
|
this.getPos = props.getPos;
|
|
4767
5013
|
this.mount();
|
|
4768
5014
|
}
|
|
@@ -4794,7 +5040,11 @@ var NodeView = class {
|
|
|
4794
5040
|
y = handleBox.y - domBox.y + offsetY;
|
|
4795
5041
|
}
|
|
4796
5042
|
(_g = event.dataTransfer) == null ? void 0 : _g.setDragImage(this.dom, x, y);
|
|
4797
|
-
const
|
|
5043
|
+
const pos = this.getPos();
|
|
5044
|
+
if (typeof pos !== "number") {
|
|
5045
|
+
return;
|
|
5046
|
+
}
|
|
5047
|
+
const selection = NodeSelection4.create(view.state.doc, pos);
|
|
4798
5048
|
const transaction = view.state.tr.setSelection(selection);
|
|
4799
5049
|
view.dispatch(transaction);
|
|
4800
5050
|
}
|
|
@@ -4825,10 +5075,10 @@ var NodeView = class {
|
|
|
4825
5075
|
const isPasteEvent = event.type === "paste";
|
|
4826
5076
|
const isCutEvent = event.type === "cut";
|
|
4827
5077
|
const isClickEvent = event.type === "mousedown";
|
|
4828
|
-
if (!isDraggable && isSelectable && isDragEvent) {
|
|
5078
|
+
if (!isDraggable && isSelectable && isDragEvent && event.target === this.dom) {
|
|
4829
5079
|
event.preventDefault();
|
|
4830
5080
|
}
|
|
4831
|
-
if (isDraggable && isDragEvent && !isDragging) {
|
|
5081
|
+
if (isDraggable && isDragEvent && !isDragging && event.target === this.dom) {
|
|
4832
5082
|
event.preventDefault();
|
|
4833
5083
|
return false;
|
|
4834
5084
|
}
|
|
@@ -4865,6 +5115,11 @@ var NodeView = class {
|
|
|
4865
5115
|
}
|
|
4866
5116
|
return true;
|
|
4867
5117
|
}
|
|
5118
|
+
/**
|
|
5119
|
+
* Called when a DOM [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) or a selection change happens within the view.
|
|
5120
|
+
* @return `false` if the editor should re-read the selection or re-parse the range around the mutation
|
|
5121
|
+
* @return `true` if it can safely be ignored.
|
|
5122
|
+
*/
|
|
4868
5123
|
ignoreMutation(mutation) {
|
|
4869
5124
|
if (!this.dom || !this.contentDOM) {
|
|
4870
5125
|
return true;
|
|
@@ -4895,9 +5150,15 @@ var NodeView = class {
|
|
|
4895
5150
|
}
|
|
4896
5151
|
return true;
|
|
4897
5152
|
}
|
|
5153
|
+
/**
|
|
5154
|
+
* Update the attributes of the prosemirror node.
|
|
5155
|
+
*/
|
|
4898
5156
|
updateAttributes(attributes) {
|
|
4899
5157
|
this.editor.commands.command(({ tr }) => {
|
|
4900
5158
|
const pos = this.getPos();
|
|
5159
|
+
if (typeof pos !== "number") {
|
|
5160
|
+
return false;
|
|
5161
|
+
}
|
|
4901
5162
|
tr.setNodeMarkup(pos, void 0, {
|
|
4902
5163
|
...this.node.attrs,
|
|
4903
5164
|
...attributes
|
|
@@ -4905,8 +5166,14 @@ var NodeView = class {
|
|
|
4905
5166
|
return true;
|
|
4906
5167
|
});
|
|
4907
5168
|
}
|
|
5169
|
+
/**
|
|
5170
|
+
* Delete the node.
|
|
5171
|
+
*/
|
|
4908
5172
|
deleteNode() {
|
|
4909
5173
|
const from = this.getPos();
|
|
5174
|
+
if (typeof from !== "number") {
|
|
5175
|
+
return;
|
|
5176
|
+
}
|
|
4910
5177
|
const to = from + this.node.nodeSize;
|
|
4911
5178
|
this.editor.commands.deleteRange({ from, to });
|
|
4912
5179
|
}
|