diff --git a/src-web/components/HttpRequestPane.tsx b/src-web/components/HttpRequestPane.tsx index a4dae84d..3506434c 100644 --- a/src-web/components/HttpRequestPane.tsx +++ b/src-web/components/HttpRequestPane.tsx @@ -4,7 +4,7 @@ import type { GenericCompletionOption } from '@yaakapp-internal/plugins'; import classNames from 'classnames'; import { atom, useAtomValue } from 'jotai'; import type { CSSProperties } from 'react'; -import React, { lazy, useCallback, useMemo, useState } from 'react'; +import React, { useCallback, useMemo, useState } from 'react'; import { activeRequestIdAtom } from '../hooks/useActiveRequestId'; import { useCancelHttpResponse } from '../hooks/useCancelHttpResponse'; import { useHttpAuthenticationSummaries } from '../hooks/useHttpAuthentication'; @@ -46,15 +46,10 @@ import { FormMultipartEditor } from './FormMultipartEditor'; import { FormUrlencodedEditor } from './FormUrlencodedEditor'; import { HeadersEditor } from './HeadersEditor'; import { HttpAuthenticationEditor } from './HttpAuthenticationEditor'; +import { MarkdownEditor } from './MarkdownEditor'; import { UrlBar } from './UrlBar'; import { UrlParametersEditor } from './UrlParameterEditor'; - -const GraphQLEditor = lazy(() => - import('./GraphQLEditor').then((m) => ({ default: m.GraphQLEditor })), -); -const MarkdownEditor = lazy(() => - import('./MarkdownEditor').then((m) => ({ default: m.MarkdownEditor })), -); +import { GraphQLEditor } from './GraphQLEditor'; interface Props { style: CSSProperties; diff --git a/src-web/components/HttpResponsePane.tsx b/src-web/components/HttpResponsePane.tsx index 65723b40..79ed88b0 100644 --- a/src-web/components/HttpResponsePane.tsx +++ b/src-web/components/HttpResponsePane.tsx @@ -1,7 +1,7 @@ import type { HttpResponse } from '@yaakapp-internal/models'; import classNames from 'classnames'; import type { CSSProperties, ReactNode } from 'react'; -import React, { lazy , useCallback, useMemo } from 'react'; +import React, { useCallback, useMemo } from 'react'; import { useLocalStorage } from 'react-use'; import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse'; import { useResponseViewMode } from '../hooks/useResponseViewMode'; @@ -27,10 +27,7 @@ import { CsvViewer } from './responseViewers/CsvViewer'; import { EventStreamViewer } from './responseViewers/EventStreamViewer'; import { HTMLOrTextViewer } from './responseViewers/HTMLOrTextViewer'; import { ImageViewer } from './responseViewers/ImageViewer'; - -const PdfViewer = lazy(() => - import('./responseViewers/PdfViewer').then((m) => ({ default: m.PdfViewer })), -); +import { PdfViewer } from './responseViewers/PdfViewer'; import { SvgViewer } from './responseViewers/SvgViewer'; import { VideoViewer } from './responseViewers/VideoViewer'; import { ErrorBoundary } from './ErrorBoundary'; diff --git a/src-web/components/RedirectToLatestWorkspace.tsx b/src-web/components/RedirectToLatestWorkspace.tsx index 958ae55d..acc87588 100644 --- a/src-web/components/RedirectToLatestWorkspace.tsx +++ b/src-web/components/RedirectToLatestWorkspace.tsx @@ -32,6 +32,7 @@ export function RedirectToLatestWorkspace() { request_id: requestId, }; + console.log("Redirecting to workspace", params, search); await router.navigate({ to: '/workspaces/$workspaceId', params, search }); })(); }, [recentWorkspaces, workspaces, workspaces.length]); diff --git a/src-web/components/core/Editor/Editor.tsx b/src-web/components/core/Editor/Editor.tsx index d4e93838..285a0f1c 100644 --- a/src-web/components/core/Editor/Editor.tsx +++ b/src-web/components/core/Editor/Editor.tsx @@ -4,6 +4,7 @@ import type { EditorStateConfig, Extension } from '@codemirror/state'; import { Compartment, EditorState } from '@codemirror/state'; import { EditorView, keymap, placeholder as placeholderExt, tooltips } from '@codemirror/view'; import { emacs } from '@replit/codemirror-emacs'; +import { vim } from '@replit/codemirror-vim'; import { vscodeKeymap } from '@replit/codemirror-vscode-keymap'; import type { EditorKeymap, EnvironmentVariable } from '@yaakapp-internal/models'; @@ -47,8 +48,6 @@ import { import type { GenericCompletionConfig } from './genericCompletion'; import { singleLineExtensions } from './singleLine'; -const { vim } = await import('@replit/codemirror-vim'); - // VSCode's Tab actions mess with the single-line editor tab actions, so remove it. const vsCodeWithoutTab = vscodeKeymap.filter((k) => k.key !== 'Tab'); @@ -366,7 +365,7 @@ export const Editor = forwardRef(function E useEffect(() => { if (cm.current === null) return; const { view, languageCompartment } = cm.current; - getLanguageExtension({ + const ext = getLanguageExtension({ useTemplating, language, environmentVariables, @@ -375,9 +374,8 @@ export const Editor = forwardRef(function E onClickVariable, onClickMissingVariable, onClickPathParameter, - }).then((ext) => { - view.dispatch({ effects: languageCompartment.reconfigure(ext) }); }); + view.dispatch({ effects: languageCompartment.reconfigure(ext) }); }, [ language, autocomplete, @@ -401,7 +399,7 @@ export const Editor = forwardRef(function E try { const languageCompartment = new Compartment(); - getLanguageExtension({ + const langExt = getLanguageExtension({ useTemplating, language, completionOptions, @@ -410,57 +408,56 @@ export const Editor = forwardRef(function E onClickVariable, onClickMissingVariable, onClickPathParameter, - }).then((langExt) => { - const extensions = [ - languageCompartment.of(langExt), - placeholderCompartment.current.of(placeholderExt(placeholderElFromText(placeholder))), - wrapLinesCompartment.current.of(wrapLines ? EditorView.lineWrapping : emptyExtension), - tabIndentCompartment.current.of( - !disableTabIndent ? keymap.of([indentWithTab]) : emptyExtension, - ), - keymapCompartment.current.of( - keymapExtensions[settings.editorKeymap] ?? keymapExtensions['default'], - ), - ...getExtensions({ - container, - readOnly, - singleLine, - hideGutter, - stateKey, - onChange: handleChange, - onPaste: handlePaste, - onPasteOverwrite: handlePasteOverwrite, - onFocus: handleFocus, - onBlur: handleBlur, - onKeyDown: handleKeyDown, - }), - ...(extraExtensions ?? []), - ]; - - const cachedJsonState = getCachedEditorState(defaultValue ?? '', stateKey); - - const doc = `${defaultValue ?? ''}`; - const config: EditorStateConfig = { extensions, doc }; - - const state = cachedJsonState - ? EditorState.fromJSON(cachedJsonState, config, stateFields) - : EditorState.create(config); - - const view = new EditorView({ state, parent: container }); - - // For large documents, the parser may parse the max number of lines and fail to add - // things like fold markers because of it. - // This forces it to parse more but keeps the timeout to the default of 100 ms. - forceParsing(view, 9e6, 100); - - cm.current = { view, languageCompartment }; - if (autoFocus) { - view.focus(); - } - if (autoSelect) { - view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } }); - } }); + const extensions = [ + languageCompartment.of(langExt), + placeholderCompartment.current.of(placeholderExt(placeholderElFromText(placeholder))), + wrapLinesCompartment.current.of(wrapLines ? EditorView.lineWrapping : emptyExtension), + tabIndentCompartment.current.of( + !disableTabIndent ? keymap.of([indentWithTab]) : emptyExtension, + ), + keymapCompartment.current.of( + keymapExtensions[settings.editorKeymap] ?? keymapExtensions['default'], + ), + ...getExtensions({ + container, + readOnly, + singleLine, + hideGutter, + stateKey, + onChange: handleChange, + onPaste: handlePaste, + onPasteOverwrite: handlePasteOverwrite, + onFocus: handleFocus, + onBlur: handleBlur, + onKeyDown: handleKeyDown, + }), + ...(extraExtensions ?? []), + ]; + + const cachedJsonState = getCachedEditorState(defaultValue ?? '', stateKey); + + const doc = `${defaultValue ?? ''}`; + const config: EditorStateConfig = { extensions, doc }; + + const state = cachedJsonState + ? EditorState.fromJSON(cachedJsonState, config, stateFields) + : EditorState.create(config); + + const view = new EditorView({ state, parent: container }); + + // For large documents, the parser may parse the max number of lines and fail to add + // things like fold markers because of it. + // This forces it to parse more but keeps the timeout to the default of 100 ms. + forceParsing(view, 9e6, 100); + + cm.current = { view, languageCompartment }; + if (autoFocus) { + view.focus(); + } + if (autoSelect) { + view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } }); + } } catch (e) { console.log('Failed to initialize Codemirror', e); } diff --git a/src-web/components/core/Editor/extensions.ts b/src-web/components/core/Editor/extensions.ts index 05759545..02ff07c6 100644 --- a/src-web/components/core/Editor/extensions.ts +++ b/src-web/components/core/Editor/extensions.ts @@ -5,6 +5,8 @@ import { completionKeymap, } from '@codemirror/autocomplete'; import { history, historyKeymap } from '@codemirror/commands'; +import { javascript } from '@codemirror/lang-javascript'; +import { markdown } from '@codemirror/lang-markdown'; import type { LanguageSupport } from '@codemirror/language'; import { codeFolding, @@ -37,7 +39,12 @@ import { pluralizeCount } from '../../../lib/pluralize'; import type { EditorProps } from './Editor'; import { text } from './text/extension'; import type { TwigCompletionOption } from './twig/completion'; +import { twig } from './twig/extension'; import { pathParametersPlugin } from './twig/pathParameters'; +import { json } from '@codemirror/lang-json'; +import { xml } from '@codemirror/lang-xml'; +import { pairs } from './pairs/extension'; +import { url } from './url/extension'; export const syntaxHighlightStyle = HighlightStyle.define([ { @@ -70,23 +77,23 @@ const closeBracketsExtensions: Extension = [closeBrackets(), keymap.of([...close const syntaxExtensions: Record< NonNullable, - null | (() => Promise) + null | (() => LanguageSupport) > = { graphql: null, - json: () => import('@codemirror/lang-json').then((m) => m.json()), - javascript: () => import('@codemirror/lang-javascript').then((m) => m.javascript()), + json: json, + javascript: javascript, // HTML as XML because HTML is oddly slow - html: () => import('@codemirror/lang-xml').then((m) => m.xml()), - xml: () => import('@codemirror/lang-xml').then((m) => m.xml()), - url: () => import('./url/extension').then((m) => m.url()), - pairs: () => import('./pairs/extension').then((m) => m.pairs()), - text: () => import('./text/extension').then((m) => m.text()), - markdown: () => import('@codemirror/lang-markdown').then((m) => m.markdown()), + html: xml, + xml: xml, + url: url, + pairs: pairs, + text: text, + markdown: markdown, }; const closeBracketsFor: (keyof typeof syntaxExtensions)[] = ['json', 'javascript', 'graphql']; -export async function getLanguageExtension({ +export function getLanguageExtension({ useTemplating, language = 'text', environmentVariables, @@ -120,13 +127,12 @@ export async function getLanguageExtension({ } const base_ = syntaxExtensions[language ?? 'text'] ?? text(); - const base = typeof base_ === 'function' ? await base_() : text(); + const base = typeof base_ === 'function' ? base_() : text(); if (!useTemplating) { return [base, extraExtensions]; } - const { twig } = await import('./twig/extension'); return twig({ base, environmentVariables,