change code editor to codemirror.

This commit is contained in:
2023-04-07 10:00:29 +08:00
parent 007de440d6
commit 0862b0ff91
14 changed files with 335 additions and 2744 deletions

55
src/shared/CodeEditor.vue Normal file
View File

@@ -0,0 +1,55 @@
<script lang="ts" setup>
import { Codemirror } from "vue-codemirror"
import { cpp } from "@codemirror/lang-cpp"
import { python } from "@codemirror/lang-python"
import { java } from "@codemirror/lang-java"
import { javascript } from "@codemirror/lang-javascript"
import { LANGUAGE } from "~/utils/types"
import { EditorView } from "@codemirror/view"
const styleTheme = EditorView.baseTheme({
"&.cm-editor.cm-focused": {
outline: "none",
},
})
interface Props {
value: string
language?: LANGUAGE
fontSize?: number
height?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "C",
fontSize: 20,
height: "100%",
})
const code = ref(props.value)
const emit = defineEmits(["update:value"])
const lang = computed(() => {
if (props.language === "C" || props.language === "C++") return cpp()
if (props.language === "Java") return java()
if (props.language === "JavaScript") return javascript()
return python()
})
function onChange(v: string) {
emit("update:value", v)
}
</script>
<template>
<Codemirror
v-model="code"
:extensions="[styleTheme, lang]"
indentWithTab
:tabSize="4"
@change="onChange"
:style="{
height: props.height,
fontSize: props.fontSize + 'px',
}"
/>
</template>

View File

@@ -35,7 +35,6 @@ onMounted(() => {
const menus = computed<MenuOption[]>(() => [
{
show: false,
label: () =>
h(RouterLink, { to: "/learn/step-1" }, { default: () => "自学" }),
key: "learn",

View File

@@ -1,107 +0,0 @@
<script setup lang="ts">
import type * as Monaco from "monaco-editor"
import { LANGUAGE_FORMAT_VALUE } from "utils/constants"
import { LANGUAGE } from "utils/types"
import { isMobile } from "~/shared/composables/breakpoints"
import { isDark } from "./composables/dark"
import { init, monaco } from "./composables/monaco"
interface Props {
value: string
language?: LANGUAGE
height?: string
fontSize?: number
class?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "C",
height: "calc(100vh - 92px)",
fontSize: 20,
class: "",
})
const emit = defineEmits<{
(e: "update:value", value: string): void
}>()
const monacoEditorRef = ref()
let editor: Monaco.editor.IStandaloneCodeEditor
let model: Monaco.editor.ITextModel
onMounted(async () => {
if (!monaco.value) await init()
model = monaco.value!.editor.createModel(
props.value,
LANGUAGE_FORMAT_VALUE[props.language]
)
editor = monaco.value!.editor.create(monacoEditorRef.value, {
model,
theme: isDark.value ? "dark" : "light", // 官方自带三种主题vs, hc-black, or vs-dark
minimap: {
enabled: false,
},
lineNumbersMinChars: 2,
automaticLayout: true, // 自适应布局
tabSize: 4,
fontSize: props.fontSize || (isMobile.value ? 20 : 22), // 字体大小
scrollBeyondLastLine: false,
lineDecorationsWidth: 0,
scrollBeyondLastColumn: 0,
glyphMargin: false,
scrollbar: {
useShadows: false,
vertical: "hidden",
horizontal: "hidden",
},
overviewRulerLanes: 0,
})
model.onDidChangeContent(() => {
const value = model.getValue().toString()
emit("update:value", value)
})
editor.onKeyDown((e) => {
if ((e.ctrlKey || e.metaKey) && e.code === "KeyS") {
e.preventDefault()
}
if ((e.ctrlKey || e.metaKey) && e.code === "KeyR") {
e.preventDefault()
}
})
watchEffect(() => {
if (!monaco.value) return
monaco.value.editor.setModelLanguage(
model,
LANGUAGE_FORMAT_VALUE[props.language]
)
})
watchEffect(() => {
if (props.value !== model.getValue()) {
model.setValue(props.value)
}
})
watchEffect(() => {
if (!monaco.value) return
monaco.value.editor.setTheme(isDark.value ? "dark" : "light")
})
})
onUnmounted(() => {
editor && editor.dispose()
})
</script>
<template>
<div
v-if="monaco"
ref="monacoEditorRef"
:class="props.class"
:style="{ height: props.height }"
></div>
<div v-else :style="{ height: props.height }"></div>
</template>
<style scoped></style>

View File

@@ -1,25 +0,0 @@
import loader, { Monaco } from "@monaco-editor/loader"
import * as monaco0301 from "monaco-editor"
import { isLowVersion } from "~/utils/functions"
export const monaco = ref<Monaco>()
export async function init() {
if (isLowVersion) {
loader.config({ monaco: monaco0301 })
} else {
loader.config({
paths: { vs: "https://cdn.staticfile.org/monaco-editor/0.36.1/min/vs" },
"vs/nls": { availableLanguages: { "*": "zh-cn" } },
})
}
const [m, light, dark] = await Promise.all([
loader.init(),
fetch("/light.json").then((t) => t.json()),
fetch("/dark.json").then((t) => t.json()),
])
monaco.value = m
monaco.value.editor.defineTheme("light", light)
monaco.value.editor.defineTheme("dark", dark)
}