# -*- coding: utf-8 -*- # # frozen_string_literal: true module Rouge module Lexers class GraphQL < RegexLexer desc 'GraphQL' tag 'graphql' filenames '*.graphql', '*.gql' mimetypes 'application/graphql' name = /[_A-Za-z][_0-9A-Za-z]*/ state :root do rule /\b(?:query|mutation|subscription)\b/, Keyword, :query_definition rule /\{/ do token Punctuation push :query_definition push :selection_set end rule /\bfragment\b/, Keyword, :fragment_definition rule /\b(?:type|interface|enum)\b/, Keyword, :type_definition rule /\b(?:input|schema)\b/, Keyword, :type_definition rule /\bunion\b/, Keyword, :union_definition mixin :basic # Markdown descriptions rule /(""")(.*?)(""")/m do |m| token Str::Double, m[1] delegate Markdown, m[2] token Str::Double, m[3] end end state :basic do rule /\s+/m, Text::Whitespace rule /#.*$/, Comment rule /[!,]/, Punctuation end state :has_directives do rule /(@#{name})(\s*)(\()/ do groups Keyword, Text::Whitespace, Punctuation push :arguments end rule /@#{name}\b/, Keyword end state :fragment_definition do rule /\bon\b/, Keyword mixin :query_definition end state :query_definition do mixin :has_directives rule /\b#{name}\b/, Name rule /\(/, Punctuation, :variable_definitions rule /\{/, Punctuation, :selection_set mixin :basic end state :type_definition do rule /\bimplements\b/, Keyword rule /\b#{name}\b/, Name rule /\(/, Punctuation, :variable_definitions rule /\{/, Punctuation, :type_definition_set mixin :basic end state :union_definition do rule /\b#{name}\b/, Name rule /\=/, Punctuation, :union_definition_variant mixin :basic end state :union_definition_variant do rule /\b#{name}\b/ do token Name pop! push :union_definition_pipe end mixin :basic end state :union_definition_pipe do rule /\|/ do token Punctuation pop! push :union_definition_variant end rule /(?!\||\s+|#[^\n]*)/ do pop! 2 end mixin :basic end state :type_definition_set do rule /\}/ do token Punctuation pop! 2 end rule /\b(#{name})(\s*)(\()/ do groups Name, Text::Whitespace, Punctuation push :variable_definitions end rule /\b#{name}\b/, Name rule /:/, Punctuation, :type_names mixin :basic end state :arguments do rule /\)/ do token Punctuation pop! end rule /\b#{name}\b/, Name rule /:/, Punctuation, :value mixin :basic end state :variable_definitions do rule /\)/ do token Punctuation pop! end rule /\$#{name}\b/, Name::Variable rule /\b#{name}\b/, Name rule /:/, Punctuation, :type_names rule /\=/, Punctuation, :value mixin :basic end state :type_names do rule /\b(?:Int|Float|String|Boolean|ID)\b/, Name::Builtin, :pop! rule /\b#{name}\b/, Name, :pop! rule /\[/, Punctuation, :type_name_list mixin :basic end state :type_name_list do rule /\b(?:Int|Float|String|Boolean|ID)\b/, Name::Builtin rule /\b#{name}\b/, Name rule /\]/ do token Punctuation pop! 2 end mixin :basic end state :selection_set do mixin :has_directives rule /\}/ do token Punctuation pop! pop! if state?(:query_definition) || state?(:fragment_definition) end rule /\b(#{name})(\s*)(\()/ do groups Name, Text::Whitespace, Punctuation push :arguments end rule /\b(#{name})(\s*)(:)/ do groups Name, Text::Whitespace, Punctuation end rule /\b#{name}\b/, Name rule /(\.\.\.)(\s+)(on)\b/ do groups Punctuation, Text::Whitespace, Keyword end rule /\.\.\./, Punctuation rule /\{/, Punctuation, :selection_set mixin :basic end state :list do rule /\]/ do token Punctuation pop! pop! if state?(:value) end mixin :value end state :object do rule /\}/ do token Punctuation pop! pop! if state?(:value) end rule /\b(#{name})(\s*)(:)/ do groups Name, Text::Whitespace, Punctuation push :value end mixin :basic end state :value do pop_unless_list = ->(t) { ->(m) { token t pop! unless state?(:list) } } # Multiline strings rule /""".*?"""/m, Str::Double rule /\$#{name}\b/, &pop_unless_list[Name::Variable] rule /\b(?:true|false|null)\b/, &pop_unless_list[Keyword::Constant] rule /[+-]?[0-9]+\.[0-9]+(?:[eE][+-]?[0-9]+)?/, &pop_unless_list[Num::Float] rule /[+-]?[1-9][0-9]*(?:[eE][+-]?[0-9]+)?/, &pop_unless_list[Num::Integer] rule /"(\\[\\"]|[^"])*"/, &pop_unless_list[Str::Double] rule /\b#{name}\b/, &pop_unless_list[Name] rule /\{/, Punctuation, :object rule /\[/, Punctuation, :list mixin :basic end end end end