open-webui/src/lib/components/common/CodeEditor.svelte

87 lines
2.1 KiB
Svelte
Raw Normal View History

2024-06-10 22:24:26 +00:00
<script lang="ts">
import { basicSetup, EditorView } from 'codemirror';
import { keymap, placeholder } from '@codemirror/view';
2024-06-10 23:02:23 +00:00
import { Compartment, EditorState } from '@codemirror/state';
2024-06-10 22:24:26 +00:00
import { acceptCompletion } from '@codemirror/autocomplete';
import { indentWithTab } from '@codemirror/commands';
import { python } from '@codemirror/lang-python';
import { oneDark } from '@codemirror/theme-one-dark';
import { onMount } from 'svelte';
export let value = '';
2024-06-10 23:02:23 +00:00
let codeEditor;
let isDarkMode = false;
let editorTheme = new Compartment();
let extensions = [
basicSetup,
keymap.of([{ key: 'Tab', run: acceptCompletion }, indentWithTab]),
python(),
placeholder('Enter your code here...'),
EditorView.updateListener.of((e) => {
if (e.docChanged) {
value = e.state.doc.toString();
}
}),
editorTheme.of([])
];
2024-06-10 22:24:26 +00:00
onMount(() => {
2024-06-10 23:02:23 +00:00
// Check if html class has dark mode
isDarkMode = document.documentElement.classList.contains('dark');
2024-06-10 22:24:26 +00:00
// python code editor, highlight python code
2024-06-10 23:02:23 +00:00
codeEditor = new EditorView({
2024-06-10 22:24:26 +00:00
state: EditorState.create({
2024-06-10 23:02:23 +00:00
doc: '',
extensions: extensions
2024-06-10 22:24:26 +00:00
}),
parent: document.getElementById('code-textarea')
});
2024-06-10 23:02:23 +00:00
if (isDarkMode) {
codeEditor.dispatch({
effects: editorTheme.reconfigure(oneDark)
});
}
// listen to html class changes this should fire only when dark mode is toggled
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
const _isDarkMode = document.documentElement.classList.contains('dark');
if (_isDarkMode !== isDarkMode) {
isDarkMode = _isDarkMode;
if (_isDarkMode) {
codeEditor.dispatch({
effects: editorTheme.reconfigure(oneDark)
});
} else {
codeEditor.dispatch({
effects: editorTheme.reconfigure()
});
}
}
}
});
});
observer.observe(document.documentElement, {
attributes: true,
attributeFilter: ['class']
});
return () => {
observer.disconnect();
};
2024-06-10 22:24:26 +00:00
});
</script>
2024-06-10 23:02:23 +00:00
<div id="code-textarea" class="h-full w-full" />