1064 lines
30 KiB
Plaintext
1064 lines
30 KiB
Plaintext
import {
|
|
tippy_esm_default
|
|
} from "/_nuxt/node_modules/.cache/vite/client/deps/chunk-LEYSHZA4.js?v=e4f18c29";
|
|
import {
|
|
CommandManager,
|
|
Editor,
|
|
Extension,
|
|
InputRule,
|
|
Mark,
|
|
Node,
|
|
NodePos,
|
|
NodeView,
|
|
PasteRule,
|
|
Tracker,
|
|
callOrReturn,
|
|
combineTransactionSteps,
|
|
createChainableState,
|
|
createDocument,
|
|
createNodeFromContent,
|
|
createStyleTag,
|
|
defaultBlockAt,
|
|
deleteProps,
|
|
elementFromString,
|
|
escapeForRegEx,
|
|
findChildren,
|
|
findChildrenInRange,
|
|
findDuplicates,
|
|
findParentNode,
|
|
findParentNodeClosestToPos,
|
|
fromString,
|
|
generateHTML,
|
|
generateJSON,
|
|
generateText,
|
|
getAttributes,
|
|
getAttributesFromExtensions,
|
|
getChangedRanges,
|
|
getDebugJSON,
|
|
getExtensionField,
|
|
getHTMLFromFragment,
|
|
getMarkAttributes,
|
|
getMarkRange,
|
|
getMarkType,
|
|
getMarksBetween,
|
|
getNodeAtPosition,
|
|
getNodeAttributes,
|
|
getNodeType,
|
|
getRenderedAttributes,
|
|
getSchema,
|
|
getSchemaByResolvedExtensions,
|
|
getSchemaTypeByName,
|
|
getSchemaTypeNameByName,
|
|
getSplittedAttributes,
|
|
getText,
|
|
getTextBetween,
|
|
getTextContentFromNodes,
|
|
getTextSerializersFromSchema,
|
|
index,
|
|
injectExtensionAttributesToParseRule,
|
|
inputRulesPlugin,
|
|
isActive,
|
|
isAtEndOfNode,
|
|
isAtStartOfNode,
|
|
isEmptyObject,
|
|
isExtensionRulesEnabled,
|
|
isFunction,
|
|
isList,
|
|
isMacOS,
|
|
isMarkActive,
|
|
isNodeActive,
|
|
isNodeEmpty,
|
|
isNodeSelection,
|
|
isNumber,
|
|
isPlainObject,
|
|
isRegExp,
|
|
isString,
|
|
isTextSelection,
|
|
isiOS,
|
|
markInputRule,
|
|
markPasteRule,
|
|
mergeAttributes,
|
|
mergeDeep,
|
|
minMax,
|
|
nodeInputRule,
|
|
nodePasteRule,
|
|
objectIncludes,
|
|
pasteRulesPlugin,
|
|
posToDOMRect,
|
|
removeDuplicates,
|
|
resolveFocusPosition,
|
|
selectionToInsertionEnd,
|
|
splitExtensions,
|
|
textInputRule,
|
|
textPasteRule,
|
|
textblockTypeInputRule,
|
|
wrappingInputRule
|
|
} from "/_nuxt/node_modules/.cache/vite/client/deps/chunk-BTMXSOA4.js?v=e4f18c29";
|
|
import {
|
|
Plugin,
|
|
PluginKey
|
|
} from "/_nuxt/node_modules/.cache/vite/client/deps/chunk-B5J3BDGG.js?v=e4f18c29";
|
|
import "/_nuxt/node_modules/.cache/vite/client/deps/chunk-V4OQ3NZ2.js?v=e4f18c29";
|
|
|
|
// node_modules/@tiptap/extension-bubble-menu/dist/index.js
|
|
var BubbleMenuView = class {
|
|
constructor({ editor, element, view, tippyOptions = {}, updateDelay = 250, shouldShow }) {
|
|
this.preventHide = false;
|
|
this.shouldShow = ({ view: view2, state, from, to }) => {
|
|
const { doc, selection } = state;
|
|
const { empty } = selection;
|
|
const isEmptyTextBlock = !doc.textBetween(from, to).length && isTextSelection(state.selection);
|
|
const isChildOfMenu = this.element.contains(document.activeElement);
|
|
const hasEditorFocus = view2.hasFocus() || isChildOfMenu;
|
|
if (!hasEditorFocus || empty || isEmptyTextBlock || !this.editor.isEditable) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
this.mousedownHandler = () => {
|
|
this.preventHide = true;
|
|
};
|
|
this.dragstartHandler = () => {
|
|
this.hide();
|
|
};
|
|
this.focusHandler = () => {
|
|
setTimeout(() => this.update(this.editor.view));
|
|
};
|
|
this.blurHandler = ({ event }) => {
|
|
var _a;
|
|
if (this.preventHide) {
|
|
this.preventHide = false;
|
|
return;
|
|
}
|
|
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) && ((_a = this.element.parentNode) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget))) {
|
|
return;
|
|
}
|
|
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) === this.editor.view.dom) {
|
|
return;
|
|
}
|
|
this.hide();
|
|
};
|
|
this.tippyBlurHandler = (event) => {
|
|
this.blurHandler({ event });
|
|
};
|
|
this.handleDebouncedUpdate = (view2, oldState) => {
|
|
const selectionChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.selection.eq(view2.state.selection));
|
|
const docChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.doc.eq(view2.state.doc));
|
|
if (!selectionChanged && !docChanged) {
|
|
return;
|
|
}
|
|
if (this.updateDebounceTimer) {
|
|
clearTimeout(this.updateDebounceTimer);
|
|
}
|
|
this.updateDebounceTimer = window.setTimeout(() => {
|
|
this.updateHandler(view2, selectionChanged, docChanged, oldState);
|
|
}, this.updateDelay);
|
|
};
|
|
this.updateHandler = (view2, selectionChanged, docChanged, oldState) => {
|
|
var _a, _b, _c;
|
|
const { state, composing } = view2;
|
|
const { selection } = state;
|
|
const isSame = !selectionChanged && !docChanged;
|
|
if (composing || isSame) {
|
|
return;
|
|
}
|
|
this.createTooltip();
|
|
const { ranges } = selection;
|
|
const from = Math.min(...ranges.map((range) => range.$from.pos));
|
|
const to = Math.max(...ranges.map((range) => range.$to.pos));
|
|
const shouldShow2 = (_a = this.shouldShow) === null || _a === void 0 ? void 0 : _a.call(this, {
|
|
editor: this.editor,
|
|
element: this.element,
|
|
view: view2,
|
|
state,
|
|
oldState,
|
|
from,
|
|
to
|
|
});
|
|
if (!shouldShow2) {
|
|
this.hide();
|
|
return;
|
|
}
|
|
(_b = this.tippy) === null || _b === void 0 ? void 0 : _b.setProps({
|
|
getReferenceClientRect: ((_c = this.tippyOptions) === null || _c === void 0 ? void 0 : _c.getReferenceClientRect) || (() => {
|
|
if (isNodeSelection(state.selection)) {
|
|
let node = view2.nodeDOM(from);
|
|
if (node) {
|
|
const nodeViewWrapper = node.dataset.nodeViewWrapper ? node : node.querySelector("[data-node-view-wrapper]");
|
|
if (nodeViewWrapper) {
|
|
node = nodeViewWrapper.firstChild;
|
|
}
|
|
if (node) {
|
|
return node.getBoundingClientRect();
|
|
}
|
|
}
|
|
}
|
|
return posToDOMRect(view2, from, to);
|
|
})
|
|
});
|
|
this.show();
|
|
};
|
|
this.editor = editor;
|
|
this.element = element;
|
|
this.view = view;
|
|
this.updateDelay = updateDelay;
|
|
if (shouldShow) {
|
|
this.shouldShow = shouldShow;
|
|
}
|
|
this.element.addEventListener("mousedown", this.mousedownHandler, { capture: true });
|
|
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
|
|
this.editor.on("focus", this.focusHandler);
|
|
this.editor.on("blur", this.blurHandler);
|
|
this.tippyOptions = tippyOptions;
|
|
this.element.remove();
|
|
this.element.style.visibility = "visible";
|
|
}
|
|
createTooltip() {
|
|
const { element: editorElement } = this.editor.options;
|
|
const editorIsAttached = !!editorElement.parentElement;
|
|
if (this.tippy || !editorIsAttached) {
|
|
return;
|
|
}
|
|
this.tippy = tippy_esm_default(editorElement, {
|
|
duration: 0,
|
|
getReferenceClientRect: null,
|
|
content: this.element,
|
|
interactive: true,
|
|
trigger: "manual",
|
|
placement: "top",
|
|
hideOnClick: "toggle",
|
|
...this.tippyOptions
|
|
});
|
|
if (this.tippy.popper.firstChild) {
|
|
this.tippy.popper.firstChild.addEventListener("blur", this.tippyBlurHandler);
|
|
}
|
|
}
|
|
update(view, oldState) {
|
|
const { state } = view;
|
|
const hasValidSelection = state.selection.from !== state.selection.to;
|
|
if (this.updateDelay > 0 && hasValidSelection) {
|
|
this.handleDebouncedUpdate(view, oldState);
|
|
return;
|
|
}
|
|
const selectionChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.selection.eq(view.state.selection));
|
|
const docChanged = !(oldState === null || oldState === void 0 ? void 0 : oldState.doc.eq(view.state.doc));
|
|
this.updateHandler(view, selectionChanged, docChanged, oldState);
|
|
}
|
|
show() {
|
|
var _a;
|
|
(_a = this.tippy) === null || _a === void 0 ? void 0 : _a.show();
|
|
}
|
|
hide() {
|
|
var _a;
|
|
(_a = this.tippy) === null || _a === void 0 ? void 0 : _a.hide();
|
|
}
|
|
destroy() {
|
|
var _a, _b;
|
|
if ((_a = this.tippy) === null || _a === void 0 ? void 0 : _a.popper.firstChild) {
|
|
this.tippy.popper.firstChild.removeEventListener("blur", this.tippyBlurHandler);
|
|
}
|
|
(_b = this.tippy) === null || _b === void 0 ? void 0 : _b.destroy();
|
|
this.element.removeEventListener("mousedown", this.mousedownHandler, { capture: true });
|
|
this.view.dom.removeEventListener("dragstart", this.dragstartHandler);
|
|
this.editor.off("focus", this.focusHandler);
|
|
this.editor.off("blur", this.blurHandler);
|
|
}
|
|
};
|
|
var BubbleMenuPlugin = (options) => {
|
|
return new Plugin({
|
|
key: typeof options.pluginKey === "string" ? new PluginKey(options.pluginKey) : options.pluginKey,
|
|
view: (view) => new BubbleMenuView({ view, ...options })
|
|
});
|
|
};
|
|
var BubbleMenu = Extension.create({
|
|
name: "bubbleMenu",
|
|
addOptions() {
|
|
return {
|
|
element: null,
|
|
tippyOptions: {},
|
|
pluginKey: "bubbleMenu",
|
|
updateDelay: void 0,
|
|
shouldShow: null
|
|
};
|
|
},
|
|
addProseMirrorPlugins() {
|
|
if (!this.options.element) {
|
|
return [];
|
|
}
|
|
return [
|
|
BubbleMenuPlugin({
|
|
pluginKey: this.options.pluginKey,
|
|
editor: this.editor,
|
|
element: this.options.element,
|
|
tippyOptions: this.options.tippyOptions,
|
|
updateDelay: this.options.updateDelay,
|
|
shouldShow: this.options.shouldShow
|
|
})
|
|
];
|
|
}
|
|
});
|
|
|
|
// node_modules/@tiptap/vue-3/dist/index.js
|
|
import { defineComponent, ref, onMounted, onBeforeUnmount, h, markRaw, customRef, getCurrentInstance, watchEffect, nextTick, unref, shallowRef, reactive, render, provide } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29";
|
|
|
|
// node_modules/@tiptap/extension-floating-menu/dist/index.js
|
|
var FloatingMenuView = class {
|
|
constructor({ editor, element, view, tippyOptions = {}, shouldShow }) {
|
|
this.preventHide = false;
|
|
this.shouldShow = ({ view: view2, state }) => {
|
|
const { selection } = state;
|
|
const { $anchor, empty } = selection;
|
|
const isRootDepth = $anchor.depth === 1;
|
|
const isEmptyTextBlock = $anchor.parent.isTextblock && !$anchor.parent.type.spec.code && !$anchor.parent.textContent;
|
|
if (!view2.hasFocus() || !empty || !isRootDepth || !isEmptyTextBlock || !this.editor.isEditable) {
|
|
return false;
|
|
}
|
|
return true;
|
|
};
|
|
this.mousedownHandler = () => {
|
|
this.preventHide = true;
|
|
};
|
|
this.focusHandler = () => {
|
|
setTimeout(() => this.update(this.editor.view));
|
|
};
|
|
this.blurHandler = ({ event }) => {
|
|
var _a;
|
|
if (this.preventHide) {
|
|
this.preventHide = false;
|
|
return;
|
|
}
|
|
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) && ((_a = this.element.parentNode) === null || _a === void 0 ? void 0 : _a.contains(event.relatedTarget))) {
|
|
return;
|
|
}
|
|
if ((event === null || event === void 0 ? void 0 : event.relatedTarget) === this.editor.view.dom) {
|
|
return;
|
|
}
|
|
this.hide();
|
|
};
|
|
this.tippyBlurHandler = (event) => {
|
|
this.blurHandler({ event });
|
|
};
|
|
this.editor = editor;
|
|
this.element = element;
|
|
this.view = view;
|
|
if (shouldShow) {
|
|
this.shouldShow = shouldShow;
|
|
}
|
|
this.element.addEventListener("mousedown", this.mousedownHandler, { capture: true });
|
|
this.editor.on("focus", this.focusHandler);
|
|
this.editor.on("blur", this.blurHandler);
|
|
this.tippyOptions = tippyOptions;
|
|
this.element.remove();
|
|
this.element.style.visibility = "visible";
|
|
}
|
|
createTooltip() {
|
|
const { element: editorElement } = this.editor.options;
|
|
const editorIsAttached = !!editorElement.parentElement;
|
|
if (this.tippy || !editorIsAttached) {
|
|
return;
|
|
}
|
|
this.tippy = tippy_esm_default(editorElement, {
|
|
duration: 0,
|
|
getReferenceClientRect: null,
|
|
content: this.element,
|
|
interactive: true,
|
|
trigger: "manual",
|
|
placement: "right",
|
|
hideOnClick: "toggle",
|
|
...this.tippyOptions
|
|
});
|
|
if (this.tippy.popper.firstChild) {
|
|
this.tippy.popper.firstChild.addEventListener("blur", this.tippyBlurHandler);
|
|
}
|
|
}
|
|
update(view, oldState) {
|
|
var _a, _b, _c;
|
|
const { state } = view;
|
|
const { doc, selection } = state;
|
|
const { from, to } = selection;
|
|
const isSame = oldState && oldState.doc.eq(doc) && oldState.selection.eq(selection);
|
|
if (isSame) {
|
|
return;
|
|
}
|
|
this.createTooltip();
|
|
const shouldShow = (_a = this.shouldShow) === null || _a === void 0 ? void 0 : _a.call(this, {
|
|
editor: this.editor,
|
|
view,
|
|
state,
|
|
oldState
|
|
});
|
|
if (!shouldShow) {
|
|
this.hide();
|
|
return;
|
|
}
|
|
(_b = this.tippy) === null || _b === void 0 ? void 0 : _b.setProps({
|
|
getReferenceClientRect: ((_c = this.tippyOptions) === null || _c === void 0 ? void 0 : _c.getReferenceClientRect) || (() => posToDOMRect(view, from, to))
|
|
});
|
|
this.show();
|
|
}
|
|
show() {
|
|
var _a;
|
|
(_a = this.tippy) === null || _a === void 0 ? void 0 : _a.show();
|
|
}
|
|
hide() {
|
|
var _a;
|
|
(_a = this.tippy) === null || _a === void 0 ? void 0 : _a.hide();
|
|
}
|
|
destroy() {
|
|
var _a, _b;
|
|
if ((_a = this.tippy) === null || _a === void 0 ? void 0 : _a.popper.firstChild) {
|
|
this.tippy.popper.firstChild.removeEventListener("blur", this.tippyBlurHandler);
|
|
}
|
|
(_b = this.tippy) === null || _b === void 0 ? void 0 : _b.destroy();
|
|
this.element.removeEventListener("mousedown", this.mousedownHandler, { capture: true });
|
|
this.editor.off("focus", this.focusHandler);
|
|
this.editor.off("blur", this.blurHandler);
|
|
}
|
|
};
|
|
var FloatingMenuPlugin = (options) => {
|
|
return new Plugin({
|
|
key: typeof options.pluginKey === "string" ? new PluginKey(options.pluginKey) : options.pluginKey,
|
|
view: (view) => new FloatingMenuView({ view, ...options })
|
|
});
|
|
};
|
|
var FloatingMenu = Extension.create({
|
|
name: "floatingMenu",
|
|
addOptions() {
|
|
return {
|
|
element: null,
|
|
tippyOptions: {},
|
|
pluginKey: "floatingMenu",
|
|
shouldShow: null
|
|
};
|
|
},
|
|
addProseMirrorPlugins() {
|
|
if (!this.options.element) {
|
|
return [];
|
|
}
|
|
return [
|
|
FloatingMenuPlugin({
|
|
pluginKey: this.options.pluginKey,
|
|
editor: this.editor,
|
|
element: this.options.element,
|
|
tippyOptions: this.options.tippyOptions,
|
|
shouldShow: this.options.shouldShow
|
|
})
|
|
];
|
|
}
|
|
});
|
|
|
|
// node_modules/@tiptap/vue-3/dist/index.js
|
|
var BubbleMenu2 = defineComponent({
|
|
name: "BubbleMenu",
|
|
props: {
|
|
pluginKey: {
|
|
type: [String, Object],
|
|
default: "bubbleMenu"
|
|
},
|
|
editor: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
updateDelay: {
|
|
type: Number,
|
|
default: void 0
|
|
},
|
|
tippyOptions: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
shouldShow: {
|
|
type: Function,
|
|
default: null
|
|
}
|
|
},
|
|
setup(props, { slots }) {
|
|
const root = ref(null);
|
|
onMounted(() => {
|
|
const { updateDelay, editor, pluginKey, shouldShow, tippyOptions } = props;
|
|
editor.registerPlugin(BubbleMenuPlugin({
|
|
updateDelay,
|
|
editor,
|
|
element: root.value,
|
|
pluginKey,
|
|
shouldShow,
|
|
tippyOptions
|
|
}));
|
|
});
|
|
onBeforeUnmount(() => {
|
|
const { pluginKey, editor } = props;
|
|
editor.unregisterPlugin(pluginKey);
|
|
});
|
|
return () => {
|
|
var _a;
|
|
return h("div", { ref: root }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
|
|
};
|
|
}
|
|
});
|
|
function useDebouncedRef(value) {
|
|
return customRef((track, trigger) => {
|
|
return {
|
|
get() {
|
|
track();
|
|
return value;
|
|
},
|
|
set(newValue) {
|
|
value = newValue;
|
|
requestAnimationFrame(() => {
|
|
requestAnimationFrame(() => {
|
|
trigger();
|
|
});
|
|
});
|
|
}
|
|
};
|
|
});
|
|
}
|
|
var Editor2 = class extends Editor {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
this.contentComponent = null;
|
|
this.appContext = null;
|
|
this.reactiveState = useDebouncedRef(this.view.state);
|
|
this.reactiveExtensionStorage = useDebouncedRef(this.extensionStorage);
|
|
this.on("beforeTransaction", ({ nextState }) => {
|
|
this.reactiveState.value = nextState;
|
|
this.reactiveExtensionStorage.value = this.extensionStorage;
|
|
});
|
|
return markRaw(this);
|
|
}
|
|
get state() {
|
|
return this.reactiveState ? this.reactiveState.value : this.view.state;
|
|
}
|
|
get storage() {
|
|
return this.reactiveExtensionStorage ? this.reactiveExtensionStorage.value : super.storage;
|
|
}
|
|
/**
|
|
* Register a ProseMirror plugin.
|
|
*/
|
|
registerPlugin(plugin, handlePlugins) {
|
|
const nextState = super.registerPlugin(plugin, handlePlugins);
|
|
if (this.reactiveState) {
|
|
this.reactiveState.value = nextState;
|
|
}
|
|
return nextState;
|
|
}
|
|
/**
|
|
* Unregister a ProseMirror plugin.
|
|
*/
|
|
unregisterPlugin(nameOrPluginKey) {
|
|
const nextState = super.unregisterPlugin(nameOrPluginKey);
|
|
if (this.reactiveState && nextState) {
|
|
this.reactiveState.value = nextState;
|
|
}
|
|
return nextState;
|
|
}
|
|
};
|
|
var EditorContent = defineComponent({
|
|
name: "EditorContent",
|
|
props: {
|
|
editor: {
|
|
default: null,
|
|
type: Object
|
|
}
|
|
},
|
|
setup(props) {
|
|
const rootEl = ref();
|
|
const instance = getCurrentInstance();
|
|
watchEffect(() => {
|
|
const editor = props.editor;
|
|
if (editor && editor.options.element && rootEl.value) {
|
|
nextTick(() => {
|
|
if (!rootEl.value || !editor.options.element.firstChild) {
|
|
return;
|
|
}
|
|
const element = unref(rootEl.value);
|
|
rootEl.value.append(...editor.options.element.childNodes);
|
|
editor.contentComponent = instance.ctx._;
|
|
if (instance) {
|
|
editor.appContext = {
|
|
...instance.appContext,
|
|
// Vue internally uses prototype chain to forward/shadow injects across the entire component chain
|
|
// so don't use object spread operator or 'Object.assign' and just set `provides` as is on editor's appContext
|
|
// @ts-expect-error forward instance's 'provides' into appContext
|
|
provides: instance.provides
|
|
};
|
|
}
|
|
editor.setOptions({
|
|
element
|
|
});
|
|
editor.createNodeViews();
|
|
});
|
|
}
|
|
});
|
|
onBeforeUnmount(() => {
|
|
const editor = props.editor;
|
|
if (!editor) {
|
|
return;
|
|
}
|
|
editor.contentComponent = null;
|
|
editor.appContext = null;
|
|
});
|
|
return { rootEl };
|
|
},
|
|
render() {
|
|
return h("div", {
|
|
ref: (el) => {
|
|
this.rootEl = el;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
var FloatingMenu2 = defineComponent({
|
|
name: "FloatingMenu",
|
|
props: {
|
|
pluginKey: {
|
|
// TODO: TypeScript breaks :(
|
|
// type: [String, Object as PropType<Exclude<FloatingMenuPluginProps['pluginKey'], string>>],
|
|
type: null,
|
|
default: "floatingMenu"
|
|
},
|
|
editor: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
tippyOptions: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
shouldShow: {
|
|
type: Function,
|
|
default: null
|
|
}
|
|
},
|
|
setup(props, { slots }) {
|
|
const root = ref(null);
|
|
onMounted(() => {
|
|
const { pluginKey, editor, tippyOptions, shouldShow } = props;
|
|
editor.registerPlugin(FloatingMenuPlugin({
|
|
pluginKey,
|
|
editor,
|
|
element: root.value,
|
|
tippyOptions,
|
|
shouldShow
|
|
}));
|
|
});
|
|
onBeforeUnmount(() => {
|
|
const { pluginKey, editor } = props;
|
|
editor.unregisterPlugin(pluginKey);
|
|
});
|
|
return () => {
|
|
var _a;
|
|
return h("div", { ref: root }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
|
|
};
|
|
}
|
|
});
|
|
var NodeViewContent = defineComponent({
|
|
name: "NodeViewContent",
|
|
props: {
|
|
as: {
|
|
type: String,
|
|
default: "div"
|
|
}
|
|
},
|
|
render() {
|
|
return h(this.as, {
|
|
style: {
|
|
whiteSpace: "pre-wrap"
|
|
},
|
|
"data-node-view-content": ""
|
|
});
|
|
}
|
|
});
|
|
var NodeViewWrapper = defineComponent({
|
|
name: "NodeViewWrapper",
|
|
props: {
|
|
as: {
|
|
type: String,
|
|
default: "div"
|
|
}
|
|
},
|
|
inject: ["onDragStart", "decorationClasses"],
|
|
render() {
|
|
var _a, _b;
|
|
return h(this.as, {
|
|
// @ts-ignore
|
|
class: this.decorationClasses,
|
|
style: {
|
|
whiteSpace: "normal"
|
|
},
|
|
"data-node-view-wrapper": "",
|
|
// @ts-ignore (https://github.com/vuejs/vue-next/issues/3031)
|
|
onDragstart: this.onDragStart
|
|
}, (_b = (_a = this.$slots).default) === null || _b === void 0 ? void 0 : _b.call(_a));
|
|
}
|
|
});
|
|
var useEditor = (options = {}) => {
|
|
const editor = shallowRef();
|
|
onMounted(() => {
|
|
editor.value = new Editor2(options);
|
|
});
|
|
onBeforeUnmount(() => {
|
|
var _a, _b, _c;
|
|
const nodes = (_a = editor.value) === null || _a === void 0 ? void 0 : _a.options.element;
|
|
const newEl = nodes === null || nodes === void 0 ? void 0 : nodes.cloneNode(true);
|
|
(_b = nodes === null || nodes === void 0 ? void 0 : nodes.parentNode) === null || _b === void 0 ? void 0 : _b.replaceChild(newEl, nodes);
|
|
(_c = editor.value) === null || _c === void 0 ? void 0 : _c.destroy();
|
|
});
|
|
return editor;
|
|
};
|
|
var VueRenderer = class {
|
|
constructor(component, { props = {}, editor }) {
|
|
this.editor = editor;
|
|
this.component = markRaw(component);
|
|
this.el = document.createElement("div");
|
|
this.props = reactive(props);
|
|
this.renderedComponent = this.renderComponent();
|
|
}
|
|
get element() {
|
|
return this.renderedComponent.el;
|
|
}
|
|
get ref() {
|
|
var _a, _b, _c, _d;
|
|
if ((_b = (_a = this.renderedComponent.vNode) === null || _a === void 0 ? void 0 : _a.component) === null || _b === void 0 ? void 0 : _b.exposed) {
|
|
return this.renderedComponent.vNode.component.exposed;
|
|
}
|
|
return (_d = (_c = this.renderedComponent.vNode) === null || _c === void 0 ? void 0 : _c.component) === null || _d === void 0 ? void 0 : _d.proxy;
|
|
}
|
|
renderComponent() {
|
|
let vNode = h(this.component, this.props);
|
|
if (this.editor.appContext) {
|
|
vNode.appContext = this.editor.appContext;
|
|
}
|
|
if (typeof document !== "undefined" && this.el) {
|
|
render(vNode, this.el);
|
|
}
|
|
const destroy = () => {
|
|
if (this.el) {
|
|
render(null, this.el);
|
|
}
|
|
this.el = null;
|
|
vNode = null;
|
|
};
|
|
return { vNode, destroy, el: this.el ? this.el.firstElementChild : null };
|
|
}
|
|
updateProps(props = {}) {
|
|
Object.entries(props).forEach(([key, value]) => {
|
|
this.props[key] = value;
|
|
});
|
|
this.renderComponent();
|
|
}
|
|
destroy() {
|
|
this.renderedComponent.destroy();
|
|
}
|
|
};
|
|
var nodeViewProps = {
|
|
editor: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
node: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
decorations: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
selected: {
|
|
type: Boolean,
|
|
required: true
|
|
},
|
|
extension: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
getPos: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
updateAttributes: {
|
|
type: Function,
|
|
required: true
|
|
},
|
|
deleteNode: {
|
|
type: Function,
|
|
required: true
|
|
}
|
|
};
|
|
var VueNodeView = class extends NodeView {
|
|
mount() {
|
|
const props = {
|
|
editor: this.editor,
|
|
node: this.node,
|
|
decorations: this.decorations,
|
|
innerDecorations: this.innerDecorations,
|
|
view: this.view,
|
|
selected: false,
|
|
extension: this.extension,
|
|
HTMLAttributes: this.HTMLAttributes,
|
|
getPos: () => this.getPos(),
|
|
updateAttributes: (attributes = {}) => this.updateAttributes(attributes),
|
|
deleteNode: () => this.deleteNode()
|
|
};
|
|
const onDragStart = this.onDragStart.bind(this);
|
|
this.decorationClasses = ref(this.getDecorationClasses());
|
|
const extendedComponent = defineComponent({
|
|
extends: { ...this.component },
|
|
props: Object.keys(props),
|
|
template: this.component.template,
|
|
setup: (reactiveProps) => {
|
|
var _a, _b;
|
|
provide("onDragStart", onDragStart);
|
|
provide("decorationClasses", this.decorationClasses);
|
|
return (_b = (_a = this.component).setup) === null || _b === void 0 ? void 0 : _b.call(_a, reactiveProps, {
|
|
expose: () => void 0
|
|
});
|
|
},
|
|
// add support for scoped styles
|
|
// @ts-ignore
|
|
// eslint-disable-next-line
|
|
__scopeId: this.component.__scopeId,
|
|
// add support for CSS Modules
|
|
// @ts-ignore
|
|
// eslint-disable-next-line
|
|
__cssModules: this.component.__cssModules,
|
|
// add support for vue devtools
|
|
// @ts-ignore
|
|
// eslint-disable-next-line
|
|
__name: this.component.__name,
|
|
// @ts-ignore
|
|
// eslint-disable-next-line
|
|
__file: this.component.__file
|
|
});
|
|
this.handleSelectionUpdate = this.handleSelectionUpdate.bind(this);
|
|
this.editor.on("selectionUpdate", this.handleSelectionUpdate);
|
|
this.renderer = new VueRenderer(extendedComponent, {
|
|
editor: this.editor,
|
|
props
|
|
});
|
|
}
|
|
/**
|
|
* Return the DOM element.
|
|
* This is the element that will be used to display the node view.
|
|
*/
|
|
get dom() {
|
|
if (!this.renderer.element || !this.renderer.element.hasAttribute("data-node-view-wrapper")) {
|
|
throw Error("Please use the NodeViewWrapper component for your node view.");
|
|
}
|
|
return this.renderer.element;
|
|
}
|
|
/**
|
|
* Return the content DOM element.
|
|
* This is the element that will be used to display the rich-text content of the node.
|
|
*/
|
|
get contentDOM() {
|
|
if (this.node.isLeaf) {
|
|
return null;
|
|
}
|
|
return this.dom.querySelector("[data-node-view-content]");
|
|
}
|
|
/**
|
|
* On editor selection update, check if the node is selected.
|
|
* If it is, call `selectNode`, otherwise call `deselectNode`.
|
|
*/
|
|
handleSelectionUpdate() {
|
|
const { from, to } = this.editor.state.selection;
|
|
const pos = this.getPos();
|
|
if (typeof pos !== "number") {
|
|
return;
|
|
}
|
|
if (from <= pos && to >= pos + this.node.nodeSize) {
|
|
if (this.renderer.props.selected) {
|
|
return;
|
|
}
|
|
this.selectNode();
|
|
} else {
|
|
if (!this.renderer.props.selected) {
|
|
return;
|
|
}
|
|
this.deselectNode();
|
|
}
|
|
}
|
|
/**
|
|
* On update, update the React component.
|
|
* To prevent unnecessary updates, the `update` option can be used.
|
|
*/
|
|
update(node, decorations, innerDecorations) {
|
|
const rerenderComponent = (props) => {
|
|
this.decorationClasses.value = this.getDecorationClasses();
|
|
this.renderer.updateProps(props);
|
|
};
|
|
if (typeof this.options.update === "function") {
|
|
const oldNode = this.node;
|
|
const oldDecorations = this.decorations;
|
|
const oldInnerDecorations = this.innerDecorations;
|
|
this.node = node;
|
|
this.decorations = decorations;
|
|
this.innerDecorations = innerDecorations;
|
|
return this.options.update({
|
|
oldNode,
|
|
oldDecorations,
|
|
newNode: node,
|
|
newDecorations: decorations,
|
|
oldInnerDecorations,
|
|
innerDecorations,
|
|
updateProps: () => rerenderComponent({ node, decorations, innerDecorations })
|
|
});
|
|
}
|
|
if (node.type !== this.node.type) {
|
|
return false;
|
|
}
|
|
if (node === this.node && this.decorations === decorations && this.innerDecorations === innerDecorations) {
|
|
return true;
|
|
}
|
|
this.node = node;
|
|
this.decorations = decorations;
|
|
this.innerDecorations = innerDecorations;
|
|
rerenderComponent({ node, decorations, innerDecorations });
|
|
return true;
|
|
}
|
|
/**
|
|
* Select the node.
|
|
* Add the `selected` prop and the `ProseMirror-selectednode` class.
|
|
*/
|
|
selectNode() {
|
|
this.renderer.updateProps({
|
|
selected: true
|
|
});
|
|
if (this.renderer.element) {
|
|
this.renderer.element.classList.add("ProseMirror-selectednode");
|
|
}
|
|
}
|
|
/**
|
|
* Deselect the node.
|
|
* Remove the `selected` prop and the `ProseMirror-selectednode` class.
|
|
*/
|
|
deselectNode() {
|
|
this.renderer.updateProps({
|
|
selected: false
|
|
});
|
|
if (this.renderer.element) {
|
|
this.renderer.element.classList.remove("ProseMirror-selectednode");
|
|
}
|
|
}
|
|
getDecorationClasses() {
|
|
return this.decorations.map((item) => item.type.attrs.class).flat().join(" ");
|
|
}
|
|
destroy() {
|
|
this.renderer.destroy();
|
|
this.editor.off("selectionUpdate", this.handleSelectionUpdate);
|
|
}
|
|
};
|
|
function VueNodeViewRenderer(component, options) {
|
|
return (props) => {
|
|
if (!props.editor.contentComponent) {
|
|
return {};
|
|
}
|
|
const normalizedComponent = typeof component === "function" && "__vccOpts" in component ? component.__vccOpts : component;
|
|
return new VueNodeView(normalizedComponent, props, options);
|
|
};
|
|
}
|
|
export {
|
|
BubbleMenu2 as BubbleMenu,
|
|
CommandManager,
|
|
Editor2 as Editor,
|
|
EditorContent,
|
|
Extension,
|
|
FloatingMenu2 as FloatingMenu,
|
|
InputRule,
|
|
Mark,
|
|
Node,
|
|
NodePos,
|
|
NodeView,
|
|
NodeViewContent,
|
|
NodeViewWrapper,
|
|
PasteRule,
|
|
Tracker,
|
|
VueNodeViewRenderer,
|
|
VueRenderer,
|
|
callOrReturn,
|
|
combineTransactionSteps,
|
|
createChainableState,
|
|
createDocument,
|
|
createNodeFromContent,
|
|
createStyleTag,
|
|
defaultBlockAt,
|
|
deleteProps,
|
|
elementFromString,
|
|
escapeForRegEx,
|
|
index as extensions,
|
|
findChildren,
|
|
findChildrenInRange,
|
|
findDuplicates,
|
|
findParentNode,
|
|
findParentNodeClosestToPos,
|
|
fromString,
|
|
generateHTML,
|
|
generateJSON,
|
|
generateText,
|
|
getAttributes,
|
|
getAttributesFromExtensions,
|
|
getChangedRanges,
|
|
getDebugJSON,
|
|
getExtensionField,
|
|
getHTMLFromFragment,
|
|
getMarkAttributes,
|
|
getMarkRange,
|
|
getMarkType,
|
|
getMarksBetween,
|
|
getNodeAtPosition,
|
|
getNodeAttributes,
|
|
getNodeType,
|
|
getRenderedAttributes,
|
|
getSchema,
|
|
getSchemaByResolvedExtensions,
|
|
getSchemaTypeByName,
|
|
getSchemaTypeNameByName,
|
|
getSplittedAttributes,
|
|
getText,
|
|
getTextBetween,
|
|
getTextContentFromNodes,
|
|
getTextSerializersFromSchema,
|
|
injectExtensionAttributesToParseRule,
|
|
inputRulesPlugin,
|
|
isActive,
|
|
isAtEndOfNode,
|
|
isAtStartOfNode,
|
|
isEmptyObject,
|
|
isExtensionRulesEnabled,
|
|
isFunction,
|
|
isList,
|
|
isMacOS,
|
|
isMarkActive,
|
|
isNodeActive,
|
|
isNodeEmpty,
|
|
isNodeSelection,
|
|
isNumber,
|
|
isPlainObject,
|
|
isRegExp,
|
|
isString,
|
|
isTextSelection,
|
|
isiOS,
|
|
markInputRule,
|
|
markPasteRule,
|
|
mergeAttributes,
|
|
mergeDeep,
|
|
minMax,
|
|
nodeInputRule,
|
|
nodePasteRule,
|
|
nodeViewProps,
|
|
objectIncludes,
|
|
pasteRulesPlugin,
|
|
posToDOMRect,
|
|
removeDuplicates,
|
|
resolveFocusPosition,
|
|
selectionToInsertionEnd,
|
|
splitExtensions,
|
|
textInputRule,
|
|
textPasteRule,
|
|
textblockTypeInputRule,
|
|
useEditor,
|
|
wrappingInputRule
|
|
};
|
|
//# sourceMappingURL=@tiptap_vue-3.js.map
|