123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- <script lang="ts">
- import { basicSetup, EditorView } from 'codemirror';
- import { keymap, placeholder } from '@codemirror/view';
- import { Compartment, EditorState } from '@codemirror/state';
- import { acceptCompletion } from '@codemirror/autocomplete';
- import { indentWithTab } from '@codemirror/commands';
- import { indentUnit, LanguageDescription } from '@codemirror/language';
- import { languages } from '@codemirror/language-data';
- import { oneDark } from '@codemirror/theme-one-dark';
- import { onMount, createEventDispatcher, getContext, tick } from 'svelte';
- import { formatPythonCode } from '$lib/apis/utils';
- import { toast } from 'svelte-sonner';
- const dispatch = createEventDispatcher();
- const i18n = getContext('i18n');
- export let boilerplate = '';
- export let value = '';
- export let onSave = () => {};
- export let onChange = () => {};
- let _value = '';
- $: if (value) {
- updateValue();
- }
- const updateValue = () => {
- if (_value !== value) {
- _value = value;
- if (codeEditor) {
- codeEditor.dispatch({
- changes: [{ from: 0, to: codeEditor.state.doc.length, insert: _value }]
- });
- }
- }
- };
- export let id = '';
- export let lang = '';
- let codeEditor;
- export const focus = () => {
- codeEditor.focus();
- };
- let isDarkMode = false;
- let editorTheme = new Compartment();
- let editorLanguage = new Compartment();
- languages.push(
- LanguageDescription.of({
- name: 'HCL',
- extensions: ['hcl', 'tf'],
- load() {
- return import('codemirror-lang-hcl').then((m) => m.hcl());
- }
- })
- );
- const getLang = async () => {
- const language = languages.find((l) => l.alias.includes(lang));
- return await language?.load();
- };
- export const formatPythonCodeHandler = async () => {
- if (codeEditor) {
- const res = await formatPythonCode(localStorage.token, _value).catch((error) => {
- toast.error(`${error}`);
- return null;
- });
- if (res && res.code) {
- const formattedCode = res.code;
- codeEditor.dispatch({
- changes: [{ from: 0, to: codeEditor.state.doc.length, insert: formattedCode }]
- });
- _value = formattedCode;
- onChange(_value);
- await tick();
- toast.success($i18n.t('Code formatted successfully'));
- return true;
- }
- return false;
- }
- return false;
- };
- let extensions = [
- basicSetup,
- keymap.of([{ key: 'Tab', run: acceptCompletion }, indentWithTab]),
- indentUnit.of(' '),
- placeholder('Enter your code here...'),
- EditorView.updateListener.of((e) => {
- if (e.docChanged) {
- _value = e.state.doc.toString();
- onChange(_value);
- }
- }),
- editorTheme.of([]),
- editorLanguage.of([])
- ];
- $: if (lang) {
- setLanguage();
- }
- const setLanguage = async () => {
- const language = await getLang();
- if (language && codeEditor) {
- codeEditor.dispatch({
- effects: editorLanguage.reconfigure(language)
- });
- }
- };
- onMount(() => {
- console.log(value);
- if (value === '') {
- value = boilerplate;
- }
- _value = value;
- // Check if html class has dark mode
- isDarkMode = document.documentElement.classList.contains('dark');
- // python code editor, highlight python code
- codeEditor = new EditorView({
- state: EditorState.create({
- doc: _value,
- extensions: extensions
- }),
- parent: document.getElementById(`code-textarea-${id}`)
- });
- 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']
- });
- const keydownHandler = async (e) => {
- if ((e.ctrlKey || e.metaKey) && e.key === 's') {
- e.preventDefault();
- onSave();
- }
- // Format code when Ctrl + Shift + F is pressed
- if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.key === 'f') {
- e.preventDefault();
- await formatPythonCodeHandler();
- }
- };
- document.addEventListener('keydown', keydownHandler);
- return () => {
- observer.disconnect();
- document.removeEventListener('keydown', keydownHandler);
- };
- });
- </script>
- <div id="code-textarea-{id}" class="h-full w-full" />
|