feat: introduce graphql mode for codemirror
This commit is contained in:
@@ -300,6 +300,7 @@ import { getCurrentStrategyID } from "~/helpers/network"
|
|||||||
import { makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
import { makeGQLRequest } from "~/helpers/types/HoppGQLRequest"
|
||||||
import { useCodemirror } from "~/helpers/editor/codemirror"
|
import { useCodemirror } from "~/helpers/editor/codemirror"
|
||||||
import "codemirror/mode/javascript/javascript"
|
import "codemirror/mode/javascript/javascript"
|
||||||
|
import "~/helpers/editor/modes/graphql"
|
||||||
import jsonLinter from "~/helpers/editor/linting/json"
|
import jsonLinter from "~/helpers/editor/linting/json"
|
||||||
import { createGQLQueryLinter } from "~/helpers/editor/linting/gqlQuery"
|
import { createGQLQueryLinter } from "~/helpers/editor/linting/gqlQuery"
|
||||||
import queryCompleter from "~/helpers/editor/completion/gqlQuery"
|
import queryCompleter from "~/helpers/editor/completion/gqlQuery"
|
||||||
@@ -365,7 +366,7 @@ const schemaString = useReadonlyStream(props.conn.schema$, null)
|
|||||||
|
|
||||||
useCodemirror(queryEditor, gqlQueryString, {
|
useCodemirror(queryEditor, gqlQueryString, {
|
||||||
extendedEditorConfig: {
|
extendedEditorConfig: {
|
||||||
mode: "application/ld+json",
|
mode: "graphql",
|
||||||
},
|
},
|
||||||
linter: createGQLQueryLinter(schemaString),
|
linter: createGQLQueryLinter(schemaString),
|
||||||
completer: queryCompleter(schemaString),
|
completer: queryCompleter(schemaString),
|
||||||
|
|||||||
80
helpers/editor/modes/graphql.ts
Normal file
80
helpers/editor/modes/graphql.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2021 GraphQL Contributors
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import CodeMirror from "codemirror"
|
||||||
|
import {
|
||||||
|
LexRules,
|
||||||
|
ParseRules,
|
||||||
|
isIgnored,
|
||||||
|
onlineParser,
|
||||||
|
State,
|
||||||
|
} from "graphql-language-service-parser"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The GraphQL mode is defined as a tokenizer along with a list of rules, each
|
||||||
|
* of which is either a function or an array.
|
||||||
|
*
|
||||||
|
* * Function: Provided a token and the stream, returns an expected next step.
|
||||||
|
* * Array: A list of steps to take in order.
|
||||||
|
*
|
||||||
|
* A step is either another rule, or a terminal description of a token. If it
|
||||||
|
* is a rule, that rule is pushed onto the stack and the parsing continues from
|
||||||
|
* that point.
|
||||||
|
*
|
||||||
|
* If it is a terminal description, the token is checked against it using a
|
||||||
|
* `match` function. If the match is successful, the token is colored and the
|
||||||
|
* rule is stepped forward. If the match is unsuccessful, the remainder of the
|
||||||
|
* rule is skipped and the previous rule is advanced.
|
||||||
|
*
|
||||||
|
* This parsing algorithm allows for incremental online parsing within various
|
||||||
|
* levels of the syntax tree and results in a structured `state` linked-list
|
||||||
|
* which contains the relevant information to produce valuable typeaheads.
|
||||||
|
*/
|
||||||
|
CodeMirror.defineMode("graphql", (config) => {
|
||||||
|
const parser = onlineParser({
|
||||||
|
eatWhitespace: (stream) => stream.eatWhile(isIgnored),
|
||||||
|
lexRules: LexRules,
|
||||||
|
parseRules: ParseRules,
|
||||||
|
editorConfig: { tabSize: 2 },
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
config,
|
||||||
|
startState: parser.startState,
|
||||||
|
token: parser.token as unknown as CodeMirror.Mode<any>["token"], // TODO: Check if the types are indeed compatible
|
||||||
|
indent,
|
||||||
|
electricInput: /^\s*[})\]]/,
|
||||||
|
fold: "brace",
|
||||||
|
lineComment: "#",
|
||||||
|
closeBrackets: {
|
||||||
|
pairs: '()[]{}""',
|
||||||
|
explode: "()[]{}",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Seems the electricInput type in @types/codemirror is wrong (i.e it is written as electricinput instead of electricInput)
|
||||||
|
function indent(
|
||||||
|
this: CodeMirror.Mode<any> & {
|
||||||
|
electricInput?: RegExp
|
||||||
|
config?: CodeMirror.EditorConfiguration
|
||||||
|
},
|
||||||
|
state: State,
|
||||||
|
textAfter: string
|
||||||
|
) {
|
||||||
|
const levels = state.levels
|
||||||
|
// If there is no stack of levels, use the current level.
|
||||||
|
// Otherwise, use the top level, pre-emptively dedenting for close braces.
|
||||||
|
const level =
|
||||||
|
!levels || levels.length === 0
|
||||||
|
? state.indentLevel
|
||||||
|
: levels[levels.length - 1] -
|
||||||
|
(this.electricInput?.test(textAfter) ? 1 : 0)
|
||||||
|
return (level || 0) * (this.config?.indentUnit || 0)
|
||||||
|
}
|
||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -5,6 +5,7 @@
|
|||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
|
"name": "hoppscotch",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/client": "^3.4.10",
|
"@apollo/client": "^3.4.10",
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
"fuse.js": "^6.4.6",
|
"fuse.js": "^6.4.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-language-service-interface": "^2.8.4",
|
"graphql-language-service-interface": "^2.8.4",
|
||||||
|
"graphql-language-service-parser": "^1.9.2",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
"fuse.js": "^6.4.6",
|
"fuse.js": "^6.4.6",
|
||||||
"graphql": "^15.5.0",
|
"graphql": "^15.5.0",
|
||||||
"graphql-language-service-interface": "^2.8.4",
|
"graphql-language-service-interface": "^2.8.4",
|
||||||
|
"graphql-language-service-parser": "^1.9.2",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
|
|||||||
Reference in New Issue
Block a user