Resolve "Monaco Playground Typing and Rollup Bundles"
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<template>
|
||||
<div class="code-editor">
|
||||
<div ref="editorContainer" class="code-editor" />
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, watch } from 'vue';
|
||||
import loader, { Monaco } from '@monaco-editor/loader';
|
||||
|
||||
import { ImportedLib } from '../utils/useXOCashLibs';
|
||||
|
||||
export type CodeEditorProps = {
|
||||
// List of .d.ts files to import into the editor.
|
||||
libs?: Record<string, ImportedLib>;
|
||||
|
||||
// Color scheme of the editor
|
||||
isDark?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<CodeEditorProps>(), {
|
||||
libs: () => ({}),
|
||||
isDark: false,
|
||||
});
|
||||
|
||||
const code = defineModel<string>();
|
||||
|
||||
const monacoInstance = ref<Monaco | null>(null);
|
||||
const editorContainer = ref<HTMLElement | null>(null);
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'execute'): void;
|
||||
}>();
|
||||
|
||||
watch(() => props.libs, async () => {
|
||||
updateEditorTypes();
|
||||
});
|
||||
|
||||
|
||||
function updateEditorTypes() {
|
||||
monacoInstance.value?.languages.typescript.typescriptDefaults.setExtraLibs(
|
||||
Object.entries(props.libs).map(([name, content]) => {
|
||||
// Dont add the library if it is empty
|
||||
if (!content) return null;
|
||||
|
||||
const moduleContent = `declare module "${name}" { ${content.libTypes} }`;
|
||||
|
||||
return { uri: `inmemory://model/${name}.d.ts`, content: moduleContent };
|
||||
}).filter((lib) => lib !== null)
|
||||
);
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
// Load Monaco Editor
|
||||
loader.init().then((monaco) => {
|
||||
monacoInstance.value = monaco;
|
||||
|
||||
// Throw if our editor container is not found
|
||||
if (!editorContainer.value) {
|
||||
throw new Error('Editor container not found');
|
||||
}
|
||||
|
||||
// Disable unnecessary validations
|
||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: false,
|
||||
noSyntaxValidation: false,
|
||||
diagnosticCodesToIgnore: [ 1375 ] // Ignore "top-level await" error
|
||||
});
|
||||
|
||||
// Add our typescript compiler options
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
|
||||
target: monaco.languages.typescript.ScriptTarget.ESNext,
|
||||
allowNonTsExtensions: true,
|
||||
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
||||
module: monaco.languages.typescript.ModuleKind.ESNext,
|
||||
noEmit: true,
|
||||
lib: ["esnext", "dom"],
|
||||
checkJs: true,
|
||||
isolatedModules: true,
|
||||
allowSyntheticDefaultImports: true
|
||||
});
|
||||
|
||||
// Enable eager mode. Tries to move LSP on worker thread
|
||||
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
|
||||
|
||||
// Add extra libs to the editor
|
||||
updateEditorTypes();
|
||||
|
||||
// Define a theme to change the background color of the editor
|
||||
monaco.editor.defineTheme('xo-sandbox', {
|
||||
base: props.isDark ? 'vs-dark' : 'vs',
|
||||
inherit: true,
|
||||
rules: [],
|
||||
colors: {
|
||||
"editor.background": props.isDark ? '#161618' : '#f5f5f5'
|
||||
}
|
||||
});
|
||||
|
||||
// Create our editor into the container
|
||||
const editor = monaco.editor.create(editorContainer.value, {
|
||||
value: code.value,
|
||||
language: 'typescript',
|
||||
theme: 'xo-sandbox',
|
||||
automaticLayout: true,
|
||||
scrollBeyondLastLine: false,
|
||||
suggest: {
|
||||
showClasses: true,
|
||||
showFunctions: true,
|
||||
showVariables: true,
|
||||
showModules: true,
|
||||
showProperties: true,
|
||||
showWords: true,
|
||||
},
|
||||
});
|
||||
|
||||
// Add control + S keybinding to execute code
|
||||
editor.addAction({
|
||||
id: `execute-code`,
|
||||
label: 'Execute Code',
|
||||
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS],
|
||||
run: () => {
|
||||
emit('execute')
|
||||
}
|
||||
});
|
||||
|
||||
// Update the code value when the editor content changes
|
||||
editor.onDidChangeModelContent(() => {
|
||||
code.value = editor.getValue();
|
||||
});
|
||||
});
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.code-editor {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user