md-editor-v3
Version:
Markdown editor for vue3, developed in jsx and typescript, dark theme、beautify content by prettier、render articles directly、paste or clip the picture and upload it...
330 lines (329 loc) • 9.72 kB
JavaScript
;
const vue = require("vue");
const config = require("./config.cjs");
const vueTsx = require("./vue-tsx.cjs");
const dom = require("./dom.cjs");
const lucideVueNext = require("lucide-vue-next");
const index = require("./index5.cjs");
const Github = () => vue.createVNode("svg", {
"xmlns": "http://www.w3.org/2000/svg",
"viewBox": "0 0 24 24",
"fill": "none",
"stroke": "currentColor",
"stroke-width": "2",
"stroke-linecap": "round",
"stroke-linejoin": "round",
"class": "lucide lucide-github-icon"
}, [vue.createVNode("path", {
"d": "M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
}, null), vue.createVNode("path", {
"d": "M9 18c-4.51 2-5-2-7-2"
}, null)]);
const iconMaps = {
bold: lucideVueNext.Bold,
underline: lucideVueNext.Underline,
italic: lucideVueNext.Italic,
"strike-through": lucideVueNext.Strikethrough,
title: lucideVueNext.Heading,
sub: lucideVueNext.Subscript,
sup: lucideVueNext.Superscript,
quote: lucideVueNext.Quote,
"unordered-list": lucideVueNext.List,
"ordered-list": lucideVueNext.ListOrdered,
task: lucideVueNext.ListTodo,
"code-row": lucideVueNext.Code,
code: lucideVueNext.SquareCode,
link: lucideVueNext.Link,
image: lucideVueNext.Image,
table: lucideVueNext.Table,
revoke: lucideVueNext.Reply,
next: lucideVueNext.Forward,
save: lucideVueNext.Save,
prettier: lucideVueNext.SquareCode,
minimize: lucideVueNext.Minimize2,
maximize: lucideVueNext.Maximize2,
"fullscreen-exit": lucideVueNext.Shrink,
fullscreen: lucideVueNext.Expand,
"preview-only": lucideVueNext.View,
preview: lucideVueNext.Eye,
"preview-html": lucideVueNext.CodeXml,
catalog: lucideVueNext.ListTree,
github: Github,
mermaid: lucideVueNext.ChartArea,
formula: lucideVueNext.SquareSigma,
close: lucideVueNext.X,
delete: lucideVueNext.Trash2,
upload: lucideVueNext.Upload
};
const Icon$1 = /* @__PURE__ */ vue.defineComponent({
name: `${config.prefix}-icon-set`,
props: {
name: {
type: String,
default: ""
}
},
setup(props2) {
return () => {
return vue.h(iconMaps[props2.name], {
class: `${config.prefix}-icon`
});
};
}
});
const Icon = /* @__PURE__ */ vue.defineComponent({
name: `${config.prefix}-icon`,
props: {
name: {
type: String,
default: ""
}
},
setup(props2) {
const customIcon = vue.inject("customIcon");
return () => {
const item = customIcon.value[props2.name];
if (typeof item === "object") {
return typeof item.component === "object" ? vue.h(item.component, item.props) : vue.createVNode("span", {
"innerHTML": item.component
}, null);
}
return vue.createVNode(Icon$1, {
"name": props2.name
}, null);
};
}
});
const props = {
title: {
type: [String, Object],
default: ""
},
visible: {
type: Boolean,
default: false
},
width: {
type: String,
default: "auto"
},
height: {
type: String,
default: "auto"
},
onClose: {
type: Function
},
showAdjust: {
type: Boolean,
default: false
},
isFullscreen: {
type: Boolean,
default: false
},
onAdjust: {
type: Function,
default: () => {
}
},
class: {
type: String,
default: void 0
},
style: {
type: [Object, String],
default: () => ({})
},
showMask: {
type: Boolean,
default: true
}
};
const MdModal = /* @__PURE__ */ vue.defineComponent({
name: "MdModal",
props,
emits: ["onClose"],
setup(props2, ctx) {
const themeRef = vue.inject("theme");
const rootRef = vue.inject("rootRef");
const modalVisible = vue.ref(props2.visible);
const modalClass = vue.ref([`${config.prefix}-modal`]);
const modalRef = vue.ref();
const modalHeaderRef = vue.ref();
const bodyRef = vue.ref();
const containerRef = vue.shallowRef();
let keyMoveClear = () => {
};
const state = vue.reactive({
maskStyle: {
zIndex: -1
},
modalStyle: {
zIndex: -1
},
initPos: {
left: "0px",
top: "0px"
},
historyPos: {
left: "0px",
top: "0px"
}
});
const innerSize = vue.computed(() => {
if (props2.isFullscreen) {
return {
width: "100%",
height: "100%"
};
} else {
return {
width: props2.width,
height: props2.height
};
}
});
vue.watch(() => props2.isFullscreen, (nVal) => {
if (nVal) {
keyMoveClear();
} else {
vue.nextTick(() => {
keyMoveClear = dom.keyMove(modalHeaderRef.value, (left, top) => {
state.initPos.left = left + "px";
state.initPos.top = top + "px";
});
});
}
});
vue.watch(() => props2.visible, (nVal) => {
if (nVal) {
state.maskStyle.zIndex = config.globalConfig.editorConfig.zIndex + index.getZIndexIncrement();
state.modalStyle.zIndex = config.globalConfig.editorConfig.zIndex + index.getZIndexIncrement();
modalClass.value.push("zoom-in");
modalVisible.value = nVal;
vue.nextTick(() => {
const halfWidth = modalRef.value.offsetWidth / 2;
const halfHeight = modalRef.value.offsetHeight / 2;
const halfClientWidth = document.documentElement.clientWidth / 2;
const halfClientHeight = document.documentElement.clientHeight / 2;
state.initPos.left = halfClientWidth - halfWidth + "px";
state.initPos.top = halfClientHeight - halfHeight + "px";
if (!props2.isFullscreen) {
keyMoveClear = dom.keyMove(modalHeaderRef.value, (left, top) => {
state.initPos.left = left + "px";
state.initPos.top = top + "px";
});
}
});
setTimeout(() => {
modalClass.value = modalClass.value.filter((item) => item !== "zoom-in");
}, 140);
} else {
modalClass.value.push("zoom-out");
keyMoveClear();
setTimeout(() => {
modalClass.value = modalClass.value.filter((item) => item !== "zoom-out");
modalVisible.value = nVal;
}, 130);
}
});
const internalStyle = vue.computed(() => ({
display: modalVisible.value ? "block" : "none"
}));
const combinedStyle = vue.computed(() => {
if (typeof props2.style === "string") {
return [props2.style, internalStyle.value].join("; ");
} else if (props2.style instanceof Object) {
return {
...internalStyle.value,
...props2.style
};
} else {
return internalStyle.value;
}
});
vue.onMounted(() => {
var _a;
const rootNode = (_a = rootRef.value) == null ? void 0 : _a.getRootNode();
bodyRef.value = rootNode instanceof Document ? document.body : rootNode;
});
return () => {
const slotDefault = vueTsx.getSlot({
ctx
});
const slotTitle = vueTsx.getSlot({
props: props2,
ctx
}, "title");
return bodyRef.value ? vue.createVNode(vue.Teleport, {
"to": bodyRef.value
}, {
default: () => [vue.createVNode("div", {
"ref": containerRef,
"class": `${config.prefix}-modal-container`,
"data-theme": themeRef.value
}, [vue.createVNode("div", {
"class": props2.class,
"style": combinedStyle.value
}, [props2.showMask && vue.createVNode("div", {
"class": `${config.prefix}-modal-mask`,
"style": state.maskStyle,
"onClick": () => {
var _a;
(_a = props2.onClose) == null ? void 0 : _a.call(props2);
ctx.emit("onClose");
}
}, null), vue.createVNode("div", {
"class": modalClass.value,
"style": {
...state.modalStyle,
...state.initPos,
...innerSize.value
},
"ref": modalRef
}, [vue.createVNode("div", {
"class": `${config.prefix}-modal-header`,
"ref": modalHeaderRef
}, [slotTitle || ""]), vue.createVNode("div", {
"class": `${config.prefix}-modal-body`
}, [slotDefault]), vue.createVNode("div", {
"class": `${config.prefix}-modal-func`
}, [props2.showAdjust && vue.createVNode("div", {
"class": `${config.prefix}-modal-adjust`,
"onClick": (e) => {
e.stopPropagation();
if (!props2.isFullscreen) {
state.historyPos = state.initPos;
state.initPos = {
left: "0",
top: "0"
};
} else {
state.initPos = state.historyPos;
}
props2.onAdjust(!props2.isFullscreen);
}
}, [vue.createVNode(Icon, {
"name": props2.isFullscreen ? "minimize" : "maximize"
}, null)]), vue.createVNode("div", {
"class": `${config.prefix}-modal-close`,
"onClick": (e) => {
var _a;
e.stopPropagation();
(_a = props2.onClose) == null ? void 0 : _a.call(props2);
ctx.emit("onClose");
}
}, [vue.createVNode(Icon, {
"name": "close"
}, null)])])])])])]
}) : "";
};
}
});
MdModal.install = (app) => {
app.component(MdModal.name, MdModal);
return app;
};
exports.Icon = Icon;
exports.MdModal = MdModal;