@tiptap/core 2.0.0-beta.21 → 2.0.0-beta.210
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/README.md +2 -2
- package/dist/index.cjs +4311 -0
- package/dist/index.d.ts +2330 -0
- package/dist/index.js +4311 -0
- package/package.json +39 -25
- package/src/CommandManager.ts +76 -86
- package/src/Editor.ts +120 -81
- package/src/EventEmitter.ts +14 -4
- package/src/Extension.ts +280 -108
- package/src/ExtensionManager.ts +254 -108
- package/src/InputRule.ts +260 -0
- package/src/Mark.ts +398 -147
- package/src/Node.ts +437 -171
- package/src/NodeView.ts +132 -63
- package/src/PasteRule.ts +240 -0
- package/src/Tracker.ts +38 -0
- package/src/commands/blur.ts +12 -6
- package/src/commands/clearContent.ts +3 -3
- package/src/commands/clearNodes.ts +31 -19
- package/src/commands/command.ts +2 -2
- package/src/commands/createParagraphNear.ts +5 -4
- package/src/commands/deleteCurrentNode.ts +41 -0
- package/src/commands/deleteNode.ts +37 -0
- package/src/commands/deleteRange.ts +3 -3
- package/src/commands/deleteSelection.ts +5 -4
- package/src/commands/enter.ts +3 -3
- package/src/commands/exitCode.ts +5 -4
- package/src/commands/extendMarkRange.ts +16 -12
- package/src/commands/first.ts +3 -3
- package/src/commands/focus.ts +47 -44
- package/src/commands/forEach.ts +24 -0
- package/src/commands/index.ts +50 -0
- package/src/commands/insertContent.ts +17 -24
- package/src/commands/insertContentAt.ts +94 -0
- package/src/commands/join.ts +53 -0
- package/src/commands/keyboardShortcut.ts +6 -6
- package/src/commands/lift.ts +8 -7
- package/src/commands/liftEmptyBlock.ts +5 -4
- package/src/commands/liftListItem.ts +7 -6
- package/src/commands/newlineInCode.ts +5 -4
- package/src/commands/resetAttributes.ts +18 -12
- package/src/commands/scrollIntoView.ts +3 -3
- package/src/commands/selectAll.ts +8 -6
- package/src/commands/selectNodeBackward.ts +5 -4
- package/src/commands/selectNodeForward.ts +5 -4
- package/src/commands/selectParentNode.ts +5 -4
- package/src/commands/selectTextblockEnd.ts +20 -0
- package/src/commands/selectTextblockStart.ts +20 -0
- package/src/commands/setContent.ts +9 -16
- package/src/commands/setMark.ts +90 -14
- package/src/commands/setMeta.ts +18 -0
- package/src/commands/setNode.ts +32 -8
- package/src/commands/setNodeSelection.ts +27 -0
- package/src/commands/setTextSelection.ts +31 -0
- package/src/commands/sinkListItem.ts +7 -6
- package/src/commands/splitBlock.ts +31 -41
- package/src/commands/splitListItem.ts +46 -29
- package/src/commands/toggleList.ts +88 -20
- package/src/commands/toggleMark.ts +19 -8
- package/src/commands/toggleNode.ts +11 -6
- package/src/commands/toggleWrap.ts +10 -10
- package/src/commands/undoInputRule.ts +34 -5
- package/src/commands/unsetAllMarks.ts +7 -11
- package/src/commands/unsetMark.ts +36 -23
- package/src/commands/updateAttributes.ts +27 -15
- package/src/commands/wrapIn.ts +7 -12
- package/src/commands/wrapInList.ts +7 -6
- package/src/extensions/clipboardTextSerializer.ts +15 -36
- package/src/extensions/commands.ts +3 -147
- package/src/extensions/editable.ts +2 -1
- package/src/extensions/focusEvents.ts +4 -6
- package/src/extensions/index.ts +1 -0
- package/src/extensions/keymap.ts +106 -13
- package/src/extensions/tabindex.ts +18 -0
- package/src/helpers/combineTransactionSteps.ts +21 -0
- package/src/helpers/createChainableState.ts +38 -0
- package/src/helpers/createDocument.ts +5 -6
- package/src/helpers/createNodeFromContent.ts +20 -28
- package/src/helpers/defaultBlockAt.ts +13 -0
- package/src/helpers/findChildren.ts +18 -0
- package/src/helpers/findChildrenInRange.ts +36 -0
- package/src/helpers/findParentNode.ts +4 -3
- package/src/helpers/findParentNodeClosestToPos.ts +13 -7
- package/src/helpers/generateHTML.ts +7 -6
- package/src/helpers/generateJSON.ts +12 -0
- package/src/helpers/generateText.ts +27 -0
- package/src/helpers/getAttributes.ts +26 -0
- package/src/helpers/getAttributesFromExtensions.ts +42 -14
- package/src/helpers/getChangedRanges.ts +83 -0
- package/src/helpers/getDebugJSON.ts +54 -0
- package/src/helpers/getExtensionField.ts +25 -0
- package/src/helpers/getHTMLFromFragment.ts +5 -6
- package/src/helpers/getMarkAttributes.ts +18 -11
- package/src/helpers/getMarkRange.ts +41 -8
- package/src/helpers/getMarkType.ts +8 -2
- package/src/helpers/getMarksBetween.ts +34 -10
- package/src/helpers/getNodeAttributes.ts +14 -13
- package/src/helpers/getNodeType.ts +8 -2
- package/src/helpers/getRenderedAttributes.ts +9 -7
- package/src/helpers/getSchema.ts +7 -133
- package/src/helpers/getSchemaByResolvedExtensions.ts +192 -0
- package/src/helpers/getSchemaTypeByName.ts +3 -11
- package/src/helpers/getSchemaTypeNameByName.ts +2 -2
- package/src/helpers/getSplittedAttributes.ts +4 -4
- package/src/helpers/getText.ts +19 -0
- package/src/helpers/getTextBetween.ts +46 -0
- package/src/helpers/getTextContentFromNodes.ts +26 -0
- package/src/helpers/getTextSerializersFromSchema.ts +11 -0
- package/src/helpers/index.ts +33 -0
- package/src/helpers/injectExtensionAttributesToParseRule.ts +22 -23
- package/src/helpers/isActive.ts +10 -6
- package/src/helpers/isExtensionRulesEnabled.ts +15 -0
- package/src/helpers/isList.ts +14 -7
- package/src/helpers/isMarkActive.ts +49 -27
- package/src/helpers/isNodeActive.ts +29 -39
- package/src/helpers/isNodeEmpty.ts +2 -2
- package/src/helpers/isNodeSelection.ts +3 -4
- package/src/helpers/isTextSelection.ts +3 -4
- package/src/helpers/posToDOMRect.ts +35 -0
- package/src/helpers/resolveFocusPosition.ts +42 -0
- package/src/helpers/selectionToInsertionEnd.ts +3 -3
- package/src/helpers/splitExtensions.ts +3 -3
- package/src/index.ts +15 -24
- package/src/inputRules/index.ts +5 -0
- package/src/inputRules/markInputRule.ts +59 -40
- package/src/inputRules/nodeInputRule.ts +45 -12
- package/src/inputRules/textInputRule.ts +35 -0
- package/src/inputRules/textblockTypeInputRule.ts +37 -0
- package/src/inputRules/wrappingInputRule.ts +59 -0
- package/src/pasteRules/index.ts +3 -0
- package/src/pasteRules/markPasteRule.ts +61 -53
- package/src/pasteRules/nodePasteRule.ts +37 -0
- package/src/pasteRules/textPasteRule.ts +35 -0
- package/src/style.ts +16 -3
- package/src/types.ts +170 -97
- package/src/utilities/callOrReturn.ts +6 -3
- package/src/utilities/createStyleTag.ts +12 -1
- package/src/utilities/deleteProps.ts +2 -4
- package/src/utilities/elementFromString.ts +4 -5
- package/src/utilities/escapeForRegEx.ts +4 -0
- package/src/utilities/findDuplicates.ts +5 -0
- package/src/utilities/fromString.ts +2 -2
- package/src/utilities/index.ts +20 -0
- package/src/utilities/isEmptyObject.ts +2 -2
- package/src/utilities/isFunction.ts +3 -0
- package/src/utilities/isMacOS.ts +5 -0
- package/src/utilities/isNumber.ts +3 -0
- package/src/utilities/isPlainObject.ts +8 -5
- package/src/utilities/isRegExp.ts +3 -0
- package/src/utilities/isString.ts +3 -0
- package/src/utilities/isiOS.ts +12 -0
- package/src/utilities/mergeAttributes.ts +2 -3
- package/src/utilities/mergeDeep.ts +2 -3
- package/src/utilities/minMax.ts +1 -1
- package/src/utilities/objectIncludes.ts +17 -5
- package/src/utilities/removeDuplicates.ts +15 -0
- package/CHANGELOG.md +0 -365
- package/LICENSE.md +0 -21
- package/dist/packages/core/src/CommandManager.d.ts +0 -13
- package/dist/packages/core/src/Editor.d.ts +0 -142
- package/dist/packages/core/src/EventEmitter.d.ts +0 -7
- package/dist/packages/core/src/Extension.d.ts +0 -148
- package/dist/packages/core/src/ExtensionManager.d.ts +0 -24
- package/dist/packages/core/src/Mark.d.ts +0 -211
- package/dist/packages/core/src/Node.d.ts +0 -265
- package/dist/packages/core/src/NodeView.d.ts +0 -31
- package/dist/packages/core/src/commands/blur.d.ts +0 -12
- package/dist/packages/core/src/commands/clearContent.d.ts +0 -12
- package/dist/packages/core/src/commands/clearNodes.d.ts +0 -12
- package/dist/packages/core/src/commands/command.d.ts +0 -12
- package/dist/packages/core/src/commands/createParagraphNear.d.ts +0 -12
- package/dist/packages/core/src/commands/deleteRange.d.ts +0 -12
- package/dist/packages/core/src/commands/deleteSelection.d.ts +0 -12
- package/dist/packages/core/src/commands/enter.d.ts +0 -12
- package/dist/packages/core/src/commands/exitCode.d.ts +0 -12
- package/dist/packages/core/src/commands/extendMarkRange.d.ts +0 -13
- package/dist/packages/core/src/commands/first.d.ts +0 -12
- package/dist/packages/core/src/commands/focus.d.ts +0 -12
- package/dist/packages/core/src/commands/insertContent.d.ts +0 -12
- package/dist/packages/core/src/commands/insertHTML.d.ts +0 -12
- package/dist/packages/core/src/commands/insertNode.d.ts +0 -13
- package/dist/packages/core/src/commands/insertText.d.ts +0 -12
- package/dist/packages/core/src/commands/joinBackward.d.ts +0 -12
- package/dist/packages/core/src/commands/joinForward.d.ts +0 -12
- package/dist/packages/core/src/commands/keyboardShortcut.d.ts +0 -12
- package/dist/packages/core/src/commands/lift.d.ts +0 -13
- package/dist/packages/core/src/commands/liftEmptyBlock.d.ts +0 -12
- package/dist/packages/core/src/commands/liftListItem.d.ts +0 -13
- package/dist/packages/core/src/commands/newlineInCode.d.ts +0 -12
- package/dist/packages/core/src/commands/replace.d.ts +0 -13
- package/dist/packages/core/src/commands/replaceRange.d.ts +0 -13
- package/dist/packages/core/src/commands/resetAttributes.d.ts +0 -13
- package/dist/packages/core/src/commands/resetNodeAttributes.d.ts +0 -13
- package/dist/packages/core/src/commands/scrollIntoView.d.ts +0 -12
- package/dist/packages/core/src/commands/selectAll.d.ts +0 -12
- package/dist/packages/core/src/commands/selectNodeBackward.d.ts +0 -12
- package/dist/packages/core/src/commands/selectNodeForward.d.ts +0 -12
- package/dist/packages/core/src/commands/selectParentNode.d.ts +0 -12
- package/dist/packages/core/src/commands/setContent.d.ts +0 -12
- package/dist/packages/core/src/commands/setMark.d.ts +0 -13
- package/dist/packages/core/src/commands/setNode.d.ts +0 -13
- package/dist/packages/core/src/commands/sinkListItem.d.ts +0 -13
- package/dist/packages/core/src/commands/splitBlock.d.ts +0 -14
- package/dist/packages/core/src/commands/splitListItem.d.ts +0 -13
- package/dist/packages/core/src/commands/toggleList.d.ts +0 -13
- package/dist/packages/core/src/commands/toggleMark.d.ts +0 -13
- package/dist/packages/core/src/commands/toggleNode.d.ts +0 -13
- package/dist/packages/core/src/commands/toggleWrap.d.ts +0 -13
- package/dist/packages/core/src/commands/undoInputRule.d.ts +0 -12
- package/dist/packages/core/src/commands/unsetAllMarks.d.ts +0 -12
- package/dist/packages/core/src/commands/unsetMark.d.ts +0 -13
- package/dist/packages/core/src/commands/updateAttributes.d.ts +0 -13
- package/dist/packages/core/src/commands/updateNodeAttributes.d.ts +0 -13
- package/dist/packages/core/src/commands/wrapIn.d.ts +0 -13
- package/dist/packages/core/src/commands/wrapInList.d.ts +0 -13
- package/dist/packages/core/src/extensions/clipboardTextSerializer.d.ts +0 -2
- package/dist/packages/core/src/extensions/commands.d.ts +0 -100
- package/dist/packages/core/src/extensions/editable.d.ts +0 -2
- package/dist/packages/core/src/extensions/focusEvents.d.ts +0 -2
- package/dist/packages/core/src/extensions/index.d.ts +0 -5
- package/dist/packages/core/src/extensions/keymap.d.ts +0 -2
- package/dist/packages/core/src/helpers/createDocument.d.ts +0 -4
- package/dist/packages/core/src/helpers/createNodeFromContent.d.ts +0 -8
- package/dist/packages/core/src/helpers/findParentNode.d.ts +0 -9
- package/dist/packages/core/src/helpers/findParentNodeClosestToPos.d.ts +0 -8
- package/dist/packages/core/src/helpers/generateHTML.d.ts +0 -2
- package/dist/packages/core/src/helpers/getAttributesFromExtensions.d.ts +0 -6
- package/dist/packages/core/src/helpers/getHTMLFromFragment.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarkAttributes.d.ts +0 -4
- package/dist/packages/core/src/helpers/getMarkRange.d.ts +0 -3
- package/dist/packages/core/src/helpers/getMarkType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getMarksBetween.d.ts +0 -3
- package/dist/packages/core/src/helpers/getNodeAttributes.d.ts +0 -4
- package/dist/packages/core/src/helpers/getNodeType.d.ts +0 -2
- package/dist/packages/core/src/helpers/getRenderedAttributes.d.ts +0 -3
- package/dist/packages/core/src/helpers/getSchema.d.ts +0 -3
- package/dist/packages/core/src/helpers/getSchemaTypeByName.d.ts +0 -2
- package/dist/packages/core/src/helpers/getSchemaTypeNameByName.d.ts +0 -2
- package/dist/packages/core/src/helpers/getSplittedAttributes.d.ts +0 -2
- package/dist/packages/core/src/helpers/injectExtensionAttributesToParseRule.d.ts +0 -9
- package/dist/packages/core/src/helpers/isActive.d.ts +0 -3
- package/dist/packages/core/src/helpers/isList.d.ts +0 -2
- package/dist/packages/core/src/helpers/isMarkActive.d.ts +0 -4
- package/dist/packages/core/src/helpers/isNodeActive.d.ts +0 -4
- package/dist/packages/core/src/helpers/isNodeEmpty.d.ts +0 -2
- package/dist/packages/core/src/helpers/isNodeSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/isTextSelection.d.ts +0 -2
- package/dist/packages/core/src/helpers/selectionToInsertionEnd.d.ts +0 -2
- package/dist/packages/core/src/helpers/splitExtensions.d.ts +0 -9
- package/dist/packages/core/src/index.d.ts +0 -30
- package/dist/packages/core/src/inputRules/markInputRule.d.ts +0 -3
- package/dist/packages/core/src/inputRules/nodeInputRule.d.ts +0 -3
- package/dist/packages/core/src/pasteRules/markPasteRule.d.ts +0 -3
- package/dist/packages/core/src/style.d.ts +0 -2
- package/dist/packages/core/src/types.d.ts +0 -154
- package/dist/packages/core/src/utilities/callOrReturn.d.ts +0 -8
- package/dist/packages/core/src/utilities/createStyleTag.d.ts +0 -1
- package/dist/packages/core/src/utilities/deleteProps.d.ts +0 -7
- package/dist/packages/core/src/utilities/elementFromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/fromString.d.ts +0 -1
- package/dist/packages/core/src/utilities/isClass.d.ts +0 -1
- package/dist/packages/core/src/utilities/isEmptyObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/isPlainObject.d.ts +0 -1
- package/dist/packages/core/src/utilities/mergeAttributes.d.ts +0 -2
- package/dist/packages/core/src/utilities/mergeDeep.d.ts +0 -2
- package/dist/packages/core/src/utilities/minMax.d.ts +0 -1
- package/dist/packages/core/src/utilities/objectIncludes.d.ts +0 -7
- package/dist/packages/core/src/utilities/removeElement.d.ts +0 -1
- package/dist/tiptap-core.bundle.umd.min.js +0 -17
- package/dist/tiptap-core.bundle.umd.min.js.map +0 -1
- package/dist/tiptap-core.cjs.js +0 -3027
- package/dist/tiptap-core.cjs.js.map +0 -1
- package/dist/tiptap-core.esm.js +0 -3002
- package/dist/tiptap-core.esm.js.map +0 -1
- package/dist/tiptap-core.umd.js +0 -3024
- package/dist/tiptap-core.umd.js.map +0 -1
- package/src/commands/insertHTML.ts +0 -30
- package/src/commands/insertNode.ts +0 -33
- package/src/commands/insertText.ts +0 -22
- package/src/commands/joinBackward.ts +0 -17
- package/src/commands/joinForward.ts +0 -17
- package/src/commands/replace.ts +0 -20
- package/src/commands/replaceRange.ts +0 -36
- package/src/commands/resetNodeAttributes.ts +0 -33
- package/src/commands/updateNodeAttributes.ts +0 -35
- package/src/utilities/isClass.ts +0 -7
- package/src/utilities/isObject.ts +0 -10
- package/src/utilities/removeElement.ts +0 -5
package/dist/index.js
ADDED
|
@@ -0,0 +1,4311 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/helpers/createChainableState.ts
|
|
8
|
+
function createChainableState(config) {
|
|
9
|
+
const { state, transaction } = config;
|
|
10
|
+
let { selection } = transaction;
|
|
11
|
+
let { doc } = transaction;
|
|
12
|
+
let { storedMarks } = transaction;
|
|
13
|
+
return {
|
|
14
|
+
...state,
|
|
15
|
+
apply: state.apply.bind(state),
|
|
16
|
+
applyTransaction: state.applyTransaction.bind(state),
|
|
17
|
+
filterTransaction: state.filterTransaction,
|
|
18
|
+
plugins: state.plugins,
|
|
19
|
+
schema: state.schema,
|
|
20
|
+
reconfigure: state.reconfigure.bind(state),
|
|
21
|
+
toJSON: state.toJSON.bind(state),
|
|
22
|
+
get storedMarks() {
|
|
23
|
+
return storedMarks;
|
|
24
|
+
},
|
|
25
|
+
get selection() {
|
|
26
|
+
return selection;
|
|
27
|
+
},
|
|
28
|
+
get doc() {
|
|
29
|
+
return doc;
|
|
30
|
+
},
|
|
31
|
+
get tr() {
|
|
32
|
+
selection = transaction.selection;
|
|
33
|
+
doc = transaction.doc;
|
|
34
|
+
storedMarks = transaction.storedMarks;
|
|
35
|
+
return transaction;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/CommandManager.ts
|
|
41
|
+
var CommandManager = class {
|
|
42
|
+
constructor(props) {
|
|
43
|
+
this.editor = props.editor;
|
|
44
|
+
this.rawCommands = this.editor.extensionManager.commands;
|
|
45
|
+
this.customState = props.state;
|
|
46
|
+
}
|
|
47
|
+
get hasCustomState() {
|
|
48
|
+
return !!this.customState;
|
|
49
|
+
}
|
|
50
|
+
get state() {
|
|
51
|
+
return this.customState || this.editor.state;
|
|
52
|
+
}
|
|
53
|
+
get commands() {
|
|
54
|
+
const { rawCommands, editor, state } = this;
|
|
55
|
+
const { view } = editor;
|
|
56
|
+
const { tr } = state;
|
|
57
|
+
const props = this.buildProps(tr);
|
|
58
|
+
return Object.fromEntries(
|
|
59
|
+
Object.entries(rawCommands).map(([name, command2]) => {
|
|
60
|
+
const method = (...args) => {
|
|
61
|
+
const callback = command2(...args)(props);
|
|
62
|
+
if (!tr.getMeta("preventDispatch") && !this.hasCustomState) {
|
|
63
|
+
view.dispatch(tr);
|
|
64
|
+
}
|
|
65
|
+
return callback;
|
|
66
|
+
};
|
|
67
|
+
return [name, method];
|
|
68
|
+
})
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
get chain() {
|
|
72
|
+
return () => this.createChain();
|
|
73
|
+
}
|
|
74
|
+
get can() {
|
|
75
|
+
return () => this.createCan();
|
|
76
|
+
}
|
|
77
|
+
createChain(startTr, shouldDispatch = true) {
|
|
78
|
+
const { rawCommands, editor, state } = this;
|
|
79
|
+
const { view } = editor;
|
|
80
|
+
const callbacks = [];
|
|
81
|
+
const hasStartTransaction = !!startTr;
|
|
82
|
+
const tr = startTr || state.tr;
|
|
83
|
+
const run3 = () => {
|
|
84
|
+
if (!hasStartTransaction && shouldDispatch && !tr.getMeta("preventDispatch") && !this.hasCustomState) {
|
|
85
|
+
view.dispatch(tr);
|
|
86
|
+
}
|
|
87
|
+
return callbacks.every((callback) => callback === true);
|
|
88
|
+
};
|
|
89
|
+
const chain = {
|
|
90
|
+
...Object.fromEntries(
|
|
91
|
+
Object.entries(rawCommands).map(([name, command2]) => {
|
|
92
|
+
const chainedCommand = (...args) => {
|
|
93
|
+
const props = this.buildProps(tr, shouldDispatch);
|
|
94
|
+
const callback = command2(...args)(props);
|
|
95
|
+
callbacks.push(callback);
|
|
96
|
+
return chain;
|
|
97
|
+
};
|
|
98
|
+
return [name, chainedCommand];
|
|
99
|
+
})
|
|
100
|
+
),
|
|
101
|
+
run: run3
|
|
102
|
+
};
|
|
103
|
+
return chain;
|
|
104
|
+
}
|
|
105
|
+
createCan(startTr) {
|
|
106
|
+
const { rawCommands, state } = this;
|
|
107
|
+
const dispatch = false;
|
|
108
|
+
const tr = startTr || state.tr;
|
|
109
|
+
const props = this.buildProps(tr, dispatch);
|
|
110
|
+
const formattedCommands = Object.fromEntries(
|
|
111
|
+
Object.entries(rawCommands).map(([name, command2]) => {
|
|
112
|
+
return [name, (...args) => command2(...args)({ ...props, dispatch: void 0 })];
|
|
113
|
+
})
|
|
114
|
+
);
|
|
115
|
+
return {
|
|
116
|
+
...formattedCommands,
|
|
117
|
+
chain: () => this.createChain(tr, dispatch)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
buildProps(tr, shouldDispatch = true) {
|
|
121
|
+
const { rawCommands, editor, state } = this;
|
|
122
|
+
const { view } = editor;
|
|
123
|
+
if (state.storedMarks) {
|
|
124
|
+
tr.setStoredMarks(state.storedMarks);
|
|
125
|
+
}
|
|
126
|
+
const props = {
|
|
127
|
+
tr,
|
|
128
|
+
editor,
|
|
129
|
+
view,
|
|
130
|
+
state: createChainableState({
|
|
131
|
+
state,
|
|
132
|
+
transaction: tr
|
|
133
|
+
}),
|
|
134
|
+
dispatch: shouldDispatch ? () => void 0 : void 0,
|
|
135
|
+
chain: () => this.createChain(tr),
|
|
136
|
+
can: () => this.createCan(tr),
|
|
137
|
+
get commands() {
|
|
138
|
+
return Object.fromEntries(
|
|
139
|
+
Object.entries(rawCommands).map(([name, command2]) => {
|
|
140
|
+
return [name, (...args) => command2(...args)(props)];
|
|
141
|
+
})
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
return props;
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// src/Editor.ts
|
|
150
|
+
import {
|
|
151
|
+
EditorState as EditorState4
|
|
152
|
+
} from "@tiptap/pm/state";
|
|
153
|
+
import { EditorView } from "@tiptap/pm/view";
|
|
154
|
+
|
|
155
|
+
// src/EventEmitter.ts
|
|
156
|
+
var EventEmitter = class {
|
|
157
|
+
constructor() {
|
|
158
|
+
this.callbacks = {};
|
|
159
|
+
}
|
|
160
|
+
on(event, fn) {
|
|
161
|
+
if (!this.callbacks[event]) {
|
|
162
|
+
this.callbacks[event] = [];
|
|
163
|
+
}
|
|
164
|
+
this.callbacks[event].push(fn);
|
|
165
|
+
return this;
|
|
166
|
+
}
|
|
167
|
+
emit(event, ...args) {
|
|
168
|
+
const callbacks = this.callbacks[event];
|
|
169
|
+
if (callbacks) {
|
|
170
|
+
callbacks.forEach((callback) => callback.apply(this, args));
|
|
171
|
+
}
|
|
172
|
+
return this;
|
|
173
|
+
}
|
|
174
|
+
off(event, fn) {
|
|
175
|
+
const callbacks = this.callbacks[event];
|
|
176
|
+
if (callbacks) {
|
|
177
|
+
if (fn) {
|
|
178
|
+
this.callbacks[event] = callbacks.filter((callback) => callback !== fn);
|
|
179
|
+
} else {
|
|
180
|
+
delete this.callbacks[event];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
removeAllListeners() {
|
|
186
|
+
this.callbacks = {};
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
// src/ExtensionManager.ts
|
|
191
|
+
import { keymap } from "@tiptap/pm/keymap";
|
|
192
|
+
|
|
193
|
+
// src/helpers/getExtensionField.ts
|
|
194
|
+
function getExtensionField(extension, field, context) {
|
|
195
|
+
if (extension.config[field] === void 0 && extension.parent) {
|
|
196
|
+
return getExtensionField(extension.parent, field, context);
|
|
197
|
+
}
|
|
198
|
+
if (typeof extension.config[field] === "function") {
|
|
199
|
+
const value = extension.config[field].bind({
|
|
200
|
+
...context,
|
|
201
|
+
parent: extension.parent ? getExtensionField(extension.parent, field, context) : null
|
|
202
|
+
});
|
|
203
|
+
return value;
|
|
204
|
+
}
|
|
205
|
+
return extension.config[field];
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// src/helpers/splitExtensions.ts
|
|
209
|
+
function splitExtensions(extensions) {
|
|
210
|
+
const baseExtensions = extensions.filter((extension) => extension.type === "extension");
|
|
211
|
+
const nodeExtensions = extensions.filter((extension) => extension.type === "node");
|
|
212
|
+
const markExtensions = extensions.filter((extension) => extension.type === "mark");
|
|
213
|
+
return {
|
|
214
|
+
baseExtensions,
|
|
215
|
+
nodeExtensions,
|
|
216
|
+
markExtensions
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// src/helpers/getAttributesFromExtensions.ts
|
|
221
|
+
function getAttributesFromExtensions(extensions) {
|
|
222
|
+
const extensionAttributes = [];
|
|
223
|
+
const { nodeExtensions, markExtensions } = splitExtensions(extensions);
|
|
224
|
+
const nodeAndMarkExtensions = [...nodeExtensions, ...markExtensions];
|
|
225
|
+
const defaultAttribute = {
|
|
226
|
+
default: null,
|
|
227
|
+
rendered: true,
|
|
228
|
+
renderHTML: null,
|
|
229
|
+
parseHTML: null,
|
|
230
|
+
keepOnSplit: true,
|
|
231
|
+
isRequired: false
|
|
232
|
+
};
|
|
233
|
+
extensions.forEach((extension) => {
|
|
234
|
+
const context = {
|
|
235
|
+
name: extension.name,
|
|
236
|
+
options: extension.options,
|
|
237
|
+
storage: extension.storage
|
|
238
|
+
};
|
|
239
|
+
const addGlobalAttributes = getExtensionField(
|
|
240
|
+
extension,
|
|
241
|
+
"addGlobalAttributes",
|
|
242
|
+
context
|
|
243
|
+
);
|
|
244
|
+
if (!addGlobalAttributes) {
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
const globalAttributes = addGlobalAttributes();
|
|
248
|
+
globalAttributes.forEach((globalAttribute) => {
|
|
249
|
+
globalAttribute.types.forEach((type) => {
|
|
250
|
+
Object.entries(globalAttribute.attributes).forEach(([name, attribute]) => {
|
|
251
|
+
extensionAttributes.push({
|
|
252
|
+
type,
|
|
253
|
+
name,
|
|
254
|
+
attribute: {
|
|
255
|
+
...defaultAttribute,
|
|
256
|
+
...attribute
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
nodeAndMarkExtensions.forEach((extension) => {
|
|
264
|
+
const context = {
|
|
265
|
+
name: extension.name,
|
|
266
|
+
options: extension.options,
|
|
267
|
+
storage: extension.storage
|
|
268
|
+
};
|
|
269
|
+
const addAttributes = getExtensionField(
|
|
270
|
+
extension,
|
|
271
|
+
"addAttributes",
|
|
272
|
+
context
|
|
273
|
+
);
|
|
274
|
+
if (!addAttributes) {
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const attributes = addAttributes();
|
|
278
|
+
Object.entries(attributes).forEach(([name, attribute]) => {
|
|
279
|
+
const mergedAttr = {
|
|
280
|
+
...defaultAttribute,
|
|
281
|
+
...attribute
|
|
282
|
+
};
|
|
283
|
+
if ((attribute == null ? void 0 : attribute.isRequired) && (attribute == null ? void 0 : attribute.default) === void 0) {
|
|
284
|
+
delete mergedAttr.default;
|
|
285
|
+
}
|
|
286
|
+
extensionAttributes.push({
|
|
287
|
+
type: extension.name,
|
|
288
|
+
name,
|
|
289
|
+
attribute: mergedAttr
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
return extensionAttributes;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// src/helpers/getNodeType.ts
|
|
297
|
+
function getNodeType(nameOrType, schema) {
|
|
298
|
+
if (typeof nameOrType === "string") {
|
|
299
|
+
if (!schema.nodes[nameOrType]) {
|
|
300
|
+
throw Error(
|
|
301
|
+
`There is no node type named '${nameOrType}'. Maybe you forgot to add the extension?`
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
return schema.nodes[nameOrType];
|
|
305
|
+
}
|
|
306
|
+
return nameOrType;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/utilities/mergeAttributes.ts
|
|
310
|
+
function mergeAttributes(...objects) {
|
|
311
|
+
return objects.filter((item) => !!item).reduce((items, item) => {
|
|
312
|
+
const mergedAttributes = { ...items };
|
|
313
|
+
Object.entries(item).forEach(([key, value]) => {
|
|
314
|
+
const exists = mergedAttributes[key];
|
|
315
|
+
if (!exists) {
|
|
316
|
+
mergedAttributes[key] = value;
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (key === "class") {
|
|
320
|
+
mergedAttributes[key] = [mergedAttributes[key], value].join(" ");
|
|
321
|
+
} else if (key === "style") {
|
|
322
|
+
mergedAttributes[key] = [mergedAttributes[key], value].join("; ");
|
|
323
|
+
} else {
|
|
324
|
+
mergedAttributes[key] = value;
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
return mergedAttributes;
|
|
328
|
+
}, {});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// src/helpers/getRenderedAttributes.ts
|
|
332
|
+
function getRenderedAttributes(nodeOrMark, extensionAttributes) {
|
|
333
|
+
return extensionAttributes.filter((item) => item.attribute.rendered).map((item) => {
|
|
334
|
+
if (!item.attribute.renderHTML) {
|
|
335
|
+
return {
|
|
336
|
+
[item.name]: nodeOrMark.attrs[item.name]
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
return item.attribute.renderHTML(nodeOrMark.attrs) || {};
|
|
340
|
+
}).reduce((attributes, attribute) => mergeAttributes(attributes, attribute), {});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// src/helpers/getSchemaByResolvedExtensions.ts
|
|
344
|
+
import { Schema } from "@tiptap/pm/model";
|
|
345
|
+
|
|
346
|
+
// src/utilities/isFunction.ts
|
|
347
|
+
function isFunction(value) {
|
|
348
|
+
return typeof value === "function";
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// src/utilities/callOrReturn.ts
|
|
352
|
+
function callOrReturn(value, context = void 0, ...props) {
|
|
353
|
+
if (isFunction(value)) {
|
|
354
|
+
if (context) {
|
|
355
|
+
return value.bind(context)(...props);
|
|
356
|
+
}
|
|
357
|
+
return value(...props);
|
|
358
|
+
}
|
|
359
|
+
return value;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// src/utilities/isEmptyObject.ts
|
|
363
|
+
function isEmptyObject(value = {}) {
|
|
364
|
+
return Object.keys(value).length === 0 && value.constructor === Object;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// src/utilities/fromString.ts
|
|
368
|
+
function fromString(value) {
|
|
369
|
+
if (typeof value !== "string") {
|
|
370
|
+
return value;
|
|
371
|
+
}
|
|
372
|
+
if (value.match(/^[+-]?(?:\d*\.)?\d+$/)) {
|
|
373
|
+
return Number(value);
|
|
374
|
+
}
|
|
375
|
+
if (value === "true") {
|
|
376
|
+
return true;
|
|
377
|
+
}
|
|
378
|
+
if (value === "false") {
|
|
379
|
+
return false;
|
|
380
|
+
}
|
|
381
|
+
return value;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/helpers/injectExtensionAttributesToParseRule.ts
|
|
385
|
+
function injectExtensionAttributesToParseRule(parseRule, extensionAttributes) {
|
|
386
|
+
if (parseRule.style) {
|
|
387
|
+
return parseRule;
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
...parseRule,
|
|
391
|
+
getAttrs: (node) => {
|
|
392
|
+
const oldAttributes = parseRule.getAttrs ? parseRule.getAttrs(node) : parseRule.attrs;
|
|
393
|
+
if (oldAttributes === false) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
const newAttributes = extensionAttributes.reduce((items, item) => {
|
|
397
|
+
const value = item.attribute.parseHTML ? item.attribute.parseHTML(node) : fromString(node.getAttribute(item.name));
|
|
398
|
+
if (value === null || value === void 0) {
|
|
399
|
+
return items;
|
|
400
|
+
}
|
|
401
|
+
return {
|
|
402
|
+
...items,
|
|
403
|
+
[item.name]: value
|
|
404
|
+
};
|
|
405
|
+
}, {});
|
|
406
|
+
return { ...oldAttributes, ...newAttributes };
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// src/helpers/getSchemaByResolvedExtensions.ts
|
|
412
|
+
function cleanUpSchemaItem(data) {
|
|
413
|
+
return Object.fromEntries(
|
|
414
|
+
Object.entries(data).filter(([key, value]) => {
|
|
415
|
+
if (key === "attrs" && isEmptyObject(value)) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
return value !== null && value !== void 0;
|
|
419
|
+
})
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
function getSchemaByResolvedExtensions(extensions) {
|
|
423
|
+
var _a;
|
|
424
|
+
const allAttributes = getAttributesFromExtensions(extensions);
|
|
425
|
+
const { nodeExtensions, markExtensions } = splitExtensions(extensions);
|
|
426
|
+
const topNode = (_a = nodeExtensions.find((extension) => getExtensionField(extension, "topNode"))) == null ? void 0 : _a.name;
|
|
427
|
+
const nodes = Object.fromEntries(
|
|
428
|
+
nodeExtensions.map((extension) => {
|
|
429
|
+
const extensionAttributes = allAttributes.filter(
|
|
430
|
+
(attribute) => attribute.type === extension.name
|
|
431
|
+
);
|
|
432
|
+
const context = {
|
|
433
|
+
name: extension.name,
|
|
434
|
+
options: extension.options,
|
|
435
|
+
storage: extension.storage
|
|
436
|
+
};
|
|
437
|
+
const extraNodeFields = extensions.reduce((fields, e) => {
|
|
438
|
+
const extendNodeSchema = getExtensionField(
|
|
439
|
+
e,
|
|
440
|
+
"extendNodeSchema",
|
|
441
|
+
context
|
|
442
|
+
);
|
|
443
|
+
return {
|
|
444
|
+
...fields,
|
|
445
|
+
...extendNodeSchema ? extendNodeSchema(extension) : {}
|
|
446
|
+
};
|
|
447
|
+
}, {});
|
|
448
|
+
const schema = cleanUpSchemaItem({
|
|
449
|
+
...extraNodeFields,
|
|
450
|
+
content: callOrReturn(
|
|
451
|
+
getExtensionField(extension, "content", context)
|
|
452
|
+
),
|
|
453
|
+
marks: callOrReturn(getExtensionField(extension, "marks", context)),
|
|
454
|
+
group: callOrReturn(getExtensionField(extension, "group", context)),
|
|
455
|
+
inline: callOrReturn(getExtensionField(extension, "inline", context)),
|
|
456
|
+
atom: callOrReturn(getExtensionField(extension, "atom", context)),
|
|
457
|
+
selectable: callOrReturn(
|
|
458
|
+
getExtensionField(extension, "selectable", context)
|
|
459
|
+
),
|
|
460
|
+
draggable: callOrReturn(
|
|
461
|
+
getExtensionField(extension, "draggable", context)
|
|
462
|
+
),
|
|
463
|
+
code: callOrReturn(getExtensionField(extension, "code", context)),
|
|
464
|
+
defining: callOrReturn(
|
|
465
|
+
getExtensionField(extension, "defining", context)
|
|
466
|
+
),
|
|
467
|
+
isolating: callOrReturn(
|
|
468
|
+
getExtensionField(extension, "isolating", context)
|
|
469
|
+
),
|
|
470
|
+
attrs: Object.fromEntries(
|
|
471
|
+
extensionAttributes.map((extensionAttribute) => {
|
|
472
|
+
var _a2;
|
|
473
|
+
return [extensionAttribute.name, { default: (_a2 = extensionAttribute == null ? void 0 : extensionAttribute.attribute) == null ? void 0 : _a2.default }];
|
|
474
|
+
})
|
|
475
|
+
)
|
|
476
|
+
});
|
|
477
|
+
const parseHTML = callOrReturn(
|
|
478
|
+
getExtensionField(extension, "parseHTML", context)
|
|
479
|
+
);
|
|
480
|
+
if (parseHTML) {
|
|
481
|
+
schema.parseDOM = parseHTML.map((parseRule) => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
|
|
482
|
+
}
|
|
483
|
+
const renderHTML = getExtensionField(
|
|
484
|
+
extension,
|
|
485
|
+
"renderHTML",
|
|
486
|
+
context
|
|
487
|
+
);
|
|
488
|
+
if (renderHTML) {
|
|
489
|
+
schema.toDOM = (node) => renderHTML({
|
|
490
|
+
node,
|
|
491
|
+
HTMLAttributes: getRenderedAttributes(node, extensionAttributes)
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
const renderText = getExtensionField(
|
|
495
|
+
extension,
|
|
496
|
+
"renderText",
|
|
497
|
+
context
|
|
498
|
+
);
|
|
499
|
+
if (renderText) {
|
|
500
|
+
schema.toText = renderText;
|
|
501
|
+
}
|
|
502
|
+
return [extension.name, schema];
|
|
503
|
+
})
|
|
504
|
+
);
|
|
505
|
+
const marks = Object.fromEntries(
|
|
506
|
+
markExtensions.map((extension) => {
|
|
507
|
+
const extensionAttributes = allAttributes.filter(
|
|
508
|
+
(attribute) => attribute.type === extension.name
|
|
509
|
+
);
|
|
510
|
+
const context = {
|
|
511
|
+
name: extension.name,
|
|
512
|
+
options: extension.options,
|
|
513
|
+
storage: extension.storage
|
|
514
|
+
};
|
|
515
|
+
const extraMarkFields = extensions.reduce((fields, e) => {
|
|
516
|
+
const extendMarkSchema = getExtensionField(
|
|
517
|
+
e,
|
|
518
|
+
"extendMarkSchema",
|
|
519
|
+
context
|
|
520
|
+
);
|
|
521
|
+
return {
|
|
522
|
+
...fields,
|
|
523
|
+
...extendMarkSchema ? extendMarkSchema(extension) : {}
|
|
524
|
+
};
|
|
525
|
+
}, {});
|
|
526
|
+
const schema = cleanUpSchemaItem({
|
|
527
|
+
...extraMarkFields,
|
|
528
|
+
inclusive: callOrReturn(
|
|
529
|
+
getExtensionField(extension, "inclusive", context)
|
|
530
|
+
),
|
|
531
|
+
excludes: callOrReturn(
|
|
532
|
+
getExtensionField(extension, "excludes", context)
|
|
533
|
+
),
|
|
534
|
+
group: callOrReturn(getExtensionField(extension, "group", context)),
|
|
535
|
+
spanning: callOrReturn(
|
|
536
|
+
getExtensionField(extension, "spanning", context)
|
|
537
|
+
),
|
|
538
|
+
code: callOrReturn(getExtensionField(extension, "code", context)),
|
|
539
|
+
attrs: Object.fromEntries(
|
|
540
|
+
extensionAttributes.map((extensionAttribute) => {
|
|
541
|
+
var _a2;
|
|
542
|
+
return [extensionAttribute.name, { default: (_a2 = extensionAttribute == null ? void 0 : extensionAttribute.attribute) == null ? void 0 : _a2.default }];
|
|
543
|
+
})
|
|
544
|
+
)
|
|
545
|
+
});
|
|
546
|
+
const parseHTML = callOrReturn(
|
|
547
|
+
getExtensionField(extension, "parseHTML", context)
|
|
548
|
+
);
|
|
549
|
+
if (parseHTML) {
|
|
550
|
+
schema.parseDOM = parseHTML.map((parseRule) => injectExtensionAttributesToParseRule(parseRule, extensionAttributes));
|
|
551
|
+
}
|
|
552
|
+
const renderHTML = getExtensionField(
|
|
553
|
+
extension,
|
|
554
|
+
"renderHTML",
|
|
555
|
+
context
|
|
556
|
+
);
|
|
557
|
+
if (renderHTML) {
|
|
558
|
+
schema.toDOM = (mark) => renderHTML({
|
|
559
|
+
mark,
|
|
560
|
+
HTMLAttributes: getRenderedAttributes(mark, extensionAttributes)
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
return [extension.name, schema];
|
|
564
|
+
})
|
|
565
|
+
);
|
|
566
|
+
return new Schema({
|
|
567
|
+
topNode,
|
|
568
|
+
nodes,
|
|
569
|
+
marks
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/helpers/getSchemaTypeByName.ts
|
|
574
|
+
function getSchemaTypeByName(name, schema) {
|
|
575
|
+
return schema.nodes[name] || schema.marks[name] || null;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// src/helpers/isExtensionRulesEnabled.ts
|
|
579
|
+
function isExtensionRulesEnabled(extension, enabled) {
|
|
580
|
+
if (Array.isArray(enabled)) {
|
|
581
|
+
return enabled.some((enabledExtension) => {
|
|
582
|
+
const name = typeof enabledExtension === "string" ? enabledExtension : enabledExtension.name;
|
|
583
|
+
return name === extension.name;
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
return enabled;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
// src/InputRule.ts
|
|
590
|
+
import { Plugin } from "@tiptap/pm/state";
|
|
591
|
+
|
|
592
|
+
// src/helpers/getTextContentFromNodes.ts
|
|
593
|
+
var getTextContentFromNodes = ($from, maxMatch = 500) => {
|
|
594
|
+
let textBefore = "";
|
|
595
|
+
const sliceEndPos = $from.parentOffset;
|
|
596
|
+
$from.parent.nodesBetween(
|
|
597
|
+
Math.max(0, sliceEndPos - maxMatch),
|
|
598
|
+
sliceEndPos,
|
|
599
|
+
(node, pos, parent, index) => {
|
|
600
|
+
var _a, _b;
|
|
601
|
+
const chunk = ((_b = (_a = node.type.spec).toText) == null ? void 0 : _b.call(_a, {
|
|
602
|
+
node,
|
|
603
|
+
pos,
|
|
604
|
+
parent,
|
|
605
|
+
index
|
|
606
|
+
})) || node.textContent || "%leaf%";
|
|
607
|
+
textBefore += chunk.slice(0, Math.max(0, sliceEndPos - pos));
|
|
608
|
+
}
|
|
609
|
+
);
|
|
610
|
+
return textBefore;
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// src/utilities/isRegExp.ts
|
|
614
|
+
function isRegExp(value) {
|
|
615
|
+
return Object.prototype.toString.call(value) === "[object RegExp]";
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
// src/InputRule.ts
|
|
619
|
+
var InputRule = class {
|
|
620
|
+
constructor(config) {
|
|
621
|
+
this.find = config.find;
|
|
622
|
+
this.handler = config.handler;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
var inputRuleMatcherHandler = (text, find) => {
|
|
626
|
+
if (isRegExp(find)) {
|
|
627
|
+
return find.exec(text);
|
|
628
|
+
}
|
|
629
|
+
const inputRuleMatch = find(text);
|
|
630
|
+
if (!inputRuleMatch) {
|
|
631
|
+
return null;
|
|
632
|
+
}
|
|
633
|
+
const result = [inputRuleMatch.text];
|
|
634
|
+
result.index = inputRuleMatch.index;
|
|
635
|
+
result.input = text;
|
|
636
|
+
result.data = inputRuleMatch.data;
|
|
637
|
+
if (inputRuleMatch.replaceWith) {
|
|
638
|
+
if (!inputRuleMatch.text.includes(inputRuleMatch.replaceWith)) {
|
|
639
|
+
console.warn(
|
|
640
|
+
'[tiptap warn]: "inputRuleMatch.replaceWith" must be part of "inputRuleMatch.text".'
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
result.push(inputRuleMatch.replaceWith);
|
|
644
|
+
}
|
|
645
|
+
return result;
|
|
646
|
+
};
|
|
647
|
+
function run(config) {
|
|
648
|
+
var _a;
|
|
649
|
+
const {
|
|
650
|
+
editor,
|
|
651
|
+
from,
|
|
652
|
+
to,
|
|
653
|
+
text,
|
|
654
|
+
rules,
|
|
655
|
+
plugin
|
|
656
|
+
} = config;
|
|
657
|
+
const { view } = editor;
|
|
658
|
+
if (view.composing) {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
const $from = view.state.doc.resolve(from);
|
|
662
|
+
if ($from.parent.type.spec.code || !!((_a = $from.nodeBefore || $from.nodeAfter) == null ? void 0 : _a.marks.find((mark) => mark.type.spec.code))) {
|
|
663
|
+
return false;
|
|
664
|
+
}
|
|
665
|
+
let matched = false;
|
|
666
|
+
const textBefore = getTextContentFromNodes($from) + text;
|
|
667
|
+
rules.forEach((rule) => {
|
|
668
|
+
if (matched) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
const match = inputRuleMatcherHandler(textBefore, rule.find);
|
|
672
|
+
if (!match) {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
const tr = view.state.tr;
|
|
676
|
+
const state = createChainableState({
|
|
677
|
+
state: view.state,
|
|
678
|
+
transaction: tr
|
|
679
|
+
});
|
|
680
|
+
const range = {
|
|
681
|
+
from: from - (match[0].length - text.length),
|
|
682
|
+
to
|
|
683
|
+
};
|
|
684
|
+
const { commands, chain, can } = new CommandManager({
|
|
685
|
+
editor,
|
|
686
|
+
state
|
|
687
|
+
});
|
|
688
|
+
const handler = rule.handler({
|
|
689
|
+
state,
|
|
690
|
+
range,
|
|
691
|
+
match,
|
|
692
|
+
commands,
|
|
693
|
+
chain,
|
|
694
|
+
can
|
|
695
|
+
});
|
|
696
|
+
if (handler === null || !tr.steps.length) {
|
|
697
|
+
return;
|
|
698
|
+
}
|
|
699
|
+
tr.setMeta(plugin, {
|
|
700
|
+
transform: tr,
|
|
701
|
+
from,
|
|
702
|
+
to,
|
|
703
|
+
text
|
|
704
|
+
});
|
|
705
|
+
view.dispatch(tr);
|
|
706
|
+
matched = true;
|
|
707
|
+
});
|
|
708
|
+
return matched;
|
|
709
|
+
}
|
|
710
|
+
function inputRulesPlugin(props) {
|
|
711
|
+
const { editor, rules } = props;
|
|
712
|
+
const plugin = new Plugin({
|
|
713
|
+
state: {
|
|
714
|
+
init() {
|
|
715
|
+
return null;
|
|
716
|
+
},
|
|
717
|
+
apply(tr, prev) {
|
|
718
|
+
const stored = tr.getMeta(plugin);
|
|
719
|
+
if (stored) {
|
|
720
|
+
return stored;
|
|
721
|
+
}
|
|
722
|
+
return tr.selectionSet || tr.docChanged ? null : prev;
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
props: {
|
|
726
|
+
handleTextInput(view, from, to, text) {
|
|
727
|
+
return run({
|
|
728
|
+
editor,
|
|
729
|
+
from,
|
|
730
|
+
to,
|
|
731
|
+
text,
|
|
732
|
+
rules,
|
|
733
|
+
plugin
|
|
734
|
+
});
|
|
735
|
+
},
|
|
736
|
+
handleDOMEvents: {
|
|
737
|
+
compositionend: (view) => {
|
|
738
|
+
setTimeout(() => {
|
|
739
|
+
const { $cursor } = view.state.selection;
|
|
740
|
+
if ($cursor) {
|
|
741
|
+
run({
|
|
742
|
+
editor,
|
|
743
|
+
from: $cursor.pos,
|
|
744
|
+
to: $cursor.pos,
|
|
745
|
+
text: "",
|
|
746
|
+
rules,
|
|
747
|
+
plugin
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
return false;
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
handleKeyDown(view, event) {
|
|
755
|
+
if (event.key !== "Enter") {
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
const { $cursor } = view.state.selection;
|
|
759
|
+
if ($cursor) {
|
|
760
|
+
return run({
|
|
761
|
+
editor,
|
|
762
|
+
from: $cursor.pos,
|
|
763
|
+
to: $cursor.pos,
|
|
764
|
+
text: "\n",
|
|
765
|
+
rules,
|
|
766
|
+
plugin
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
isInputRules: true
|
|
773
|
+
});
|
|
774
|
+
return plugin;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
// src/PasteRule.ts
|
|
778
|
+
import { Plugin as Plugin2 } from "@tiptap/pm/state";
|
|
779
|
+
|
|
780
|
+
// src/utilities/isNumber.ts
|
|
781
|
+
function isNumber(value) {
|
|
782
|
+
return typeof value === "number";
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/PasteRule.ts
|
|
786
|
+
var PasteRule = class {
|
|
787
|
+
constructor(config) {
|
|
788
|
+
this.find = config.find;
|
|
789
|
+
this.handler = config.handler;
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
var pasteRuleMatcherHandler = (text, find) => {
|
|
793
|
+
if (isRegExp(find)) {
|
|
794
|
+
return [...text.matchAll(find)];
|
|
795
|
+
}
|
|
796
|
+
const matches = find(text);
|
|
797
|
+
if (!matches) {
|
|
798
|
+
return [];
|
|
799
|
+
}
|
|
800
|
+
return matches.map((pasteRuleMatch) => {
|
|
801
|
+
const result = [pasteRuleMatch.text];
|
|
802
|
+
result.index = pasteRuleMatch.index;
|
|
803
|
+
result.input = text;
|
|
804
|
+
result.data = pasteRuleMatch.data;
|
|
805
|
+
if (pasteRuleMatch.replaceWith) {
|
|
806
|
+
if (!pasteRuleMatch.text.includes(pasteRuleMatch.replaceWith)) {
|
|
807
|
+
console.warn(
|
|
808
|
+
'[tiptap warn]: "pasteRuleMatch.replaceWith" must be part of "pasteRuleMatch.text".'
|
|
809
|
+
);
|
|
810
|
+
}
|
|
811
|
+
result.push(pasteRuleMatch.replaceWith);
|
|
812
|
+
}
|
|
813
|
+
return result;
|
|
814
|
+
});
|
|
815
|
+
};
|
|
816
|
+
function run2(config) {
|
|
817
|
+
const {
|
|
818
|
+
editor,
|
|
819
|
+
state,
|
|
820
|
+
from,
|
|
821
|
+
to,
|
|
822
|
+
rule
|
|
823
|
+
} = config;
|
|
824
|
+
const { commands, chain, can } = new CommandManager({
|
|
825
|
+
editor,
|
|
826
|
+
state
|
|
827
|
+
});
|
|
828
|
+
const handlers = [];
|
|
829
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
830
|
+
if (!node.isTextblock || node.type.spec.code) {
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
const resolvedFrom = Math.max(from, pos);
|
|
834
|
+
const resolvedTo = Math.min(to, pos + node.content.size);
|
|
835
|
+
const textToMatch = node.textBetween(resolvedFrom - pos, resolvedTo - pos, void 0, "\uFFFC");
|
|
836
|
+
const matches = pasteRuleMatcherHandler(textToMatch, rule.find);
|
|
837
|
+
matches.forEach((match) => {
|
|
838
|
+
if (match.index === void 0) {
|
|
839
|
+
return;
|
|
840
|
+
}
|
|
841
|
+
const start = resolvedFrom + match.index + 1;
|
|
842
|
+
const end = start + match[0].length;
|
|
843
|
+
const range = {
|
|
844
|
+
from: state.tr.mapping.map(start),
|
|
845
|
+
to: state.tr.mapping.map(end)
|
|
846
|
+
};
|
|
847
|
+
const handler = rule.handler({
|
|
848
|
+
state,
|
|
849
|
+
range,
|
|
850
|
+
match,
|
|
851
|
+
commands,
|
|
852
|
+
chain,
|
|
853
|
+
can
|
|
854
|
+
});
|
|
855
|
+
handlers.push(handler);
|
|
856
|
+
});
|
|
857
|
+
});
|
|
858
|
+
const success = handlers.every((handler) => handler !== null);
|
|
859
|
+
return success;
|
|
860
|
+
}
|
|
861
|
+
function pasteRulesPlugin(props) {
|
|
862
|
+
const { editor, rules } = props;
|
|
863
|
+
let dragSourceElement = null;
|
|
864
|
+
let isPastedFromProseMirror = false;
|
|
865
|
+
let isDroppedFromProseMirror = false;
|
|
866
|
+
const plugins = rules.map((rule) => {
|
|
867
|
+
return new Plugin2({
|
|
868
|
+
view(view) {
|
|
869
|
+
const handleDragstart = (event) => {
|
|
870
|
+
var _a;
|
|
871
|
+
dragSourceElement = ((_a = view.dom.parentElement) == null ? void 0 : _a.contains(event.target)) ? view.dom.parentElement : null;
|
|
872
|
+
};
|
|
873
|
+
window.addEventListener("dragstart", handleDragstart);
|
|
874
|
+
return {
|
|
875
|
+
destroy() {
|
|
876
|
+
window.removeEventListener("dragstart", handleDragstart);
|
|
877
|
+
}
|
|
878
|
+
};
|
|
879
|
+
},
|
|
880
|
+
props: {
|
|
881
|
+
handleDOMEvents: {
|
|
882
|
+
drop: (view) => {
|
|
883
|
+
isDroppedFromProseMirror = dragSourceElement === view.dom.parentElement;
|
|
884
|
+
return false;
|
|
885
|
+
},
|
|
886
|
+
paste: (view, event) => {
|
|
887
|
+
var _a;
|
|
888
|
+
const html = (_a = event.clipboardData) == null ? void 0 : _a.getData("text/html");
|
|
889
|
+
isPastedFromProseMirror = !!(html == null ? void 0 : html.includes("data-pm-slice"));
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
},
|
|
894
|
+
appendTransaction: (transactions, oldState, state) => {
|
|
895
|
+
const transaction = transactions[0];
|
|
896
|
+
const isPaste = transaction.getMeta("uiEvent") === "paste" && !isPastedFromProseMirror;
|
|
897
|
+
const isDrop = transaction.getMeta("uiEvent") === "drop" && !isDroppedFromProseMirror;
|
|
898
|
+
if (!isPaste && !isDrop) {
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
const from = oldState.doc.content.findDiffStart(state.doc.content);
|
|
902
|
+
const to = oldState.doc.content.findDiffEnd(state.doc.content);
|
|
903
|
+
if (!isNumber(from) || !to || from === to.b) {
|
|
904
|
+
return;
|
|
905
|
+
}
|
|
906
|
+
const tr = state.tr;
|
|
907
|
+
const chainableState = createChainableState({
|
|
908
|
+
state,
|
|
909
|
+
transaction: tr
|
|
910
|
+
});
|
|
911
|
+
const handler = run2({
|
|
912
|
+
editor,
|
|
913
|
+
state: chainableState,
|
|
914
|
+
from: Math.max(from - 1, 0),
|
|
915
|
+
to: to.b - 1,
|
|
916
|
+
rule
|
|
917
|
+
});
|
|
918
|
+
if (!handler || !tr.steps.length) {
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
return tr;
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
return plugins;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// src/utilities/findDuplicates.ts
|
|
929
|
+
function findDuplicates(items) {
|
|
930
|
+
const filtered = items.filter((el, index) => items.indexOf(el) !== index);
|
|
931
|
+
return [...new Set(filtered)];
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/ExtensionManager.ts
|
|
935
|
+
var ExtensionManager = class {
|
|
936
|
+
constructor(extensions, editor) {
|
|
937
|
+
this.splittableMarks = [];
|
|
938
|
+
this.editor = editor;
|
|
939
|
+
this.extensions = ExtensionManager.resolve(extensions);
|
|
940
|
+
this.schema = getSchemaByResolvedExtensions(this.extensions);
|
|
941
|
+
this.extensions.forEach((extension) => {
|
|
942
|
+
var _a;
|
|
943
|
+
this.editor.extensionStorage[extension.name] = extension.storage;
|
|
944
|
+
const context = {
|
|
945
|
+
name: extension.name,
|
|
946
|
+
options: extension.options,
|
|
947
|
+
storage: extension.storage,
|
|
948
|
+
editor: this.editor,
|
|
949
|
+
type: getSchemaTypeByName(extension.name, this.schema)
|
|
950
|
+
};
|
|
951
|
+
if (extension.type === "mark") {
|
|
952
|
+
const keepOnSplit = (_a = callOrReturn(getExtensionField(extension, "keepOnSplit", context))) != null ? _a : true;
|
|
953
|
+
if (keepOnSplit) {
|
|
954
|
+
this.splittableMarks.push(extension.name);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
const onBeforeCreate = getExtensionField(
|
|
958
|
+
extension,
|
|
959
|
+
"onBeforeCreate",
|
|
960
|
+
context
|
|
961
|
+
);
|
|
962
|
+
if (onBeforeCreate) {
|
|
963
|
+
this.editor.on("beforeCreate", onBeforeCreate);
|
|
964
|
+
}
|
|
965
|
+
const onCreate = getExtensionField(extension, "onCreate", context);
|
|
966
|
+
if (onCreate) {
|
|
967
|
+
this.editor.on("create", onCreate);
|
|
968
|
+
}
|
|
969
|
+
const onUpdate = getExtensionField(extension, "onUpdate", context);
|
|
970
|
+
if (onUpdate) {
|
|
971
|
+
this.editor.on("update", onUpdate);
|
|
972
|
+
}
|
|
973
|
+
const onSelectionUpdate = getExtensionField(
|
|
974
|
+
extension,
|
|
975
|
+
"onSelectionUpdate",
|
|
976
|
+
context
|
|
977
|
+
);
|
|
978
|
+
if (onSelectionUpdate) {
|
|
979
|
+
this.editor.on("selectionUpdate", onSelectionUpdate);
|
|
980
|
+
}
|
|
981
|
+
const onTransaction = getExtensionField(
|
|
982
|
+
extension,
|
|
983
|
+
"onTransaction",
|
|
984
|
+
context
|
|
985
|
+
);
|
|
986
|
+
if (onTransaction) {
|
|
987
|
+
this.editor.on("transaction", onTransaction);
|
|
988
|
+
}
|
|
989
|
+
const onFocus = getExtensionField(extension, "onFocus", context);
|
|
990
|
+
if (onFocus) {
|
|
991
|
+
this.editor.on("focus", onFocus);
|
|
992
|
+
}
|
|
993
|
+
const onBlur = getExtensionField(extension, "onBlur", context);
|
|
994
|
+
if (onBlur) {
|
|
995
|
+
this.editor.on("blur", onBlur);
|
|
996
|
+
}
|
|
997
|
+
const onDestroy = getExtensionField(extension, "onDestroy", context);
|
|
998
|
+
if (onDestroy) {
|
|
999
|
+
this.editor.on("destroy", onDestroy);
|
|
1000
|
+
}
|
|
1001
|
+
});
|
|
1002
|
+
}
|
|
1003
|
+
static resolve(extensions) {
|
|
1004
|
+
const resolvedExtensions = ExtensionManager.sort(ExtensionManager.flatten(extensions));
|
|
1005
|
+
const duplicatedNames = findDuplicates(resolvedExtensions.map((extension) => extension.name));
|
|
1006
|
+
if (duplicatedNames.length) {
|
|
1007
|
+
console.warn(
|
|
1008
|
+
`[tiptap warn]: Duplicate extension names found: [${duplicatedNames.map((item) => `'${item}'`).join(", ")}]. This can lead to issues.`
|
|
1009
|
+
);
|
|
1010
|
+
}
|
|
1011
|
+
return resolvedExtensions;
|
|
1012
|
+
}
|
|
1013
|
+
static flatten(extensions) {
|
|
1014
|
+
return extensions.map((extension) => {
|
|
1015
|
+
const context = {
|
|
1016
|
+
name: extension.name,
|
|
1017
|
+
options: extension.options,
|
|
1018
|
+
storage: extension.storage
|
|
1019
|
+
};
|
|
1020
|
+
const addExtensions = getExtensionField(
|
|
1021
|
+
extension,
|
|
1022
|
+
"addExtensions",
|
|
1023
|
+
context
|
|
1024
|
+
);
|
|
1025
|
+
if (addExtensions) {
|
|
1026
|
+
return [extension, ...this.flatten(addExtensions())];
|
|
1027
|
+
}
|
|
1028
|
+
return extension;
|
|
1029
|
+
}).flat(10);
|
|
1030
|
+
}
|
|
1031
|
+
static sort(extensions) {
|
|
1032
|
+
const defaultPriority = 100;
|
|
1033
|
+
return extensions.sort((a, b) => {
|
|
1034
|
+
const priorityA = getExtensionField(a, "priority") || defaultPriority;
|
|
1035
|
+
const priorityB = getExtensionField(b, "priority") || defaultPriority;
|
|
1036
|
+
if (priorityA > priorityB) {
|
|
1037
|
+
return -1;
|
|
1038
|
+
}
|
|
1039
|
+
if (priorityA < priorityB) {
|
|
1040
|
+
return 1;
|
|
1041
|
+
}
|
|
1042
|
+
return 0;
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
get commands() {
|
|
1046
|
+
return this.extensions.reduce((commands, extension) => {
|
|
1047
|
+
const context = {
|
|
1048
|
+
name: extension.name,
|
|
1049
|
+
options: extension.options,
|
|
1050
|
+
storage: extension.storage,
|
|
1051
|
+
editor: this.editor,
|
|
1052
|
+
type: getSchemaTypeByName(extension.name, this.schema)
|
|
1053
|
+
};
|
|
1054
|
+
const addCommands = getExtensionField(
|
|
1055
|
+
extension,
|
|
1056
|
+
"addCommands",
|
|
1057
|
+
context
|
|
1058
|
+
);
|
|
1059
|
+
if (!addCommands) {
|
|
1060
|
+
return commands;
|
|
1061
|
+
}
|
|
1062
|
+
return {
|
|
1063
|
+
...commands,
|
|
1064
|
+
...addCommands()
|
|
1065
|
+
};
|
|
1066
|
+
}, {});
|
|
1067
|
+
}
|
|
1068
|
+
get plugins() {
|
|
1069
|
+
const { editor } = this;
|
|
1070
|
+
const extensions = ExtensionManager.sort([...this.extensions].reverse());
|
|
1071
|
+
const inputRules = [];
|
|
1072
|
+
const pasteRules = [];
|
|
1073
|
+
const allPlugins = extensions.map((extension) => {
|
|
1074
|
+
const context = {
|
|
1075
|
+
name: extension.name,
|
|
1076
|
+
options: extension.options,
|
|
1077
|
+
storage: extension.storage,
|
|
1078
|
+
editor,
|
|
1079
|
+
type: getSchemaTypeByName(extension.name, this.schema)
|
|
1080
|
+
};
|
|
1081
|
+
const plugins = [];
|
|
1082
|
+
const addKeyboardShortcuts = getExtensionField(
|
|
1083
|
+
extension,
|
|
1084
|
+
"addKeyboardShortcuts",
|
|
1085
|
+
context
|
|
1086
|
+
);
|
|
1087
|
+
let defaultBindings = {};
|
|
1088
|
+
if (extension.type === "mark" && extension.config.exitable) {
|
|
1089
|
+
defaultBindings.ArrowRight = () => Mark.handleExit({ editor, mark: extension });
|
|
1090
|
+
}
|
|
1091
|
+
if (addKeyboardShortcuts) {
|
|
1092
|
+
const bindings = Object.fromEntries(
|
|
1093
|
+
Object.entries(addKeyboardShortcuts()).map(([shortcut, method]) => {
|
|
1094
|
+
return [shortcut, () => method({ editor })];
|
|
1095
|
+
})
|
|
1096
|
+
);
|
|
1097
|
+
defaultBindings = { ...defaultBindings, ...bindings };
|
|
1098
|
+
}
|
|
1099
|
+
const keyMapPlugin = keymap(defaultBindings);
|
|
1100
|
+
plugins.push(keyMapPlugin);
|
|
1101
|
+
const addInputRules = getExtensionField(
|
|
1102
|
+
extension,
|
|
1103
|
+
"addInputRules",
|
|
1104
|
+
context
|
|
1105
|
+
);
|
|
1106
|
+
if (isExtensionRulesEnabled(extension, editor.options.enableInputRules) && addInputRules) {
|
|
1107
|
+
inputRules.push(...addInputRules());
|
|
1108
|
+
}
|
|
1109
|
+
const addPasteRules = getExtensionField(
|
|
1110
|
+
extension,
|
|
1111
|
+
"addPasteRules",
|
|
1112
|
+
context
|
|
1113
|
+
);
|
|
1114
|
+
if (isExtensionRulesEnabled(extension, editor.options.enablePasteRules) && addPasteRules) {
|
|
1115
|
+
pasteRules.push(...addPasteRules());
|
|
1116
|
+
}
|
|
1117
|
+
const addProseMirrorPlugins = getExtensionField(
|
|
1118
|
+
extension,
|
|
1119
|
+
"addProseMirrorPlugins",
|
|
1120
|
+
context
|
|
1121
|
+
);
|
|
1122
|
+
if (addProseMirrorPlugins) {
|
|
1123
|
+
const proseMirrorPlugins = addProseMirrorPlugins();
|
|
1124
|
+
plugins.push(...proseMirrorPlugins);
|
|
1125
|
+
}
|
|
1126
|
+
return plugins;
|
|
1127
|
+
}).flat();
|
|
1128
|
+
return [
|
|
1129
|
+
inputRulesPlugin({
|
|
1130
|
+
editor,
|
|
1131
|
+
rules: inputRules
|
|
1132
|
+
}),
|
|
1133
|
+
...pasteRulesPlugin({
|
|
1134
|
+
editor,
|
|
1135
|
+
rules: pasteRules
|
|
1136
|
+
}),
|
|
1137
|
+
...allPlugins
|
|
1138
|
+
];
|
|
1139
|
+
}
|
|
1140
|
+
get attributes() {
|
|
1141
|
+
return getAttributesFromExtensions(this.extensions);
|
|
1142
|
+
}
|
|
1143
|
+
get nodeViews() {
|
|
1144
|
+
const { editor } = this;
|
|
1145
|
+
const { nodeExtensions } = splitExtensions(this.extensions);
|
|
1146
|
+
return Object.fromEntries(
|
|
1147
|
+
nodeExtensions.filter((extension) => !!getExtensionField(extension, "addNodeView")).map((extension) => {
|
|
1148
|
+
const extensionAttributes = this.attributes.filter(
|
|
1149
|
+
(attribute) => attribute.type === extension.name
|
|
1150
|
+
);
|
|
1151
|
+
const context = {
|
|
1152
|
+
name: extension.name,
|
|
1153
|
+
options: extension.options,
|
|
1154
|
+
storage: extension.storage,
|
|
1155
|
+
editor,
|
|
1156
|
+
type: getNodeType(extension.name, this.schema)
|
|
1157
|
+
};
|
|
1158
|
+
const addNodeView = getExtensionField(
|
|
1159
|
+
extension,
|
|
1160
|
+
"addNodeView",
|
|
1161
|
+
context
|
|
1162
|
+
);
|
|
1163
|
+
if (!addNodeView) {
|
|
1164
|
+
return [];
|
|
1165
|
+
}
|
|
1166
|
+
const nodeview = (node, view, getPos, decorations) => {
|
|
1167
|
+
const HTMLAttributes = getRenderedAttributes(node, extensionAttributes);
|
|
1168
|
+
return addNodeView()({
|
|
1169
|
+
editor,
|
|
1170
|
+
node,
|
|
1171
|
+
getPos,
|
|
1172
|
+
decorations,
|
|
1173
|
+
HTMLAttributes,
|
|
1174
|
+
extension
|
|
1175
|
+
});
|
|
1176
|
+
};
|
|
1177
|
+
return [extension.name, nodeview];
|
|
1178
|
+
})
|
|
1179
|
+
);
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
|
|
1183
|
+
// src/extensions/index.ts
|
|
1184
|
+
var extensions_exports = {};
|
|
1185
|
+
__export(extensions_exports, {
|
|
1186
|
+
ClipboardTextSerializer: () => ClipboardTextSerializer,
|
|
1187
|
+
Commands: () => Commands,
|
|
1188
|
+
Editable: () => Editable,
|
|
1189
|
+
FocusEvents: () => FocusEvents,
|
|
1190
|
+
Keymap: () => Keymap,
|
|
1191
|
+
Tabindex: () => Tabindex
|
|
1192
|
+
});
|
|
1193
|
+
|
|
1194
|
+
// src/extensions/clipboardTextSerializer.ts
|
|
1195
|
+
import { Plugin as Plugin3, PluginKey } from "@tiptap/pm/state";
|
|
1196
|
+
|
|
1197
|
+
// src/utilities/isPlainObject.ts
|
|
1198
|
+
function getType(value) {
|
|
1199
|
+
return Object.prototype.toString.call(value).slice(8, -1);
|
|
1200
|
+
}
|
|
1201
|
+
function isPlainObject(value) {
|
|
1202
|
+
if (getType(value) !== "Object") {
|
|
1203
|
+
return false;
|
|
1204
|
+
}
|
|
1205
|
+
return value.constructor === Object && Object.getPrototypeOf(value) === Object.prototype;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
// src/utilities/mergeDeep.ts
|
|
1209
|
+
function mergeDeep(target, source) {
|
|
1210
|
+
const output = { ...target };
|
|
1211
|
+
if (isPlainObject(target) && isPlainObject(source)) {
|
|
1212
|
+
Object.keys(source).forEach((key) => {
|
|
1213
|
+
if (isPlainObject(source[key])) {
|
|
1214
|
+
if (!(key in target)) {
|
|
1215
|
+
Object.assign(output, { [key]: source[key] });
|
|
1216
|
+
} else {
|
|
1217
|
+
output[key] = mergeDeep(target[key], source[key]);
|
|
1218
|
+
}
|
|
1219
|
+
} else {
|
|
1220
|
+
Object.assign(output, { [key]: source[key] });
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
return output;
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/Extension.ts
|
|
1228
|
+
var Extension = class {
|
|
1229
|
+
constructor(config = {}) {
|
|
1230
|
+
this.type = "extension";
|
|
1231
|
+
this.name = "extension";
|
|
1232
|
+
this.parent = null;
|
|
1233
|
+
this.child = null;
|
|
1234
|
+
this.config = {
|
|
1235
|
+
name: this.name,
|
|
1236
|
+
defaultOptions: {}
|
|
1237
|
+
};
|
|
1238
|
+
this.config = {
|
|
1239
|
+
...this.config,
|
|
1240
|
+
...config
|
|
1241
|
+
};
|
|
1242
|
+
this.name = this.config.name;
|
|
1243
|
+
if (config.defaultOptions) {
|
|
1244
|
+
console.warn(
|
|
1245
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
|
|
1246
|
+
);
|
|
1247
|
+
}
|
|
1248
|
+
this.options = this.config.defaultOptions;
|
|
1249
|
+
if (this.config.addOptions) {
|
|
1250
|
+
this.options = callOrReturn(
|
|
1251
|
+
getExtensionField(this, "addOptions", {
|
|
1252
|
+
name: this.name
|
|
1253
|
+
})
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
this.storage = callOrReturn(
|
|
1257
|
+
getExtensionField(this, "addStorage", {
|
|
1258
|
+
name: this.name,
|
|
1259
|
+
options: this.options
|
|
1260
|
+
})
|
|
1261
|
+
) || {};
|
|
1262
|
+
}
|
|
1263
|
+
static create(config = {}) {
|
|
1264
|
+
return new Extension(config);
|
|
1265
|
+
}
|
|
1266
|
+
configure(options = {}) {
|
|
1267
|
+
const extension = this.extend();
|
|
1268
|
+
extension.options = mergeDeep(this.options, options);
|
|
1269
|
+
extension.storage = callOrReturn(
|
|
1270
|
+
getExtensionField(extension, "addStorage", {
|
|
1271
|
+
name: extension.name,
|
|
1272
|
+
options: extension.options
|
|
1273
|
+
})
|
|
1274
|
+
);
|
|
1275
|
+
return extension;
|
|
1276
|
+
}
|
|
1277
|
+
extend(extendedConfig = {}) {
|
|
1278
|
+
const extension = new Extension(extendedConfig);
|
|
1279
|
+
extension.parent = this;
|
|
1280
|
+
this.child = extension;
|
|
1281
|
+
extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
|
|
1282
|
+
if (extendedConfig.defaultOptions) {
|
|
1283
|
+
console.warn(
|
|
1284
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
extension.options = callOrReturn(
|
|
1288
|
+
getExtensionField(extension, "addOptions", {
|
|
1289
|
+
name: extension.name
|
|
1290
|
+
})
|
|
1291
|
+
);
|
|
1292
|
+
extension.storage = callOrReturn(
|
|
1293
|
+
getExtensionField(extension, "addStorage", {
|
|
1294
|
+
name: extension.name,
|
|
1295
|
+
options: extension.options
|
|
1296
|
+
})
|
|
1297
|
+
);
|
|
1298
|
+
return extension;
|
|
1299
|
+
}
|
|
1300
|
+
};
|
|
1301
|
+
|
|
1302
|
+
// src/helpers/getTextBetween.ts
|
|
1303
|
+
function getTextBetween(startNode, range, options) {
|
|
1304
|
+
const { from, to } = range;
|
|
1305
|
+
const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
|
|
1306
|
+
let text = "";
|
|
1307
|
+
let separated = true;
|
|
1308
|
+
startNode.nodesBetween(from, to, (node, pos, parent, index) => {
|
|
1309
|
+
var _a;
|
|
1310
|
+
const textSerializer = textSerializers == null ? void 0 : textSerializers[node.type.name];
|
|
1311
|
+
if (textSerializer) {
|
|
1312
|
+
if (node.isBlock && !separated) {
|
|
1313
|
+
text += blockSeparator;
|
|
1314
|
+
separated = true;
|
|
1315
|
+
}
|
|
1316
|
+
if (parent) {
|
|
1317
|
+
text += textSerializer({
|
|
1318
|
+
node,
|
|
1319
|
+
pos,
|
|
1320
|
+
parent,
|
|
1321
|
+
index,
|
|
1322
|
+
range
|
|
1323
|
+
});
|
|
1324
|
+
}
|
|
1325
|
+
} else if (node.isText) {
|
|
1326
|
+
text += (_a = node == null ? void 0 : node.text) == null ? void 0 : _a.slice(Math.max(from, pos) - pos, to - pos);
|
|
1327
|
+
separated = false;
|
|
1328
|
+
} else if (node.isBlock && !separated) {
|
|
1329
|
+
text += blockSeparator;
|
|
1330
|
+
separated = true;
|
|
1331
|
+
}
|
|
1332
|
+
});
|
|
1333
|
+
return text;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
// src/helpers/getTextSerializersFromSchema.ts
|
|
1337
|
+
function getTextSerializersFromSchema(schema) {
|
|
1338
|
+
return Object.fromEntries(
|
|
1339
|
+
Object.entries(schema.nodes).filter(([, node]) => node.spec.toText).map(([name, node]) => [name, node.spec.toText])
|
|
1340
|
+
);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
// src/extensions/clipboardTextSerializer.ts
|
|
1344
|
+
var ClipboardTextSerializer = Extension.create({
|
|
1345
|
+
name: "clipboardTextSerializer",
|
|
1346
|
+
addProseMirrorPlugins() {
|
|
1347
|
+
return [
|
|
1348
|
+
new Plugin3({
|
|
1349
|
+
key: new PluginKey("clipboardTextSerializer"),
|
|
1350
|
+
props: {
|
|
1351
|
+
clipboardTextSerializer: () => {
|
|
1352
|
+
const { editor } = this;
|
|
1353
|
+
const { state, schema } = editor;
|
|
1354
|
+
const { doc, selection } = state;
|
|
1355
|
+
const { ranges } = selection;
|
|
1356
|
+
const from = Math.min(...ranges.map((range2) => range2.$from.pos));
|
|
1357
|
+
const to = Math.max(...ranges.map((range2) => range2.$to.pos));
|
|
1358
|
+
const textSerializers = getTextSerializersFromSchema(schema);
|
|
1359
|
+
const range = { from, to };
|
|
1360
|
+
return getTextBetween(doc, range, {
|
|
1361
|
+
textSerializers
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
})
|
|
1366
|
+
];
|
|
1367
|
+
}
|
|
1368
|
+
});
|
|
1369
|
+
|
|
1370
|
+
// src/commands/index.ts
|
|
1371
|
+
var commands_exports = {};
|
|
1372
|
+
__export(commands_exports, {
|
|
1373
|
+
blur: () => blur,
|
|
1374
|
+
clearContent: () => clearContent,
|
|
1375
|
+
clearNodes: () => clearNodes,
|
|
1376
|
+
command: () => command,
|
|
1377
|
+
createParagraphNear: () => createParagraphNear,
|
|
1378
|
+
deleteCurrentNode: () => deleteCurrentNode,
|
|
1379
|
+
deleteNode: () => deleteNode,
|
|
1380
|
+
deleteRange: () => deleteRange,
|
|
1381
|
+
deleteSelection: () => deleteSelection,
|
|
1382
|
+
enter: () => enter,
|
|
1383
|
+
exitCode: () => exitCode,
|
|
1384
|
+
extendMarkRange: () => extendMarkRange,
|
|
1385
|
+
first: () => first,
|
|
1386
|
+
focus: () => focus,
|
|
1387
|
+
forEach: () => forEach,
|
|
1388
|
+
insertContent: () => insertContent,
|
|
1389
|
+
insertContentAt: () => insertContentAt,
|
|
1390
|
+
joinBackward: () => joinBackward,
|
|
1391
|
+
joinDown: () => joinDown,
|
|
1392
|
+
joinForward: () => joinForward,
|
|
1393
|
+
joinUp: () => joinUp,
|
|
1394
|
+
keyboardShortcut: () => keyboardShortcut,
|
|
1395
|
+
lift: () => lift,
|
|
1396
|
+
liftEmptyBlock: () => liftEmptyBlock,
|
|
1397
|
+
liftListItem: () => liftListItem,
|
|
1398
|
+
newlineInCode: () => newlineInCode,
|
|
1399
|
+
resetAttributes: () => resetAttributes,
|
|
1400
|
+
scrollIntoView: () => scrollIntoView,
|
|
1401
|
+
selectAll: () => selectAll,
|
|
1402
|
+
selectNodeBackward: () => selectNodeBackward,
|
|
1403
|
+
selectNodeForward: () => selectNodeForward,
|
|
1404
|
+
selectParentNode: () => selectParentNode,
|
|
1405
|
+
selectTextblockEnd: () => selectTextblockEnd,
|
|
1406
|
+
selectTextblockStart: () => selectTextblockStart,
|
|
1407
|
+
setContent: () => setContent,
|
|
1408
|
+
setMark: () => setMark,
|
|
1409
|
+
setMeta: () => setMeta,
|
|
1410
|
+
setNode: () => setNode,
|
|
1411
|
+
setNodeSelection: () => setNodeSelection,
|
|
1412
|
+
setTextSelection: () => setTextSelection,
|
|
1413
|
+
sinkListItem: () => sinkListItem,
|
|
1414
|
+
splitBlock: () => splitBlock,
|
|
1415
|
+
splitListItem: () => splitListItem,
|
|
1416
|
+
toggleList: () => toggleList,
|
|
1417
|
+
toggleMark: () => toggleMark,
|
|
1418
|
+
toggleNode: () => toggleNode,
|
|
1419
|
+
toggleWrap: () => toggleWrap,
|
|
1420
|
+
undoInputRule: () => undoInputRule,
|
|
1421
|
+
unsetAllMarks: () => unsetAllMarks,
|
|
1422
|
+
unsetMark: () => unsetMark,
|
|
1423
|
+
updateAttributes: () => updateAttributes,
|
|
1424
|
+
wrapIn: () => wrapIn,
|
|
1425
|
+
wrapInList: () => wrapInList
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
// src/commands/blur.ts
|
|
1429
|
+
var blur = () => ({ editor, view }) => {
|
|
1430
|
+
requestAnimationFrame(() => {
|
|
1431
|
+
var _a;
|
|
1432
|
+
if (!editor.isDestroyed) {
|
|
1433
|
+
view.dom.blur();
|
|
1434
|
+
(_a = window == null ? void 0 : window.getSelection()) == null ? void 0 : _a.removeAllRanges();
|
|
1435
|
+
}
|
|
1436
|
+
});
|
|
1437
|
+
return true;
|
|
1438
|
+
};
|
|
1439
|
+
|
|
1440
|
+
// src/commands/clearContent.ts
|
|
1441
|
+
var clearContent = (emitUpdate = false) => ({ commands }) => {
|
|
1442
|
+
return commands.setContent("", emitUpdate);
|
|
1443
|
+
};
|
|
1444
|
+
|
|
1445
|
+
// src/commands/clearNodes.ts
|
|
1446
|
+
import { liftTarget } from "@tiptap/pm/transform";
|
|
1447
|
+
var clearNodes = () => ({ state, tr, dispatch }) => {
|
|
1448
|
+
const { selection } = tr;
|
|
1449
|
+
const { ranges } = selection;
|
|
1450
|
+
if (!dispatch) {
|
|
1451
|
+
return true;
|
|
1452
|
+
}
|
|
1453
|
+
ranges.forEach(({ $from, $to }) => {
|
|
1454
|
+
state.doc.nodesBetween($from.pos, $to.pos, (node, pos) => {
|
|
1455
|
+
if (node.type.isText) {
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
const { doc, mapping } = tr;
|
|
1459
|
+
const $mappedFrom = doc.resolve(mapping.map(pos));
|
|
1460
|
+
const $mappedTo = doc.resolve(mapping.map(pos + node.nodeSize));
|
|
1461
|
+
const nodeRange = $mappedFrom.blockRange($mappedTo);
|
|
1462
|
+
if (!nodeRange) {
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
const targetLiftDepth = liftTarget(nodeRange);
|
|
1466
|
+
if (node.type.isTextblock) {
|
|
1467
|
+
const { defaultType } = $mappedFrom.parent.contentMatchAt($mappedFrom.index());
|
|
1468
|
+
tr.setNodeMarkup(nodeRange.start, defaultType);
|
|
1469
|
+
}
|
|
1470
|
+
if (targetLiftDepth || targetLiftDepth === 0) {
|
|
1471
|
+
tr.lift(nodeRange, targetLiftDepth);
|
|
1472
|
+
}
|
|
1473
|
+
});
|
|
1474
|
+
});
|
|
1475
|
+
return true;
|
|
1476
|
+
};
|
|
1477
|
+
|
|
1478
|
+
// src/commands/command.ts
|
|
1479
|
+
var command = (fn) => (props) => {
|
|
1480
|
+
return fn(props);
|
|
1481
|
+
};
|
|
1482
|
+
|
|
1483
|
+
// src/commands/createParagraphNear.ts
|
|
1484
|
+
import { createParagraphNear as originalCreateParagraphNear } from "@tiptap/pm/commands";
|
|
1485
|
+
var createParagraphNear = () => ({ state, dispatch }) => {
|
|
1486
|
+
return originalCreateParagraphNear(state, dispatch);
|
|
1487
|
+
};
|
|
1488
|
+
|
|
1489
|
+
// src/commands/deleteCurrentNode.ts
|
|
1490
|
+
var deleteCurrentNode = () => ({ tr, dispatch }) => {
|
|
1491
|
+
const { selection } = tr;
|
|
1492
|
+
const currentNode = selection.$anchor.node();
|
|
1493
|
+
if (currentNode.content.size > 0) {
|
|
1494
|
+
return false;
|
|
1495
|
+
}
|
|
1496
|
+
const $pos = tr.selection.$anchor;
|
|
1497
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
1498
|
+
const node = $pos.node(depth);
|
|
1499
|
+
if (node.type === currentNode.type) {
|
|
1500
|
+
if (dispatch) {
|
|
1501
|
+
const from = $pos.before(depth);
|
|
1502
|
+
const to = $pos.after(depth);
|
|
1503
|
+
tr.delete(from, to).scrollIntoView();
|
|
1504
|
+
}
|
|
1505
|
+
return true;
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
return false;
|
|
1509
|
+
};
|
|
1510
|
+
|
|
1511
|
+
// src/commands/deleteNode.ts
|
|
1512
|
+
var deleteNode = (typeOrName) => ({ tr, state, dispatch }) => {
|
|
1513
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
1514
|
+
const $pos = tr.selection.$anchor;
|
|
1515
|
+
for (let depth = $pos.depth; depth > 0; depth -= 1) {
|
|
1516
|
+
const node = $pos.node(depth);
|
|
1517
|
+
if (node.type === type) {
|
|
1518
|
+
if (dispatch) {
|
|
1519
|
+
const from = $pos.before(depth);
|
|
1520
|
+
const to = $pos.after(depth);
|
|
1521
|
+
tr.delete(from, to).scrollIntoView();
|
|
1522
|
+
}
|
|
1523
|
+
return true;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
return false;
|
|
1527
|
+
};
|
|
1528
|
+
|
|
1529
|
+
// src/commands/deleteRange.ts
|
|
1530
|
+
var deleteRange = (range) => ({ tr, dispatch }) => {
|
|
1531
|
+
const { from, to } = range;
|
|
1532
|
+
if (dispatch) {
|
|
1533
|
+
tr.delete(from, to);
|
|
1534
|
+
}
|
|
1535
|
+
return true;
|
|
1536
|
+
};
|
|
1537
|
+
|
|
1538
|
+
// src/commands/deleteSelection.ts
|
|
1539
|
+
import { deleteSelection as originalDeleteSelection } from "@tiptap/pm/commands";
|
|
1540
|
+
var deleteSelection = () => ({ state, dispatch }) => {
|
|
1541
|
+
return originalDeleteSelection(state, dispatch);
|
|
1542
|
+
};
|
|
1543
|
+
|
|
1544
|
+
// src/commands/enter.ts
|
|
1545
|
+
var enter = () => ({ commands }) => {
|
|
1546
|
+
return commands.keyboardShortcut("Enter");
|
|
1547
|
+
};
|
|
1548
|
+
|
|
1549
|
+
// src/commands/exitCode.ts
|
|
1550
|
+
import { exitCode as originalExitCode } from "@tiptap/pm/commands";
|
|
1551
|
+
var exitCode = () => ({ state, dispatch }) => {
|
|
1552
|
+
return originalExitCode(state, dispatch);
|
|
1553
|
+
};
|
|
1554
|
+
|
|
1555
|
+
// src/commands/extendMarkRange.ts
|
|
1556
|
+
import { TextSelection as TextSelection2 } from "@tiptap/pm/state";
|
|
1557
|
+
|
|
1558
|
+
// src/utilities/objectIncludes.ts
|
|
1559
|
+
function objectIncludes(object1, object2, options = { strict: true }) {
|
|
1560
|
+
const keys = Object.keys(object2);
|
|
1561
|
+
if (!keys.length) {
|
|
1562
|
+
return true;
|
|
1563
|
+
}
|
|
1564
|
+
return keys.every((key) => {
|
|
1565
|
+
if (options.strict) {
|
|
1566
|
+
return object2[key] === object1[key];
|
|
1567
|
+
}
|
|
1568
|
+
if (isRegExp(object2[key])) {
|
|
1569
|
+
return object2[key].test(object1[key]);
|
|
1570
|
+
}
|
|
1571
|
+
return object2[key] === object1[key];
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
// src/helpers/getMarkRange.ts
|
|
1576
|
+
function findMarkInSet(marks, type, attributes = {}) {
|
|
1577
|
+
return marks.find((item) => {
|
|
1578
|
+
return item.type === type && objectIncludes(item.attrs, attributes);
|
|
1579
|
+
});
|
|
1580
|
+
}
|
|
1581
|
+
function isMarkInSet(marks, type, attributes = {}) {
|
|
1582
|
+
return !!findMarkInSet(marks, type, attributes);
|
|
1583
|
+
}
|
|
1584
|
+
function getMarkRange($pos, type, attributes = {}) {
|
|
1585
|
+
if (!$pos || !type) {
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
let start = $pos.parent.childAfter($pos.parentOffset);
|
|
1589
|
+
if ($pos.parentOffset === start.offset && start.offset !== 0) {
|
|
1590
|
+
start = $pos.parent.childBefore($pos.parentOffset);
|
|
1591
|
+
}
|
|
1592
|
+
if (!start.node) {
|
|
1593
|
+
return;
|
|
1594
|
+
}
|
|
1595
|
+
const mark = findMarkInSet([...start.node.marks], type, attributes);
|
|
1596
|
+
if (!mark) {
|
|
1597
|
+
return;
|
|
1598
|
+
}
|
|
1599
|
+
let startIndex = start.index;
|
|
1600
|
+
let startPos = $pos.start() + start.offset;
|
|
1601
|
+
let endIndex = startIndex + 1;
|
|
1602
|
+
let endPos = startPos + start.node.nodeSize;
|
|
1603
|
+
findMarkInSet([...start.node.marks], type, attributes);
|
|
1604
|
+
while (startIndex > 0 && mark.isInSet($pos.parent.child(startIndex - 1).marks)) {
|
|
1605
|
+
startIndex -= 1;
|
|
1606
|
+
startPos -= $pos.parent.child(startIndex).nodeSize;
|
|
1607
|
+
}
|
|
1608
|
+
while (endIndex < $pos.parent.childCount && isMarkInSet([...$pos.parent.child(endIndex).marks], type, attributes)) {
|
|
1609
|
+
endPos += $pos.parent.child(endIndex).nodeSize;
|
|
1610
|
+
endIndex += 1;
|
|
1611
|
+
}
|
|
1612
|
+
return {
|
|
1613
|
+
from: startPos,
|
|
1614
|
+
to: endPos
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
// src/helpers/getMarkType.ts
|
|
1619
|
+
function getMarkType(nameOrType, schema) {
|
|
1620
|
+
if (typeof nameOrType === "string") {
|
|
1621
|
+
if (!schema.marks[nameOrType]) {
|
|
1622
|
+
throw Error(
|
|
1623
|
+
`There is no mark type named '${nameOrType}'. Maybe you forgot to add the extension?`
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
return schema.marks[nameOrType];
|
|
1627
|
+
}
|
|
1628
|
+
return nameOrType;
|
|
1629
|
+
}
|
|
1630
|
+
|
|
1631
|
+
// src/commands/extendMarkRange.ts
|
|
1632
|
+
var extendMarkRange = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
|
|
1633
|
+
const type = getMarkType(typeOrName, state.schema);
|
|
1634
|
+
const { doc, selection } = tr;
|
|
1635
|
+
const { $from, from, to } = selection;
|
|
1636
|
+
if (dispatch) {
|
|
1637
|
+
const range = getMarkRange($from, type, attributes);
|
|
1638
|
+
if (range && range.from <= from && range.to >= to) {
|
|
1639
|
+
const newSelection = TextSelection2.create(doc, range.from, range.to);
|
|
1640
|
+
tr.setSelection(newSelection);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
return true;
|
|
1644
|
+
};
|
|
1645
|
+
|
|
1646
|
+
// src/commands/first.ts
|
|
1647
|
+
var first = (commands) => (props) => {
|
|
1648
|
+
const items = typeof commands === "function" ? commands(props) : commands;
|
|
1649
|
+
for (let i = 0; i < items.length; i += 1) {
|
|
1650
|
+
if (items[i](props)) {
|
|
1651
|
+
return true;
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
return false;
|
|
1655
|
+
};
|
|
1656
|
+
|
|
1657
|
+
// src/helpers/isTextSelection.ts
|
|
1658
|
+
import { TextSelection as TextSelection3 } from "@tiptap/pm/state";
|
|
1659
|
+
function isTextSelection(value) {
|
|
1660
|
+
return value instanceof TextSelection3;
|
|
1661
|
+
}
|
|
1662
|
+
|
|
1663
|
+
// src/helpers/resolveFocusPosition.ts
|
|
1664
|
+
import { Selection, TextSelection as TextSelection4 } from "@tiptap/pm/state";
|
|
1665
|
+
|
|
1666
|
+
// src/utilities/minMax.ts
|
|
1667
|
+
function minMax(value = 0, min = 0, max = 0) {
|
|
1668
|
+
return Math.min(Math.max(value, min), max);
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
// src/helpers/resolveFocusPosition.ts
|
|
1672
|
+
function resolveFocusPosition(doc, position = null) {
|
|
1673
|
+
if (!position) {
|
|
1674
|
+
return null;
|
|
1675
|
+
}
|
|
1676
|
+
const selectionAtStart = Selection.atStart(doc);
|
|
1677
|
+
const selectionAtEnd = Selection.atEnd(doc);
|
|
1678
|
+
if (position === "start" || position === true) {
|
|
1679
|
+
return selectionAtStart;
|
|
1680
|
+
}
|
|
1681
|
+
if (position === "end") {
|
|
1682
|
+
return selectionAtEnd;
|
|
1683
|
+
}
|
|
1684
|
+
const minPos = selectionAtStart.from;
|
|
1685
|
+
const maxPos = selectionAtEnd.to;
|
|
1686
|
+
if (position === "all") {
|
|
1687
|
+
return TextSelection4.create(
|
|
1688
|
+
doc,
|
|
1689
|
+
minMax(0, minPos, maxPos),
|
|
1690
|
+
minMax(doc.content.size, minPos, maxPos)
|
|
1691
|
+
);
|
|
1692
|
+
}
|
|
1693
|
+
return TextSelection4.create(
|
|
1694
|
+
doc,
|
|
1695
|
+
minMax(position, minPos, maxPos),
|
|
1696
|
+
minMax(position, minPos, maxPos)
|
|
1697
|
+
);
|
|
1698
|
+
}
|
|
1699
|
+
|
|
1700
|
+
// src/utilities/isiOS.ts
|
|
1701
|
+
function isiOS() {
|
|
1702
|
+
return [
|
|
1703
|
+
"iPad Simulator",
|
|
1704
|
+
"iPhone Simulator",
|
|
1705
|
+
"iPod Simulator",
|
|
1706
|
+
"iPad",
|
|
1707
|
+
"iPhone",
|
|
1708
|
+
"iPod"
|
|
1709
|
+
].includes(navigator.platform) || navigator.userAgent.includes("Mac") && "ontouchend" in document;
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
// src/commands/focus.ts
|
|
1713
|
+
var focus = (position = null, options = {}) => ({
|
|
1714
|
+
editor,
|
|
1715
|
+
view,
|
|
1716
|
+
tr,
|
|
1717
|
+
dispatch
|
|
1718
|
+
}) => {
|
|
1719
|
+
options = {
|
|
1720
|
+
scrollIntoView: true,
|
|
1721
|
+
...options
|
|
1722
|
+
};
|
|
1723
|
+
const delayedFocus = () => {
|
|
1724
|
+
if (isiOS()) {
|
|
1725
|
+
view.dom.focus();
|
|
1726
|
+
}
|
|
1727
|
+
requestAnimationFrame(() => {
|
|
1728
|
+
if (!editor.isDestroyed) {
|
|
1729
|
+
view.focus();
|
|
1730
|
+
if (options == null ? void 0 : options.scrollIntoView) {
|
|
1731
|
+
editor.commands.scrollIntoView();
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
});
|
|
1735
|
+
};
|
|
1736
|
+
if (view.hasFocus() && position === null || position === false) {
|
|
1737
|
+
return true;
|
|
1738
|
+
}
|
|
1739
|
+
if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
|
|
1740
|
+
delayedFocus();
|
|
1741
|
+
return true;
|
|
1742
|
+
}
|
|
1743
|
+
const selection = resolveFocusPosition(tr.doc, position) || editor.state.selection;
|
|
1744
|
+
const isSameSelection = editor.state.selection.eq(selection);
|
|
1745
|
+
if (dispatch) {
|
|
1746
|
+
if (!isSameSelection) {
|
|
1747
|
+
tr.setSelection(selection);
|
|
1748
|
+
}
|
|
1749
|
+
if (isSameSelection && tr.storedMarks) {
|
|
1750
|
+
tr.setStoredMarks(tr.storedMarks);
|
|
1751
|
+
}
|
|
1752
|
+
delayedFocus();
|
|
1753
|
+
}
|
|
1754
|
+
return true;
|
|
1755
|
+
};
|
|
1756
|
+
|
|
1757
|
+
// src/commands/forEach.ts
|
|
1758
|
+
var forEach = (items, fn) => (props) => {
|
|
1759
|
+
return items.every((item, index) => fn(item, { ...props, index }));
|
|
1760
|
+
};
|
|
1761
|
+
|
|
1762
|
+
// src/commands/insertContent.ts
|
|
1763
|
+
var insertContent = (value, options) => ({ tr, commands }) => {
|
|
1764
|
+
return commands.insertContentAt(
|
|
1765
|
+
{ from: tr.selection.from, to: tr.selection.to },
|
|
1766
|
+
value,
|
|
1767
|
+
options
|
|
1768
|
+
);
|
|
1769
|
+
};
|
|
1770
|
+
|
|
1771
|
+
// src/helpers/createNodeFromContent.ts
|
|
1772
|
+
import {
|
|
1773
|
+
DOMParser,
|
|
1774
|
+
Fragment
|
|
1775
|
+
} from "@tiptap/pm/model";
|
|
1776
|
+
|
|
1777
|
+
// src/utilities/elementFromString.ts
|
|
1778
|
+
function elementFromString(value) {
|
|
1779
|
+
const wrappedValue = `<body>${value}</body>`;
|
|
1780
|
+
return new window.DOMParser().parseFromString(wrappedValue, "text/html").body;
|
|
1781
|
+
}
|
|
1782
|
+
|
|
1783
|
+
// src/helpers/createNodeFromContent.ts
|
|
1784
|
+
function createNodeFromContent(content, schema, options) {
|
|
1785
|
+
options = {
|
|
1786
|
+
slice: true,
|
|
1787
|
+
parseOptions: {},
|
|
1788
|
+
...options
|
|
1789
|
+
};
|
|
1790
|
+
if (typeof content === "object" && content !== null) {
|
|
1791
|
+
try {
|
|
1792
|
+
if (Array.isArray(content)) {
|
|
1793
|
+
return Fragment.fromArray(content.map((item) => schema.nodeFromJSON(item)));
|
|
1794
|
+
}
|
|
1795
|
+
return schema.nodeFromJSON(content);
|
|
1796
|
+
} catch (error) {
|
|
1797
|
+
console.warn("[tiptap warn]: Invalid content.", "Passed value:", content, "Error:", error);
|
|
1798
|
+
return createNodeFromContent("", schema, options);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
if (typeof content === "string") {
|
|
1802
|
+
const parser = DOMParser.fromSchema(schema);
|
|
1803
|
+
return options.slice ? parser.parseSlice(elementFromString(content), options.parseOptions).content : parser.parse(elementFromString(content), options.parseOptions);
|
|
1804
|
+
}
|
|
1805
|
+
return createNodeFromContent("", schema, options);
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
// src/helpers/selectionToInsertionEnd.ts
|
|
1809
|
+
import { Selection as Selection2 } from "@tiptap/pm/state";
|
|
1810
|
+
import { ReplaceAroundStep, ReplaceStep } from "@tiptap/pm/transform";
|
|
1811
|
+
function selectionToInsertionEnd(tr, startLen, bias) {
|
|
1812
|
+
const last = tr.steps.length - 1;
|
|
1813
|
+
if (last < startLen) {
|
|
1814
|
+
return;
|
|
1815
|
+
}
|
|
1816
|
+
const step = tr.steps[last];
|
|
1817
|
+
if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep)) {
|
|
1818
|
+
return;
|
|
1819
|
+
}
|
|
1820
|
+
const map = tr.mapping.maps[last];
|
|
1821
|
+
let end = 0;
|
|
1822
|
+
map.forEach((_from, _to, _newFrom, newTo) => {
|
|
1823
|
+
if (end === 0) {
|
|
1824
|
+
end = newTo;
|
|
1825
|
+
}
|
|
1826
|
+
});
|
|
1827
|
+
tr.setSelection(Selection2.near(tr.doc.resolve(end), bias));
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
// src/commands/insertContentAt.ts
|
|
1831
|
+
var isFragment = (nodeOrFragment) => {
|
|
1832
|
+
return nodeOrFragment.toString().startsWith("<");
|
|
1833
|
+
};
|
|
1834
|
+
var insertContentAt = (position, value, options) => ({ tr, dispatch, editor }) => {
|
|
1835
|
+
if (dispatch) {
|
|
1836
|
+
options = {
|
|
1837
|
+
parseOptions: {},
|
|
1838
|
+
updateSelection: true,
|
|
1839
|
+
...options
|
|
1840
|
+
};
|
|
1841
|
+
const content = createNodeFromContent(value, editor.schema, {
|
|
1842
|
+
parseOptions: {
|
|
1843
|
+
preserveWhitespace: "full",
|
|
1844
|
+
...options.parseOptions
|
|
1845
|
+
}
|
|
1846
|
+
});
|
|
1847
|
+
if (content.toString() === "<>") {
|
|
1848
|
+
return true;
|
|
1849
|
+
}
|
|
1850
|
+
let { from, to } = typeof position === "number" ? { from: position, to: position } : position;
|
|
1851
|
+
let isOnlyTextContent = true;
|
|
1852
|
+
let isOnlyBlockContent = true;
|
|
1853
|
+
const nodes = isFragment(content) ? content : [content];
|
|
1854
|
+
nodes.forEach((node) => {
|
|
1855
|
+
node.check();
|
|
1856
|
+
isOnlyTextContent = isOnlyTextContent ? node.isText && node.marks.length === 0 : false;
|
|
1857
|
+
isOnlyBlockContent = isOnlyBlockContent ? node.isBlock : false;
|
|
1858
|
+
});
|
|
1859
|
+
if (from === to && isOnlyBlockContent) {
|
|
1860
|
+
const { parent } = tr.doc.resolve(from);
|
|
1861
|
+
const isEmptyTextBlock = parent.isTextblock && !parent.type.spec.code && !parent.childCount;
|
|
1862
|
+
if (isEmptyTextBlock) {
|
|
1863
|
+
from -= 1;
|
|
1864
|
+
to += 1;
|
|
1865
|
+
}
|
|
1866
|
+
}
|
|
1867
|
+
if (isOnlyTextContent) {
|
|
1868
|
+
tr.insertText(value, from, to);
|
|
1869
|
+
} else {
|
|
1870
|
+
tr.replaceWith(from, to, content);
|
|
1871
|
+
}
|
|
1872
|
+
if (options.updateSelection) {
|
|
1873
|
+
selectionToInsertionEnd(tr, tr.steps.length - 1, -1);
|
|
1874
|
+
}
|
|
1875
|
+
}
|
|
1876
|
+
return true;
|
|
1877
|
+
};
|
|
1878
|
+
|
|
1879
|
+
// src/commands/join.ts
|
|
1880
|
+
import {
|
|
1881
|
+
joinBackward as originalJoinBackward,
|
|
1882
|
+
joinDown as originalJoinDown,
|
|
1883
|
+
joinForward as originalJoinForward,
|
|
1884
|
+
joinUp as originalJoinUp
|
|
1885
|
+
} from "@tiptap/pm/commands";
|
|
1886
|
+
var joinUp = () => ({ state, dispatch }) => {
|
|
1887
|
+
return originalJoinUp(state, dispatch);
|
|
1888
|
+
};
|
|
1889
|
+
var joinDown = () => ({ state, dispatch }) => {
|
|
1890
|
+
return originalJoinDown(state, dispatch);
|
|
1891
|
+
};
|
|
1892
|
+
var joinBackward = () => ({ state, dispatch }) => {
|
|
1893
|
+
return originalJoinBackward(state, dispatch);
|
|
1894
|
+
};
|
|
1895
|
+
var joinForward = () => ({ state, dispatch }) => {
|
|
1896
|
+
return originalJoinForward(state, dispatch);
|
|
1897
|
+
};
|
|
1898
|
+
|
|
1899
|
+
// src/utilities/isMacOS.ts
|
|
1900
|
+
function isMacOS() {
|
|
1901
|
+
return typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false;
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
// src/commands/keyboardShortcut.ts
|
|
1905
|
+
function normalizeKeyName(name) {
|
|
1906
|
+
const parts = name.split(/-(?!$)/);
|
|
1907
|
+
let result = parts[parts.length - 1];
|
|
1908
|
+
if (result === "Space") {
|
|
1909
|
+
result = " ";
|
|
1910
|
+
}
|
|
1911
|
+
let alt;
|
|
1912
|
+
let ctrl;
|
|
1913
|
+
let shift;
|
|
1914
|
+
let meta;
|
|
1915
|
+
for (let i = 0; i < parts.length - 1; i += 1) {
|
|
1916
|
+
const mod = parts[i];
|
|
1917
|
+
if (/^(cmd|meta|m)$/i.test(mod)) {
|
|
1918
|
+
meta = true;
|
|
1919
|
+
} else if (/^a(lt)?$/i.test(mod)) {
|
|
1920
|
+
alt = true;
|
|
1921
|
+
} else if (/^(c|ctrl|control)$/i.test(mod)) {
|
|
1922
|
+
ctrl = true;
|
|
1923
|
+
} else if (/^s(hift)?$/i.test(mod)) {
|
|
1924
|
+
shift = true;
|
|
1925
|
+
} else if (/^mod$/i.test(mod)) {
|
|
1926
|
+
if (isiOS() || isMacOS()) {
|
|
1927
|
+
meta = true;
|
|
1928
|
+
} else {
|
|
1929
|
+
ctrl = true;
|
|
1930
|
+
}
|
|
1931
|
+
} else {
|
|
1932
|
+
throw new Error(`Unrecognized modifier name: ${mod}`);
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
if (alt) {
|
|
1936
|
+
result = `Alt-${result}`;
|
|
1937
|
+
}
|
|
1938
|
+
if (ctrl) {
|
|
1939
|
+
result = `Ctrl-${result}`;
|
|
1940
|
+
}
|
|
1941
|
+
if (meta) {
|
|
1942
|
+
result = `Meta-${result}`;
|
|
1943
|
+
}
|
|
1944
|
+
if (shift) {
|
|
1945
|
+
result = `Shift-${result}`;
|
|
1946
|
+
}
|
|
1947
|
+
return result;
|
|
1948
|
+
}
|
|
1949
|
+
var keyboardShortcut = (name) => ({
|
|
1950
|
+
editor,
|
|
1951
|
+
view,
|
|
1952
|
+
tr,
|
|
1953
|
+
dispatch
|
|
1954
|
+
}) => {
|
|
1955
|
+
const keys = normalizeKeyName(name).split(/-(?!$)/);
|
|
1956
|
+
const key = keys.find((item) => !["Alt", "Ctrl", "Meta", "Shift"].includes(item));
|
|
1957
|
+
const event = new KeyboardEvent("keydown", {
|
|
1958
|
+
key: key === "Space" ? " " : key,
|
|
1959
|
+
altKey: keys.includes("Alt"),
|
|
1960
|
+
ctrlKey: keys.includes("Ctrl"),
|
|
1961
|
+
metaKey: keys.includes("Meta"),
|
|
1962
|
+
shiftKey: keys.includes("Shift"),
|
|
1963
|
+
bubbles: true,
|
|
1964
|
+
cancelable: true
|
|
1965
|
+
});
|
|
1966
|
+
const capturedTransaction = editor.captureTransaction(() => {
|
|
1967
|
+
view.someProp("handleKeyDown", (f) => f(view, event));
|
|
1968
|
+
});
|
|
1969
|
+
capturedTransaction == null ? void 0 : capturedTransaction.steps.forEach((step) => {
|
|
1970
|
+
const newStep = step.map(tr.mapping);
|
|
1971
|
+
if (newStep && dispatch) {
|
|
1972
|
+
tr.maybeStep(newStep);
|
|
1973
|
+
}
|
|
1974
|
+
});
|
|
1975
|
+
return true;
|
|
1976
|
+
};
|
|
1977
|
+
|
|
1978
|
+
// src/commands/lift.ts
|
|
1979
|
+
import { lift as originalLift } from "@tiptap/pm/commands";
|
|
1980
|
+
|
|
1981
|
+
// src/helpers/isNodeActive.ts
|
|
1982
|
+
function isNodeActive(state, typeOrName, attributes = {}) {
|
|
1983
|
+
const { from, to, empty } = state.selection;
|
|
1984
|
+
const type = typeOrName ? getNodeType(typeOrName, state.schema) : null;
|
|
1985
|
+
const nodeRanges = [];
|
|
1986
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
1987
|
+
if (node.isText) {
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
const relativeFrom = Math.max(from, pos);
|
|
1991
|
+
const relativeTo = Math.min(to, pos + node.nodeSize);
|
|
1992
|
+
nodeRanges.push({
|
|
1993
|
+
node,
|
|
1994
|
+
from: relativeFrom,
|
|
1995
|
+
to: relativeTo
|
|
1996
|
+
});
|
|
1997
|
+
});
|
|
1998
|
+
const selectionRange = to - from;
|
|
1999
|
+
const matchedNodeRanges = nodeRanges.filter((nodeRange) => {
|
|
2000
|
+
if (!type) {
|
|
2001
|
+
return true;
|
|
2002
|
+
}
|
|
2003
|
+
return type.name === nodeRange.node.type.name;
|
|
2004
|
+
}).filter((nodeRange) => objectIncludes(nodeRange.node.attrs, attributes, { strict: false }));
|
|
2005
|
+
if (empty) {
|
|
2006
|
+
return !!matchedNodeRanges.length;
|
|
2007
|
+
}
|
|
2008
|
+
const range = matchedNodeRanges.reduce((sum, nodeRange) => sum + nodeRange.to - nodeRange.from, 0);
|
|
2009
|
+
return range >= selectionRange;
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
// src/commands/lift.ts
|
|
2013
|
+
var lift = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
|
|
2014
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2015
|
+
const isActive2 = isNodeActive(state, type, attributes);
|
|
2016
|
+
if (!isActive2) {
|
|
2017
|
+
return false;
|
|
2018
|
+
}
|
|
2019
|
+
return originalLift(state, dispatch);
|
|
2020
|
+
};
|
|
2021
|
+
|
|
2022
|
+
// src/commands/liftEmptyBlock.ts
|
|
2023
|
+
import { liftEmptyBlock as originalLiftEmptyBlock } from "@tiptap/pm/commands";
|
|
2024
|
+
var liftEmptyBlock = () => ({ state, dispatch }) => {
|
|
2025
|
+
return originalLiftEmptyBlock(state, dispatch);
|
|
2026
|
+
};
|
|
2027
|
+
|
|
2028
|
+
// src/commands/liftListItem.ts
|
|
2029
|
+
import { liftListItem as originalLiftListItem } from "@tiptap/pm/schema-list";
|
|
2030
|
+
var liftListItem = (typeOrName) => ({ state, dispatch }) => {
|
|
2031
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2032
|
+
return originalLiftListItem(type)(state, dispatch);
|
|
2033
|
+
};
|
|
2034
|
+
|
|
2035
|
+
// src/commands/newlineInCode.ts
|
|
2036
|
+
import { newlineInCode as originalNewlineInCode } from "@tiptap/pm/commands";
|
|
2037
|
+
var newlineInCode = () => ({ state, dispatch }) => {
|
|
2038
|
+
return originalNewlineInCode(state, dispatch);
|
|
2039
|
+
};
|
|
2040
|
+
|
|
2041
|
+
// src/helpers/getSchemaTypeNameByName.ts
|
|
2042
|
+
function getSchemaTypeNameByName(name, schema) {
|
|
2043
|
+
if (schema.nodes[name]) {
|
|
2044
|
+
return "node";
|
|
2045
|
+
}
|
|
2046
|
+
if (schema.marks[name]) {
|
|
2047
|
+
return "mark";
|
|
2048
|
+
}
|
|
2049
|
+
return null;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
// src/utilities/deleteProps.ts
|
|
2053
|
+
function deleteProps(obj, propOrProps) {
|
|
2054
|
+
const props = typeof propOrProps === "string" ? [propOrProps] : propOrProps;
|
|
2055
|
+
return Object.keys(obj).reduce((newObj, prop) => {
|
|
2056
|
+
if (!props.includes(prop)) {
|
|
2057
|
+
newObj[prop] = obj[prop];
|
|
2058
|
+
}
|
|
2059
|
+
return newObj;
|
|
2060
|
+
}, {});
|
|
2061
|
+
}
|
|
2062
|
+
|
|
2063
|
+
// src/commands/resetAttributes.ts
|
|
2064
|
+
var resetAttributes = (typeOrName, attributes) => ({ tr, state, dispatch }) => {
|
|
2065
|
+
let nodeType = null;
|
|
2066
|
+
let markType = null;
|
|
2067
|
+
const schemaType = getSchemaTypeNameByName(
|
|
2068
|
+
typeof typeOrName === "string" ? typeOrName : typeOrName.name,
|
|
2069
|
+
state.schema
|
|
2070
|
+
);
|
|
2071
|
+
if (!schemaType) {
|
|
2072
|
+
return false;
|
|
2073
|
+
}
|
|
2074
|
+
if (schemaType === "node") {
|
|
2075
|
+
nodeType = getNodeType(typeOrName, state.schema);
|
|
2076
|
+
}
|
|
2077
|
+
if (schemaType === "mark") {
|
|
2078
|
+
markType = getMarkType(typeOrName, state.schema);
|
|
2079
|
+
}
|
|
2080
|
+
if (dispatch) {
|
|
2081
|
+
tr.selection.ranges.forEach((range) => {
|
|
2082
|
+
state.doc.nodesBetween(range.$from.pos, range.$to.pos, (node, pos) => {
|
|
2083
|
+
if (nodeType && nodeType === node.type) {
|
|
2084
|
+
tr.setNodeMarkup(pos, void 0, deleteProps(node.attrs, attributes));
|
|
2085
|
+
}
|
|
2086
|
+
if (markType && node.marks.length) {
|
|
2087
|
+
node.marks.forEach((mark) => {
|
|
2088
|
+
if (markType === mark.type) {
|
|
2089
|
+
tr.addMark(
|
|
2090
|
+
pos,
|
|
2091
|
+
pos + node.nodeSize,
|
|
2092
|
+
markType.create(deleteProps(mark.attrs, attributes))
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
});
|
|
2096
|
+
}
|
|
2097
|
+
});
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
return true;
|
|
2101
|
+
};
|
|
2102
|
+
|
|
2103
|
+
// src/commands/scrollIntoView.ts
|
|
2104
|
+
var scrollIntoView = () => ({ tr, dispatch }) => {
|
|
2105
|
+
if (dispatch) {
|
|
2106
|
+
tr.scrollIntoView();
|
|
2107
|
+
}
|
|
2108
|
+
return true;
|
|
2109
|
+
};
|
|
2110
|
+
|
|
2111
|
+
// src/commands/selectAll.ts
|
|
2112
|
+
var selectAll = () => ({ tr, commands }) => {
|
|
2113
|
+
return commands.setTextSelection({
|
|
2114
|
+
from: 0,
|
|
2115
|
+
to: tr.doc.content.size
|
|
2116
|
+
});
|
|
2117
|
+
};
|
|
2118
|
+
|
|
2119
|
+
// src/commands/selectNodeBackward.ts
|
|
2120
|
+
import { selectNodeBackward as originalSelectNodeBackward } from "@tiptap/pm/commands";
|
|
2121
|
+
var selectNodeBackward = () => ({ state, dispatch }) => {
|
|
2122
|
+
return originalSelectNodeBackward(state, dispatch);
|
|
2123
|
+
};
|
|
2124
|
+
|
|
2125
|
+
// src/commands/selectNodeForward.ts
|
|
2126
|
+
import { selectNodeForward as originalSelectNodeForward } from "@tiptap/pm/commands";
|
|
2127
|
+
var selectNodeForward = () => ({ state, dispatch }) => {
|
|
2128
|
+
return originalSelectNodeForward(state, dispatch);
|
|
2129
|
+
};
|
|
2130
|
+
|
|
2131
|
+
// src/commands/selectParentNode.ts
|
|
2132
|
+
import { selectParentNode as originalSelectParentNode } from "@tiptap/pm/commands";
|
|
2133
|
+
var selectParentNode = () => ({ state, dispatch }) => {
|
|
2134
|
+
return originalSelectParentNode(state, dispatch);
|
|
2135
|
+
};
|
|
2136
|
+
|
|
2137
|
+
// src/commands/selectTextblockEnd.ts
|
|
2138
|
+
import { selectTextblockEnd as originalSelectTextblockEnd } from "@tiptap/pm/commands";
|
|
2139
|
+
var selectTextblockEnd = () => ({ state, dispatch }) => {
|
|
2140
|
+
return originalSelectTextblockEnd(state, dispatch);
|
|
2141
|
+
};
|
|
2142
|
+
|
|
2143
|
+
// src/commands/selectTextblockStart.ts
|
|
2144
|
+
import { selectTextblockStart as originalSelectTextblockStart } from "@tiptap/pm/commands";
|
|
2145
|
+
var selectTextblockStart = () => ({ state, dispatch }) => {
|
|
2146
|
+
return originalSelectTextblockStart(state, dispatch);
|
|
2147
|
+
};
|
|
2148
|
+
|
|
2149
|
+
// src/helpers/createDocument.ts
|
|
2150
|
+
function createDocument(content, schema, parseOptions = {}) {
|
|
2151
|
+
return createNodeFromContent(content, schema, { slice: false, parseOptions });
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
// src/commands/setContent.ts
|
|
2155
|
+
var setContent = (content, emitUpdate = false, parseOptions = {}) => ({ tr, editor, dispatch }) => {
|
|
2156
|
+
const { doc } = tr;
|
|
2157
|
+
const document2 = createDocument(content, editor.schema, parseOptions);
|
|
2158
|
+
if (dispatch) {
|
|
2159
|
+
tr.replaceWith(0, doc.content.size, document2).setMeta("preventUpdate", !emitUpdate);
|
|
2160
|
+
}
|
|
2161
|
+
return true;
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// src/helpers/combineTransactionSteps.ts
|
|
2165
|
+
import { Transform } from "@tiptap/pm/transform";
|
|
2166
|
+
function combineTransactionSteps(oldDoc, transactions) {
|
|
2167
|
+
const transform = new Transform(oldDoc);
|
|
2168
|
+
transactions.forEach((transaction) => {
|
|
2169
|
+
transaction.steps.forEach((step) => {
|
|
2170
|
+
transform.step(step);
|
|
2171
|
+
});
|
|
2172
|
+
});
|
|
2173
|
+
return transform;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
// src/helpers/defaultBlockAt.ts
|
|
2177
|
+
function defaultBlockAt(match) {
|
|
2178
|
+
for (let i = 0; i < match.edgeCount; i += 1) {
|
|
2179
|
+
const { type } = match.edge(i);
|
|
2180
|
+
if (type.isTextblock && !type.hasRequiredAttrs()) {
|
|
2181
|
+
return type;
|
|
2182
|
+
}
|
|
2183
|
+
}
|
|
2184
|
+
return null;
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
// src/helpers/findChildren.ts
|
|
2188
|
+
function findChildren(node, predicate) {
|
|
2189
|
+
const nodesWithPos = [];
|
|
2190
|
+
node.descendants((child, pos) => {
|
|
2191
|
+
if (predicate(child)) {
|
|
2192
|
+
nodesWithPos.push({
|
|
2193
|
+
node: child,
|
|
2194
|
+
pos
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
});
|
|
2198
|
+
return nodesWithPos;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
// src/helpers/findChildrenInRange.ts
|
|
2202
|
+
function findChildrenInRange(node, range, predicate) {
|
|
2203
|
+
const nodesWithPos = [];
|
|
2204
|
+
node.nodesBetween(range.from, range.to, (child, pos) => {
|
|
2205
|
+
if (predicate(child)) {
|
|
2206
|
+
nodesWithPos.push({
|
|
2207
|
+
node: child,
|
|
2208
|
+
pos
|
|
2209
|
+
});
|
|
2210
|
+
}
|
|
2211
|
+
});
|
|
2212
|
+
return nodesWithPos;
|
|
2213
|
+
}
|
|
2214
|
+
|
|
2215
|
+
// src/helpers/findParentNodeClosestToPos.ts
|
|
2216
|
+
function findParentNodeClosestToPos($pos, predicate) {
|
|
2217
|
+
for (let i = $pos.depth; i > 0; i -= 1) {
|
|
2218
|
+
const node = $pos.node(i);
|
|
2219
|
+
if (predicate(node)) {
|
|
2220
|
+
return {
|
|
2221
|
+
pos: i > 0 ? $pos.before(i) : 0,
|
|
2222
|
+
start: $pos.start(i),
|
|
2223
|
+
depth: i,
|
|
2224
|
+
node
|
|
2225
|
+
};
|
|
2226
|
+
}
|
|
2227
|
+
}
|
|
2228
|
+
}
|
|
2229
|
+
|
|
2230
|
+
// src/helpers/findParentNode.ts
|
|
2231
|
+
function findParentNode(predicate) {
|
|
2232
|
+
return (selection) => findParentNodeClosestToPos(selection.$from, predicate);
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
// src/helpers/generateHTML.ts
|
|
2236
|
+
import { Node } from "@tiptap/pm/model";
|
|
2237
|
+
|
|
2238
|
+
// src/helpers/getHTMLFromFragment.ts
|
|
2239
|
+
import { DOMSerializer } from "@tiptap/pm/model";
|
|
2240
|
+
function getHTMLFromFragment(fragment, schema) {
|
|
2241
|
+
const documentFragment = DOMSerializer.fromSchema(schema).serializeFragment(fragment);
|
|
2242
|
+
const temporaryDocument = document.implementation.createHTMLDocument();
|
|
2243
|
+
const container = temporaryDocument.createElement("div");
|
|
2244
|
+
container.appendChild(documentFragment);
|
|
2245
|
+
return container.innerHTML;
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
// src/helpers/getSchema.ts
|
|
2249
|
+
function getSchema(extensions) {
|
|
2250
|
+
const resolvedExtensions = ExtensionManager.resolve(extensions);
|
|
2251
|
+
return getSchemaByResolvedExtensions(resolvedExtensions);
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
// src/helpers/generateHTML.ts
|
|
2255
|
+
function generateHTML(doc, extensions) {
|
|
2256
|
+
const schema = getSchema(extensions);
|
|
2257
|
+
const contentNode = Node.fromJSON(schema, doc);
|
|
2258
|
+
return getHTMLFromFragment(contentNode.content, schema);
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
// src/helpers/generateJSON.ts
|
|
2262
|
+
import { DOMParser as DOMParser2 } from "@tiptap/pm/model";
|
|
2263
|
+
function generateJSON(html, extensions) {
|
|
2264
|
+
const schema = getSchema(extensions);
|
|
2265
|
+
const dom = elementFromString(html);
|
|
2266
|
+
return DOMParser2.fromSchema(schema).parse(dom).toJSON();
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
// src/helpers/generateText.ts
|
|
2270
|
+
import { Node as Node2 } from "@tiptap/pm/model";
|
|
2271
|
+
|
|
2272
|
+
// src/helpers/getText.ts
|
|
2273
|
+
function getText(node, options) {
|
|
2274
|
+
const range = {
|
|
2275
|
+
from: 0,
|
|
2276
|
+
to: node.content.size
|
|
2277
|
+
};
|
|
2278
|
+
return getTextBetween(node, range, options);
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
// src/helpers/generateText.ts
|
|
2282
|
+
function generateText(doc, extensions, options) {
|
|
2283
|
+
const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
|
|
2284
|
+
const schema = getSchema(extensions);
|
|
2285
|
+
const contentNode = Node2.fromJSON(schema, doc);
|
|
2286
|
+
return getText(contentNode, {
|
|
2287
|
+
blockSeparator,
|
|
2288
|
+
textSerializers: {
|
|
2289
|
+
...getTextSerializersFromSchema(schema),
|
|
2290
|
+
...textSerializers
|
|
2291
|
+
}
|
|
2292
|
+
});
|
|
2293
|
+
}
|
|
2294
|
+
|
|
2295
|
+
// src/helpers/getMarkAttributes.ts
|
|
2296
|
+
function getMarkAttributes(state, typeOrName) {
|
|
2297
|
+
const type = getMarkType(typeOrName, state.schema);
|
|
2298
|
+
const { from, to, empty } = state.selection;
|
|
2299
|
+
const marks = [];
|
|
2300
|
+
if (empty) {
|
|
2301
|
+
if (state.storedMarks) {
|
|
2302
|
+
marks.push(...state.storedMarks);
|
|
2303
|
+
}
|
|
2304
|
+
marks.push(...state.selection.$head.marks());
|
|
2305
|
+
} else {
|
|
2306
|
+
state.doc.nodesBetween(from, to, (node) => {
|
|
2307
|
+
marks.push(...node.marks);
|
|
2308
|
+
});
|
|
2309
|
+
}
|
|
2310
|
+
const mark = marks.find((markItem) => markItem.type.name === type.name);
|
|
2311
|
+
if (!mark) {
|
|
2312
|
+
return {};
|
|
2313
|
+
}
|
|
2314
|
+
return { ...mark.attrs };
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
// src/helpers/getNodeAttributes.ts
|
|
2318
|
+
function getNodeAttributes(state, typeOrName) {
|
|
2319
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2320
|
+
const { from, to } = state.selection;
|
|
2321
|
+
const nodes = [];
|
|
2322
|
+
state.doc.nodesBetween(from, to, (node2) => {
|
|
2323
|
+
nodes.push(node2);
|
|
2324
|
+
});
|
|
2325
|
+
const node = nodes.reverse().find((nodeItem) => nodeItem.type.name === type.name);
|
|
2326
|
+
if (!node) {
|
|
2327
|
+
return {};
|
|
2328
|
+
}
|
|
2329
|
+
return { ...node.attrs };
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
// src/helpers/getAttributes.ts
|
|
2333
|
+
function getAttributes(state, typeOrName) {
|
|
2334
|
+
const schemaType = getSchemaTypeNameByName(
|
|
2335
|
+
typeof typeOrName === "string" ? typeOrName : typeOrName.name,
|
|
2336
|
+
state.schema
|
|
2337
|
+
);
|
|
2338
|
+
if (schemaType === "node") {
|
|
2339
|
+
return getNodeAttributes(state, typeOrName);
|
|
2340
|
+
}
|
|
2341
|
+
if (schemaType === "mark") {
|
|
2342
|
+
return getMarkAttributes(state, typeOrName);
|
|
2343
|
+
}
|
|
2344
|
+
return {};
|
|
2345
|
+
}
|
|
2346
|
+
|
|
2347
|
+
// src/utilities/removeDuplicates.ts
|
|
2348
|
+
function removeDuplicates(array, by = JSON.stringify) {
|
|
2349
|
+
const seen = {};
|
|
2350
|
+
return array.filter((item) => {
|
|
2351
|
+
const key = by(item);
|
|
2352
|
+
return Object.prototype.hasOwnProperty.call(seen, key) ? false : seen[key] = true;
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
// src/helpers/getChangedRanges.ts
|
|
2357
|
+
function simplifyChangedRanges(changes) {
|
|
2358
|
+
const uniqueChanges = removeDuplicates(changes);
|
|
2359
|
+
return uniqueChanges.length === 1 ? uniqueChanges : uniqueChanges.filter((change, index) => {
|
|
2360
|
+
const rest = uniqueChanges.filter((_, i) => i !== index);
|
|
2361
|
+
return !rest.some((otherChange) => {
|
|
2362
|
+
return change.oldRange.from >= otherChange.oldRange.from && change.oldRange.to <= otherChange.oldRange.to && change.newRange.from >= otherChange.newRange.from && change.newRange.to <= otherChange.newRange.to;
|
|
2363
|
+
});
|
|
2364
|
+
});
|
|
2365
|
+
}
|
|
2366
|
+
function getChangedRanges(transform) {
|
|
2367
|
+
const { mapping, steps } = transform;
|
|
2368
|
+
const changes = [];
|
|
2369
|
+
mapping.maps.forEach((stepMap, index) => {
|
|
2370
|
+
const ranges = [];
|
|
2371
|
+
if (!stepMap.ranges.length) {
|
|
2372
|
+
const { from, to } = steps[index];
|
|
2373
|
+
if (from === void 0 || to === void 0) {
|
|
2374
|
+
return;
|
|
2375
|
+
}
|
|
2376
|
+
ranges.push({ from, to });
|
|
2377
|
+
} else {
|
|
2378
|
+
stepMap.forEach((from, to) => {
|
|
2379
|
+
ranges.push({ from, to });
|
|
2380
|
+
});
|
|
2381
|
+
}
|
|
2382
|
+
ranges.forEach(({ from, to }) => {
|
|
2383
|
+
const newStart = mapping.slice(index).map(from, -1);
|
|
2384
|
+
const newEnd = mapping.slice(index).map(to);
|
|
2385
|
+
const oldStart = mapping.invert().map(newStart, -1);
|
|
2386
|
+
const oldEnd = mapping.invert().map(newEnd);
|
|
2387
|
+
changes.push({
|
|
2388
|
+
oldRange: {
|
|
2389
|
+
from: oldStart,
|
|
2390
|
+
to: oldEnd
|
|
2391
|
+
},
|
|
2392
|
+
newRange: {
|
|
2393
|
+
from: newStart,
|
|
2394
|
+
to: newEnd
|
|
2395
|
+
}
|
|
2396
|
+
});
|
|
2397
|
+
});
|
|
2398
|
+
});
|
|
2399
|
+
return simplifyChangedRanges(changes);
|
|
2400
|
+
}
|
|
2401
|
+
|
|
2402
|
+
// src/helpers/getDebugJSON.ts
|
|
2403
|
+
function getDebugJSON(node, startOffset = 0) {
|
|
2404
|
+
const isTopNode = node.type === node.type.schema.topNodeType;
|
|
2405
|
+
const increment = isTopNode ? 0 : 1;
|
|
2406
|
+
const from = startOffset;
|
|
2407
|
+
const to = from + node.nodeSize;
|
|
2408
|
+
const marks = node.marks.map((mark) => {
|
|
2409
|
+
const output2 = {
|
|
2410
|
+
type: mark.type.name
|
|
2411
|
+
};
|
|
2412
|
+
if (Object.keys(mark.attrs).length) {
|
|
2413
|
+
output2.attrs = { ...mark.attrs };
|
|
2414
|
+
}
|
|
2415
|
+
return output2;
|
|
2416
|
+
});
|
|
2417
|
+
const attrs = { ...node.attrs };
|
|
2418
|
+
const output = {
|
|
2419
|
+
type: node.type.name,
|
|
2420
|
+
from,
|
|
2421
|
+
to
|
|
2422
|
+
};
|
|
2423
|
+
if (Object.keys(attrs).length) {
|
|
2424
|
+
output.attrs = attrs;
|
|
2425
|
+
}
|
|
2426
|
+
if (marks.length) {
|
|
2427
|
+
output.marks = marks;
|
|
2428
|
+
}
|
|
2429
|
+
if (node.content.childCount) {
|
|
2430
|
+
output.content = [];
|
|
2431
|
+
node.forEach((child, offset) => {
|
|
2432
|
+
var _a;
|
|
2433
|
+
(_a = output.content) == null ? void 0 : _a.push(getDebugJSON(child, startOffset + offset + increment));
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
if (node.text) {
|
|
2437
|
+
output.text = node.text;
|
|
2438
|
+
}
|
|
2439
|
+
return output;
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
// src/helpers/getMarksBetween.ts
|
|
2443
|
+
function getMarksBetween(from, to, doc) {
|
|
2444
|
+
const marks = [];
|
|
2445
|
+
if (from === to) {
|
|
2446
|
+
doc.resolve(from).marks().forEach((mark) => {
|
|
2447
|
+
const $pos = doc.resolve(from - 1);
|
|
2448
|
+
const range = getMarkRange($pos, mark.type);
|
|
2449
|
+
if (!range) {
|
|
2450
|
+
return;
|
|
2451
|
+
}
|
|
2452
|
+
marks.push({
|
|
2453
|
+
mark,
|
|
2454
|
+
...range
|
|
2455
|
+
});
|
|
2456
|
+
});
|
|
2457
|
+
} else {
|
|
2458
|
+
doc.nodesBetween(from, to, (node, pos) => {
|
|
2459
|
+
marks.push(
|
|
2460
|
+
...node.marks.map((mark) => ({
|
|
2461
|
+
from: pos,
|
|
2462
|
+
to: pos + node.nodeSize,
|
|
2463
|
+
mark
|
|
2464
|
+
}))
|
|
2465
|
+
);
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
return marks;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
// src/helpers/isMarkActive.ts
|
|
2472
|
+
function isMarkActive(state, typeOrName, attributes = {}) {
|
|
2473
|
+
const { empty, ranges } = state.selection;
|
|
2474
|
+
const type = typeOrName ? getMarkType(typeOrName, state.schema) : null;
|
|
2475
|
+
if (empty) {
|
|
2476
|
+
return !!(state.storedMarks || state.selection.$from.marks()).filter((mark) => {
|
|
2477
|
+
if (!type) {
|
|
2478
|
+
return true;
|
|
2479
|
+
}
|
|
2480
|
+
return type.name === mark.type.name;
|
|
2481
|
+
}).find((mark) => objectIncludes(mark.attrs, attributes, { strict: false }));
|
|
2482
|
+
}
|
|
2483
|
+
let selectionRange = 0;
|
|
2484
|
+
const markRanges = [];
|
|
2485
|
+
ranges.forEach(({ $from, $to }) => {
|
|
2486
|
+
const from = $from.pos;
|
|
2487
|
+
const to = $to.pos;
|
|
2488
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
2489
|
+
if (!node.isText && !node.marks.length) {
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
const relativeFrom = Math.max(from, pos);
|
|
2493
|
+
const relativeTo = Math.min(to, pos + node.nodeSize);
|
|
2494
|
+
const range2 = relativeTo - relativeFrom;
|
|
2495
|
+
selectionRange += range2;
|
|
2496
|
+
markRanges.push(
|
|
2497
|
+
...node.marks.map((mark) => ({
|
|
2498
|
+
mark,
|
|
2499
|
+
from: relativeFrom,
|
|
2500
|
+
to: relativeTo
|
|
2501
|
+
}))
|
|
2502
|
+
);
|
|
2503
|
+
});
|
|
2504
|
+
});
|
|
2505
|
+
if (selectionRange === 0) {
|
|
2506
|
+
return false;
|
|
2507
|
+
}
|
|
2508
|
+
const matchedRange = markRanges.filter((markRange) => {
|
|
2509
|
+
if (!type) {
|
|
2510
|
+
return true;
|
|
2511
|
+
}
|
|
2512
|
+
return type.name === markRange.mark.type.name;
|
|
2513
|
+
}).filter((markRange) => objectIncludes(markRange.mark.attrs, attributes, { strict: false })).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
|
|
2514
|
+
const excludedRange = markRanges.filter((markRange) => {
|
|
2515
|
+
if (!type) {
|
|
2516
|
+
return true;
|
|
2517
|
+
}
|
|
2518
|
+
return markRange.mark.type !== type && markRange.mark.type.excludes(type);
|
|
2519
|
+
}).reduce((sum, markRange) => sum + markRange.to - markRange.from, 0);
|
|
2520
|
+
const range = matchedRange > 0 ? matchedRange + excludedRange : matchedRange;
|
|
2521
|
+
return range >= selectionRange;
|
|
2522
|
+
}
|
|
2523
|
+
|
|
2524
|
+
// src/helpers/isActive.ts
|
|
2525
|
+
function isActive(state, name, attributes = {}) {
|
|
2526
|
+
if (!name) {
|
|
2527
|
+
return isNodeActive(state, null, attributes) || isMarkActive(state, null, attributes);
|
|
2528
|
+
}
|
|
2529
|
+
const schemaType = getSchemaTypeNameByName(name, state.schema);
|
|
2530
|
+
if (schemaType === "node") {
|
|
2531
|
+
return isNodeActive(state, name, attributes);
|
|
2532
|
+
}
|
|
2533
|
+
if (schemaType === "mark") {
|
|
2534
|
+
return isMarkActive(state, name, attributes);
|
|
2535
|
+
}
|
|
2536
|
+
return false;
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
// src/helpers/isList.ts
|
|
2540
|
+
function isList(name, extensions) {
|
|
2541
|
+
const { nodeExtensions } = splitExtensions(extensions);
|
|
2542
|
+
const extension = nodeExtensions.find((item) => item.name === name);
|
|
2543
|
+
if (!extension) {
|
|
2544
|
+
return false;
|
|
2545
|
+
}
|
|
2546
|
+
const context = {
|
|
2547
|
+
name: extension.name,
|
|
2548
|
+
options: extension.options,
|
|
2549
|
+
storage: extension.storage
|
|
2550
|
+
};
|
|
2551
|
+
const group = callOrReturn(getExtensionField(extension, "group", context));
|
|
2552
|
+
if (typeof group !== "string") {
|
|
2553
|
+
return false;
|
|
2554
|
+
}
|
|
2555
|
+
return group.split(" ").includes("list");
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
// src/helpers/isNodeEmpty.ts
|
|
2559
|
+
function isNodeEmpty(node) {
|
|
2560
|
+
var _a;
|
|
2561
|
+
const defaultContent = (_a = node.type.createAndFill()) == null ? void 0 : _a.toJSON();
|
|
2562
|
+
const content = node.toJSON();
|
|
2563
|
+
return JSON.stringify(defaultContent) === JSON.stringify(content);
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
// src/helpers/isNodeSelection.ts
|
|
2567
|
+
import { NodeSelection } from "@tiptap/pm/state";
|
|
2568
|
+
function isNodeSelection(value) {
|
|
2569
|
+
return value instanceof NodeSelection;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
// src/helpers/posToDOMRect.ts
|
|
2573
|
+
function posToDOMRect(view, from, to) {
|
|
2574
|
+
const minPos = 0;
|
|
2575
|
+
const maxPos = view.state.doc.content.size;
|
|
2576
|
+
const resolvedFrom = minMax(from, minPos, maxPos);
|
|
2577
|
+
const resolvedEnd = minMax(to, minPos, maxPos);
|
|
2578
|
+
const start = view.coordsAtPos(resolvedFrom);
|
|
2579
|
+
const end = view.coordsAtPos(resolvedEnd, -1);
|
|
2580
|
+
const top = Math.min(start.top, end.top);
|
|
2581
|
+
const bottom = Math.max(start.bottom, end.bottom);
|
|
2582
|
+
const left = Math.min(start.left, end.left);
|
|
2583
|
+
const right = Math.max(start.right, end.right);
|
|
2584
|
+
const width = right - left;
|
|
2585
|
+
const height = bottom - top;
|
|
2586
|
+
const x = left;
|
|
2587
|
+
const y = top;
|
|
2588
|
+
const data = {
|
|
2589
|
+
top,
|
|
2590
|
+
bottom,
|
|
2591
|
+
left,
|
|
2592
|
+
right,
|
|
2593
|
+
width,
|
|
2594
|
+
height,
|
|
2595
|
+
x,
|
|
2596
|
+
y
|
|
2597
|
+
};
|
|
2598
|
+
return {
|
|
2599
|
+
...data,
|
|
2600
|
+
toJSON: () => data
|
|
2601
|
+
};
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2604
|
+
// src/commands/setMark.ts
|
|
2605
|
+
function canSetMark(state, tr, newMarkType) {
|
|
2606
|
+
var _a;
|
|
2607
|
+
const { selection } = tr;
|
|
2608
|
+
let cursor = null;
|
|
2609
|
+
if (isTextSelection(selection)) {
|
|
2610
|
+
cursor = selection.$cursor;
|
|
2611
|
+
}
|
|
2612
|
+
if (cursor) {
|
|
2613
|
+
const currentMarks = (_a = state.storedMarks) != null ? _a : cursor.marks();
|
|
2614
|
+
return !!newMarkType.isInSet(currentMarks) || !currentMarks.some((mark) => mark.type.excludes(newMarkType));
|
|
2615
|
+
}
|
|
2616
|
+
const { ranges } = selection;
|
|
2617
|
+
return ranges.some(({ $from, $to }) => {
|
|
2618
|
+
let someNodeSupportsMark = $from.depth === 0 ? state.doc.inlineContent && state.doc.type.allowsMarkType(newMarkType) : false;
|
|
2619
|
+
state.doc.nodesBetween($from.pos, $to.pos, (node, _pos, parent) => {
|
|
2620
|
+
if (someNodeSupportsMark) {
|
|
2621
|
+
return false;
|
|
2622
|
+
}
|
|
2623
|
+
if (node.isInline) {
|
|
2624
|
+
const parentAllowsMarkType = !parent || parent.type.allowsMarkType(newMarkType);
|
|
2625
|
+
const currentMarksAllowMarkType = !!newMarkType.isInSet(node.marks) || !node.marks.some((otherMark) => otherMark.type.excludes(newMarkType));
|
|
2626
|
+
someNodeSupportsMark = parentAllowsMarkType && currentMarksAllowMarkType;
|
|
2627
|
+
}
|
|
2628
|
+
return !someNodeSupportsMark;
|
|
2629
|
+
});
|
|
2630
|
+
return someNodeSupportsMark;
|
|
2631
|
+
});
|
|
2632
|
+
}
|
|
2633
|
+
var setMark = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
|
|
2634
|
+
const { selection } = tr;
|
|
2635
|
+
const { empty, ranges } = selection;
|
|
2636
|
+
const type = getMarkType(typeOrName, state.schema);
|
|
2637
|
+
if (dispatch) {
|
|
2638
|
+
if (empty) {
|
|
2639
|
+
const oldAttributes = getMarkAttributes(state, type);
|
|
2640
|
+
tr.addStoredMark(
|
|
2641
|
+
type.create({
|
|
2642
|
+
...oldAttributes,
|
|
2643
|
+
...attributes
|
|
2644
|
+
})
|
|
2645
|
+
);
|
|
2646
|
+
} else {
|
|
2647
|
+
ranges.forEach((range) => {
|
|
2648
|
+
const from = range.$from.pos;
|
|
2649
|
+
const to = range.$to.pos;
|
|
2650
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
2651
|
+
const trimmedFrom = Math.max(pos, from);
|
|
2652
|
+
const trimmedTo = Math.min(pos + node.nodeSize, to);
|
|
2653
|
+
const someHasMark = node.marks.find((mark) => mark.type === type);
|
|
2654
|
+
if (someHasMark) {
|
|
2655
|
+
node.marks.forEach((mark) => {
|
|
2656
|
+
if (type === mark.type) {
|
|
2657
|
+
tr.addMark(
|
|
2658
|
+
trimmedFrom,
|
|
2659
|
+
trimmedTo,
|
|
2660
|
+
type.create({
|
|
2661
|
+
...mark.attrs,
|
|
2662
|
+
...attributes
|
|
2663
|
+
})
|
|
2664
|
+
);
|
|
2665
|
+
}
|
|
2666
|
+
});
|
|
2667
|
+
} else {
|
|
2668
|
+
tr.addMark(trimmedFrom, trimmedTo, type.create(attributes));
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
});
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
return canSetMark(state, tr, type);
|
|
2675
|
+
};
|
|
2676
|
+
|
|
2677
|
+
// src/commands/setMeta.ts
|
|
2678
|
+
var setMeta = (key, value) => ({ tr }) => {
|
|
2679
|
+
tr.setMeta(key, value);
|
|
2680
|
+
return true;
|
|
2681
|
+
};
|
|
2682
|
+
|
|
2683
|
+
// src/commands/setNode.ts
|
|
2684
|
+
import { setBlockType } from "@tiptap/pm/commands";
|
|
2685
|
+
var setNode = (typeOrName, attributes = {}) => ({ state, dispatch, chain }) => {
|
|
2686
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2687
|
+
if (!type.isTextblock) {
|
|
2688
|
+
console.warn('[tiptap warn]: Currently "setNode()" only supports text block nodes.');
|
|
2689
|
+
return false;
|
|
2690
|
+
}
|
|
2691
|
+
return chain().command(({ commands }) => {
|
|
2692
|
+
const canSetBlock = setBlockType(type, attributes)(state);
|
|
2693
|
+
if (canSetBlock) {
|
|
2694
|
+
return true;
|
|
2695
|
+
}
|
|
2696
|
+
return commands.clearNodes();
|
|
2697
|
+
}).command(({ state: updatedState }) => {
|
|
2698
|
+
return setBlockType(type, attributes)(updatedState, dispatch);
|
|
2699
|
+
}).run();
|
|
2700
|
+
};
|
|
2701
|
+
|
|
2702
|
+
// src/commands/setNodeSelection.ts
|
|
2703
|
+
import { NodeSelection as NodeSelection2 } from "@tiptap/pm/state";
|
|
2704
|
+
var setNodeSelection = (position) => ({ tr, dispatch }) => {
|
|
2705
|
+
if (dispatch) {
|
|
2706
|
+
const { doc } = tr;
|
|
2707
|
+
const from = minMax(position, 0, doc.content.size);
|
|
2708
|
+
const selection = NodeSelection2.create(doc, from);
|
|
2709
|
+
tr.setSelection(selection);
|
|
2710
|
+
}
|
|
2711
|
+
return true;
|
|
2712
|
+
};
|
|
2713
|
+
|
|
2714
|
+
// src/commands/setTextSelection.ts
|
|
2715
|
+
import { TextSelection as TextSelection5 } from "@tiptap/pm/state";
|
|
2716
|
+
var setTextSelection = (position) => ({ tr, dispatch }) => {
|
|
2717
|
+
if (dispatch) {
|
|
2718
|
+
const { doc } = tr;
|
|
2719
|
+
const { from, to } = typeof position === "number" ? { from: position, to: position } : position;
|
|
2720
|
+
const minPos = TextSelection5.atStart(doc).from;
|
|
2721
|
+
const maxPos = TextSelection5.atEnd(doc).to;
|
|
2722
|
+
const resolvedFrom = minMax(from, minPos, maxPos);
|
|
2723
|
+
const resolvedEnd = minMax(to, minPos, maxPos);
|
|
2724
|
+
const selection = TextSelection5.create(doc, resolvedFrom, resolvedEnd);
|
|
2725
|
+
tr.setSelection(selection);
|
|
2726
|
+
}
|
|
2727
|
+
return true;
|
|
2728
|
+
};
|
|
2729
|
+
|
|
2730
|
+
// src/commands/sinkListItem.ts
|
|
2731
|
+
import { sinkListItem as originalSinkListItem } from "@tiptap/pm/schema-list";
|
|
2732
|
+
var sinkListItem = (typeOrName) => ({ state, dispatch }) => {
|
|
2733
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2734
|
+
return originalSinkListItem(type)(state, dispatch);
|
|
2735
|
+
};
|
|
2736
|
+
|
|
2737
|
+
// src/commands/splitBlock.ts
|
|
2738
|
+
import { NodeSelection as NodeSelection3, TextSelection as TextSelection6 } from "@tiptap/pm/state";
|
|
2739
|
+
import { canSplit } from "@tiptap/pm/transform";
|
|
2740
|
+
|
|
2741
|
+
// src/helpers/getSplittedAttributes.ts
|
|
2742
|
+
function getSplittedAttributes(extensionAttributes, typeName, attributes) {
|
|
2743
|
+
return Object.fromEntries(Object.entries(attributes).filter(([name]) => {
|
|
2744
|
+
const extensionAttribute = extensionAttributes.find((item) => {
|
|
2745
|
+
return item.type === typeName && item.name === name;
|
|
2746
|
+
});
|
|
2747
|
+
if (!extensionAttribute) {
|
|
2748
|
+
return false;
|
|
2749
|
+
}
|
|
2750
|
+
return extensionAttribute.attribute.keepOnSplit;
|
|
2751
|
+
}));
|
|
2752
|
+
}
|
|
2753
|
+
|
|
2754
|
+
// src/commands/splitBlock.ts
|
|
2755
|
+
function ensureMarks(state, splittableMarks) {
|
|
2756
|
+
const marks = state.storedMarks || state.selection.$to.parentOffset && state.selection.$from.marks();
|
|
2757
|
+
if (marks) {
|
|
2758
|
+
const filteredMarks = marks.filter((mark) => splittableMarks == null ? void 0 : splittableMarks.includes(mark.type.name));
|
|
2759
|
+
state.tr.ensureMarks(filteredMarks);
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
var splitBlock = ({ keepMarks = true } = {}) => ({
|
|
2763
|
+
tr,
|
|
2764
|
+
state,
|
|
2765
|
+
dispatch,
|
|
2766
|
+
editor
|
|
2767
|
+
}) => {
|
|
2768
|
+
const { selection, doc } = tr;
|
|
2769
|
+
const { $from, $to } = selection;
|
|
2770
|
+
const extensionAttributes = editor.extensionManager.attributes;
|
|
2771
|
+
const newAttributes = getSplittedAttributes(
|
|
2772
|
+
extensionAttributes,
|
|
2773
|
+
$from.node().type.name,
|
|
2774
|
+
$from.node().attrs
|
|
2775
|
+
);
|
|
2776
|
+
if (selection instanceof NodeSelection3 && selection.node.isBlock) {
|
|
2777
|
+
if (!$from.parentOffset || !canSplit(doc, $from.pos)) {
|
|
2778
|
+
return false;
|
|
2779
|
+
}
|
|
2780
|
+
if (dispatch) {
|
|
2781
|
+
if (keepMarks) {
|
|
2782
|
+
ensureMarks(state, editor.extensionManager.splittableMarks);
|
|
2783
|
+
}
|
|
2784
|
+
tr.split($from.pos).scrollIntoView();
|
|
2785
|
+
}
|
|
2786
|
+
return true;
|
|
2787
|
+
}
|
|
2788
|
+
if (!$from.parent.isBlock) {
|
|
2789
|
+
return false;
|
|
2790
|
+
}
|
|
2791
|
+
if (dispatch) {
|
|
2792
|
+
const atEnd = $to.parentOffset === $to.parent.content.size;
|
|
2793
|
+
if (selection instanceof TextSelection6) {
|
|
2794
|
+
tr.deleteSelection();
|
|
2795
|
+
}
|
|
2796
|
+
const deflt = $from.depth === 0 ? void 0 : defaultBlockAt($from.node(-1).contentMatchAt($from.indexAfter(-1)));
|
|
2797
|
+
let types = atEnd && deflt ? [
|
|
2798
|
+
{
|
|
2799
|
+
type: deflt,
|
|
2800
|
+
attrs: newAttributes
|
|
2801
|
+
}
|
|
2802
|
+
] : void 0;
|
|
2803
|
+
let can = canSplit(tr.doc, tr.mapping.map($from.pos), 1, types);
|
|
2804
|
+
if (!types && !can && canSplit(tr.doc, tr.mapping.map($from.pos), 1, deflt ? [{ type: deflt }] : void 0)) {
|
|
2805
|
+
can = true;
|
|
2806
|
+
types = deflt ? [
|
|
2807
|
+
{
|
|
2808
|
+
type: deflt,
|
|
2809
|
+
attrs: newAttributes
|
|
2810
|
+
}
|
|
2811
|
+
] : void 0;
|
|
2812
|
+
}
|
|
2813
|
+
if (can) {
|
|
2814
|
+
tr.split(tr.mapping.map($from.pos), 1, types);
|
|
2815
|
+
if (deflt && !atEnd && !$from.parentOffset && $from.parent.type !== deflt) {
|
|
2816
|
+
const first2 = tr.mapping.map($from.before());
|
|
2817
|
+
const $first = tr.doc.resolve(first2);
|
|
2818
|
+
if ($from.node(-1).canReplaceWith($first.index(), $first.index() + 1, deflt)) {
|
|
2819
|
+
tr.setNodeMarkup(tr.mapping.map($from.before()), deflt);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
if (keepMarks) {
|
|
2824
|
+
ensureMarks(state, editor.extensionManager.splittableMarks);
|
|
2825
|
+
}
|
|
2826
|
+
tr.scrollIntoView();
|
|
2827
|
+
}
|
|
2828
|
+
return true;
|
|
2829
|
+
};
|
|
2830
|
+
|
|
2831
|
+
// src/commands/splitListItem.ts
|
|
2832
|
+
import {
|
|
2833
|
+
Fragment as Fragment3,
|
|
2834
|
+
Slice
|
|
2835
|
+
} from "@tiptap/pm/model";
|
|
2836
|
+
import { TextSelection as TextSelection7 } from "@tiptap/pm/state";
|
|
2837
|
+
import { canSplit as canSplit2 } from "@tiptap/pm/transform";
|
|
2838
|
+
var splitListItem = (typeOrName) => ({
|
|
2839
|
+
tr,
|
|
2840
|
+
state,
|
|
2841
|
+
dispatch,
|
|
2842
|
+
editor
|
|
2843
|
+
}) => {
|
|
2844
|
+
var _a;
|
|
2845
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
2846
|
+
const { $from, $to } = state.selection;
|
|
2847
|
+
const node = state.selection.node;
|
|
2848
|
+
if (node && node.isBlock || $from.depth < 2 || !$from.sameParent($to)) {
|
|
2849
|
+
return false;
|
|
2850
|
+
}
|
|
2851
|
+
const grandParent = $from.node(-1);
|
|
2852
|
+
if (grandParent.type !== type) {
|
|
2853
|
+
return false;
|
|
2854
|
+
}
|
|
2855
|
+
const extensionAttributes = editor.extensionManager.attributes;
|
|
2856
|
+
if ($from.parent.content.size === 0 && $from.node(-1).childCount === $from.indexAfter(-1)) {
|
|
2857
|
+
if ($from.depth === 2 || $from.node(-3).type !== type || $from.index(-2) !== $from.node(-2).childCount - 1) {
|
|
2858
|
+
return false;
|
|
2859
|
+
}
|
|
2860
|
+
if (dispatch) {
|
|
2861
|
+
let wrap = Fragment3.empty;
|
|
2862
|
+
const depthBefore = $from.index(-1) ? 1 : $from.index(-2) ? 2 : 3;
|
|
2863
|
+
for (let d = $from.depth - depthBefore; d >= $from.depth - 3; d -= 1) {
|
|
2864
|
+
wrap = Fragment3.from($from.node(d).copy(wrap));
|
|
2865
|
+
}
|
|
2866
|
+
const depthAfter = $from.indexAfter(-1) < $from.node(-2).childCount ? 1 : $from.indexAfter(-2) < $from.node(-3).childCount ? 2 : 3;
|
|
2867
|
+
const newNextTypeAttributes2 = getSplittedAttributes(
|
|
2868
|
+
extensionAttributes,
|
|
2869
|
+
$from.node().type.name,
|
|
2870
|
+
$from.node().attrs
|
|
2871
|
+
);
|
|
2872
|
+
const nextType2 = ((_a = type.contentMatch.defaultType) == null ? void 0 : _a.createAndFill(newNextTypeAttributes2)) || void 0;
|
|
2873
|
+
wrap = wrap.append(Fragment3.from(type.createAndFill(null, nextType2) || void 0));
|
|
2874
|
+
const start = $from.before($from.depth - (depthBefore - 1));
|
|
2875
|
+
tr.replace(start, $from.after(-depthAfter), new Slice(wrap, 4 - depthBefore, 0));
|
|
2876
|
+
let sel = -1;
|
|
2877
|
+
tr.doc.nodesBetween(start, tr.doc.content.size, (n, pos) => {
|
|
2878
|
+
if (sel > -1) {
|
|
2879
|
+
return false;
|
|
2880
|
+
}
|
|
2881
|
+
if (n.isTextblock && n.content.size === 0) {
|
|
2882
|
+
sel = pos + 1;
|
|
2883
|
+
}
|
|
2884
|
+
});
|
|
2885
|
+
if (sel > -1) {
|
|
2886
|
+
tr.setSelection(TextSelection7.near(tr.doc.resolve(sel)));
|
|
2887
|
+
}
|
|
2888
|
+
tr.scrollIntoView();
|
|
2889
|
+
}
|
|
2890
|
+
return true;
|
|
2891
|
+
}
|
|
2892
|
+
const nextType = $to.pos === $from.end() ? grandParent.contentMatchAt(0).defaultType : null;
|
|
2893
|
+
const newTypeAttributes = getSplittedAttributes(
|
|
2894
|
+
extensionAttributes,
|
|
2895
|
+
grandParent.type.name,
|
|
2896
|
+
grandParent.attrs
|
|
2897
|
+
);
|
|
2898
|
+
const newNextTypeAttributes = getSplittedAttributes(
|
|
2899
|
+
extensionAttributes,
|
|
2900
|
+
$from.node().type.name,
|
|
2901
|
+
$from.node().attrs
|
|
2902
|
+
);
|
|
2903
|
+
tr.delete($from.pos, $to.pos);
|
|
2904
|
+
const types = nextType ? [
|
|
2905
|
+
{ type, attrs: newTypeAttributes },
|
|
2906
|
+
{ type: nextType, attrs: newNextTypeAttributes }
|
|
2907
|
+
] : [{ type, attrs: newTypeAttributes }];
|
|
2908
|
+
if (!canSplit2(tr.doc, $from.pos, 2)) {
|
|
2909
|
+
return false;
|
|
2910
|
+
}
|
|
2911
|
+
if (dispatch) {
|
|
2912
|
+
tr.split($from.pos, 2, types).scrollIntoView();
|
|
2913
|
+
}
|
|
2914
|
+
return true;
|
|
2915
|
+
};
|
|
2916
|
+
|
|
2917
|
+
// src/commands/toggleList.ts
|
|
2918
|
+
import { canJoin } from "@tiptap/pm/transform";
|
|
2919
|
+
var joinListBackwards = (tr, listType) => {
|
|
2920
|
+
const list = findParentNode((node) => node.type === listType)(tr.selection);
|
|
2921
|
+
if (!list) {
|
|
2922
|
+
return true;
|
|
2923
|
+
}
|
|
2924
|
+
const before = tr.doc.resolve(Math.max(0, list.pos - 1)).before(list.depth);
|
|
2925
|
+
if (before === void 0) {
|
|
2926
|
+
return true;
|
|
2927
|
+
}
|
|
2928
|
+
const nodeBefore = tr.doc.nodeAt(before);
|
|
2929
|
+
const canJoinBackwards = list.node.type === (nodeBefore == null ? void 0 : nodeBefore.type) && canJoin(tr.doc, list.pos);
|
|
2930
|
+
if (!canJoinBackwards) {
|
|
2931
|
+
return true;
|
|
2932
|
+
}
|
|
2933
|
+
tr.join(list.pos);
|
|
2934
|
+
return true;
|
|
2935
|
+
};
|
|
2936
|
+
var joinListForwards = (tr, listType) => {
|
|
2937
|
+
const list = findParentNode((node) => node.type === listType)(tr.selection);
|
|
2938
|
+
if (!list) {
|
|
2939
|
+
return true;
|
|
2940
|
+
}
|
|
2941
|
+
const after = tr.doc.resolve(list.start).after(list.depth);
|
|
2942
|
+
if (after === void 0) {
|
|
2943
|
+
return true;
|
|
2944
|
+
}
|
|
2945
|
+
const nodeAfter = tr.doc.nodeAt(after);
|
|
2946
|
+
const canJoinForwards = list.node.type === (nodeAfter == null ? void 0 : nodeAfter.type) && canJoin(tr.doc, after);
|
|
2947
|
+
if (!canJoinForwards) {
|
|
2948
|
+
return true;
|
|
2949
|
+
}
|
|
2950
|
+
tr.join(after);
|
|
2951
|
+
return true;
|
|
2952
|
+
};
|
|
2953
|
+
var toggleList = (listTypeOrName, itemTypeOrName) => ({
|
|
2954
|
+
editor,
|
|
2955
|
+
tr,
|
|
2956
|
+
state,
|
|
2957
|
+
dispatch,
|
|
2958
|
+
chain,
|
|
2959
|
+
commands,
|
|
2960
|
+
can
|
|
2961
|
+
}) => {
|
|
2962
|
+
const { extensions } = editor.extensionManager;
|
|
2963
|
+
const listType = getNodeType(listTypeOrName, state.schema);
|
|
2964
|
+
const itemType = getNodeType(itemTypeOrName, state.schema);
|
|
2965
|
+
const { selection } = state;
|
|
2966
|
+
const { $from, $to } = selection;
|
|
2967
|
+
const range = $from.blockRange($to);
|
|
2968
|
+
if (!range) {
|
|
2969
|
+
return false;
|
|
2970
|
+
}
|
|
2971
|
+
const parentList = findParentNode((node) => isList(node.type.name, extensions))(selection);
|
|
2972
|
+
if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
|
|
2973
|
+
if (parentList.node.type === listType) {
|
|
2974
|
+
return commands.liftListItem(itemType);
|
|
2975
|
+
}
|
|
2976
|
+
if (isList(parentList.node.type.name, extensions) && listType.validContent(parentList.node.content) && dispatch) {
|
|
2977
|
+
return chain().command(() => {
|
|
2978
|
+
tr.setNodeMarkup(parentList.pos, listType);
|
|
2979
|
+
return true;
|
|
2980
|
+
}).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
return chain().command(() => {
|
|
2984
|
+
const canWrapInList = can().wrapInList(listType);
|
|
2985
|
+
if (canWrapInList) {
|
|
2986
|
+
return true;
|
|
2987
|
+
}
|
|
2988
|
+
return commands.clearNodes();
|
|
2989
|
+
}).wrapInList(listType).command(() => joinListBackwards(tr, listType)).command(() => joinListForwards(tr, listType)).run();
|
|
2990
|
+
};
|
|
2991
|
+
|
|
2992
|
+
// src/commands/toggleMark.ts
|
|
2993
|
+
var toggleMark = (typeOrName, attributes = {}, options = {}) => ({ state, commands }) => {
|
|
2994
|
+
const { extendEmptyMarkRange = false } = options;
|
|
2995
|
+
const type = getMarkType(typeOrName, state.schema);
|
|
2996
|
+
const isActive2 = isMarkActive(state, type, attributes);
|
|
2997
|
+
if (isActive2) {
|
|
2998
|
+
return commands.unsetMark(type, { extendEmptyMarkRange });
|
|
2999
|
+
}
|
|
3000
|
+
return commands.setMark(type, attributes);
|
|
3001
|
+
};
|
|
3002
|
+
|
|
3003
|
+
// src/commands/toggleNode.ts
|
|
3004
|
+
var toggleNode = (typeOrName, toggleTypeOrName, attributes = {}) => ({ state, commands }) => {
|
|
3005
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
3006
|
+
const toggleType = getNodeType(toggleTypeOrName, state.schema);
|
|
3007
|
+
const isActive2 = isNodeActive(state, type, attributes);
|
|
3008
|
+
if (isActive2) {
|
|
3009
|
+
return commands.setNode(toggleType);
|
|
3010
|
+
}
|
|
3011
|
+
return commands.setNode(type, attributes);
|
|
3012
|
+
};
|
|
3013
|
+
|
|
3014
|
+
// src/commands/toggleWrap.ts
|
|
3015
|
+
var toggleWrap = (typeOrName, attributes = {}) => ({ state, commands }) => {
|
|
3016
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
3017
|
+
const isActive2 = isNodeActive(state, type, attributes);
|
|
3018
|
+
if (isActive2) {
|
|
3019
|
+
return commands.lift(type);
|
|
3020
|
+
}
|
|
3021
|
+
return commands.wrapIn(type, attributes);
|
|
3022
|
+
};
|
|
3023
|
+
|
|
3024
|
+
// src/commands/undoInputRule.ts
|
|
3025
|
+
var undoInputRule = () => ({ state, dispatch }) => {
|
|
3026
|
+
const plugins = state.plugins;
|
|
3027
|
+
for (let i = 0; i < plugins.length; i += 1) {
|
|
3028
|
+
const plugin = plugins[i];
|
|
3029
|
+
let undoable;
|
|
3030
|
+
if (plugin.spec.isInputRules && (undoable = plugin.getState(state))) {
|
|
3031
|
+
if (dispatch) {
|
|
3032
|
+
const tr = state.tr;
|
|
3033
|
+
const toUndo = undoable.transform;
|
|
3034
|
+
for (let j = toUndo.steps.length - 1; j >= 0; j -= 1) {
|
|
3035
|
+
tr.step(toUndo.steps[j].invert(toUndo.docs[j]));
|
|
3036
|
+
}
|
|
3037
|
+
if (undoable.text) {
|
|
3038
|
+
const marks = tr.doc.resolve(undoable.from).marks();
|
|
3039
|
+
tr.replaceWith(undoable.from, undoable.to, state.schema.text(undoable.text, marks));
|
|
3040
|
+
} else {
|
|
3041
|
+
tr.delete(undoable.from, undoable.to);
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
return true;
|
|
3045
|
+
}
|
|
3046
|
+
}
|
|
3047
|
+
return false;
|
|
3048
|
+
};
|
|
3049
|
+
|
|
3050
|
+
// src/commands/unsetAllMarks.ts
|
|
3051
|
+
var unsetAllMarks = () => ({ tr, dispatch }) => {
|
|
3052
|
+
const { selection } = tr;
|
|
3053
|
+
const { empty, ranges } = selection;
|
|
3054
|
+
if (empty) {
|
|
3055
|
+
return true;
|
|
3056
|
+
}
|
|
3057
|
+
if (dispatch) {
|
|
3058
|
+
ranges.forEach((range) => {
|
|
3059
|
+
tr.removeMark(range.$from.pos, range.$to.pos);
|
|
3060
|
+
});
|
|
3061
|
+
}
|
|
3062
|
+
return true;
|
|
3063
|
+
};
|
|
3064
|
+
|
|
3065
|
+
// src/commands/unsetMark.ts
|
|
3066
|
+
var unsetMark = (typeOrName, options = {}) => ({ tr, state, dispatch }) => {
|
|
3067
|
+
var _a;
|
|
3068
|
+
const { extendEmptyMarkRange = false } = options;
|
|
3069
|
+
const { selection } = tr;
|
|
3070
|
+
const type = getMarkType(typeOrName, state.schema);
|
|
3071
|
+
const { $from, empty, ranges } = selection;
|
|
3072
|
+
if (!dispatch) {
|
|
3073
|
+
return true;
|
|
3074
|
+
}
|
|
3075
|
+
if (empty && extendEmptyMarkRange) {
|
|
3076
|
+
let { from, to } = selection;
|
|
3077
|
+
const attrs = (_a = $from.marks().find((mark) => mark.type === type)) == null ? void 0 : _a.attrs;
|
|
3078
|
+
const range = getMarkRange($from, type, attrs);
|
|
3079
|
+
if (range) {
|
|
3080
|
+
from = range.from;
|
|
3081
|
+
to = range.to;
|
|
3082
|
+
}
|
|
3083
|
+
tr.removeMark(from, to, type);
|
|
3084
|
+
} else {
|
|
3085
|
+
ranges.forEach((range) => {
|
|
3086
|
+
tr.removeMark(range.$from.pos, range.$to.pos, type);
|
|
3087
|
+
});
|
|
3088
|
+
}
|
|
3089
|
+
tr.removeStoredMark(type);
|
|
3090
|
+
return true;
|
|
3091
|
+
};
|
|
3092
|
+
|
|
3093
|
+
// src/commands/updateAttributes.ts
|
|
3094
|
+
var updateAttributes = (typeOrName, attributes = {}) => ({ tr, state, dispatch }) => {
|
|
3095
|
+
let nodeType = null;
|
|
3096
|
+
let markType = null;
|
|
3097
|
+
const schemaType = getSchemaTypeNameByName(
|
|
3098
|
+
typeof typeOrName === "string" ? typeOrName : typeOrName.name,
|
|
3099
|
+
state.schema
|
|
3100
|
+
);
|
|
3101
|
+
if (!schemaType) {
|
|
3102
|
+
return false;
|
|
3103
|
+
}
|
|
3104
|
+
if (schemaType === "node") {
|
|
3105
|
+
nodeType = getNodeType(typeOrName, state.schema);
|
|
3106
|
+
}
|
|
3107
|
+
if (schemaType === "mark") {
|
|
3108
|
+
markType = getMarkType(typeOrName, state.schema);
|
|
3109
|
+
}
|
|
3110
|
+
if (dispatch) {
|
|
3111
|
+
tr.selection.ranges.forEach((range) => {
|
|
3112
|
+
const from = range.$from.pos;
|
|
3113
|
+
const to = range.$to.pos;
|
|
3114
|
+
state.doc.nodesBetween(from, to, (node, pos) => {
|
|
3115
|
+
if (nodeType && nodeType === node.type) {
|
|
3116
|
+
tr.setNodeMarkup(pos, void 0, {
|
|
3117
|
+
...node.attrs,
|
|
3118
|
+
...attributes
|
|
3119
|
+
});
|
|
3120
|
+
}
|
|
3121
|
+
if (markType && node.marks.length) {
|
|
3122
|
+
node.marks.forEach((mark) => {
|
|
3123
|
+
if (markType === mark.type) {
|
|
3124
|
+
const trimmedFrom = Math.max(pos, from);
|
|
3125
|
+
const trimmedTo = Math.min(pos + node.nodeSize, to);
|
|
3126
|
+
tr.addMark(
|
|
3127
|
+
trimmedFrom,
|
|
3128
|
+
trimmedTo,
|
|
3129
|
+
markType.create({
|
|
3130
|
+
...mark.attrs,
|
|
3131
|
+
...attributes
|
|
3132
|
+
})
|
|
3133
|
+
);
|
|
3134
|
+
}
|
|
3135
|
+
});
|
|
3136
|
+
}
|
|
3137
|
+
});
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
return true;
|
|
3141
|
+
};
|
|
3142
|
+
|
|
3143
|
+
// src/commands/wrapIn.ts
|
|
3144
|
+
import { wrapIn as originalWrapIn } from "@tiptap/pm/commands";
|
|
3145
|
+
var wrapIn = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
|
|
3146
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
3147
|
+
return originalWrapIn(type, attributes)(state, dispatch);
|
|
3148
|
+
};
|
|
3149
|
+
|
|
3150
|
+
// src/commands/wrapInList.ts
|
|
3151
|
+
import { wrapInList as originalWrapInList } from "@tiptap/pm/schema-list";
|
|
3152
|
+
var wrapInList = (typeOrName, attributes = {}) => ({ state, dispatch }) => {
|
|
3153
|
+
const type = getNodeType(typeOrName, state.schema);
|
|
3154
|
+
return originalWrapInList(type, attributes)(state, dispatch);
|
|
3155
|
+
};
|
|
3156
|
+
|
|
3157
|
+
// src/extensions/commands.ts
|
|
3158
|
+
var Commands = Extension.create({
|
|
3159
|
+
name: "commands",
|
|
3160
|
+
addCommands() {
|
|
3161
|
+
return {
|
|
3162
|
+
...commands_exports
|
|
3163
|
+
};
|
|
3164
|
+
}
|
|
3165
|
+
});
|
|
3166
|
+
|
|
3167
|
+
// src/extensions/editable.ts
|
|
3168
|
+
import { Plugin as Plugin4, PluginKey as PluginKey2 } from "@tiptap/pm/state";
|
|
3169
|
+
var Editable = Extension.create({
|
|
3170
|
+
name: "editable",
|
|
3171
|
+
addProseMirrorPlugins() {
|
|
3172
|
+
return [
|
|
3173
|
+
new Plugin4({
|
|
3174
|
+
key: new PluginKey2("editable"),
|
|
3175
|
+
props: {
|
|
3176
|
+
editable: () => this.editor.options.editable
|
|
3177
|
+
}
|
|
3178
|
+
})
|
|
3179
|
+
];
|
|
3180
|
+
}
|
|
3181
|
+
});
|
|
3182
|
+
|
|
3183
|
+
// src/extensions/focusEvents.ts
|
|
3184
|
+
import { Plugin as Plugin5, PluginKey as PluginKey3 } from "@tiptap/pm/state";
|
|
3185
|
+
var FocusEvents = Extension.create({
|
|
3186
|
+
name: "focusEvents",
|
|
3187
|
+
addProseMirrorPlugins() {
|
|
3188
|
+
const { editor } = this;
|
|
3189
|
+
return [
|
|
3190
|
+
new Plugin5({
|
|
3191
|
+
key: new PluginKey3("focusEvents"),
|
|
3192
|
+
props: {
|
|
3193
|
+
handleDOMEvents: {
|
|
3194
|
+
focus: (view, event) => {
|
|
3195
|
+
editor.isFocused = true;
|
|
3196
|
+
const transaction = editor.state.tr.setMeta("focus", { event }).setMeta("addToHistory", false);
|
|
3197
|
+
view.dispatch(transaction);
|
|
3198
|
+
return false;
|
|
3199
|
+
},
|
|
3200
|
+
blur: (view, event) => {
|
|
3201
|
+
editor.isFocused = false;
|
|
3202
|
+
const transaction = editor.state.tr.setMeta("blur", { event }).setMeta("addToHistory", false);
|
|
3203
|
+
view.dispatch(transaction);
|
|
3204
|
+
return false;
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
}
|
|
3208
|
+
})
|
|
3209
|
+
];
|
|
3210
|
+
}
|
|
3211
|
+
});
|
|
3212
|
+
|
|
3213
|
+
// src/extensions/keymap.ts
|
|
3214
|
+
import { Plugin as Plugin6, PluginKey as PluginKey4, Selection as Selection3 } from "@tiptap/pm/state";
|
|
3215
|
+
var Keymap = Extension.create({
|
|
3216
|
+
name: "keymap",
|
|
3217
|
+
addKeyboardShortcuts() {
|
|
3218
|
+
const handleBackspace = () => this.editor.commands.first(({ commands }) => [
|
|
3219
|
+
() => commands.undoInputRule(),
|
|
3220
|
+
() => commands.command(({ tr }) => {
|
|
3221
|
+
const { selection, doc } = tr;
|
|
3222
|
+
const { empty, $anchor } = selection;
|
|
3223
|
+
const { pos, parent } = $anchor;
|
|
3224
|
+
const isAtStart = Selection3.atStart(doc).from === pos;
|
|
3225
|
+
if (!empty || !isAtStart || !parent.type.isTextblock || parent.textContent.length) {
|
|
3226
|
+
return false;
|
|
3227
|
+
}
|
|
3228
|
+
return commands.clearNodes();
|
|
3229
|
+
}),
|
|
3230
|
+
() => commands.deleteSelection(),
|
|
3231
|
+
() => commands.joinBackward(),
|
|
3232
|
+
() => commands.selectNodeBackward()
|
|
3233
|
+
]);
|
|
3234
|
+
const handleDelete = () => this.editor.commands.first(({ commands }) => [
|
|
3235
|
+
() => commands.deleteSelection(),
|
|
3236
|
+
() => commands.deleteCurrentNode(),
|
|
3237
|
+
() => commands.joinForward(),
|
|
3238
|
+
() => commands.selectNodeForward()
|
|
3239
|
+
]);
|
|
3240
|
+
const handleEnter = () => this.editor.commands.first(({ commands }) => [
|
|
3241
|
+
() => commands.newlineInCode(),
|
|
3242
|
+
() => commands.createParagraphNear(),
|
|
3243
|
+
() => commands.liftEmptyBlock(),
|
|
3244
|
+
() => commands.splitBlock()
|
|
3245
|
+
]);
|
|
3246
|
+
const baseKeymap = {
|
|
3247
|
+
Enter: handleEnter,
|
|
3248
|
+
"Mod-Enter": () => this.editor.commands.exitCode(),
|
|
3249
|
+
Backspace: handleBackspace,
|
|
3250
|
+
"Mod-Backspace": handleBackspace,
|
|
3251
|
+
"Shift-Backspace": handleBackspace,
|
|
3252
|
+
Delete: handleDelete,
|
|
3253
|
+
"Mod-Delete": handleDelete,
|
|
3254
|
+
"Mod-a": () => this.editor.commands.selectAll()
|
|
3255
|
+
};
|
|
3256
|
+
const pcKeymap = {
|
|
3257
|
+
...baseKeymap
|
|
3258
|
+
};
|
|
3259
|
+
const macKeymap = {
|
|
3260
|
+
...baseKeymap,
|
|
3261
|
+
"Ctrl-h": handleBackspace,
|
|
3262
|
+
"Alt-Backspace": handleBackspace,
|
|
3263
|
+
"Ctrl-d": handleDelete,
|
|
3264
|
+
"Ctrl-Alt-Backspace": handleDelete,
|
|
3265
|
+
"Alt-Delete": handleDelete,
|
|
3266
|
+
"Alt-d": handleDelete,
|
|
3267
|
+
"Ctrl-a": () => this.editor.commands.selectTextblockStart(),
|
|
3268
|
+
"Ctrl-e": () => this.editor.commands.selectTextblockEnd()
|
|
3269
|
+
};
|
|
3270
|
+
if (isiOS() || isMacOS()) {
|
|
3271
|
+
return macKeymap;
|
|
3272
|
+
}
|
|
3273
|
+
return pcKeymap;
|
|
3274
|
+
},
|
|
3275
|
+
addProseMirrorPlugins() {
|
|
3276
|
+
return [
|
|
3277
|
+
new Plugin6({
|
|
3278
|
+
key: new PluginKey4("clearDocument"),
|
|
3279
|
+
appendTransaction: (transactions, oldState, newState) => {
|
|
3280
|
+
const docChanges = transactions.some((transaction) => transaction.docChanged) && !oldState.doc.eq(newState.doc);
|
|
3281
|
+
if (!docChanges) {
|
|
3282
|
+
return;
|
|
3283
|
+
}
|
|
3284
|
+
const { empty, from, to } = oldState.selection;
|
|
3285
|
+
const allFrom = Selection3.atStart(oldState.doc).from;
|
|
3286
|
+
const allEnd = Selection3.atEnd(oldState.doc).to;
|
|
3287
|
+
const allWasSelected = from === allFrom && to === allEnd;
|
|
3288
|
+
const isEmpty = newState.doc.textBetween(0, newState.doc.content.size, " ", " ").length === 0;
|
|
3289
|
+
if (empty || !allWasSelected || !isEmpty) {
|
|
3290
|
+
return;
|
|
3291
|
+
}
|
|
3292
|
+
const tr = newState.tr;
|
|
3293
|
+
const state = createChainableState({
|
|
3294
|
+
state: newState,
|
|
3295
|
+
transaction: tr
|
|
3296
|
+
});
|
|
3297
|
+
const { commands } = new CommandManager({
|
|
3298
|
+
editor: this.editor,
|
|
3299
|
+
state
|
|
3300
|
+
});
|
|
3301
|
+
commands.clearNodes();
|
|
3302
|
+
if (!tr.steps.length) {
|
|
3303
|
+
return;
|
|
3304
|
+
}
|
|
3305
|
+
return tr;
|
|
3306
|
+
}
|
|
3307
|
+
})
|
|
3308
|
+
];
|
|
3309
|
+
}
|
|
3310
|
+
});
|
|
3311
|
+
|
|
3312
|
+
// src/extensions/tabindex.ts
|
|
3313
|
+
import { Plugin as Plugin7, PluginKey as PluginKey5 } from "@tiptap/pm/state";
|
|
3314
|
+
var Tabindex = Extension.create({
|
|
3315
|
+
name: "tabindex",
|
|
3316
|
+
addProseMirrorPlugins() {
|
|
3317
|
+
return [
|
|
3318
|
+
new Plugin7({
|
|
3319
|
+
key: new PluginKey5("tabindex"),
|
|
3320
|
+
props: {
|
|
3321
|
+
attributes: this.editor.isEditable ? { tabindex: "0" } : {}
|
|
3322
|
+
}
|
|
3323
|
+
})
|
|
3324
|
+
];
|
|
3325
|
+
}
|
|
3326
|
+
});
|
|
3327
|
+
|
|
3328
|
+
// src/style.ts
|
|
3329
|
+
var style = `.ProseMirror {
|
|
3330
|
+
position: relative;
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
.ProseMirror {
|
|
3334
|
+
word-wrap: break-word;
|
|
3335
|
+
white-space: pre-wrap;
|
|
3336
|
+
white-space: break-spaces;
|
|
3337
|
+
-webkit-font-variant-ligatures: none;
|
|
3338
|
+
font-variant-ligatures: none;
|
|
3339
|
+
font-feature-settings: "liga" 0; /* the above doesn't seem to work in Edge */
|
|
3340
|
+
}
|
|
3341
|
+
|
|
3342
|
+
.ProseMirror [contenteditable="false"] {
|
|
3343
|
+
white-space: normal;
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
.ProseMirror [contenteditable="false"] [contenteditable="true"] {
|
|
3347
|
+
white-space: pre-wrap;
|
|
3348
|
+
}
|
|
3349
|
+
|
|
3350
|
+
.ProseMirror pre {
|
|
3351
|
+
white-space: pre-wrap;
|
|
3352
|
+
}
|
|
3353
|
+
|
|
3354
|
+
img.ProseMirror-separator {
|
|
3355
|
+
display: inline !important;
|
|
3356
|
+
border: none !important;
|
|
3357
|
+
margin: 0 !important;
|
|
3358
|
+
width: 1px !important;
|
|
3359
|
+
height: 1px !important;
|
|
3360
|
+
}
|
|
3361
|
+
|
|
3362
|
+
.ProseMirror-gapcursor {
|
|
3363
|
+
display: none;
|
|
3364
|
+
pointer-events: none;
|
|
3365
|
+
position: absolute;
|
|
3366
|
+
margin: 0;
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
.ProseMirror-gapcursor:after {
|
|
3370
|
+
content: "";
|
|
3371
|
+
display: block;
|
|
3372
|
+
position: absolute;
|
|
3373
|
+
top: -2px;
|
|
3374
|
+
width: 20px;
|
|
3375
|
+
border-top: 1px solid black;
|
|
3376
|
+
animation: ProseMirror-cursor-blink 1.1s steps(2, start) infinite;
|
|
3377
|
+
}
|
|
3378
|
+
|
|
3379
|
+
@keyframes ProseMirror-cursor-blink {
|
|
3380
|
+
to {
|
|
3381
|
+
visibility: hidden;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
.ProseMirror-hideselection *::selection {
|
|
3386
|
+
background: transparent;
|
|
3387
|
+
}
|
|
3388
|
+
|
|
3389
|
+
.ProseMirror-hideselection *::-moz-selection {
|
|
3390
|
+
background: transparent;
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
.ProseMirror-hideselection * {
|
|
3394
|
+
caret-color: transparent;
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
.ProseMirror-focused .ProseMirror-gapcursor {
|
|
3398
|
+
display: block;
|
|
3399
|
+
}
|
|
3400
|
+
|
|
3401
|
+
.tippy-box[data-animation=fade][data-state=hidden] {
|
|
3402
|
+
opacity: 0
|
|
3403
|
+
}`;
|
|
3404
|
+
|
|
3405
|
+
// src/utilities/createStyleTag.ts
|
|
3406
|
+
function createStyleTag(style2, nonce) {
|
|
3407
|
+
const tipTapStyleTag = document.querySelector("style[data-tiptap-style]");
|
|
3408
|
+
if (tipTapStyleTag !== null) {
|
|
3409
|
+
return tipTapStyleTag;
|
|
3410
|
+
}
|
|
3411
|
+
const styleNode = document.createElement("style");
|
|
3412
|
+
if (nonce) {
|
|
3413
|
+
styleNode.setAttribute("nonce", nonce);
|
|
3414
|
+
}
|
|
3415
|
+
styleNode.setAttribute("data-tiptap-style", "");
|
|
3416
|
+
styleNode.innerHTML = style2;
|
|
3417
|
+
document.getElementsByTagName("head")[0].appendChild(styleNode);
|
|
3418
|
+
return styleNode;
|
|
3419
|
+
}
|
|
3420
|
+
|
|
3421
|
+
// src/Editor.ts
|
|
3422
|
+
var Editor = class extends EventEmitter {
|
|
3423
|
+
constructor(options = {}) {
|
|
3424
|
+
super();
|
|
3425
|
+
this.isFocused = false;
|
|
3426
|
+
this.extensionStorage = {};
|
|
3427
|
+
this.options = {
|
|
3428
|
+
element: document.createElement("div"),
|
|
3429
|
+
content: "",
|
|
3430
|
+
injectCSS: true,
|
|
3431
|
+
injectNonce: void 0,
|
|
3432
|
+
extensions: [],
|
|
3433
|
+
autofocus: false,
|
|
3434
|
+
editable: true,
|
|
3435
|
+
editorProps: {},
|
|
3436
|
+
parseOptions: {},
|
|
3437
|
+
enableInputRules: true,
|
|
3438
|
+
enablePasteRules: true,
|
|
3439
|
+
enableCoreExtensions: true,
|
|
3440
|
+
onBeforeCreate: () => null,
|
|
3441
|
+
onCreate: () => null,
|
|
3442
|
+
onUpdate: () => null,
|
|
3443
|
+
onSelectionUpdate: () => null,
|
|
3444
|
+
onTransaction: () => null,
|
|
3445
|
+
onFocus: () => null,
|
|
3446
|
+
onBlur: () => null,
|
|
3447
|
+
onDestroy: () => null
|
|
3448
|
+
};
|
|
3449
|
+
this.isCapturingTransaction = false;
|
|
3450
|
+
this.capturedTransaction = null;
|
|
3451
|
+
this.setOptions(options);
|
|
3452
|
+
this.createExtensionManager();
|
|
3453
|
+
this.createCommandManager();
|
|
3454
|
+
this.createSchema();
|
|
3455
|
+
this.on("beforeCreate", this.options.onBeforeCreate);
|
|
3456
|
+
this.emit("beforeCreate", { editor: this });
|
|
3457
|
+
this.createView();
|
|
3458
|
+
this.injectCSS();
|
|
3459
|
+
this.on("create", this.options.onCreate);
|
|
3460
|
+
this.on("update", this.options.onUpdate);
|
|
3461
|
+
this.on("selectionUpdate", this.options.onSelectionUpdate);
|
|
3462
|
+
this.on("transaction", this.options.onTransaction);
|
|
3463
|
+
this.on("focus", this.options.onFocus);
|
|
3464
|
+
this.on("blur", this.options.onBlur);
|
|
3465
|
+
this.on("destroy", this.options.onDestroy);
|
|
3466
|
+
window.setTimeout(() => {
|
|
3467
|
+
if (this.isDestroyed) {
|
|
3468
|
+
return;
|
|
3469
|
+
}
|
|
3470
|
+
this.commands.focus(this.options.autofocus);
|
|
3471
|
+
this.emit("create", { editor: this });
|
|
3472
|
+
}, 0);
|
|
3473
|
+
}
|
|
3474
|
+
get storage() {
|
|
3475
|
+
return this.extensionStorage;
|
|
3476
|
+
}
|
|
3477
|
+
get commands() {
|
|
3478
|
+
return this.commandManager.commands;
|
|
3479
|
+
}
|
|
3480
|
+
chain() {
|
|
3481
|
+
return this.commandManager.chain();
|
|
3482
|
+
}
|
|
3483
|
+
can() {
|
|
3484
|
+
return this.commandManager.can();
|
|
3485
|
+
}
|
|
3486
|
+
injectCSS() {
|
|
3487
|
+
if (this.options.injectCSS && document) {
|
|
3488
|
+
this.css = createStyleTag(style, this.options.injectNonce);
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3491
|
+
setOptions(options = {}) {
|
|
3492
|
+
this.options = {
|
|
3493
|
+
...this.options,
|
|
3494
|
+
...options
|
|
3495
|
+
};
|
|
3496
|
+
if (!this.view || !this.state || this.isDestroyed) {
|
|
3497
|
+
return;
|
|
3498
|
+
}
|
|
3499
|
+
if (this.options.editorProps) {
|
|
3500
|
+
this.view.setProps(this.options.editorProps);
|
|
3501
|
+
}
|
|
3502
|
+
this.view.updateState(this.state);
|
|
3503
|
+
}
|
|
3504
|
+
setEditable(editable, emitUpdate = true) {
|
|
3505
|
+
this.setOptions({ editable });
|
|
3506
|
+
if (emitUpdate) {
|
|
3507
|
+
this.emit("update", { editor: this, transaction: this.state.tr });
|
|
3508
|
+
}
|
|
3509
|
+
}
|
|
3510
|
+
get isEditable() {
|
|
3511
|
+
return this.options.editable && this.view && this.view.editable;
|
|
3512
|
+
}
|
|
3513
|
+
get state() {
|
|
3514
|
+
return this.view.state;
|
|
3515
|
+
}
|
|
3516
|
+
registerPlugin(plugin, handlePlugins) {
|
|
3517
|
+
const plugins = isFunction(handlePlugins) ? handlePlugins(plugin, [...this.state.plugins]) : [...this.state.plugins, plugin];
|
|
3518
|
+
const state = this.state.reconfigure({ plugins });
|
|
3519
|
+
this.view.updateState(state);
|
|
3520
|
+
}
|
|
3521
|
+
unregisterPlugin(nameOrPluginKey) {
|
|
3522
|
+
if (this.isDestroyed) {
|
|
3523
|
+
return;
|
|
3524
|
+
}
|
|
3525
|
+
const name = typeof nameOrPluginKey === "string" ? `${nameOrPluginKey}$` : nameOrPluginKey.key;
|
|
3526
|
+
const state = this.state.reconfigure({
|
|
3527
|
+
plugins: this.state.plugins.filter((plugin) => !plugin.key.startsWith(name))
|
|
3528
|
+
});
|
|
3529
|
+
this.view.updateState(state);
|
|
3530
|
+
}
|
|
3531
|
+
createExtensionManager() {
|
|
3532
|
+
const coreExtensions = this.options.enableCoreExtensions ? Object.values(extensions_exports) : [];
|
|
3533
|
+
const allExtensions = [...coreExtensions, ...this.options.extensions].filter((extension) => {
|
|
3534
|
+
return ["extension", "node", "mark"].includes(extension == null ? void 0 : extension.type);
|
|
3535
|
+
});
|
|
3536
|
+
this.extensionManager = new ExtensionManager(allExtensions, this);
|
|
3537
|
+
}
|
|
3538
|
+
createCommandManager() {
|
|
3539
|
+
this.commandManager = new CommandManager({
|
|
3540
|
+
editor: this
|
|
3541
|
+
});
|
|
3542
|
+
}
|
|
3543
|
+
createSchema() {
|
|
3544
|
+
this.schema = this.extensionManager.schema;
|
|
3545
|
+
}
|
|
3546
|
+
createView() {
|
|
3547
|
+
const doc = createDocument(this.options.content, this.schema, this.options.parseOptions);
|
|
3548
|
+
const selection = resolveFocusPosition(doc, this.options.autofocus);
|
|
3549
|
+
this.view = new EditorView(this.options.element, {
|
|
3550
|
+
...this.options.editorProps,
|
|
3551
|
+
dispatchTransaction: this.dispatchTransaction.bind(this),
|
|
3552
|
+
state: EditorState4.create({
|
|
3553
|
+
doc,
|
|
3554
|
+
selection: selection || void 0
|
|
3555
|
+
})
|
|
3556
|
+
});
|
|
3557
|
+
const newState = this.state.reconfigure({
|
|
3558
|
+
plugins: this.extensionManager.plugins
|
|
3559
|
+
});
|
|
3560
|
+
this.view.updateState(newState);
|
|
3561
|
+
this.createNodeViews();
|
|
3562
|
+
const dom = this.view.dom;
|
|
3563
|
+
dom.editor = this;
|
|
3564
|
+
}
|
|
3565
|
+
createNodeViews() {
|
|
3566
|
+
this.view.setProps({
|
|
3567
|
+
nodeViews: this.extensionManager.nodeViews
|
|
3568
|
+
});
|
|
3569
|
+
}
|
|
3570
|
+
captureTransaction(fn) {
|
|
3571
|
+
this.isCapturingTransaction = true;
|
|
3572
|
+
fn();
|
|
3573
|
+
this.isCapturingTransaction = false;
|
|
3574
|
+
const tr = this.capturedTransaction;
|
|
3575
|
+
this.capturedTransaction = null;
|
|
3576
|
+
return tr;
|
|
3577
|
+
}
|
|
3578
|
+
dispatchTransaction(transaction) {
|
|
3579
|
+
if (this.isCapturingTransaction) {
|
|
3580
|
+
if (!this.capturedTransaction) {
|
|
3581
|
+
this.capturedTransaction = transaction;
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3584
|
+
transaction.steps.forEach((step) => {
|
|
3585
|
+
var _a;
|
|
3586
|
+
return (_a = this.capturedTransaction) == null ? void 0 : _a.step(step);
|
|
3587
|
+
});
|
|
3588
|
+
return;
|
|
3589
|
+
}
|
|
3590
|
+
const state = this.state.apply(transaction);
|
|
3591
|
+
const selectionHasChanged = !this.state.selection.eq(state.selection);
|
|
3592
|
+
this.view.updateState(state);
|
|
3593
|
+
this.emit("transaction", {
|
|
3594
|
+
editor: this,
|
|
3595
|
+
transaction
|
|
3596
|
+
});
|
|
3597
|
+
if (selectionHasChanged) {
|
|
3598
|
+
this.emit("selectionUpdate", {
|
|
3599
|
+
editor: this,
|
|
3600
|
+
transaction
|
|
3601
|
+
});
|
|
3602
|
+
}
|
|
3603
|
+
const focus2 = transaction.getMeta("focus");
|
|
3604
|
+
const blur2 = transaction.getMeta("blur");
|
|
3605
|
+
if (focus2) {
|
|
3606
|
+
this.emit("focus", {
|
|
3607
|
+
editor: this,
|
|
3608
|
+
event: focus2.event,
|
|
3609
|
+
transaction
|
|
3610
|
+
});
|
|
3611
|
+
}
|
|
3612
|
+
if (blur2) {
|
|
3613
|
+
this.emit("blur", {
|
|
3614
|
+
editor: this,
|
|
3615
|
+
event: blur2.event,
|
|
3616
|
+
transaction
|
|
3617
|
+
});
|
|
3618
|
+
}
|
|
3619
|
+
if (!transaction.docChanged || transaction.getMeta("preventUpdate")) {
|
|
3620
|
+
return;
|
|
3621
|
+
}
|
|
3622
|
+
this.emit("update", {
|
|
3623
|
+
editor: this,
|
|
3624
|
+
transaction
|
|
3625
|
+
});
|
|
3626
|
+
}
|
|
3627
|
+
getAttributes(nameOrType) {
|
|
3628
|
+
return getAttributes(this.state, nameOrType);
|
|
3629
|
+
}
|
|
3630
|
+
isActive(nameOrAttributes, attributesOrUndefined) {
|
|
3631
|
+
const name = typeof nameOrAttributes === "string" ? nameOrAttributes : null;
|
|
3632
|
+
const attributes = typeof nameOrAttributes === "string" ? attributesOrUndefined : nameOrAttributes;
|
|
3633
|
+
return isActive(this.state, name, attributes);
|
|
3634
|
+
}
|
|
3635
|
+
getJSON() {
|
|
3636
|
+
return this.state.doc.toJSON();
|
|
3637
|
+
}
|
|
3638
|
+
getHTML() {
|
|
3639
|
+
return getHTMLFromFragment(this.state.doc.content, this.schema);
|
|
3640
|
+
}
|
|
3641
|
+
getText(options) {
|
|
3642
|
+
const { blockSeparator = "\n\n", textSerializers = {} } = options || {};
|
|
3643
|
+
return getText(this.state.doc, {
|
|
3644
|
+
blockSeparator,
|
|
3645
|
+
textSerializers: {
|
|
3646
|
+
...textSerializers,
|
|
3647
|
+
...getTextSerializersFromSchema(this.schema)
|
|
3648
|
+
}
|
|
3649
|
+
});
|
|
3650
|
+
}
|
|
3651
|
+
get isEmpty() {
|
|
3652
|
+
return isNodeEmpty(this.state.doc);
|
|
3653
|
+
}
|
|
3654
|
+
getCharacterCount() {
|
|
3655
|
+
console.warn(
|
|
3656
|
+
'[tiptap warn]: "editor.getCharacterCount()" is deprecated. Please use "editor.storage.characterCount.characters()" instead.'
|
|
3657
|
+
);
|
|
3658
|
+
return this.state.doc.content.size - 2;
|
|
3659
|
+
}
|
|
3660
|
+
destroy() {
|
|
3661
|
+
this.emit("destroy");
|
|
3662
|
+
if (this.view) {
|
|
3663
|
+
this.view.destroy();
|
|
3664
|
+
}
|
|
3665
|
+
this.removeAllListeners();
|
|
3666
|
+
}
|
|
3667
|
+
get isDestroyed() {
|
|
3668
|
+
var _a;
|
|
3669
|
+
return !((_a = this.view) == null ? void 0 : _a.docView);
|
|
3670
|
+
}
|
|
3671
|
+
};
|
|
3672
|
+
|
|
3673
|
+
// src/inputRules/markInputRule.ts
|
|
3674
|
+
function markInputRule(config) {
|
|
3675
|
+
return new InputRule({
|
|
3676
|
+
find: config.find,
|
|
3677
|
+
handler: ({ state, range, match }) => {
|
|
3678
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match);
|
|
3679
|
+
if (attributes === false || attributes === null) {
|
|
3680
|
+
return null;
|
|
3681
|
+
}
|
|
3682
|
+
const { tr } = state;
|
|
3683
|
+
const captureGroup = match[match.length - 1];
|
|
3684
|
+
const fullMatch = match[0];
|
|
3685
|
+
let markEnd = range.to;
|
|
3686
|
+
if (captureGroup) {
|
|
3687
|
+
const startSpaces = fullMatch.search(/\S/);
|
|
3688
|
+
const textStart = range.from + fullMatch.indexOf(captureGroup);
|
|
3689
|
+
const textEnd = textStart + captureGroup.length;
|
|
3690
|
+
const excludedMarks = getMarksBetween(range.from, range.to, state.doc).filter((item) => {
|
|
3691
|
+
const excluded = item.mark.type.excluded;
|
|
3692
|
+
return excluded.find((type) => type === config.type && type !== item.mark.type);
|
|
3693
|
+
}).filter((item) => item.to > textStart);
|
|
3694
|
+
if (excludedMarks.length) {
|
|
3695
|
+
return null;
|
|
3696
|
+
}
|
|
3697
|
+
if (textEnd < range.to) {
|
|
3698
|
+
tr.delete(textEnd, range.to);
|
|
3699
|
+
}
|
|
3700
|
+
if (textStart > range.from) {
|
|
3701
|
+
tr.delete(range.from + startSpaces, textStart);
|
|
3702
|
+
}
|
|
3703
|
+
markEnd = range.from + startSpaces + captureGroup.length;
|
|
3704
|
+
tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
|
|
3705
|
+
tr.removeStoredMark(config.type);
|
|
3706
|
+
}
|
|
3707
|
+
}
|
|
3708
|
+
});
|
|
3709
|
+
}
|
|
3710
|
+
|
|
3711
|
+
// src/inputRules/nodeInputRule.ts
|
|
3712
|
+
function nodeInputRule(config) {
|
|
3713
|
+
return new InputRule({
|
|
3714
|
+
find: config.find,
|
|
3715
|
+
handler: ({ state, range, match }) => {
|
|
3716
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match) || {};
|
|
3717
|
+
const { tr } = state;
|
|
3718
|
+
const start = range.from;
|
|
3719
|
+
let end = range.to;
|
|
3720
|
+
if (match[1]) {
|
|
3721
|
+
const offset = match[0].lastIndexOf(match[1]);
|
|
3722
|
+
let matchStart = start + offset;
|
|
3723
|
+
if (matchStart > end) {
|
|
3724
|
+
matchStart = end;
|
|
3725
|
+
} else {
|
|
3726
|
+
end = matchStart + match[1].length;
|
|
3727
|
+
}
|
|
3728
|
+
const lastChar = match[0][match[0].length - 1];
|
|
3729
|
+
tr.insertText(lastChar, start + match[0].length - 1);
|
|
3730
|
+
tr.replaceWith(matchStart, end, config.type.create(attributes));
|
|
3731
|
+
} else if (match[0]) {
|
|
3732
|
+
tr.replaceWith(start, end, config.type.create(attributes));
|
|
3733
|
+
}
|
|
3734
|
+
}
|
|
3735
|
+
});
|
|
3736
|
+
}
|
|
3737
|
+
|
|
3738
|
+
// src/inputRules/textblockTypeInputRule.ts
|
|
3739
|
+
function textblockTypeInputRule(config) {
|
|
3740
|
+
return new InputRule({
|
|
3741
|
+
find: config.find,
|
|
3742
|
+
handler: ({ state, range, match }) => {
|
|
3743
|
+
const $start = state.doc.resolve(range.from);
|
|
3744
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match) || {};
|
|
3745
|
+
if (!$start.node(-1).canReplaceWith($start.index(-1), $start.indexAfter(-1), config.type)) {
|
|
3746
|
+
return null;
|
|
3747
|
+
}
|
|
3748
|
+
state.tr.delete(range.from, range.to).setBlockType(range.from, range.from, config.type, attributes);
|
|
3749
|
+
}
|
|
3750
|
+
});
|
|
3751
|
+
}
|
|
3752
|
+
|
|
3753
|
+
// src/inputRules/textInputRule.ts
|
|
3754
|
+
function textInputRule(config) {
|
|
3755
|
+
return new InputRule({
|
|
3756
|
+
find: config.find,
|
|
3757
|
+
handler: ({ state, range, match }) => {
|
|
3758
|
+
let insert = config.replace;
|
|
3759
|
+
let start = range.from;
|
|
3760
|
+
const end = range.to;
|
|
3761
|
+
if (match[1]) {
|
|
3762
|
+
const offset = match[0].lastIndexOf(match[1]);
|
|
3763
|
+
insert += match[0].slice(offset + match[1].length);
|
|
3764
|
+
start += offset;
|
|
3765
|
+
const cutOff = start - end;
|
|
3766
|
+
if (cutOff > 0) {
|
|
3767
|
+
insert = match[0].slice(offset - cutOff, offset) + insert;
|
|
3768
|
+
start = end;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
state.tr.insertText(insert, start, end);
|
|
3772
|
+
}
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
3775
|
+
|
|
3776
|
+
// src/inputRules/wrappingInputRule.ts
|
|
3777
|
+
import { canJoin as canJoin2, findWrapping } from "@tiptap/pm/transform";
|
|
3778
|
+
function wrappingInputRule(config) {
|
|
3779
|
+
return new InputRule({
|
|
3780
|
+
find: config.find,
|
|
3781
|
+
handler: ({ state, range, match }) => {
|
|
3782
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match) || {};
|
|
3783
|
+
const tr = state.tr.delete(range.from, range.to);
|
|
3784
|
+
const $start = tr.doc.resolve(range.from);
|
|
3785
|
+
const blockRange = $start.blockRange();
|
|
3786
|
+
const wrapping = blockRange && findWrapping(blockRange, config.type, attributes);
|
|
3787
|
+
if (!wrapping) {
|
|
3788
|
+
return null;
|
|
3789
|
+
}
|
|
3790
|
+
tr.wrap(blockRange, wrapping);
|
|
3791
|
+
const before = tr.doc.resolve(range.from - 1).nodeBefore;
|
|
3792
|
+
if (before && before.type === config.type && canJoin2(tr.doc, range.from - 1) && (!config.joinPredicate || config.joinPredicate(match, before))) {
|
|
3793
|
+
tr.join(range.from - 1);
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
});
|
|
3797
|
+
}
|
|
3798
|
+
|
|
3799
|
+
// src/Mark.ts
|
|
3800
|
+
var Mark = class {
|
|
3801
|
+
constructor(config = {}) {
|
|
3802
|
+
this.type = "mark";
|
|
3803
|
+
this.name = "mark";
|
|
3804
|
+
this.parent = null;
|
|
3805
|
+
this.child = null;
|
|
3806
|
+
this.config = {
|
|
3807
|
+
name: this.name,
|
|
3808
|
+
defaultOptions: {}
|
|
3809
|
+
};
|
|
3810
|
+
this.config = {
|
|
3811
|
+
...this.config,
|
|
3812
|
+
...config
|
|
3813
|
+
};
|
|
3814
|
+
this.name = this.config.name;
|
|
3815
|
+
if (config.defaultOptions) {
|
|
3816
|
+
console.warn(
|
|
3817
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
|
|
3818
|
+
);
|
|
3819
|
+
}
|
|
3820
|
+
this.options = this.config.defaultOptions;
|
|
3821
|
+
if (this.config.addOptions) {
|
|
3822
|
+
this.options = callOrReturn(
|
|
3823
|
+
getExtensionField(this, "addOptions", {
|
|
3824
|
+
name: this.name
|
|
3825
|
+
})
|
|
3826
|
+
);
|
|
3827
|
+
}
|
|
3828
|
+
this.storage = callOrReturn(
|
|
3829
|
+
getExtensionField(this, "addStorage", {
|
|
3830
|
+
name: this.name,
|
|
3831
|
+
options: this.options
|
|
3832
|
+
})
|
|
3833
|
+
) || {};
|
|
3834
|
+
}
|
|
3835
|
+
static create(config = {}) {
|
|
3836
|
+
return new Mark(config);
|
|
3837
|
+
}
|
|
3838
|
+
configure(options = {}) {
|
|
3839
|
+
const extension = this.extend();
|
|
3840
|
+
extension.options = mergeDeep(this.options, options);
|
|
3841
|
+
extension.storage = callOrReturn(
|
|
3842
|
+
getExtensionField(extension, "addStorage", {
|
|
3843
|
+
name: extension.name,
|
|
3844
|
+
options: extension.options
|
|
3845
|
+
})
|
|
3846
|
+
);
|
|
3847
|
+
return extension;
|
|
3848
|
+
}
|
|
3849
|
+
extend(extendedConfig = {}) {
|
|
3850
|
+
const extension = new Mark(extendedConfig);
|
|
3851
|
+
extension.parent = this;
|
|
3852
|
+
this.child = extension;
|
|
3853
|
+
extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
|
|
3854
|
+
if (extendedConfig.defaultOptions) {
|
|
3855
|
+
console.warn(
|
|
3856
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
|
|
3857
|
+
);
|
|
3858
|
+
}
|
|
3859
|
+
extension.options = callOrReturn(
|
|
3860
|
+
getExtensionField(extension, "addOptions", {
|
|
3861
|
+
name: extension.name
|
|
3862
|
+
})
|
|
3863
|
+
);
|
|
3864
|
+
extension.storage = callOrReturn(
|
|
3865
|
+
getExtensionField(extension, "addStorage", {
|
|
3866
|
+
name: extension.name,
|
|
3867
|
+
options: extension.options
|
|
3868
|
+
})
|
|
3869
|
+
);
|
|
3870
|
+
return extension;
|
|
3871
|
+
}
|
|
3872
|
+
static handleExit({ editor, mark }) {
|
|
3873
|
+
const { tr } = editor.state;
|
|
3874
|
+
const currentPos = editor.state.selection.$from;
|
|
3875
|
+
const isAtEnd = currentPos.pos === currentPos.end();
|
|
3876
|
+
if (isAtEnd) {
|
|
3877
|
+
const currentMarks = currentPos.marks();
|
|
3878
|
+
const isInMark = !!currentMarks.find((m) => (m == null ? void 0 : m.type.name) === mark.name);
|
|
3879
|
+
if (!isInMark) {
|
|
3880
|
+
return false;
|
|
3881
|
+
}
|
|
3882
|
+
const removeMark = currentMarks.find((m) => (m == null ? void 0 : m.type.name) === mark.name);
|
|
3883
|
+
if (removeMark) {
|
|
3884
|
+
tr.removeStoredMark(removeMark);
|
|
3885
|
+
}
|
|
3886
|
+
tr.insertText(" ", currentPos.pos);
|
|
3887
|
+
editor.view.dispatch(tr);
|
|
3888
|
+
return true;
|
|
3889
|
+
}
|
|
3890
|
+
return false;
|
|
3891
|
+
}
|
|
3892
|
+
};
|
|
3893
|
+
|
|
3894
|
+
// src/Node.ts
|
|
3895
|
+
var Node3 = class {
|
|
3896
|
+
constructor(config = {}) {
|
|
3897
|
+
this.type = "node";
|
|
3898
|
+
this.name = "node";
|
|
3899
|
+
this.parent = null;
|
|
3900
|
+
this.child = null;
|
|
3901
|
+
this.config = {
|
|
3902
|
+
name: this.name,
|
|
3903
|
+
defaultOptions: {}
|
|
3904
|
+
};
|
|
3905
|
+
this.config = {
|
|
3906
|
+
...this.config,
|
|
3907
|
+
...config
|
|
3908
|
+
};
|
|
3909
|
+
this.name = this.config.name;
|
|
3910
|
+
if (config.defaultOptions) {
|
|
3911
|
+
console.warn(
|
|
3912
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${this.name}".`
|
|
3913
|
+
);
|
|
3914
|
+
}
|
|
3915
|
+
this.options = this.config.defaultOptions;
|
|
3916
|
+
if (this.config.addOptions) {
|
|
3917
|
+
this.options = callOrReturn(
|
|
3918
|
+
getExtensionField(this, "addOptions", {
|
|
3919
|
+
name: this.name
|
|
3920
|
+
})
|
|
3921
|
+
);
|
|
3922
|
+
}
|
|
3923
|
+
this.storage = callOrReturn(
|
|
3924
|
+
getExtensionField(this, "addStorage", {
|
|
3925
|
+
name: this.name,
|
|
3926
|
+
options: this.options
|
|
3927
|
+
})
|
|
3928
|
+
) || {};
|
|
3929
|
+
}
|
|
3930
|
+
static create(config = {}) {
|
|
3931
|
+
return new Node3(config);
|
|
3932
|
+
}
|
|
3933
|
+
configure(options = {}) {
|
|
3934
|
+
const extension = this.extend();
|
|
3935
|
+
extension.options = mergeDeep(this.options, options);
|
|
3936
|
+
extension.storage = callOrReturn(
|
|
3937
|
+
getExtensionField(extension, "addStorage", {
|
|
3938
|
+
name: extension.name,
|
|
3939
|
+
options: extension.options
|
|
3940
|
+
})
|
|
3941
|
+
);
|
|
3942
|
+
return extension;
|
|
3943
|
+
}
|
|
3944
|
+
extend(extendedConfig = {}) {
|
|
3945
|
+
const extension = new Node3(extendedConfig);
|
|
3946
|
+
extension.parent = this;
|
|
3947
|
+
this.child = extension;
|
|
3948
|
+
extension.name = extendedConfig.name ? extendedConfig.name : extension.parent.name;
|
|
3949
|
+
if (extendedConfig.defaultOptions) {
|
|
3950
|
+
console.warn(
|
|
3951
|
+
`[tiptap warn]: BREAKING CHANGE: "defaultOptions" is deprecated. Please use "addOptions" instead. Found in extension: "${extension.name}".`
|
|
3952
|
+
);
|
|
3953
|
+
}
|
|
3954
|
+
extension.options = callOrReturn(
|
|
3955
|
+
getExtensionField(extension, "addOptions", {
|
|
3956
|
+
name: extension.name
|
|
3957
|
+
})
|
|
3958
|
+
);
|
|
3959
|
+
extension.storage = callOrReturn(
|
|
3960
|
+
getExtensionField(extension, "addStorage", {
|
|
3961
|
+
name: extension.name,
|
|
3962
|
+
options: extension.options
|
|
3963
|
+
})
|
|
3964
|
+
);
|
|
3965
|
+
return extension;
|
|
3966
|
+
}
|
|
3967
|
+
};
|
|
3968
|
+
|
|
3969
|
+
// src/NodeView.ts
|
|
3970
|
+
import { NodeSelection as NodeSelection4 } from "@tiptap/pm/state";
|
|
3971
|
+
var NodeView = class {
|
|
3972
|
+
constructor(component, props, options) {
|
|
3973
|
+
this.isDragging = false;
|
|
3974
|
+
this.component = component;
|
|
3975
|
+
this.editor = props.editor;
|
|
3976
|
+
this.options = {
|
|
3977
|
+
stopEvent: null,
|
|
3978
|
+
ignoreMutation: null,
|
|
3979
|
+
...options
|
|
3980
|
+
};
|
|
3981
|
+
this.extension = props.extension;
|
|
3982
|
+
this.node = props.node;
|
|
3983
|
+
this.decorations = props.decorations;
|
|
3984
|
+
this.getPos = props.getPos;
|
|
3985
|
+
this.mount();
|
|
3986
|
+
}
|
|
3987
|
+
mount() {
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
get dom() {
|
|
3991
|
+
return this.editor.view.dom;
|
|
3992
|
+
}
|
|
3993
|
+
get contentDOM() {
|
|
3994
|
+
return null;
|
|
3995
|
+
}
|
|
3996
|
+
onDragStart(event) {
|
|
3997
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
3998
|
+
const { view } = this.editor;
|
|
3999
|
+
const target = event.target;
|
|
4000
|
+
const dragHandle = target.nodeType === 3 ? (_a = target.parentElement) == null ? void 0 : _a.closest("[data-drag-handle]") : target.closest("[data-drag-handle]");
|
|
4001
|
+
if (!this.dom || ((_b = this.contentDOM) == null ? void 0 : _b.contains(target)) || !dragHandle) {
|
|
4002
|
+
return;
|
|
4003
|
+
}
|
|
4004
|
+
let x = 0;
|
|
4005
|
+
let y = 0;
|
|
4006
|
+
if (this.dom !== dragHandle) {
|
|
4007
|
+
const domBox = this.dom.getBoundingClientRect();
|
|
4008
|
+
const handleBox = dragHandle.getBoundingClientRect();
|
|
4009
|
+
const offsetX = (_d = event.offsetX) != null ? _d : (_c = event.nativeEvent) == null ? void 0 : _c.offsetX;
|
|
4010
|
+
const offsetY = (_f = event.offsetY) != null ? _f : (_e = event.nativeEvent) == null ? void 0 : _e.offsetY;
|
|
4011
|
+
x = handleBox.x - domBox.x + offsetX;
|
|
4012
|
+
y = handleBox.y - domBox.y + offsetY;
|
|
4013
|
+
}
|
|
4014
|
+
(_g = event.dataTransfer) == null ? void 0 : _g.setDragImage(this.dom, x, y);
|
|
4015
|
+
const selection = NodeSelection4.create(view.state.doc, this.getPos());
|
|
4016
|
+
const transaction = view.state.tr.setSelection(selection);
|
|
4017
|
+
view.dispatch(transaction);
|
|
4018
|
+
}
|
|
4019
|
+
stopEvent(event) {
|
|
4020
|
+
var _a;
|
|
4021
|
+
if (!this.dom) {
|
|
4022
|
+
return false;
|
|
4023
|
+
}
|
|
4024
|
+
if (typeof this.options.stopEvent === "function") {
|
|
4025
|
+
return this.options.stopEvent({ event });
|
|
4026
|
+
}
|
|
4027
|
+
const target = event.target;
|
|
4028
|
+
const isInElement = this.dom.contains(target) && !((_a = this.contentDOM) == null ? void 0 : _a.contains(target));
|
|
4029
|
+
if (!isInElement) {
|
|
4030
|
+
return false;
|
|
4031
|
+
}
|
|
4032
|
+
const isDropEvent = event.type === "drop";
|
|
4033
|
+
const isInput = ["INPUT", "BUTTON", "SELECT", "TEXTAREA"].includes(target.tagName) || target.isContentEditable;
|
|
4034
|
+
if (isInput && !isDropEvent) {
|
|
4035
|
+
return true;
|
|
4036
|
+
}
|
|
4037
|
+
const { isEditable } = this.editor;
|
|
4038
|
+
const { isDragging } = this;
|
|
4039
|
+
const isDraggable = !!this.node.type.spec.draggable;
|
|
4040
|
+
const isSelectable = NodeSelection4.isSelectable(this.node);
|
|
4041
|
+
const isCopyEvent = event.type === "copy";
|
|
4042
|
+
const isPasteEvent = event.type === "paste";
|
|
4043
|
+
const isCutEvent = event.type === "cut";
|
|
4044
|
+
const isClickEvent = event.type === "mousedown";
|
|
4045
|
+
const isDragEvent = event.type.startsWith("drag");
|
|
4046
|
+
if (!isDraggable && isSelectable && isDragEvent) {
|
|
4047
|
+
event.preventDefault();
|
|
4048
|
+
}
|
|
4049
|
+
if (isDraggable && isDragEvent && !isDragging) {
|
|
4050
|
+
event.preventDefault();
|
|
4051
|
+
return false;
|
|
4052
|
+
}
|
|
4053
|
+
if (isDraggable && isEditable && !isDragging && isClickEvent) {
|
|
4054
|
+
const dragHandle = target.closest("[data-drag-handle]");
|
|
4055
|
+
const isValidDragHandle = dragHandle && (this.dom === dragHandle || this.dom.contains(dragHandle));
|
|
4056
|
+
if (isValidDragHandle) {
|
|
4057
|
+
this.isDragging = true;
|
|
4058
|
+
document.addEventListener(
|
|
4059
|
+
"dragend",
|
|
4060
|
+
() => {
|
|
4061
|
+
this.isDragging = false;
|
|
4062
|
+
},
|
|
4063
|
+
{ once: true }
|
|
4064
|
+
);
|
|
4065
|
+
document.addEventListener(
|
|
4066
|
+
"mouseup",
|
|
4067
|
+
() => {
|
|
4068
|
+
this.isDragging = false;
|
|
4069
|
+
},
|
|
4070
|
+
{ once: true }
|
|
4071
|
+
);
|
|
4072
|
+
}
|
|
4073
|
+
}
|
|
4074
|
+
if (isDragging || isDropEvent || isCopyEvent || isPasteEvent || isCutEvent || isClickEvent && isSelectable) {
|
|
4075
|
+
return false;
|
|
4076
|
+
}
|
|
4077
|
+
return true;
|
|
4078
|
+
}
|
|
4079
|
+
ignoreMutation(mutation) {
|
|
4080
|
+
if (!this.dom || !this.contentDOM) {
|
|
4081
|
+
return true;
|
|
4082
|
+
}
|
|
4083
|
+
if (typeof this.options.ignoreMutation === "function") {
|
|
4084
|
+
return this.options.ignoreMutation({ mutation });
|
|
4085
|
+
}
|
|
4086
|
+
if (this.node.isLeaf || this.node.isAtom) {
|
|
4087
|
+
return true;
|
|
4088
|
+
}
|
|
4089
|
+
if (mutation.type === "selection") {
|
|
4090
|
+
return false;
|
|
4091
|
+
}
|
|
4092
|
+
if (this.dom.contains(mutation.target) && mutation.type === "childList" && isiOS() && this.editor.isFocused) {
|
|
4093
|
+
const changedNodes = [
|
|
4094
|
+
...Array.from(mutation.addedNodes),
|
|
4095
|
+
...Array.from(mutation.removedNodes)
|
|
4096
|
+
];
|
|
4097
|
+
if (changedNodes.every((node) => node.isContentEditable)) {
|
|
4098
|
+
return false;
|
|
4099
|
+
}
|
|
4100
|
+
}
|
|
4101
|
+
if (this.contentDOM === mutation.target && mutation.type === "attributes") {
|
|
4102
|
+
return true;
|
|
4103
|
+
}
|
|
4104
|
+
if (this.contentDOM.contains(mutation.target)) {
|
|
4105
|
+
return false;
|
|
4106
|
+
}
|
|
4107
|
+
return true;
|
|
4108
|
+
}
|
|
4109
|
+
updateAttributes(attributes) {
|
|
4110
|
+
this.editor.commands.command(({ tr }) => {
|
|
4111
|
+
const pos = this.getPos();
|
|
4112
|
+
tr.setNodeMarkup(pos, void 0, {
|
|
4113
|
+
...this.node.attrs,
|
|
4114
|
+
...attributes
|
|
4115
|
+
});
|
|
4116
|
+
return true;
|
|
4117
|
+
});
|
|
4118
|
+
}
|
|
4119
|
+
deleteNode() {
|
|
4120
|
+
const from = this.getPos();
|
|
4121
|
+
const to = from + this.node.nodeSize;
|
|
4122
|
+
this.editor.commands.deleteRange({ from, to });
|
|
4123
|
+
}
|
|
4124
|
+
};
|
|
4125
|
+
|
|
4126
|
+
// src/pasteRules/markPasteRule.ts
|
|
4127
|
+
function markPasteRule(config) {
|
|
4128
|
+
return new PasteRule({
|
|
4129
|
+
find: config.find,
|
|
4130
|
+
handler: ({ state, range, match }) => {
|
|
4131
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match);
|
|
4132
|
+
if (attributes === false || attributes === null) {
|
|
4133
|
+
return null;
|
|
4134
|
+
}
|
|
4135
|
+
const { tr } = state;
|
|
4136
|
+
const captureGroup = match[match.length - 1];
|
|
4137
|
+
const fullMatch = match[0];
|
|
4138
|
+
let markEnd = range.to;
|
|
4139
|
+
if (captureGroup) {
|
|
4140
|
+
const startSpaces = fullMatch.search(/\S/);
|
|
4141
|
+
const textStart = range.from + fullMatch.indexOf(captureGroup);
|
|
4142
|
+
const textEnd = textStart + captureGroup.length;
|
|
4143
|
+
const excludedMarks = getMarksBetween(range.from, range.to, state.doc).filter((item) => {
|
|
4144
|
+
const excluded = item.mark.type.excluded;
|
|
4145
|
+
return excluded.find((type) => type === config.type && type !== item.mark.type);
|
|
4146
|
+
}).filter((item) => item.to > textStart);
|
|
4147
|
+
if (excludedMarks.length) {
|
|
4148
|
+
return null;
|
|
4149
|
+
}
|
|
4150
|
+
if (textEnd < range.to) {
|
|
4151
|
+
tr.delete(textEnd, range.to);
|
|
4152
|
+
}
|
|
4153
|
+
if (textStart > range.from) {
|
|
4154
|
+
tr.delete(range.from + startSpaces, textStart);
|
|
4155
|
+
}
|
|
4156
|
+
markEnd = range.from + startSpaces + captureGroup.length;
|
|
4157
|
+
tr.addMark(range.from + startSpaces, markEnd, config.type.create(attributes || {}));
|
|
4158
|
+
tr.removeStoredMark(config.type);
|
|
4159
|
+
}
|
|
4160
|
+
}
|
|
4161
|
+
});
|
|
4162
|
+
}
|
|
4163
|
+
|
|
4164
|
+
// src/utilities/escapeForRegEx.ts
|
|
4165
|
+
function escapeForRegEx(string) {
|
|
4166
|
+
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
4167
|
+
}
|
|
4168
|
+
|
|
4169
|
+
// src/utilities/isString.ts
|
|
4170
|
+
function isString(value) {
|
|
4171
|
+
return typeof value === "string";
|
|
4172
|
+
}
|
|
4173
|
+
|
|
4174
|
+
// src/pasteRules/nodePasteRule.ts
|
|
4175
|
+
function nodePasteRule(config) {
|
|
4176
|
+
return new PasteRule({
|
|
4177
|
+
find: config.find,
|
|
4178
|
+
handler({ match, chain, range }) {
|
|
4179
|
+
const attributes = callOrReturn(config.getAttributes, void 0, match);
|
|
4180
|
+
if (attributes === false || attributes === null) {
|
|
4181
|
+
return null;
|
|
4182
|
+
}
|
|
4183
|
+
if (match.input) {
|
|
4184
|
+
chain().deleteRange(range).insertContentAt(range.from, {
|
|
4185
|
+
type: config.type.name,
|
|
4186
|
+
attrs: attributes
|
|
4187
|
+
});
|
|
4188
|
+
}
|
|
4189
|
+
}
|
|
4190
|
+
});
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4193
|
+
// src/pasteRules/textPasteRule.ts
|
|
4194
|
+
function textPasteRule(config) {
|
|
4195
|
+
return new PasteRule({
|
|
4196
|
+
find: config.find,
|
|
4197
|
+
handler: ({ state, range, match }) => {
|
|
4198
|
+
let insert = config.replace;
|
|
4199
|
+
let start = range.from;
|
|
4200
|
+
const end = range.to;
|
|
4201
|
+
if (match[1]) {
|
|
4202
|
+
const offset = match[0].lastIndexOf(match[1]);
|
|
4203
|
+
insert += match[0].slice(offset + match[1].length);
|
|
4204
|
+
start += offset;
|
|
4205
|
+
const cutOff = start - end;
|
|
4206
|
+
if (cutOff > 0) {
|
|
4207
|
+
insert = match[0].slice(offset - cutOff, offset) + insert;
|
|
4208
|
+
start = end;
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4211
|
+
state.tr.insertText(insert, start, end);
|
|
4212
|
+
}
|
|
4213
|
+
});
|
|
4214
|
+
}
|
|
4215
|
+
|
|
4216
|
+
// src/Tracker.ts
|
|
4217
|
+
var Tracker = class {
|
|
4218
|
+
constructor(transaction) {
|
|
4219
|
+
this.transaction = transaction;
|
|
4220
|
+
this.currentStep = this.transaction.steps.length;
|
|
4221
|
+
}
|
|
4222
|
+
map(position) {
|
|
4223
|
+
let deleted = false;
|
|
4224
|
+
const mappedPosition = this.transaction.steps.slice(this.currentStep).reduce((newPosition, step) => {
|
|
4225
|
+
const mapResult = step.getMap().mapResult(newPosition);
|
|
4226
|
+
if (mapResult.deleted) {
|
|
4227
|
+
deleted = true;
|
|
4228
|
+
}
|
|
4229
|
+
return mapResult.pos;
|
|
4230
|
+
}, position);
|
|
4231
|
+
return {
|
|
4232
|
+
position: mappedPosition,
|
|
4233
|
+
deleted
|
|
4234
|
+
};
|
|
4235
|
+
}
|
|
4236
|
+
};
|
|
4237
|
+
export {
|
|
4238
|
+
CommandManager,
|
|
4239
|
+
Editor,
|
|
4240
|
+
Extension,
|
|
4241
|
+
InputRule,
|
|
4242
|
+
Mark,
|
|
4243
|
+
Node3 as Node,
|
|
4244
|
+
NodeView,
|
|
4245
|
+
PasteRule,
|
|
4246
|
+
Tracker,
|
|
4247
|
+
callOrReturn,
|
|
4248
|
+
combineTransactionSteps,
|
|
4249
|
+
createStyleTag,
|
|
4250
|
+
defaultBlockAt,
|
|
4251
|
+
deleteProps,
|
|
4252
|
+
elementFromString,
|
|
4253
|
+
escapeForRegEx,
|
|
4254
|
+
extensions_exports as extensions,
|
|
4255
|
+
findChildren,
|
|
4256
|
+
findChildrenInRange,
|
|
4257
|
+
findDuplicates,
|
|
4258
|
+
findParentNode,
|
|
4259
|
+
findParentNodeClosestToPos,
|
|
4260
|
+
fromString,
|
|
4261
|
+
generateHTML,
|
|
4262
|
+
generateJSON,
|
|
4263
|
+
generateText,
|
|
4264
|
+
getAttributes,
|
|
4265
|
+
getChangedRanges,
|
|
4266
|
+
getDebugJSON,
|
|
4267
|
+
getExtensionField,
|
|
4268
|
+
getHTMLFromFragment,
|
|
4269
|
+
getMarkAttributes,
|
|
4270
|
+
getMarkRange,
|
|
4271
|
+
getMarkType,
|
|
4272
|
+
getMarksBetween,
|
|
4273
|
+
getNodeAttributes,
|
|
4274
|
+
getNodeType,
|
|
4275
|
+
getSchema,
|
|
4276
|
+
getText,
|
|
4277
|
+
getTextBetween,
|
|
4278
|
+
getTextContentFromNodes,
|
|
4279
|
+
getTextSerializersFromSchema,
|
|
4280
|
+
inputRulesPlugin,
|
|
4281
|
+
isActive,
|
|
4282
|
+
isEmptyObject,
|
|
4283
|
+
isFunction,
|
|
4284
|
+
isList,
|
|
4285
|
+
isMacOS,
|
|
4286
|
+
isMarkActive,
|
|
4287
|
+
isNodeActive,
|
|
4288
|
+
isNodeEmpty,
|
|
4289
|
+
isNodeSelection,
|
|
4290
|
+
isNumber,
|
|
4291
|
+
isPlainObject,
|
|
4292
|
+
isRegExp,
|
|
4293
|
+
isString,
|
|
4294
|
+
isTextSelection,
|
|
4295
|
+
isiOS,
|
|
4296
|
+
markInputRule,
|
|
4297
|
+
markPasteRule,
|
|
4298
|
+
mergeAttributes,
|
|
4299
|
+
mergeDeep,
|
|
4300
|
+
minMax,
|
|
4301
|
+
nodeInputRule,
|
|
4302
|
+
nodePasteRule,
|
|
4303
|
+
objectIncludes,
|
|
4304
|
+
pasteRulesPlugin,
|
|
4305
|
+
posToDOMRect,
|
|
4306
|
+
removeDuplicates,
|
|
4307
|
+
textInputRule,
|
|
4308
|
+
textPasteRule,
|
|
4309
|
+
textblockTypeInputRule,
|
|
4310
|
+
wrappingInputRule
|
|
4311
|
+
};
|