diff --git a/src-web/components/GrpcEditor.tsx b/src-web/components/GrpcEditor.tsx index f3378487..b404d5f8 100644 --- a/src-web/components/GrpcEditor.tsx +++ b/src-web/components/GrpcEditor.tsx @@ -1,7 +1,15 @@ +import { jsonLanguage } from '@codemirror/lang-json'; +import { linter } from '@codemirror/lint'; import classNames from 'classnames'; import type { EditorView } from 'codemirror'; -import { updateSchema } from 'codemirror-json-schema'; -import { useEffect, useRef } from 'react'; +import { + handleRefresh, + jsonCompletion, + jsonSchemaLinter, + stateExtensions, + updateSchema, +} from 'codemirror-json-schema'; +import { useEffect, useMemo, useRef } from 'react'; import { useAlert } from '../hooks/useAlert'; import type { ReflectResponseService } from '../hooks/useGrpc'; import { tryFormatJson } from '../lib/formatters'; @@ -101,13 +109,82 @@ export function GrpcEditor({ } }, [alert, services, request.method, request.service]); + const extraExtensions = useMemo( + () => [ + linter(jsonSchemaLinter(), { + delay: 200, + needsRefresh: handleRefresh, + }), + jsonLanguage.data.of({ + autocomplete: jsonCompletion(), + }), + stateExtensions(/** Init with empty schema **/), + ], + [], + ); + const reflectionUnavailable = reflectionError?.match(/unimplemented/i); reflectionError = reflectionUnavailable ? undefined : reflectionError; + const actions = useMemo( + () => [ +
+ +
, + ], + [ + dialog, + protoFiles.length, + reflectionError, + reflectionLoading, + reflectionUnavailable, + request.id, + services, + ], + ); + return (
- -
, - ]} + extraExtensions={extraExtensions} + actions={actions} {...extraEditorProps} /> diff --git a/src-web/components/core/Editor/Editor.tsx b/src-web/components/core/Editor/Editor.tsx index 7b4c140f..5b6a8f23 100644 --- a/src-web/components/core/Editor/Editor.tsx +++ b/src-web/components/core/Editor/Editor.tsx @@ -1,5 +1,5 @@ import { defaultKeymap } from '@codemirror/commands'; -import { Compartment, EditorState } from '@codemirror/state'; +import { Compartment, EditorState, type Extension } from '@codemirror/state'; import { keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view'; import classNames from 'classnames'; import { EditorView } from 'codemirror'; @@ -53,6 +53,7 @@ export interface EditorProps { format?: (v: string) => string; autocomplete?: GenericCompletionConfig; autocompleteVariables?: boolean; + extraExtensions?: Extension[]; actions?: ReactNode; } @@ -76,6 +77,7 @@ const _Editor = forwardRef(function Editor( singleLine, format, autocomplete, + extraExtensions, autocompleteVariables, actions, wrapLines, @@ -188,6 +190,7 @@ const _Editor = forwardRef(function Editor( onBlur: handleBlur, onKeyDown: handleKeyDown, }), + ...(extraExtensions ?? []), ], }); diff --git a/src-web/components/core/Editor/extensions.ts b/src-web/components/core/Editor/extensions.ts index c2bc72cd..028a4fc8 100644 --- a/src-web/components/core/Editor/extensions.ts +++ b/src-web/components/core/Editor/extensions.ts @@ -17,6 +17,7 @@ import { syntaxHighlighting, } from '@codemirror/language'; import { lintKeymap } from '@codemirror/lint'; + import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; import { EditorState } from '@codemirror/state'; import { @@ -85,7 +86,6 @@ const myTheme = EditorView.theme({}, { dark: true }); // ]); const syntaxExtensions: Record = { - 'application/grpc': json(), // TODO: Make JSONSchema work 'application/graphql': graphqlLanguageSupport(), 'application/json': json(), 'application/javascript': javascript(),