diff --git a/src-web/components/GraphQLEditor.tsx b/src-web/components/GraphQLEditor.tsx index 977a8787..6c0a725b 100644 --- a/src-web/components/GraphQLEditor.tsx +++ b/src-web/components/GraphQLEditor.tsx @@ -128,7 +128,7 @@ export function GraphQLEditor({ defaultValue, onChange, baseRequest, ...extraEdi return (
@@ -367,7 +368,7 @@ export const RequestPane = memo(function RequestPane({ placeholder="..." heightMode={fullHeight ? 'full' : 'auto'} defaultValue={`${activeRequest.body?.text ?? ''}`} - contentType="text/xml" + language="xml" onChange={handleBodyTextChange} /> ) : activeRequest.bodyType === BODY_TYPE_GRAPHQL ? ( @@ -402,6 +403,7 @@ export const RequestPane = memo(function RequestPane({ forceUpdateKey={forceUpdateKey} useTemplating autocompleteVariables + language={languageFromContentType(contentType)} placeholder="..." heightMode={fullHeight ? 'full' : 'auto'} defaultValue={`${activeRequest.body?.text ?? ''}`} diff --git a/src-web/components/Settings/SettingsAppearance.tsx b/src-web/components/Settings/SettingsAppearance.tsx index b7cdd5b7..132acf84 100644 --- a/src-web/components/Settings/SettingsAppearance.tsx +++ b/src-web/components/Settings/SettingsAppearance.tsx @@ -198,7 +198,7 @@ export function SettingsAppearance() { '};', ].join('\n')} heightMode="auto" - contentType="application/javascript" + language="javascript" /> diff --git a/src-web/components/Settings/SettingsDesign.tsx b/src-web/components/Settings/SettingsDesign.tsx index 1725fa7c..a959e686 100644 --- a/src-web/components/Settings/SettingsDesign.tsx +++ b/src-web/components/Settings/SettingsDesign.tsx @@ -117,7 +117,7 @@ export function SettingsDesign() { '};', ].join('\n')} heightMode="auto" - contentType="application/javascript" + language="javascript" />
diff --git a/src-web/components/UrlBar.tsx b/src-web/components/UrlBar.tsx index 8fbe8171..8ddb9739 100644 --- a/src-web/components/UrlBar.tsx +++ b/src-web/components/UrlBar.tsx @@ -67,7 +67,7 @@ export const UrlBar = memo(function UrlBar({ wrapLines={isFocused} hideLabel useTemplating - contentType="url" + language="url" className="pl-0 pr-1.5 py-0.5" name="url" label="Enter URL" diff --git a/src-web/components/core/BulkPairEditor.tsx b/src-web/components/core/BulkPairEditor.tsx index 7cf25073..738b0bf8 100644 --- a/src-web/components/core/BulkPairEditor.tsx +++ b/src-web/components/core/BulkPairEditor.tsx @@ -36,7 +36,7 @@ export function BulkPairEditor({ forceUpdateKey={forceUpdateKey} placeholder={`${namePlaceholder ?? 'name'}: ${valuePlaceholder ?? 'value'}`} defaultValue={pairsText} - contentType="pairs" + language="pairs" onChange={handleChange} /> ); diff --git a/src-web/components/core/Editor/Editor.tsx b/src-web/components/core/Editor/Editor.tsx index 682891a9..4c14729e 100644 --- a/src-web/components/core/Editor/Editor.tsx +++ b/src-web/components/core/Editor/Editor.tsx @@ -42,7 +42,7 @@ export interface EditorProps { type?: 'text' | 'password'; className?: string; heightMode?: 'auto' | 'full'; - contentType?: string | null; + language?: 'javascript' | 'json' | 'html' | 'xml' | 'graphql' | 'url' | 'pairs' | 'text'; forceUpdateKey?: string | number; autoFocus?: boolean; autoSelect?: boolean; @@ -71,7 +71,7 @@ export const Editor = forwardRef(function E readOnly, type = 'text', heightMode, - contentType, + language = 'text', autoFocus, autoSelect, placeholder, @@ -226,12 +226,12 @@ export const Editor = forwardRef(function E [dialog], ); - // Update language extension when contentType changes + // Update the language extension when the language changes useEffect(() => { if (cm.current === null) return; const { view, languageCompartment } = cm.current; const ext = getLanguageExtension({ - contentType, + language, environmentVariables, useTemplating, autocomplete, @@ -242,7 +242,7 @@ export const Editor = forwardRef(function E }); view.dispatch({ effects: languageCompartment.reconfigure(ext) }); }, [ - contentType, + language, autocomplete, useTemplating, environmentVariables, @@ -265,7 +265,7 @@ export const Editor = forwardRef(function E try { const languageCompartment = new Compartment(); const langExt = getLanguageExtension({ - contentType, + language, useTemplating, autocomplete, environmentVariables, diff --git a/src-web/components/core/Editor/extensions.ts b/src-web/components/core/Editor/extensions.ts index d15e15c6..6f215c02 100644 --- a/src-web/components/core/Editor/extensions.ts +++ b/src-web/components/core/Editor/extensions.ts @@ -32,7 +32,7 @@ import { } from '@codemirror/view'; import { tags as t } from '@lezer/highlight'; import type { EnvironmentVariable, TemplateFunction } from '@yaakapp/api'; -import { graphql, graphqlLanguageSupport } from 'cm6-graphql'; +import { graphql } from 'cm6-graphql'; import { EditorView } from 'codemirror'; import type { EditorProps } from './index'; import { pairs } from './pairs/extension'; @@ -64,19 +64,19 @@ export const syntaxHighlightStyle = HighlightStyle.define([ const syntaxTheme = EditorView.theme({}, { dark: true }); -const syntaxExtensions: Record = { - 'application/graphql': graphqlLanguageSupport(), - 'application/json': json(), - 'application/javascript': javascript(), - 'text/html': xml(), // HTML as XML because HTML is oddly slow - 'application/xml': xml(), - 'text/xml': xml(), +const syntaxExtensions: Record, LanguageSupport | null> = { + graphql: null, + json: json(), + javascript: javascript(), + html: xml(), // HTML as XML because HTML is oddly slow + xml: xml(), url: url(), pairs: pairs(), + text: text(), }; export function getLanguageExtension({ - contentType, + language, useTemplating = false, environmentVariables, autocomplete, @@ -90,12 +90,12 @@ export function getLanguageExtension({ onClickFunction: (option: TemplateFunction, tagValue: string, startPos: number) => void; onClickVariable: (option: EnvironmentVariable, tagValue: string, startPos: number) => void; onClickMissingVariable: (name: string, tagValue: string, startPos: number) => void; -} & Pick) { - const justContentType = contentType?.split(';')[0] ?? contentType ?? ''; - if (justContentType === 'application/graphql') { +} & Pick) { + if (language === 'graphql') { return graphql(); } - const base = syntaxExtensions[justContentType] ?? text(); + + const base = syntaxExtensions[language ?? 'text'] ?? text(); if (!useTemplating) { return base; } diff --git a/src-web/components/core/Input.tsx b/src-web/components/core/Input.tsx index b78a9938..62034ce7 100644 --- a/src-web/components/core/Input.tsx +++ b/src-web/components/core/Input.tsx @@ -14,7 +14,7 @@ export type InputProps = Omit< > & Pick< EditorProps, - | 'contentType' + | 'language' | 'useTemplating' | 'autocomplete' | 'forceUpdateKey' diff --git a/src-web/components/responseViewers/TextViewer.tsx b/src-web/components/responseViewers/TextViewer.tsx index 8fff7cc6..76b5ca7e 100644 --- a/src-web/components/responseViewers/TextViewer.tsx +++ b/src-web/components/responseViewers/TextViewer.tsx @@ -1,3 +1,4 @@ +import type { HttpResponse } from '@yaakapp/api'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import { useCallback, useMemo } from 'react'; @@ -8,8 +9,8 @@ import { useFilterResponse } from '../../hooks/useFilterResponse'; import { useResponseBodyText } from '../../hooks/useResponseBodyText'; import { useSaveResponse } from '../../hooks/useSaveResponse'; import { useToggle } from '../../hooks/useToggle'; +import { languageFromContentType } from '../../lib/contentType'; import { tryFormatJson, tryFormatXml } from '../../lib/formatters'; -import type { HttpResponse } from '@yaakapp/api'; import { CopyButton } from '../CopyButton'; import { Banner } from '../core/Banner'; import { Button } from '../core/Button'; @@ -63,6 +64,8 @@ export function TextViewer({ response, pretty, className }: Props) { } }, [isSearching, setFilterText]); + console.log('HELLO', contentType); + const isJson = contentType?.includes('json'); const isXml = contentType?.includes('xml') || contentType?.includes('html'); const canFilter = isJson || isXml; @@ -176,7 +179,7 @@ export function TextViewer({ response, pretty, className }: Props) { className={className} forceUpdateKey={body} defaultValue={body} - contentType={contentType} + language={languageFromContentType(contentType)} actions={actions} extraExtensions={extraExtensions} /> diff --git a/src-web/hooks/useContentTypeFromHeaders.ts b/src-web/hooks/useContentTypeFromHeaders.ts index e847f4d4..ac64198e 100644 --- a/src-web/hooks/useContentTypeFromHeaders.ts +++ b/src-web/hooks/useContentTypeFromHeaders.ts @@ -1,5 +1,5 @@ -import { useMemo } from 'react'; import type { HttpResponseHeader } from '@yaakapp/api'; +import { useMemo } from 'react'; export function useContentTypeFromHeaders(headers: HttpResponseHeader[] | null): string | null { return useMemo( diff --git a/src-web/lib/contentType.ts b/src-web/lib/contentType.ts new file mode 100644 index 00000000..7d85103c --- /dev/null +++ b/src-web/lib/contentType.ts @@ -0,0 +1,16 @@ +import type { EditorProps } from '../components/core/Editor'; + +export function languageFromContentType(contentType: string | null): EditorProps['language'] { + const justContentType = contentType?.split(';')[0] ?? contentType ?? ''; + if (justContentType.includes('json')) { + return 'json'; + } else if (justContentType.includes('xml')) { + return 'xml'; + } else if (justContentType.includes('html')) { + return 'html'; + } else if (justContentType.includes('javascript')) { + return 'javascript'; + } else { + return 'text'; + } +}