64 lines
1.4 KiB
Vue
64 lines
1.4 KiB
Vue
<script setup lang="ts">
|
|
import { json } from "@codemirror/lang-json";
|
|
import {
|
|
defaultHighlightStyle,
|
|
syntaxHighlighting,
|
|
} from "@codemirror/language";
|
|
import { EditorState } from "@codemirror/state";
|
|
import { basicSetup, EditorView } from "codemirror";
|
|
|
|
const { codes } = defineProps<{ codes: object | undefined }>();
|
|
|
|
const emit = defineEmits(["update:codes"]);
|
|
|
|
const view = ref<EditorView>();
|
|
|
|
watchEffect(() => {
|
|
if (!view.value) return;
|
|
view.value.dispatch({
|
|
changes: {
|
|
from: 0,
|
|
to: view.value.state.doc.length,
|
|
insert: JSON.stringify(codes, null, 2),
|
|
},
|
|
});
|
|
});
|
|
|
|
onMounted(() => {
|
|
const state = EditorState.create({
|
|
doc: codes ? JSON.stringify(codes, null, 2) : "",
|
|
extensions: [
|
|
basicSetup,
|
|
syntaxHighlighting(defaultHighlightStyle),
|
|
json(),
|
|
EditorState.transactionFilter.of((tr) => {
|
|
if (tr.docChanged) {
|
|
// emit("update:codes", tr.newDoc.toJSON());
|
|
debouncedUpdate(JSON.parse(tr.newDoc.toString()));
|
|
}
|
|
return tr;
|
|
}),
|
|
],
|
|
});
|
|
|
|
view.value = new EditorView({
|
|
parent: document.getElementById("code") as HTMLElement,
|
|
state: state,
|
|
});
|
|
});
|
|
|
|
const debouncedUpdate = useDebounceFn((value: object) => {
|
|
emit("update:codes", value);
|
|
}, 1000 * 3);
|
|
</script>
|
|
|
|
<template>
|
|
<div id="code"></div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
:global(.cm-editor) {
|
|
height: 100%;
|
|
}
|
|
</style>
|