11<script setup lang="ts">
2- import { EditorView , basicSetup } from ' codemirror'
3- import { Compartment , EditorState } from ' @codemirror/state'
4- import { json } from ' @codemirror/lang-json'
2+ import type * as Monaco from ' modern-monaco/editor-core'
53import { parse , iterator } from ' @humanwhocodes/momoa'
64import type { MemberNode , ObjectNode , StringNode } from ' @humanwhocodes/momoa'
7- import { vitesseLight , vitesseDark } from ' codemirror-theme-vitesse'
85import { useAsyncState } from ' @vueuse/core'
6+ import { applyMonacoTheme , createReadOnlyMonacoEditor , getMonaco } from ' ~/composables/monaco'
97
108const rpc = useRpc ()
119
@@ -57,8 +55,10 @@ const isDark = computed(
5755const editorRef = ref <HTMLDivElement | null >(null )
5856const currentDocUrl = ref (DEFAULT_DOC_URL )
5957const iframeLoading = ref (true )
60- const themeCompartment = new Compartment ()
61- let view: InstanceType <typeof EditorView > | null = null
58+ let monaco: typeof Monaco | null = null
59+ let editor: Monaco .editor .IStandaloneCodeEditor | null = null
60+ let model: Monaco .editor .ITextModel | null = null
61+ let cursorDisposable: Monaco .IDisposable | null = null
6262
6363interface SectionRange {
6464 from: number
@@ -129,9 +129,12 @@ function getDocUrlAtCursor(pos: number, _content: string): string {
129129 return DEFAULT_DOC_URL
130130}
131131
132- function updateDocUrlFromCursor(editorView : InstanceType <typeof EditorView >) {
133- const content = editorView .state .doc .toString ()
134- const pos = editorView .state .selection .main .head
132+ function updateDocUrlFromCursor() {
133+ if (! editor || ! model ) return
134+ const position = editor .getPosition ()
135+ if (! position ) return
136+ const content = model .getValue ()
137+ const pos = model .getOffsetAt (position )
135138 const url = getDocUrlAtCursor (pos , content )
136139 if (currentDocUrl .value !== url ) {
137140 currentDocUrl .value = url
@@ -141,47 +144,43 @@ function updateDocUrlFromCursor(editorView: InstanceType<typeof EditorView>) {
141144
142145const initialized = ref (false )
143146
144- function initEditor() {
147+ async function initEditor() {
145148 if (! editorRef .value || initialized .value || ! isReady .value ) return
146149
147150 const content = configData .value ?? ' {}'
148151 initConfigRanges (content )
149152
150- view = new EditorView ({
151- parent: editorRef .value ,
152- doc: content ,
153- extensions: [
154- basicSetup ,
155- json (),
156- EditorState .readOnly .of (true ),
157- EditorView .editable .of (false ),
158- themeCompartment .of (isDark .value ? vitesseDark : vitesseLight ),
159- EditorView .updateListener .of (update => {
160- if (update .selectionSet ) {
161- updateDocUrlFromCursor (update .view )
162- }
163- }),
164- EditorView .domEventHandlers ({
165- click : (_event , editorView ) => {
166- updateDocUrlFromCursor (editorView )
167- },
168- }),
169- ],
170- })
171-
172- updateDocUrlFromCursor (view )
153+ // Claim the slot synchronously so the reactive watcher can't kick off a
154+ // second init while `getMonaco` is awaited.
173155 initialized .value = true
156+
157+ monaco = await getMonaco (isDark .value )
158+
159+ if (! editorRef .value ) return
160+
161+ model = monaco .editor .createModel (content , ' json' )
162+ editor = createReadOnlyMonacoEditor (monaco , editorRef .value )
163+ editor .setModel (model )
164+
165+ applyMonacoTheme (monaco , isDark .value )
166+
167+ cursorDisposable = editor .onDidChangeCursorPosition (() => updateDocUrlFromCursor ())
168+
169+ updateDocUrlFromCursor ()
174170}
175171
176172watch ([editorRef , isReady ], () => initEditor (), { immediate: true })
177173
178174watch (isDark , dark => {
179- view ?. dispatch ({ effects: themeCompartment . reconfigure ( dark ? vitesseDark : vitesseLight ) } )
175+ if ( monaco ) applyMonacoTheme ( monaco , dark )
180176})
181177
182178onBeforeUnmount (() => {
183- view ?.destroy ()
184- view = null
179+ cursorDisposable ?.dispose ()
180+ editor ?.dispose ()
181+ model ?.dispose ()
182+ editor = null
183+ model = null
185184})
186185 </script >
187186
@@ -194,7 +193,7 @@ onBeforeUnmount(() => {
194193 <div
195194 class =" flex-1 min-h-0 min-w-0 border-b lg:border-b-0 lg:border-r border-neutral-200 dark:border-neutral-700"
196195 >
197- <div ref =" editorRef" class =" h-full min-h-[200px] lg:min-h-0 overflow-auto " />
196+ <div ref =" editorRef" class =" h-full min-h-[200px] lg:min-h-0" />
198197 </div >
199198 <div class =" flex-1 min-h-[200px] lg:min-h-0 min-w-0 relative" >
200199 <iframe
@@ -228,7 +227,9 @@ onBeforeUnmount(() => {
228227</template >
229228
230229<style >
231- .cm-editor {
232- height : 100% ;
230+ .monaco-editor ,
231+ .monaco-editor .overflow-guard {
232+ width : 100% !important ;
233+ height : 100% !important ;
233234}
234235 </style >
0 commit comments