refactor(editor): Refactor code editors to composition API (no-changelog) (#9757)

This commit is contained in:
Elias Meire
2024-06-20 14:17:12 +02:00
committed by GitHub
parent f4e2c695f2
commit 202124152c
6 changed files with 1217 additions and 1254 deletions

View File

@@ -1,11 +1,11 @@
<template>
<div :class="$style.editor">
<div ref="jsEditor" class="ph-no-capture js-editor"></div>
<div ref="jsEditorRef" class="ph-no-capture js-editor"></div>
<slot name="suffix" />
</div>
</template>
<script lang="ts">
<script setup lang="ts">
import { history, toggleComment } from '@codemirror/commands';
import { javascript } from '@codemirror/lang-javascript';
import { foldGutter, indentOnInput } from '@codemirror/language';
@@ -21,9 +21,8 @@ import {
keymap,
lineNumbers,
} from '@codemirror/view';
import { defineComponent } from 'vue';
import { computed, onMounted, ref } from 'vue';
import { codeNodeEditorTheme } from '../CodeNodeEditor/theme';
import {
autocompleteKeyMap,
enterKeyMap,
@@ -31,86 +30,72 @@ import {
tabKeyMap,
} from '@/plugins/codemirror/keymap';
import { n8nAutocompletion } from '@/plugins/codemirror/n8nLang';
import { codeNodeEditorTheme } from '../CodeNodeEditor/theme';
export default defineComponent({
name: 'JsEditor',
props: {
modelValue: {
type: String,
required: true,
},
isReadOnly: {
type: Boolean,
default: false,
},
fillParent: {
type: Boolean,
default: false,
},
rows: {
type: Number,
default: 4,
},
},
data() {
return {
editor: null as EditorView | null,
editorState: null as EditorState | null,
};
},
computed: {
doc(): string {
return this.editor?.state.doc.toString() ?? '';
},
extensions(): Extension[] {
const { isReadOnly } = this;
const extensions: Extension[] = [
javascript(),
lineNumbers(),
EditorView.lineWrapping,
EditorState.readOnly.of(isReadOnly),
EditorView.editable.of(!isReadOnly),
codeNodeEditorTheme({
isReadOnly,
maxHeight: this.fillParent ? '100%' : '40vh',
minHeight: '20vh',
rows: this.rows,
}),
];
if (!isReadOnly) {
extensions.push(
history(),
Prec.highest(
keymap.of([
...tabKeyMap(),
...enterKeyMap,
...historyKeyMap,
...autocompleteKeyMap,
{ key: 'Mod-/', run: toggleComment },
]),
),
lintGutter(),
n8nAutocompletion(),
indentOnInput(),
highlightActiveLine(),
highlightActiveLineGutter(),
foldGutter(),
dropCursor(),
EditorView.updateListener.of((viewUpdate: ViewUpdate) => {
if (!viewUpdate.docChanged || !this.editor) return;
this.$emit('update:modelValue', this.editor?.state.doc.toString());
}),
);
}
return extensions;
},
},
mounted() {
const state = EditorState.create({ doc: this.modelValue, extensions: this.extensions });
const parent = this.$refs.jsEditor as HTMLDivElement;
this.editor = new EditorView({ parent, state });
this.editorState = this.editor.state;
},
type Props = {
modelValue: string;
isReadOnly?: boolean;
fillParent?: boolean;
rows?: number;
};
const props = withDefaults(defineProps<Props>(), { fillParent: false, isReadOnly: false, rows: 4 });
const emit = defineEmits<{
(event: 'update:modelValue', value: string): void;
}>();
onMounted(() => {
const state = EditorState.create({ doc: props.modelValue, extensions: extensions.value });
const parent = jsEditorRef.value;
editor.value = new EditorView({ parent, state });
editorState.value = editor.value.state;
});
const jsEditorRef = ref<HTMLDivElement>();
const editor = ref<EditorView | null>(null);
const editorState = ref<EditorState | null>(null);
const extensions = computed(() => {
const extensionsToApply: Extension[] = [
javascript(),
lineNumbers(),
EditorView.lineWrapping,
EditorState.readOnly.of(props.isReadOnly),
EditorView.editable.of(!props.isReadOnly),
codeNodeEditorTheme({
isReadOnly: props.isReadOnly,
maxHeight: props.fillParent ? '100%' : '40vh',
minHeight: '20vh',
rows: props.rows,
}),
];
if (!props.isReadOnly) {
extensionsToApply.push(
history(),
Prec.highest(
keymap.of([
...tabKeyMap(),
...enterKeyMap,
...historyKeyMap,
...autocompleteKeyMap,
{ key: 'Mod-/', run: toggleComment },
]),
),
lintGutter(),
n8nAutocompletion(),
indentOnInput(),
highlightActiveLine(),
highlightActiveLineGutter(),
foldGutter(),
dropCursor(),
EditorView.updateListener.of((viewUpdate: ViewUpdate) => {
if (!viewUpdate.docChanged || !editor.value) return;
emit('update:modelValue', editor.value?.state.doc.toString());
}),
);
}
return extensionsToApply;
});
</script>