From db2429d1cb3d603e33d6b8764be6e46ac3d0f577 Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Sat, 2 May 2020 15:06:22 -0400 Subject: [PATCH] Added syntax highlighting to GQL Queries --- components/graphql/queryeditor.vue | 13 ++- functions/syntax/gqlQueryLangMode.js | 115 +++++++++++++++++++++++++++ 2 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 functions/syntax/gqlQueryLangMode.js diff --git a/components/graphql/queryeditor.vue b/components/graphql/queryeditor.vue index 8503c1804..72848bd3c 100644 --- a/components/graphql/queryeditor.vue +++ b/components/graphql/queryeditor.vue @@ -22,10 +22,13 @@ const DEFAULT_THEME = "twilight" import ace from "ace-builds" -import * as gql from "graphql" -import { getAutocompleteSuggestions } from "graphql-language-service-interface" import "ace-builds/webpack-resolver" import "ace-builds/src-noconflict/ext-language_tools" +import "ace-builds/src-noconflict/mode-graphqlschema" +import { defineGQLLanguageMode } from "~/functions/syntax/gqlQueryLangMode" + +import * as gql from "graphql" +import { getAutocompleteSuggestions } from "graphql-language-service-interface" import debounce from "../../functions/utils/debounce" export default { @@ -40,7 +43,7 @@ export default { }, lang: { type: String, - default: "json", + default: "gql-query", }, onRunGQLQuery: { type: Function, @@ -85,6 +88,8 @@ export default { }, mounted() { + defineGQLLanguageMode(ace) + let langTools = ace.require("ace/ext/language_tools") const editor = ace.edit(this.$refs.editor, { @@ -190,7 +195,7 @@ export default { this.parseContents(this.cacheValue) }, - parseContents: debounce(function(content) { + parseContents: debounce(function (content) { if (content !== "") { try { const doc = gql.parse(content) diff --git a/functions/syntax/gqlQueryLangMode.js b/functions/syntax/gqlQueryLangMode.js new file mode 100644 index 000000000..2adb43300 --- /dev/null +++ b/functions/syntax/gqlQueryLangMode.js @@ -0,0 +1,115 @@ +export function defineGQLLanguageMode(ace) { + // Highlighting + ace.define( + "ace/mode/gql-query-highlight", + ["require", "exports", "ace/lib/oop", "ace/mode/text_highlight_rules"], + (aceRequire, exports) => { + const oop = aceRequire("ace/lib/oop") + + const TextHighlightRules = aceRequire("ace/mode/text_highlight_rules").TextHighlightRules + + const GQLQueryTextHighlightRules = function () { + var keywords = + "type|interface|union|enum|schema|input|implements|extends|scalar|fragment|query|mutation|subscription" + + var dataTypes = "Int|Float|String|ID|Boolean" + + var literalValues = "true|false|null" + + var escapeRe = /\\(?:u[\da-fA-f]{4}|.)/ + + var keywordMapper = this.createKeywordMapper( + { + keyword: keywords, + "storage.type": dataTypes, + "constant.language": literalValues, + }, + "identifier" + ) + + this.$rules = { + start: [ + { + token: "comment", + regex: "#.*$", + }, + { + token: "paren.lparen", + regex: /[\[({]/, + next: "start", + }, + { + token: "paren.rparen", + regex: /[\])}]/, + }, + { + token: keywordMapper, + regex: "[a-zA-Z_][a-zA-Z0-9_$]*\\b", + }, + { + token: "string", // character + regex: "'(?:" + escapeRe + "|.)?'", + }, + { + token: "string.start", + regex: '"', + stateName: "qqstring", + next: [ + { token: "string", regex: /\\\s*$/, next: "qqstring" }, + { token: "constant.language.escape", regex: escapeRe }, + { token: "string.end", regex: '"|$', next: "start" }, + { defaultToken: "string" }, + ], + }, + { + token: "string.start", + regex: "'", + stateName: "singleQuoteString", + next: [ + { token: "string", regex: /\\\s*$/, next: "singleQuoteString" }, + { token: "constant.language.escape", regex: escapeRe }, + { token: "string.end", regex: "'|$", next: "start" }, + { defaultToken: "string" }, + ], + }, + { + token: "constant.numeric", + regex: /\d+\.?\d*[eE]?[\+\-]?\d*/, + }, + { + token: "variable", + regex: /\$[_A-Za-z][_0-9A-Za-z]*/, + }, + ], + } + this.normalizeRules() + } + + oop.inherits(GQLQueryTextHighlightRules, TextHighlightRules) + + exports.GQLQueryTextHighlightRules = GQLQueryTextHighlightRules + } + ) + + // Language Mode Definition + ace.define( + "ace/mode/gql-query", + ["require", "exports", "ace/mode/text", "ace/mode/gql-query-highlight"], + (aceRequire, exports) => { + const oop = aceRequire("ace/lib/oop") + const TextMode = aceRequire("ace/mode/text").Mode + const GQLQueryTextHighlightRules = aceRequire("ace/mode/gql-query-highlight") + .GQLQueryTextHighlightRules + const FoldMode = aceRequire("ace/mode/folding/cstyle").FoldMode + + const Mode = function () { + this.HighlightRules = GQLQueryTextHighlightRules + this.foldingRules = new FoldMode() + } + + oop.inherits(Mode, TextMode) + + exports.Mode = Mode + } + ) +}