diff --git a/src/Highlighter.php b/src/Highlighter.php
index fc154e6..56e6bb8 100644
--- a/src/Highlighter.php
+++ b/src/Highlighter.php
@@ -17,6 +17,7 @@
use Tempest\Highlight\Languages\DotEnv\DotEnvLanguage;
use Tempest\Highlight\Languages\Ellison\EllisonLanguage;
use Tempest\Highlight\Languages\Gdscript\GdscriptLanguage;
+use Tempest\Highlight\Languages\Graphql\GraphqlLanguage;
use Tempest\Highlight\Languages\Html\HtmlLanguage;
use Tempest\Highlight\Languages\Ini\IniLanguage;
use Tempest\Highlight\Languages\JavaScript\JavaScriptLanguage;
@@ -69,6 +70,7 @@ public function __construct(private readonly Theme $theme = new CssTheme())
->addLanguage(new DockerfileLanguage())
->addLanguage(new EllisonLanguage())
->addLanguage(new GdscriptLanguage())
+ ->addLanguage(new GraphqlLanguage())
->addLanguage(new HtmlLanguage())
->addLanguage(new JavaScriptLanguage())
->addLanguage(new JsonLanguage())
diff --git a/src/Languages/Graphql/GraphqlLanguage.php b/src/Languages/Graphql/GraphqlLanguage.php
new file mode 100644
index 0000000..3cdc132
--- /dev/null
+++ b/src/Languages/Graphql/GraphqlLanguage.php
@@ -0,0 +1,73 @@
+#.*|"""[\s\S]*?""")';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::COMMENT;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlDirectivePattern.php b/src/Languages/Graphql/Patterns/GraphqlDirectivePattern.php
new file mode 100644
index 0000000..056c72b
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlDirectivePattern.php
@@ -0,0 +1,26 @@
+@\w+)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::ATTRIBUTE;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlFieldPattern.php b/src/Languages/Graphql/Patterns/GraphqlFieldPattern.php
new file mode 100644
index 0000000..184fbf2
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlFieldPattern.php
@@ -0,0 +1,26 @@
+[_A-Za-z][_0-9A-Za-z]*)(?=\s*:)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::PROPERTY;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlKeywordPattern.php b/src/Languages/Graphql/Patterns/GraphqlKeywordPattern.php
new file mode 100644
index 0000000..008d756
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlKeywordPattern.php
@@ -0,0 +1,26 @@
+\b(query|mutation|subscription|input|schema|implements|type|interface|union|scalar|fragment|enum|on)\b)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::KEYWORD;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlLiteralPattern.php b/src/Languages/Graphql/Patterns/GraphqlLiteralPattern.php
new file mode 100644
index 0000000..7fdffe7
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlLiteralPattern.php
@@ -0,0 +1,26 @@
+\b(true|false|null|ID|ID!|String|Float|Int|Boolean)\b)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::TYPE;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlNumberPattern.php b/src/Languages/Graphql/Patterns/GraphqlNumberPattern.php
new file mode 100644
index 0000000..54aeb0b
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlNumberPattern.php
@@ -0,0 +1,26 @@
+\b\d+(\.\d+)?)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::NUMBER;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlPunctuationPattern.php b/src/Languages/Graphql/Patterns/GraphqlPunctuationPattern.php
new file mode 100644
index 0000000..df07b61
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlPunctuationPattern.php
@@ -0,0 +1,27 @@
+\.{3}|[!():=\[\]{|}]|(?([^"\\\\]|\\\\.)*)"';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::VALUE;
+ }
+}
diff --git a/src/Languages/Graphql/Patterns/GraphqlVariablePattern.php b/src/Languages/Graphql/Patterns/GraphqlVariablePattern.php
new file mode 100644
index 0000000..af1bc8b
--- /dev/null
+++ b/src/Languages/Graphql/Patterns/GraphqlVariablePattern.php
@@ -0,0 +1,26 @@
+\$[\w]+)';
+ }
+
+ public function getTokenType(): TokenTypeEnum
+ {
+ return TokenTypeEnum::VARIABLE;
+ }
+}
diff --git a/tests/Bench/Fixtures/graphql.txt b/tests/Bench/Fixtures/graphql.txt
new file mode 100644
index 0000000..a71f966
--- /dev/null
+++ b/tests/Bench/Fixtures/graphql.txt
@@ -0,0 +1,40 @@
+# Query users by name
+query UsersByName($name: String!) {
+ users($name: $name) {
+ id
+ }
+}
+
+# ======
+# Schema
+# ======
+
+"""
+A user
+"""
+type User {
+ id: ID!
+ name: String!
+}
+
+type Query {
+ """
+ Query users by name.
+ """
+ users(name: String): [User!]!
+ """
+ Query a user by ID.
+ """
+ user(id: ID!): User
+}
+
+type Mutation {
+ """
+ Create a user
+ """
+ createUser(input: CreateUserInput!): User
+}
+
+input CreateUserInput {
+ name: String!
+}
\ No newline at end of file
diff --git a/tests/Bench/HighlighterBench.php b/tests/Bench/HighlighterBench.php
index 397d321..8abe8a8 100644
--- a/tests/Bench/HighlighterBench.php
+++ b/tests/Bench/HighlighterBench.php
@@ -27,6 +27,7 @@ final class HighlighterBench
'dotenv' => 'dotenv.txt',
'ellison' => 'ellison.txt',
'gdscript' => 'gdscript.txt',
+ 'graphql' => 'graphql.txt',
'html' => 'html.txt',
'ini' => 'ini.txt',
'javascript' => 'javascript.txt',
diff --git a/tests/Languages/Graphql/GraphqlLanguageTest.php b/tests/Languages/Graphql/GraphqlLanguageTest.php
new file mode 100644
index 0000000..d09c5f9
--- /dev/null
+++ b/tests/Languages/Graphql/GraphqlLanguageTest.php
@@ -0,0 +1,81 @@
+assertSame(
+ trim($expected),
+ trim($highlighter->parse($content, 'graphql'))
+ );
+ }
+
+ public static function provide_highlighting_cases(): iterable
+ {
+ return [
+ // Test Keywords & Types
+ [
+ 'query GetUser { user { id } }',
+ 'query GetUser { user { id } }',
+ ],
+ // Test Literals & Built-in Types
+ [
+ 'scalar Custom String Boolean',
+ 'scalar Custom String Boolean',
+ ],
+ // Test Variables
+ [
+ 'query($id: ID!)',
+ 'query($id: ID!)',
+ ],
+ // Test Fields (Symbols)
+ [
+ '{ user(name: "Test") }',
+ '{ user(name: "Test") }',
+ ],
+ // Test Directives
+ [
+ 'field @deprecated',
+ 'field @deprecated',
+ ],
+ // Test Comments
+ [
+ '# This is a comment',
+ '',
+ ],
+ [
+ '"""
+ Multi-line
+ Comment
+ """
+ type User { id: ID }',
+ '
+ type User { id: ID }',
+ ],
+ // Test Numbers
+ [
+ 'offset: 10, price: 1.99',
+ 'offset: 10, price: 1.99',
+ ],
+ // Test Fragments and Spread
+ [
+ '...UserFragment',
+ '...UserFragment',
+ ],
+ ];
+ }
+}