vue-shiki-monaco
Version:
一个封shiki和monaco-editor的Vue组件
336 lines (335 loc) • 11.5 kB
JavaScript
import { defineComponent, ref, watch, onMounted, onUnmounted, onBeforeUnmount, createElementBlock, openBlock, normalizeClass, createBlock, createCommentVNode, createElementVNode, withCtx, renderSlot, normalizeStyle, unref } from "vue";
import { u as useMonacoEdit } from "../../index-Bl0GB3kH.js";
import MonacoHeader from "../Monaco-Header/index.js";
import ContextMenu from "../ContextMenu/index.js";
import { u as useContextMenu, M as MENU_PRESETS, c as createEditorContextMenu, b as MINIMAP_MENU_PRESETS, a as createMinimapContextMenu } from "../../editorMenu-BFs5QkAV.js";
import '../../global.css';import './index.css';/* empty css */
import { _ as _export_sfc } from "../../_plugin-vue_export-helper-1tPrXgE0.js";
const _sfc_main = /* @__PURE__ */ defineComponent({
__name: "index",
props: {
currentLanguage: { default: "javascript" },
currentTheme: { default: "vitesse-light" },
languages: { default: () => [
"javascript",
"typescript",
"python",
"html",
"css",
"json"
] },
themes: { default: () => [
"vitesse-light",
"vitesse-dark",
"github-light",
"github-dark"
] },
value: { default: "" },
height: { default: "400px" },
showToolbar: { type: Boolean, default: true },
autoResize: { type: Boolean, default: true },
monacoEditClass: {},
fileName: {},
contextMenu: { default: () => ({
enabled: true,
items: "full",
variant: "glass"
}) },
minimapContextMenu: { default: () => ({
enabled: true,
items: "basic",
variant: "glass"
}) },
teleportTarget: {}
},
emits: ["change", "ready"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const editorRef = ref();
let editorInstance = null;
let monacoEditHook = null;
const contextMenuItems = ref([]);
const contextMenu = useContextMenu({
items: contextMenuItems.value
});
const minimapContextMenuItems = ref([]);
const minimapContextMenu = useContextMenu({
items: minimapContextMenuItems.value
});
watch(
() => props.value,
(value) => {
if (editorInstance) {
editorInstance.setValue(value);
}
},
{ deep: 1 }
);
watch(
() => props.currentTheme,
async (newTheme) => {
if (monacoEditHook && editorInstance) {
try {
await monacoEditHook.setTheme(newTheme);
} catch (error) {
}
}
}
);
watch(
() => props.currentLanguage,
async (newLanguage) => {
if (monacoEditHook && editorInstance) {
try {
await monacoEditHook.setLanguage(newLanguage);
} catch (error) {
}
}
}
);
const initializeEditor = async () => {
if (!editorRef.value) return;
monacoEditHook = useMonacoEdit({
target: editorRef.value,
languages: props.languages,
themes: props.themes,
codeValue: props.value,
defaultTheme: props.currentTheme,
defaultLanguage: props.currentLanguage,
contextMenu: props.contextMenu
});
try {
editorInstance = await monacoEditHook.initMonacoEdit();
editorInstance.onDidChangeModelContent(() => {
const value = editorInstance?.getValue() || "";
emit("change", value);
});
emit("ready", editorInstance);
if (props.contextMenu?.enabled !== false) {
setupContextMenu();
}
if (props.autoResize) {
monacoEditHook.enableAutoResize();
}
} catch (error) {
throw error;
}
};
onMounted(async () => {
await initializeEditor();
});
onUnmounted(() => {
if (monacoEditHook) {
monacoEditHook.destroy();
}
});
const handleCopy = async () => {
if (editorInstance) {
try {
const code = editorInstance.getValue();
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(code);
return;
}
const textArea = document.createElement("textarea");
textArea.value = code;
textArea.style.position = "fixed";
textArea.style.left = "-999999px";
textArea.style.top = "-999999px";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
const successful = document.execCommand("copy");
document.body.removeChild(textArea);
if (successful) {
} else {
throw new Error("降级复制方案失败");
}
} catch (error) {
try {
const selection = editorInstance.getSelection();
if (selection && !selection.isEmpty()) {
editorInstance.trigger(
"keyboard",
"editor.action.clipboardCopyAction",
null
);
}
} catch (monacoError) {
}
}
}
};
const handleFormat = () => {
if (editorInstance) {
editorInstance.getAction("editor.action.formatDocument")?.run();
}
};
const handlePaste = async () => {
if (editorInstance) {
try {
const pasteAction = editorInstance.getAction(
"editor.action.clipboardPasteAction"
);
if (pasteAction) {
pasteAction.run();
return;
}
try {
editorInstance.trigger(
"keyboard",
"editor.action.clipboardPasteAction",
null
);
return;
} catch (triggerError) {
}
const text = await navigator.clipboard.readText();
if (text) {
const selection = editorInstance.getSelection();
if (selection) {
editorInstance.executeEdits("paste", [
{
range: selection,
text,
forceMoveMarkers: true
}
]);
editorInstance.focus();
}
}
} catch (error) {
}
}
};
const setupContextMenu = () => {
if (!editorInstance || !monacoEditHook) return;
if (props.contextMenu?.enabled !== false) {
let enabledItems = [];
if (typeof props.contextMenu?.items === "string") {
enabledItems = MENU_PRESETS[props.contextMenu.items];
} else if (Array.isArray(props.contextMenu?.items)) {
enabledItems = props.contextMenu.items;
}
contextMenuItems.value = createEditorContextMenu({
editor: editorInstance,
enabledItems,
customItems: props.contextMenu?.customItems ?? []
});
monacoEditHook.onContextMenu(async (event) => {
if (minimapContextMenu.isVisible.value) {
minimapContextMenu.hide();
}
try {
if ("permissions" in navigator) {
await navigator.permissions.query({
name: "clipboard-read"
});
}
} catch (error) {
}
contextMenu.show(event, contextMenuItems.value, editorRef.value);
});
}
if (props.minimapContextMenu?.enabled !== false) {
let minimapEnabledItems = [];
if (typeof props.minimapContextMenu?.items === "string") {
minimapEnabledItems = MINIMAP_MENU_PRESETS[props.minimapContextMenu.items];
} else if (Array.isArray(props.minimapContextMenu?.items)) {
minimapEnabledItems = props.minimapContextMenu.items;
}
minimapContextMenuItems.value = createMinimapContextMenu({
editor: editorInstance,
enabledItems: minimapEnabledItems,
customItems: props.minimapContextMenu?.customItems ?? []
});
monacoEditHook.onMinimapContextMenu(async (event) => {
if (contextMenu.isVisible.value) {
contextMenu.hide();
}
minimapContextMenu.show(event, minimapContextMenuItems.value, editorRef.value);
});
}
};
const handleContextMenuItemClick = (item) => {
if (item.type === "item") {
item.action();
contextMenu.hide();
}
};
const handleMinimapContextMenuItemClick = (item) => {
if (item.type === "item") {
item.action();
minimapContextMenu.hide();
}
};
onBeforeUnmount(() => {
monacoEditHook?.destroy();
});
__expose({
getEditor: () => editorInstance,
setValue: (value) => editorInstance?.setValue(value),
getValue: () => editorInstance?.getValue() || "",
focus: () => editorInstance?.focus(),
setTheme: (theme) => monacoEditHook?.setTheme(theme),
setLanguage: (language) => monacoEditHook?.setLanguage(language),
layout: () => monacoEditHook?.layout(),
enableAutoResize: () => monacoEditHook?.enableAutoResize(),
disableAutoResize: () => monacoEditHook?.disableAutoResize(),
copyCode: handleCopy,
pasteCode: handlePaste,
formatCode: handleFormat
});
return (_ctx, _cache) => {
return openBlock(), createElementBlock("div", {
class: normalizeClass(["monaco-editor-wrapper", props.monacoEditClass])
}, [
props.showToolbar ? (openBlock(), createBlock(MonacoHeader, {
key: 0,
"current-language": props.currentLanguage,
"file-name": props.fileName ?? "Untitled",
theme: props.currentTheme,
onCopy: handleCopy,
onFormat: handleFormat
}, {
toolbar: withCtx(() => [
renderSlot(_ctx.$slots, "toolbar", {}, void 0, true)
]),
_: 3
}, 8, ["current-language", "file-name", "theme"])) : createCommentVNode("", true),
createElementVNode("div", {
ref_key: "editorRef",
ref: editorRef,
class: normalizeClass(["monaco-editor", { noHeader: !props.showToolbar }]),
style: normalizeStyle({ height: props.height })
}, null, 6),
editorRef.value ? (openBlock(), createBlock(ContextMenu, {
key: 1,
visible: unref(contextMenu).isVisible.value,
position: unref(contextMenu).position,
items: contextMenuItems.value,
variant: props.contextMenu?.variant || "glass",
theme: props.currentTheme,
onItemClick: handleContextMenuItemClick,
onHide: unref(contextMenu).hide
}, null, 8, ["visible", "position", "items", "variant", "theme", "onHide"])) : createCommentVNode("", true),
editorRef.value ? (openBlock(), createBlock(ContextMenu, {
key: 2,
visible: unref(minimapContextMenu).isVisible.value,
position: unref(minimapContextMenu).position,
items: minimapContextMenuItems.value,
variant: props.minimapContextMenu?.variant || "glass",
theme: props.currentTheme,
onItemClick: handleMinimapContextMenuItemClick,
onHide: unref(minimapContextMenu).hide
}, null, 8, ["visible", "position", "items", "variant", "theme", "onHide"])) : createCommentVNode("", true)
], 2);
};
}
});
const Monaco = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-6b55436b"]]);
export {
Monaco as default
};
//# sourceMappingURL=index.js.map