Messy working Monaco editor.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/prettierrc",
|
||||
"semi": false,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "all",
|
||||
"printWidth": 100,
|
||||
"plugins": [
|
||||
"prettier-plugin-tailwindcss"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pluginVue from 'eslint-plugin-vue'
|
||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
||||
import pluginVue from 'eslint-plugin-vue';
|
||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript';
|
||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting';
|
||||
|
||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
||||
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
||||
@@ -21,4 +21,4 @@ export default defineConfigWithVueTs(
|
||||
pluginVue.configs['flat/essential'],
|
||||
vueTsConfigs.recommended,
|
||||
skipFormatting,
|
||||
)
|
||||
);
|
||||
|
||||
7
ui/package-lock.json
generated
7
ui/package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.0.6",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"tailwindcss": "^4.0.6",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
@@ -4156,6 +4157,12 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/monaco-editor": {
|
||||
"version": "0.52.2",
|
||||
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
|
||||
"integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/mrmime": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz",
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@tailwindcss/vite": "^4.0.6",
|
||||
"monaco-editor": "^0.52.2",
|
||||
"tailwindcss": "^4.0.6",
|
||||
"vue": "^3.5.13",
|
||||
"vue-router": "^4.5.0"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { RouterLink, RouterView } from 'vue-router'
|
||||
import { RouterLink, RouterView } from 'vue-router';
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -38,10 +38,10 @@ import { RouterLink, RouterView } from 'vue-router'
|
||||
|
||||
<footer class="bg-gray-100">
|
||||
<div class="mx-auto max-w-7xl px-4 py-4 sm:px-6 lg:px-8">
|
||||
<p class="text-center text-sm text-gray-500">© {{new Date().getFullYear()}} Glancr. All rights reserved.</p>
|
||||
<p class="text-center text-sm text-gray-500">
|
||||
© {{ new Date().getFullYear() }} Glancr - All rights reserved.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import { ref, defineAsyncComponent } from 'vue'
|
||||
|
||||
const MonacoEditor = defineAsyncComponent(() => import('@/components/MonacoEditor.vue'))
|
||||
|
||||
const code = ref('# Hello from markdown\n\n\t> this is a markdown note')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h1 class="font-bold text-red-500">Editor Placeholder</h1>
|
||||
<Suspense>
|
||||
<MonacoEditor v-model="code" language="markdown" :options="{ readOnly: false }" />
|
||||
<template #fallback>
|
||||
<div>Loading editor...</div>
|
||||
</template>
|
||||
</Suspense>
|
||||
</template>
|
||||
|
||||
96
ui/src/components/MonacoEditor.vue
Normal file
96
ui/src/components/MonacoEditor.vue
Normal file
@@ -0,0 +1,96 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
|
||||
import { editor } from 'monaco-editor/esm/vs/editor/editor.api.js'
|
||||
import { setupMonaco } from '@/workers/monaco.workers'
|
||||
|
||||
import 'monaco-editor/esm/vs/basic-languages/markdown/markdown.contribution'
|
||||
|
||||
// Load common languages for code fences
|
||||
const loadLanguage = async (language: string) => {
|
||||
switch (language) {
|
||||
case 'javascript':
|
||||
await import('monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution')
|
||||
break
|
||||
case 'typescript':
|
||||
await import('monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution')
|
||||
break
|
||||
case 'python':
|
||||
await import('monaco-editor/esm/vs/basic-languages/python/python.contribution')
|
||||
break
|
||||
// Add more languages as needed
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize monaco workers
|
||||
setupMonaco()
|
||||
|
||||
const props = defineProps<{
|
||||
modelValue: string
|
||||
language?: string
|
||||
options?: editor.IStandaloneEditorConstructionOptions
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'update:modelValue', value: string): void
|
||||
}>()
|
||||
|
||||
const editorContainer = ref<HTMLElement | null>(null)
|
||||
let editorInstance: editor.IStandaloneCodeEditor | null = null
|
||||
|
||||
// Function to detect and load languages from code fences
|
||||
const loadLanguagesFromContent = async (content: string) => {
|
||||
const codeBlockRegex = /```(\w+)/g
|
||||
const matches = [...content.matchAll(codeBlockRegex)]
|
||||
const languages = [...new Set(matches.map((match) => match[1]))]
|
||||
|
||||
await Promise.all(languages.map((lang) => loadLanguage(lang)))
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
if (!editorContainer.value) return
|
||||
|
||||
// Load initial languages from content
|
||||
await loadLanguagesFromContent(props.modelValue)
|
||||
// Create editor instance
|
||||
editorInstance = editor.create(editorContainer.value, {
|
||||
value: props.modelValue,
|
||||
language: 'markdown',
|
||||
theme: 'vs-dark',
|
||||
automaticLayout: true,
|
||||
minimap: { enabled: false },
|
||||
wordWrap: 'on',
|
||||
quickSuggestions: false,
|
||||
...props.options,
|
||||
})
|
||||
|
||||
// Handle content changes
|
||||
editorInstance.onDidChangeModelContent(() => {
|
||||
const value = editorInstance?.getValue() ?? ''
|
||||
emit('update:modelValue', value)
|
||||
loadLanguagesFromContent(value) // Load languages when content changes
|
||||
})
|
||||
})
|
||||
|
||||
// Watch for external value changes
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newValue) => {
|
||||
if (editorInstance && newValue !== editorInstance.getValue()) {
|
||||
await loadLanguagesFromContent(newValue)
|
||||
editorInstance.setValue(newValue)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// Cleanup
|
||||
onBeforeUnmount(() => {
|
||||
if (editorInstance) {
|
||||
editorInstance.dispose()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div ref="editorContainer" class="w-full h-full min-h-[300px]"></div>
|
||||
</template>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '../views/HomeView.vue'
|
||||
import NotFoundView from '../views/NotFoundView.vue'
|
||||
import { createRouter, createWebHistory } from 'vue-router';
|
||||
import HomeView from '../views/HomeView.vue';
|
||||
import NotFoundView from '../views/NotFoundView.vue';
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
@@ -19,11 +19,11 @@ const router = createRouter({
|
||||
component: () => import('../views/AboutView.vue'),
|
||||
},
|
||||
{
|
||||
path: "/:catchAll(.*)",
|
||||
path: '/:catchAll(.*)',
|
||||
name: 'not-found',
|
||||
component: NotFoundView,
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
|
||||
export default router
|
||||
export default router;
|
||||
|
||||
@@ -3,5 +3,3 @@
|
||||
<h1>This is an about page</h1>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style></style>
|
||||
|
||||
12
ui/src/workers/monaco.workers.ts
Normal file
12
ui/src/workers/monaco.workers.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
|
||||
|
||||
self.MonacoEnvironment = {
|
||||
getWorker() {
|
||||
return new editorWorker();
|
||||
},
|
||||
};
|
||||
|
||||
export function setupMonaco() {
|
||||
// This function is intentionally empty - it just needs to be imported
|
||||
// to set up the workers
|
||||
}
|
||||
@@ -1,20 +1,16 @@
|
||||
import { fileURLToPath, URL } from 'node:url'
|
||||
import { fileURLToPath, URL } from 'node:url';
|
||||
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
||||
import tailwindcss from '@tailwindcss/vite'
|
||||
import { defineConfig } from 'vite';
|
||||
import vue from '@vitejs/plugin-vue';
|
||||
import vueDevTools from 'vite-plugin-vue-devtools';
|
||||
import tailwindcss from '@tailwindcss/vite';
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [
|
||||
vue(),
|
||||
vueDevTools(),
|
||||
tailwindcss(),
|
||||
],
|
||||
plugins: [vue(), vueDevTools(), tailwindcss()],
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url))
|
||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user