Skip to content

Commit

Permalink
move copy, merge, and prettify logic to editor context in `@graphiql/…
Browse files Browse the repository at this point in the history
…react` (#2437)

* move copy query functionality to editor context

* move merge query functionality to editor context

* move prettify query functionality to editor context

* avoid inconsistent state by prettifying early

* prettify query last to throw late
  • Loading branch information
thomasheyenbrock committed May 27, 2022
1 parent 3e5295f commit 1f93350
Show file tree
Hide file tree
Showing 12 changed files with 163 additions and 144 deletions.
6 changes: 6 additions & 0 deletions .changeset/early-queens-stare.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': patch
'@graphiql/react': patch
---

Move preffity query functionality to editor context in `@graphiql/react`
6 changes: 6 additions & 0 deletions .changeset/metal-numbers-provide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': patch
'@graphiql/react': patch
---

Move copy query functionality to editor context in `@graphiql/react`
6 changes: 6 additions & 0 deletions .changeset/slimy-swans-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'graphiql': patch
'@graphiql/react': patch
---

Move merge query functionality to editor context in `@graphiql/react`
1 change: 1 addition & 0 deletions packages/graphiql-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"@graphiql/toolkit": "^0.6.0",
"codemirror": "^5.65.3",
"codemirror-graphql": "^1.3.0",
"copy-to-clipboard": "^3.2.0",
"escape-html": "^1.0.3",
"graphql-language-service": "^5.0.4",
"markdown-it": "^12.2.0"
Expand Down
24 changes: 24 additions & 0 deletions packages/graphiql-react/src/editor/context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from 'react';

import { useSchemaWithError } from '../schema';
import { useCopyQuery, useMergeQuery, usePrettifyEditors } from './hooks';
import { CodeMirrorEditor } from './types';

export type CodeMirrorEditorWithOperationFacts = CodeMirrorEditor & {
Expand All @@ -21,6 +22,9 @@ export type CodeMirrorEditorWithOperationFacts = CodeMirrorEditor & {

export type EditorContextType = {
autoCompleteLeafs(): string | undefined;
copy(): void;
merge(): void;
prettify(): void;
headerEditor: CodeMirrorEditor | null;
queryEditor: CodeMirrorEditorWithOperationFacts | null;
responseEditor: CodeMirrorEditor | null;
Expand All @@ -35,6 +39,9 @@ export const EditorContext = createContext<EditorContextType>({
autoCompleteLeafs() {
return undefined;
},
copy() {},
merge() {},
prettify() {},
headerEditor: null,
queryEditor: null,
responseEditor: null,
Expand All @@ -48,6 +55,7 @@ export const EditorContext = createContext<EditorContextType>({
type EditorContextProviderProps = {
children: ReactNode;
getDefaultFieldNames?: GetDefaultFieldNamesFn;
onCopyQuery?(query: string): void;
};

export function EditorContextProvider(props: EditorContextProviderProps) {
Expand Down Expand Up @@ -110,9 +118,22 @@ export function EditorContextProvider(props: EditorContextProviderProps) {
return result;
}, [props.getDefaultFieldNames, queryEditor, schema]);

const copy = useCopyQuery({ queryEditor, onCopyQuery: props.onCopyQuery });

const merge = useMergeQuery({ queryEditor, schema });

const prettify = usePrettifyEditors({
queryEditor,
variableEditor,
headerEditor,
});

const value = useMemo<EditorContextType>(
() => ({
autoCompleteLeafs,
copy,
merge,
prettify,
headerEditor,
queryEditor,
responseEditor,
Expand All @@ -124,6 +145,9 @@ export function EditorContextProvider(props: EditorContextProviderProps) {
}),
[
autoCompleteLeafs,
copy,
merge,
prettify,
headerEditor,
queryEditor,
responseEditor,
Expand Down
8 changes: 2 additions & 6 deletions packages/graphiql-react/src/editor/header-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
export type UseHeaderEditorArgs = {
editorTheme?: string;
onEdit?: EditCallback;
onPrettifyQuery?: EmptyCallback;
onMergeQuery?: EmptyCallback;
onRunQuery?: EmptyCallback;
readOnly?: boolean;
shouldPersistHeaders?: boolean;
Expand All @@ -27,8 +25,6 @@ export type UseHeaderEditorArgs = {
export function useHeaderEditor({
editorTheme = 'graphiql',
onEdit,
onMergeQuery,
onPrettifyQuery,
onRunQuery,
readOnly = false,
shouldPersistHeaders = false,
Expand Down Expand Up @@ -127,8 +123,8 @@ export function useHeaderEditor({
useCompletion(headerEditor);

useKeyMap(headerEditor, ['Cmd-Enter', 'Ctrl-Enter'], onRunQuery);
useKeyMap(headerEditor, ['Shift-Ctrl-P'], onPrettifyQuery);
useKeyMap(headerEditor, ['Shift-Ctrl-M'], onMergeQuery);
useKeyMap(headerEditor, ['Shift-Ctrl-P'], context.prettify);
useKeyMap(headerEditor, ['Shift-Ctrl-M'], context.merge);

useResizeEditor(headerEditor, ref);

Expand Down
100 changes: 97 additions & 3 deletions packages/graphiql-react/src/editor/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { mergeAst } from '@graphiql/toolkit';
import { EditorChange } from 'codemirror';
import { RefObject, useContext, useEffect, useRef } from 'react';
import copyToClipboard from 'copy-to-clipboard';
import { GraphQLSchema, parse, print } from 'graphql';
import { RefObject, useCallback, useContext, useEffect, useRef } from 'react';

import { ExplorerContext } from '../explorer';
import { useSchemaWithError } from '../schema';

import { StorageContext } from '../storage';
import debounce from '../utility/debounce';

import { onHasCompletion } from './completion';
import { CodeMirrorEditorWithOperationFacts } from './context';
import { CodeMirrorEditor } from './types';

export function useSynchronizeValue(
Expand Down Expand Up @@ -119,3 +122,94 @@ export function useResizeEditor(
sizeRef.current = size;
});
}

export function useCopyQuery({
queryEditor,
onCopyQuery,
}: {
queryEditor: CodeMirrorEditorWithOperationFacts | null;
onCopyQuery?(query: string): void;
}) {
return useCallback(() => {
if (!queryEditor) {
return;
}

const query = queryEditor.getValue();
copyToClipboard(query);

onCopyQuery?.(query);
}, [queryEditor, onCopyQuery]);
}

export function useMergeQuery({
queryEditor,
schema,
}: {
queryEditor?: CodeMirrorEditorWithOperationFacts | null;
schema: GraphQLSchema | null | undefined;
}) {
return useCallback(() => {
const documentAST = queryEditor?.documentAST;
const query = queryEditor?.getValue();
if (!documentAST || !query) {
return;
}

queryEditor.setValue(print(mergeAst(documentAST, schema)));
}, [queryEditor, schema]);
}

export function usePrettifyEditors({
queryEditor,
variableEditor,
headerEditor,
}: {
queryEditor: CodeMirrorEditorWithOperationFacts | null;
variableEditor: CodeMirrorEditor | null;
headerEditor: CodeMirrorEditor | null;
}) {
return useCallback(() => {
if (variableEditor) {
const variableEditorContent = variableEditor.getValue();
try {
const prettifiedVariableEditorContent = JSON.stringify(
JSON.parse(variableEditorContent),
null,
2,
);
if (prettifiedVariableEditorContent !== variableEditorContent) {
variableEditor.setValue(prettifiedVariableEditorContent);
}
} catch {
/* Parsing JSON failed, skip prettification */
}
}

if (headerEditor) {
const headerEditorContent = headerEditor.getValue();

try {
const prettifiedHeaderEditorContent = JSON.stringify(
JSON.parse(headerEditorContent),
null,
2,
);
if (prettifiedHeaderEditorContent !== headerEditorContent) {
headerEditor.setValue(prettifiedHeaderEditorContent);
}
} catch {
/* Parsing JSON failed, skip prettification */
}
}

if (queryEditor) {
const editorContent = queryEditor.getValue();
const prettifiedEditorContent = print(parse(editorContent));

if (prettifiedEditorContent !== editorContent) {
queryEditor.setValue(prettifiedEditorContent);
}
}
}, [queryEditor, variableEditor, headerEditor]);
}
12 changes: 3 additions & 9 deletions packages/graphiql-react/src/editor/query-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,8 @@ export type UseQueryEditorArgs = {
defaultValue?: string;
editorTheme?: string;
externalFragments?: string | FragmentDefinitionNode[];
onCopyQuery?: EmptyCallback;
onEdit?: EditCallback;
onEditOperationName?: EditCallback;
onPrettifyQuery?: EmptyCallback;
onMergeQuery?: EmptyCallback;
onRunQuery?: EmptyCallback;
readOnly?: boolean;
validationRules?: ValidationRule[];
Expand All @@ -47,11 +44,8 @@ export function useQueryEditor({
defaultValue = DEFAULT_VALUE,
editorTheme = 'graphiql',
externalFragments,
onCopyQuery,
onEdit,
onEditOperationName,
onMergeQuery,
onPrettifyQuery,
onRunQuery,
readOnly = false,
validationRules,
Expand Down Expand Up @@ -321,17 +315,17 @@ export function useQueryEditor({
useCompletion(queryEditor);

useKeyMap(queryEditor, ['Cmd-Enter', 'Ctrl-Enter'], onRunQuery);
useKeyMap(queryEditor, ['Shift-Ctrl-C'], onCopyQuery);
useKeyMap(queryEditor, ['Shift-Ctrl-C'], editorContext.copy);
useKeyMap(
queryEditor,
[
'Shift-Ctrl-P',
// Shift-Ctrl-P is hard coded in Firefox for private browsing so adding an alternative to Pretiffy
'Shift-Ctrl-F',
],
onPrettifyQuery,
editorContext.prettify,
);
useKeyMap(queryEditor, ['Shift-Ctrl-M'], onMergeQuery);
useKeyMap(queryEditor, ['Shift-Ctrl-M'], editorContext.merge);

useResizeEditor(queryEditor, ref);

Expand Down
8 changes: 2 additions & 6 deletions packages/graphiql-react/src/editor/variable-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ import { CodeMirrorType } from './types';
export type UseVariableEditorArgs = {
editorTheme?: string;
onEdit?: EditCallback;
onPrettifyQuery?: EmptyCallback;
onMergeQuery?: EmptyCallback;
onRunQuery?: EmptyCallback;
readOnly?: boolean;
value?: string;
Expand All @@ -27,8 +25,6 @@ export type UseVariableEditorArgs = {
export function useVariableEditor({
editorTheme = 'graphiql',
onEdit,
onMergeQuery,
onPrettifyQuery,
onRunQuery,
readOnly = false,
value,
Expand Down Expand Up @@ -137,8 +133,8 @@ export function useVariableEditor({
useCompletion(variableEditor);

useKeyMap(variableEditor, ['Cmd-Enter', 'Ctrl-Enter'], onRunQuery);
useKeyMap(variableEditor, ['Shift-Ctrl-P'], onPrettifyQuery);
useKeyMap(variableEditor, ['Shift-Ctrl-M'], onMergeQuery);
useKeyMap(variableEditor, ['Shift-Ctrl-P'], context.prettify);
useKeyMap(variableEditor, ['Shift-Ctrl-M'], context.merge);

useResizeEditor(variableEditor, ref);

Expand Down
1 change: 0 additions & 1 deletion packages/graphiql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
"dependencies": {
"@graphiql/react": "^0.2.0",
"@graphiql/toolkit": "^0.6.0",
"copy-to-clipboard": "^3.2.0",
"set-value": "^4.1.0",
"entities": "^2.0.0",
"graphql-language-service": "^5.0.4",
Expand Down
28 changes: 0 additions & 28 deletions packages/graphiql/resources/renderExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,34 +25,6 @@ search
}
});

// If variables was provided, try to format it.
if (parameters.variables) {
try {
parameters.variables = JSON.stringify(
JSON.parse(parameters.variables),
null,
2,
);
} catch (e) {
// Do nothing, we want to display the invalid JSON as a string, rather
// than present an error.
}
}

// If headers was provided, try to format it.
if (parameters.headers) {
try {
parameters.headers = JSON.stringify(
JSON.parse(parameters.headers),
null,
2,
);
} catch (e) {
// Do nothing, we want to display the invalid JSON as a string, rather
// than present an error.
}
}

// When the query and variables string is edited, update the URL bar so
// that it can be easily shared.
function onEditQuery(newQuery) {
Expand Down
Loading

0 comments on commit 1f93350

Please sign in to comment.