feat: initial graphql language definition
This commit is contained in:
5
packages/codemirror-lang-graphql/.gitignore
vendored
Normal file
5
packages/codemirror-lang-graphql/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/node_modules
|
||||
package-lock.json
|
||||
/dist
|
||||
/src/*.js
|
||||
/src/*.d.ts
|
||||
5
packages/codemirror-lang-graphql/.npmignore
Normal file
5
packages/codemirror-lang-graphql/.npmignore
Normal file
@@ -0,0 +1,5 @@
|
||||
/src
|
||||
/test
|
||||
/node_modules
|
||||
rollup.config.js
|
||||
tsconfig.json
|
||||
1
packages/codemirror-lang-graphql/README.md
Normal file
1
packages/codemirror-lang-graphql/README.md
Normal file
@@ -0,0 +1 @@
|
||||
A [CodeMirror 6](https://codemirror.net/6) language plugin for GraphQL
|
||||
32
packages/codemirror-lang-graphql/package.json
Normal file
32
packages/codemirror-lang-graphql/package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@hoppscotch/codemirror-lang-graphql",
|
||||
"version": "0.1.0",
|
||||
"description": "GraphQL language support for CodeMirror",
|
||||
"scripts": {
|
||||
"test": "mocha test/test.js",
|
||||
"prepare": "rollup -c"
|
||||
},
|
||||
"type": "module",
|
||||
"main": "dist/index.cjs",
|
||||
"module": "dist/index.js",
|
||||
"exports": {
|
||||
"import": "./dist/index.js",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"types": "dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"@codemirror/highlight": "^0.19.0",
|
||||
"@codemirror/language": "^0.19.0",
|
||||
"@lezer/lr": "^0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@lezer/generator": "^0.15.0",
|
||||
"mocha": "^9.0.1",
|
||||
"rollup": "^2.35.1",
|
||||
"rollup-plugin-dts": "^3.0.2",
|
||||
"rollup-plugin-ts": "^1.4.0",
|
||||
"typescript": "^4.3.4"
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
12
packages/codemirror-lang-graphql/rollup.config.js
Normal file
12
packages/codemirror-lang-graphql/rollup.config.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import typescript from "rollup-plugin-ts"
|
||||
import {lezer} from "@lezer/generator/rollup"
|
||||
|
||||
export default {
|
||||
input: "src/index.ts",
|
||||
external: id => id != "tslib" && !/^(\.?\/|\w:)/.test(id),
|
||||
output: [
|
||||
{file: "dist/index.cjs", format: "cjs"},
|
||||
{dir: "./dist", format: "es"}
|
||||
],
|
||||
plugins: [lezer(), typescript()]
|
||||
}
|
||||
35
packages/codemirror-lang-graphql/src/index.ts
Normal file
35
packages/codemirror-lang-graphql/src/index.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import {parser} from "./syntax.grammar"
|
||||
import {LRLanguage, LanguageSupport, indentNodeProp, foldNodeProp, foldInside, delimitedIndent} from "@codemirror/language"
|
||||
import {styleTags, tags as t} from "@codemirror/highlight"
|
||||
|
||||
export const GQLLanguage = LRLanguage.define({
|
||||
parser: parser.configure({
|
||||
props: [
|
||||
indentNodeProp.add({
|
||||
Application: delimitedIndent({closing: ")", align: false})
|
||||
}),
|
||||
foldNodeProp.add({
|
||||
Application: foldInside
|
||||
}),
|
||||
styleTags({
|
||||
Name: t.propertyName,
|
||||
OperationType: t.keyword,
|
||||
BooleanValue: t.bool,
|
||||
StringValue: t.string,
|
||||
IntValue: t.number,
|
||||
FloatValue: t.number,
|
||||
NullValue: t.null,
|
||||
ObjectValue: t.brace,
|
||||
Comment: t.lineComment,
|
||||
})
|
||||
]
|
||||
}),
|
||||
languageData: {
|
||||
commentTokens: { line: "#" },
|
||||
closeBrackets: { brackets: ["(", "[", "{", '"', '"""'] }
|
||||
}
|
||||
})
|
||||
|
||||
export function GQL() {
|
||||
return new LanguageSupport(GQLLanguage)
|
||||
}
|
||||
368
packages/codemirror-lang-graphql/src/syntax.grammar
Normal file
368
packages/codemirror-lang-graphql/src/syntax.grammar
Normal file
@@ -0,0 +1,368 @@
|
||||
@top SourceFile {
|
||||
Document
|
||||
}
|
||||
|
||||
@precedence {
|
||||
fieldDef @right,
|
||||
typeDef @right
|
||||
}
|
||||
|
||||
Document {
|
||||
Definition+
|
||||
}
|
||||
|
||||
Definition {
|
||||
ExecutableDefinition |
|
||||
TypeSystemDefinition |
|
||||
TypeSystemExtension
|
||||
}
|
||||
|
||||
ExecutableDefinition {
|
||||
OperationDefinition |
|
||||
FragmentDefinition
|
||||
}
|
||||
|
||||
TypeSystemDefinition {
|
||||
SchemaDefinition |
|
||||
TypeDefinition |
|
||||
DirectiveDefinition
|
||||
}
|
||||
|
||||
TypeSystemExtension {
|
||||
SchemaExtension |
|
||||
TypeExtension
|
||||
}
|
||||
|
||||
SchemaDefinition {
|
||||
Description? @specialize<Name, "schema"> Directives? "{" RootOperationTypeDefinition+ "}"
|
||||
}
|
||||
|
||||
SchemaExtension {
|
||||
@specialize<Name, "extend"> @specialize<Name, "schema"> Directives? "{" RootOperationTypeDefinition "}"
|
||||
}
|
||||
|
||||
TypeExtension {
|
||||
ScalarTypeExtension |
|
||||
ObjectTypeExtension |
|
||||
InterfaceTypeExtension |
|
||||
UnionTypeExtension |
|
||||
EnumTypeExtension |
|
||||
InputObjectTypeExtension
|
||||
}
|
||||
|
||||
ScalarTypeExtension {
|
||||
@specialize<Name, "extend"> @specialize<Name, "scalar"> Name Directives
|
||||
}
|
||||
|
||||
ObjectTypeExtension /* precedence: right 0 */ {
|
||||
@specialize<Name, "extend"> @specialize<Name, "type"> Name ImplementsInterfaces? Directives? !typeDef FieldsDefinition |
|
||||
@specialize<Name, "extend"> @specialize<Name, "type"> Name ImplementsInterfaces? Directives?
|
||||
}
|
||||
|
||||
InterfaceTypeExtension /* precedence: right 0 */ {
|
||||
@specialize<Name, "extend"> @specialize<Name, "interface"> Name ImplementsInterfaces? Directives? FieldsDefinition |
|
||||
@specialize<Name, "extend"> @specialize<Name, "interface"> Name ImplementsInterfaces? Directives?
|
||||
}
|
||||
|
||||
UnionTypeExtension /* precedence: right 0 */ {
|
||||
@specialize<Name, "extend"> @specialize<Name, "union"> Name Directives? UnionMemberTypes |
|
||||
@specialize<Name, "extend"> @specialize<Name, "union"> Name Directives?
|
||||
}
|
||||
|
||||
EnumTypeExtension /* precedence: right 0 */ {
|
||||
@specialize<Name, "extend"> @specialize<Name, "enum"> Name Directives? !typeDef EnumValuesDefinition |
|
||||
@specialize<Name, "extend"> @specialize<Name, "enum"> Name Directives?
|
||||
}
|
||||
|
||||
InputObjectTypeExtension /* precedence: right 0 */ {
|
||||
@specialize<Name, "extend"> @specialize<Name, "input"> Name Directives? InputFieldsDefinition+ |
|
||||
@specialize<Name, "extend"> @specialize<Name, "input"> Name Directives?
|
||||
}
|
||||
|
||||
InputFieldsDefinition {
|
||||
!fieldDef "{" InputValueDefinition+ "}"
|
||||
}
|
||||
|
||||
EnumValuesDefinition {
|
||||
!fieldDef "{" EnumValueDefinition+ "}"
|
||||
}
|
||||
|
||||
EnumValueDefinition {
|
||||
Description? EnumValue Directives?
|
||||
}
|
||||
|
||||
ImplementsInterfaces {
|
||||
ImplementsInterfaces "&" NamedType |
|
||||
@specialize<Name, "implements"> "&"? NamedType
|
||||
}
|
||||
|
||||
FieldsDefinition {
|
||||
!fieldDef "{" FieldDefinition+ "}"
|
||||
}
|
||||
|
||||
FieldDefinition {
|
||||
Description? Name ArgumentsDefinition? ":" Type Directives?
|
||||
}
|
||||
|
||||
ArgumentsDefinition {
|
||||
"(" InputValueDefinition+ ")"
|
||||
}
|
||||
|
||||
InputValueDefinition {
|
||||
Description? Name ":" Type DefaultValue? Directives?
|
||||
}
|
||||
|
||||
DefaultValue {
|
||||
"=" Value
|
||||
}
|
||||
|
||||
UnionMemberTypes {
|
||||
UnionMemberTypes "|" NamedType |
|
||||
"=" "|"? NamedType
|
||||
}
|
||||
|
||||
RootOperationTypeDefinition {
|
||||
OperationType ":" NamedType
|
||||
}
|
||||
|
||||
OperationDefinition {
|
||||
SelectionSet |
|
||||
OperationType Name? VariableDefinitions? Directives? SelectionSet
|
||||
}
|
||||
|
||||
TypeDefinition {
|
||||
ScalarTypeDefinition |
|
||||
ObjectTypeDefinition |
|
||||
InterfaceTypeDefinition |
|
||||
UnionTypeDefinition |
|
||||
EnumTypeDefinition |
|
||||
InputObjectTypeDefinition
|
||||
}
|
||||
|
||||
ScalarTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "scalar"> Name Directives?
|
||||
}
|
||||
|
||||
ObjectTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "type"> Name ImplementsInterfaces? Directives? FieldsDefinition?
|
||||
}
|
||||
|
||||
InterfaceTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "interface"> Name ImplementsInterfaces? Directives? FieldsDefinition?
|
||||
}
|
||||
|
||||
UnionTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "union"> Name Directives? UnionMemberTypes?
|
||||
}
|
||||
|
||||
EnumTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "enum"> Name Directives? !typeDef EnumValuesDefinition?
|
||||
}
|
||||
|
||||
InputObjectTypeDefinition /* precedence: right 0 */ {
|
||||
Description? @specialize<Name, "input"> Name Directives? !typeDef InputFieldsDefinition?
|
||||
}
|
||||
|
||||
VariableDefinitions {
|
||||
"(" VariableDefinition+ ")"
|
||||
}
|
||||
|
||||
VariableDefinition {
|
||||
Variable ":" Type DefaultValue? Directives? Comma?
|
||||
}
|
||||
|
||||
SelectionSet {
|
||||
"{" Selection+ "}"
|
||||
}
|
||||
|
||||
Selection {
|
||||
Field |
|
||||
InlineFragment |
|
||||
FragmentSpread
|
||||
}
|
||||
|
||||
Field {
|
||||
Alias? Name Arguments? Directive? SelectionSet?
|
||||
}
|
||||
|
||||
Alias {
|
||||
Name ":"
|
||||
}
|
||||
|
||||
Arguments {
|
||||
"(" Argument+ ")"
|
||||
}
|
||||
|
||||
Argument {
|
||||
Name ":" Value
|
||||
}
|
||||
|
||||
Value {
|
||||
Variable |
|
||||
StringValue |
|
||||
IntValue |
|
||||
FloatValue |
|
||||
BooleanValue |
|
||||
NullValue |
|
||||
EnumValue |
|
||||
ListValue |
|
||||
ObjectValue
|
||||
}
|
||||
|
||||
Variable {
|
||||
"$" Name
|
||||
}
|
||||
|
||||
EnumValue {
|
||||
Name
|
||||
}
|
||||
|
||||
ListValue {
|
||||
"[" Value* "]"
|
||||
}
|
||||
|
||||
ObjectValue {
|
||||
"{" ObjectField* "}"
|
||||
}
|
||||
|
||||
ObjectField {
|
||||
Name ":" Value Comma?
|
||||
}
|
||||
|
||||
FragmentSpread {
|
||||
"..." FragmentName Directives?
|
||||
}
|
||||
|
||||
FragmentDefinition {
|
||||
@specialize<Name, "fragment"> FragmentName TypeCondition Directives? SelectionSet
|
||||
}
|
||||
|
||||
FragmentName {
|
||||
Name
|
||||
}
|
||||
|
||||
InlineFragment {
|
||||
"..." TypeCondition? Directives? SelectionSet
|
||||
}
|
||||
|
||||
TypeCondition {
|
||||
@specialize<Name, "on"> NamedType
|
||||
}
|
||||
|
||||
Directives {
|
||||
Directive+
|
||||
}
|
||||
|
||||
Directive {
|
||||
"@" Name Arguments?
|
||||
}
|
||||
|
||||
DirectiveDefinition /* precedence: right 1 */ {
|
||||
Description? @specialize<Name, "directive"> "@" Name ArgumentsDefinition? @specialize<Name, "repeatable"> ? @specialize<Name, "on"> DirectiveLocations
|
||||
}
|
||||
|
||||
DirectiveLocations {
|
||||
DirectiveLocations "|" DirectiveLocation |
|
||||
"|"? DirectiveLocation
|
||||
}
|
||||
|
||||
DirectiveLocation {
|
||||
ExecutableDirectiveLocation |
|
||||
TypeSystemDirectiveLocation
|
||||
}
|
||||
|
||||
Type {
|
||||
NamedType |
|
||||
ListType |
|
||||
NonNullType
|
||||
}
|
||||
|
||||
NamedType {
|
||||
Name
|
||||
}
|
||||
|
||||
ListType {
|
||||
"[" Type "]"
|
||||
}
|
||||
|
||||
NonNullType {
|
||||
NamedType "!" |
|
||||
ListType "!"
|
||||
}
|
||||
|
||||
Description {
|
||||
StringValue
|
||||
}
|
||||
|
||||
OperationType {
|
||||
@specialize<Name, "query">
|
||||
| @specialize<Name, "mutation">
|
||||
| @specialize<Name, "subscription">
|
||||
}
|
||||
|
||||
BooleanValue {
|
||||
@specialize<Name, "true">
|
||||
| @specialize<Name, "false">
|
||||
}
|
||||
|
||||
NullValue {
|
||||
@specialize<Name, "null">
|
||||
}
|
||||
|
||||
ExecutableDirectiveLocation {
|
||||
@specialize<Name, "QUERY">
|
||||
| @specialize<Name, "MUTATION">
|
||||
| @specialize<Name, "SUBSCRIPTION">
|
||||
| @specialize<Name, "FIELD">
|
||||
| @specialize<Name, "FRAGMENT_DEFINITION">
|
||||
| @specialize<Name, "FRAGMENT_SPREAD">
|
||||
| @specialize<Name, "INLINE_FRAGMENT">
|
||||
| @specialize<Name, "VARIABLE_DEFINITION">
|
||||
}
|
||||
|
||||
TypeSystemDirectiveLocation {
|
||||
@specialize<Name, "SCHEMA">
|
||||
| @specialize<Name, "SCALAR">
|
||||
| @specialize<Name, "OBJECT">
|
||||
| @specialize<Name, "FIELD_DEFINITION">
|
||||
| @specialize<Name, "ARGUMENT_DEFINITION">
|
||||
| @specialize<Name, "INTERFACE">
|
||||
| @specialize<Name, "UNION">
|
||||
| @specialize<Name, "ENUM">
|
||||
| @specialize<Name, "ENUM_VALUE">
|
||||
| @specialize<Name, "INPUT_OBJECT">
|
||||
| @specialize<Name, "INPUT_FIELD_DEFINITION">
|
||||
}
|
||||
|
||||
@skip { Whitespace | Comment }
|
||||
|
||||
@tokens {
|
||||
Whitespace {
|
||||
std.whitespace
|
||||
}
|
||||
StringValue {
|
||||
"\"\"\"" (!["] | "\\n" | "\"" "\""? !["])* "\"\"\"" | "\"" !["\\\n]* "\""
|
||||
}
|
||||
IntValue {
|
||||
"-"? "0"
|
||||
| "-"? std.digit+
|
||||
}
|
||||
|
||||
FloatValue {
|
||||
IntValue ("." std.digit+ | ("e" | "E") IntValue+)
|
||||
}
|
||||
|
||||
@precedence { IntValue, FloatValue }
|
||||
|
||||
Name {
|
||||
$[_A-Za-z] $[_0-9A-Za-z]*
|
||||
}
|
||||
Comment {
|
||||
"#" ![\n]*
|
||||
}
|
||||
Comma {
|
||||
","
|
||||
}
|
||||
}
|
||||
|
||||
@detectDelim
|
||||
1
packages/codemirror-lang-graphql/test/cases.txt
Normal file
1
packages/codemirror-lang-graphql/test/cases.txt
Normal file
@@ -0,0 +1 @@
|
||||
# TODO: Write Lezer Tests
|
||||
17
packages/codemirror-lang-graphql/test/test.js
Normal file
17
packages/codemirror-lang-graphql/test/test.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import {GQLLanguage} from "../dist/index.js"
|
||||
import {fileTests} from "lezer-generator/dist/test"
|
||||
|
||||
import * as fs from "fs"
|
||||
import * as path from "path"
|
||||
import { fileURLToPath } from 'url';
|
||||
let caseDir = path.dirname(fileURLToPath(import.meta.url))
|
||||
|
||||
for (let file of fs.readdirSync(caseDir)) {
|
||||
if (!/\.txt$/.test(file)) continue
|
||||
|
||||
let name = /^[^\.]*/.exec(file)[0]
|
||||
describe(name, () => {
|
||||
for (let {name, run} of fileTests(fs.readFileSync(path.join(caseDir, file), "utf8"), file))
|
||||
it(name, () => run(GQLLanguage.parser))
|
||||
})
|
||||
}
|
||||
11
packages/codemirror-lang-graphql/tsconfig.json
Normal file
11
packages/codemirror-lang-graphql/tsconfig.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"strict": true,
|
||||
"target": "es6",
|
||||
"module": "es2020",
|
||||
"newLine": "lf",
|
||||
"declaration": true,
|
||||
"moduleResolution": "node"
|
||||
},
|
||||
"include": ["src/*.ts"]
|
||||
}
|
||||
Reference in New Issue
Block a user