| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| import { defineComponent, onMounted, ref, PropType } from 'vue' |
| import * as monaco from 'monaco-editor' |
| import { useFormItem } from 'naive-ui/es/_mixins' |
| import { call } from 'naive-ui/es/_utils' |
| import * as rpc from 'vscode-ws-jsonrpc' |
| import { |
| MonacoLanguageClient, |
| CloseAction, |
| ErrorAction, |
| MessageTransports |
| } from 'monaco-languageclient' |
| import normalizeUrl from 'normalize-url' |
| import type { |
| MaybeArray, |
| OnUpdateValue, |
| OnUpdateValueImpl, |
| monaco as Monaco |
| } from './types' |
| |
| const props = { |
| value: { |
| type: String as PropType<string>, |
| default: '' |
| }, |
| defaultValue: { |
| type: String as PropType<string> |
| }, |
| 'onUpdate:value': [Function, Array] as PropType<MaybeArray<OnUpdateValue>>, |
| onUpdateValue: [Function, Array] as PropType<MaybeArray<OnUpdateValue>>, |
| options: { |
| type: Object as PropType<Monaco.editor.IStandaloneEditorConstructionOptions>, |
| default: () => ({ |
| readOnly: false, |
| language: 'shell' |
| }) |
| }, |
| height: { |
| type: String |
| } |
| } |
| |
| export const MonacoEditor = defineComponent({ |
| name: 'monaco-editor', |
| props, |
| emits: ['change', 'focus', 'blur'], |
| setup(props, ctx) { |
| const editorRef = ref() |
| let editor = null as monaco.editor.IStandaloneCodeEditor | null |
| const formItem = useFormItem({}) |
| |
| const url = createUrl('localhost', 3001, `/${props.options.language}`) |
| const webSocket = new WebSocket(url) |
| |
| webSocket.onopen = () => { |
| const socket = rpc.toSocket(webSocket) |
| const reader = new rpc.WebSocketMessageReader(socket) |
| const writer = new rpc.WebSocketMessageWriter(socket) |
| const languageClient = createLanguageClient({ |
| reader, |
| writer |
| }) |
| languageClient.start() |
| reader.onClose(() => languageClient.stop()) |
| } |
| |
| function createLanguageClient( |
| transports: MessageTransports |
| ): MonacoLanguageClient { |
| return new MonacoLanguageClient({ |
| name: 'Studio Language Client', |
| clientOptions: { |
| // use a language id as a document selector |
| documentSelector: ['python', 'sql', 'shell'], |
| // disable the default error handler |
| errorHandler: { |
| error: () => ({ action: ErrorAction.Continue }), |
| closed: () => ({ action: CloseAction.DoNotRestart }) |
| } |
| }, |
| // create a language client connection from the JSON RPC connection on demand |
| connectionProvider: { |
| get: () => { |
| return Promise.resolve(transports) |
| } |
| } |
| }) |
| } |
| |
| function createUrl(hostname: string, port: number, path: string): string { |
| const protocol = location.protocol === 'https:' ? 'wss' : 'ws' |
| return normalizeUrl(`${protocol}://${hostname}:${port}${path}`) |
| } |
| |
| const initMonacoEditor = () => { |
| const dom = editorRef.value |
| if (dom) { |
| editor = monaco.editor.create(dom, { |
| ...props.options, |
| value: props.defaultValue ?? props.value, |
| automaticLayout: true, |
| theme: 'vs' |
| }) |
| editor.onDidChangeModelContent(() => { |
| const { onUpdateValue, 'onUpdate:value': _onUpdateValue } = props |
| const value = editor?.getValue() || '' |
| |
| if (onUpdateValue) call(onUpdateValue as OnUpdateValueImpl, value) |
| if (_onUpdateValue) call(_onUpdateValue as OnUpdateValueImpl, value) |
| ctx.emit('change', value) |
| |
| formItem.nTriggerFormChange() |
| formItem.nTriggerFormInput() |
| }) |
| editor.onDidBlurEditorWidget(() => { |
| ctx.emit('blur') |
| formItem.nTriggerFormBlur() |
| }) |
| editor.onDidFocusEditorWidget(() => { |
| ctx.emit('focus') |
| formItem.nTriggerFormFocus() |
| }) |
| } |
| } |
| |
| onMounted(() => initMonacoEditor()) |
| return () => ( |
| <div |
| ref={editorRef} |
| style={{ |
| height: props.height, |
| width: '100%', |
| border: '1px solid #eee' |
| }} |
| /> |
| ) |
| } |
| }) |