Moving files around
This commit is contained in:
169
src/lib/components/editor/Editor.svelte
Normal file
169
src/lib/components/editor/Editor.svelte
Normal file
@ -0,0 +1,169 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { EditorView } from 'codemirror';
|
||||
import { Compartment } from '@codemirror/state';
|
||||
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap } from '@codemirror/view';
|
||||
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
||||
import { searchKeymap, highlightSelectionMatches } from '@codemirror/search';
|
||||
import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
||||
import { foldGutter, indentOnInput, syntaxHighlighting, defaultHighlightStyle, bracketMatching, foldKeymap } from '@codemirror/language';
|
||||
import { lintKeymap } from '@codemirror/lint';
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
import { vim } from '@replit/codemirror-vim';
|
||||
import type { EditorSettingsStore } from '../../stores/editorSettings';
|
||||
|
||||
interface Props {
|
||||
value: string;
|
||||
language?: 'javascript' | 'html' | 'css';
|
||||
onChange?: (value: string) => void;
|
||||
onExecute?: (code: string) => void;
|
||||
editorSettings: EditorSettingsStore;
|
||||
}
|
||||
|
||||
let {
|
||||
value = '',
|
||||
language = 'javascript',
|
||||
onChange,
|
||||
onExecute,
|
||||
editorSettings
|
||||
}: Props = $props();
|
||||
|
||||
let editorContainer: HTMLDivElement;
|
||||
let editorView: EditorView | null = null;
|
||||
|
||||
const languageExtensions = {
|
||||
javascript: javascript(),
|
||||
html: html(),
|
||||
css: css()
|
||||
};
|
||||
|
||||
const lineNumbersCompartment = new Compartment();
|
||||
const lineWrappingCompartment = new Compartment();
|
||||
const vimCompartment = new Compartment();
|
||||
|
||||
const evaluateKeymap = keymap.of([
|
||||
{
|
||||
key: 'Mod-e',
|
||||
run: (view) => {
|
||||
if (onExecute) {
|
||||
const code = view.state.doc.toString();
|
||||
onExecute(code);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
onMount(() => {
|
||||
const baseExtensions = [
|
||||
highlightActiveLineGutter(),
|
||||
highlightSpecialChars(),
|
||||
history(),
|
||||
foldGutter(),
|
||||
drawSelection(),
|
||||
dropCursor(),
|
||||
indentOnInput(),
|
||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||
bracketMatching(),
|
||||
closeBrackets(),
|
||||
autocompletion(),
|
||||
rectangularSelection(),
|
||||
crosshairCursor(),
|
||||
highlightSelectionMatches(),
|
||||
keymap.of([
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...searchKeymap,
|
||||
...historyKeymap,
|
||||
...foldKeymap,
|
||||
...completionKeymap,
|
||||
...lintKeymap
|
||||
])
|
||||
];
|
||||
|
||||
const initSettings = $editorSettings;
|
||||
|
||||
editorView = new EditorView({
|
||||
doc: value,
|
||||
extensions: [
|
||||
...baseExtensions,
|
||||
languageExtensions[language],
|
||||
oneDark,
|
||||
evaluateKeymap,
|
||||
lineNumbersCompartment.of(initSettings.showLineNumbers ? lineNumbers() : []),
|
||||
lineWrappingCompartment.of(initSettings.enableLineWrapping ? EditorView.lineWrapping : []),
|
||||
vimCompartment.of(initSettings.vimMode ? vim() : []),
|
||||
EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged && onChange) {
|
||||
onChange(update.state.doc.toString());
|
||||
}
|
||||
}),
|
||||
EditorView.theme({
|
||||
'&': {
|
||||
fontSize: `${initSettings.fontSize}px`,
|
||||
fontFamily: initSettings.fontFamily
|
||||
}
|
||||
})
|
||||
],
|
||||
parent: editorContainer
|
||||
});
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
const settings = $editorSettings;
|
||||
if (!editorView) return;
|
||||
|
||||
editorView.dispatch({
|
||||
effects: [
|
||||
lineNumbersCompartment.reconfigure(settings.showLineNumbers ? lineNumbers() : []),
|
||||
lineWrappingCompartment.reconfigure(settings.enableLineWrapping ? EditorView.lineWrapping : []),
|
||||
vimCompartment.reconfigure(settings.vimMode ? vim() : [])
|
||||
]
|
||||
});
|
||||
|
||||
editorView.dom.style.fontSize = `${settings.fontSize}px`;
|
||||
editorView.dom.style.fontFamily = settings.fontFamily;
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (editorView) {
|
||||
editorView.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (editorView && value !== editorView.state.doc.toString()) {
|
||||
editorView.dispatch({
|
||||
changes: { from: 0, to: editorView.state.doc.length, insert: value }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="editor-wrapper">
|
||||
<div bind:this={editorContainer} class="editor-container"></div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.editor-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.editor-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:global(.cm-editor) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:global(.cm-scroller) {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user