66 lines
1.8 KiB
Vue
66 lines
1.8 KiB
Vue
<script lang="ts" setup>
|
|
import { cpp } from "@codemirror/lang-cpp"
|
|
import { python } from "@codemirror/lang-python"
|
|
import { sql, SQLite } from "@codemirror/lang-sql"
|
|
import { bracketMatching } from "@codemirror/language"
|
|
import { Codemirror } from "vue-codemirror"
|
|
import type { Extension } from "@codemirror/state"
|
|
import { autocompletion, closeBrackets, completeAnyWord } from "@codemirror/autocomplete"
|
|
import type { LANGUAGE } from "utils/types"
|
|
import { oneDark } from "../themes/oneDark"
|
|
import { smoothy } from "../themes/smoothy"
|
|
import { styleTheme } from "shared/extensions/baseTheme"
|
|
import { enhanceCompletion } from "shared/extensions/autocompletion"
|
|
|
|
interface Props {
|
|
language?: LANGUAGE
|
|
fontSize?: number
|
|
height?: string
|
|
readonly?: boolean
|
|
placeholder?: string
|
|
/** 追加的 CodeMirror 扩展。传一个稳定的数组实例,每次渲染新建会让编辑器反复重配 */
|
|
extraExtensions?: Extension[]
|
|
}
|
|
|
|
const {
|
|
language = "Python",
|
|
fontSize = 20,
|
|
height = "100%",
|
|
readonly = false,
|
|
placeholder = "",
|
|
extraExtensions = [],
|
|
} = defineProps<Props>()
|
|
const code = defineModel<string>("value")
|
|
|
|
const isDark = useDark()
|
|
|
|
const langExtension = computed(() => {
|
|
if (language === "SQL") return sql({ dialect: SQLite, upperCaseKeywords: true })
|
|
return language === "Python" ? python() : cpp()
|
|
})
|
|
|
|
const extensions = computed(() => [
|
|
styleTheme,
|
|
langExtension.value,
|
|
bracketMatching(),
|
|
closeBrackets(),
|
|
autocompletion({
|
|
override: [enhanceCompletion(language), completeAnyWord],
|
|
}),
|
|
isDark.value ? oneDark : smoothy,
|
|
...extraExtensions,
|
|
])
|
|
</script>
|
|
|
|
<template>
|
|
<Codemirror
|
|
v-model="code"
|
|
indentWithTab
|
|
:extensions="extensions"
|
|
:disabled="readonly"
|
|
:tab-size="4"
|
|
:placeholder="placeholder"
|
|
:style="{ height, fontSize: `${fontSize}px` }"
|
|
/>
|
|
</template>
|