From a98b5ea6fe8e8cc98a55e0fd793e6e8660ea31c1 Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Thu, 30 Dec 2021 19:47:21 +0100 Subject: chore: add prismjs for syntax highlighting --- public/prism/prism-graphql.js | 226 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 public/prism/prism-graphql.js (limited to 'public/prism/prism-graphql.js') diff --git a/public/prism/prism-graphql.js b/public/prism/prism-graphql.js new file mode 100644 index 0000000..93e906d --- /dev/null +++ b/public/prism/prism-graphql.js @@ -0,0 +1,226 @@ +Prism.languages.graphql = { + comment: /#.*/, + description: { + pattern: /(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i, + greedy: true, + alias: 'string', + inside: { + 'language-markdown': { + pattern: /(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/, + lookbehind: true, + inside: Prism.languages.markdown, + }, + }, + }, + string: { + pattern: /"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/, + greedy: true, + }, + number: /(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i, + boolean: /\b(?:false|true)\b/, + variable: /\$[a-z_]\w*/i, + directive: { + pattern: /@[a-z_]\w*/i, + alias: 'function', + }, + 'attr-name': { + pattern: /\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i, + greedy: true, + }, + 'atom-input': { + pattern: /\b[A-Z]\w*Input\b/, + alias: 'class-name', + }, + scalar: /\b(?:Boolean|Float|ID|Int|String)\b/, + constant: /\b[A-Z][A-Z_\d]*\b/, + 'class-name': { + pattern: + /(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/, + lookbehind: true, + }, + fragment: { + pattern: /(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/, + lookbehind: true, + alias: 'function', + }, + 'definition-mutation': { + pattern: /(\bmutation\s+)[a-zA-Z_]\w*/, + lookbehind: true, + alias: 'function', + }, + 'definition-query': { + pattern: /(\bquery\s+)[a-zA-Z_]\w*/, + lookbehind: true, + alias: 'function', + }, + keyword: + /\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/, + operator: /[!=|&]|\.{3}/, + 'property-query': /\w+(?=\s*\()/, + object: /\w+(?=\s*\{)/, + punctuation: /[!(){}\[\]:=,]/, + property: /\w+/, +}; + +Prism.hooks.add('after-tokenize', function afterTokenizeGraphql(env) { + if (env.language !== 'graphql') { + return; + } + + /** + * get the graphql token stream that we want to customize + * + * @typedef {InstanceType} Token + * @type {Token[]} + */ + var validTokens = env.tokens.filter(function (token) { + return ( + typeof token !== 'string' && + token.type !== 'comment' && + token.type !== 'scalar' + ); + }); + + var currentIndex = 0; + + /** + * Returns whether the token relative to the current index has the given type. + * + * @param {number} offset + * @returns {Token | undefined} + */ + function getToken(offset) { + return validTokens[currentIndex + offset]; + } + + /** + * Returns whether the token relative to the current index has the given type. + * + * @param {readonly string[]} types + * @param {number} [offset=0] + * @returns {boolean} + */ + function isTokenType(types, offset) { + offset = offset || 0; + for (var i = 0; i < types.length; i++) { + var token = getToken(i + offset); + if (!token || token.type !== types[i]) { + return false; + } + } + return true; + } + + /** + * Returns the index of the closing bracket to an opening bracket. + * + * It is assumed that `token[currentIndex - 1]` is an opening bracket. + * + * If no closing bracket could be found, `-1` will be returned. + * + * @param {RegExp} open + * @param {RegExp} close + * @returns {number} + */ + function findClosingBracket(open, close) { + var stackHeight = 1; + + for (var i = currentIndex; i < validTokens.length; i++) { + var token = validTokens[i]; + var content = token.content; + + if (token.type === 'punctuation' && typeof content === 'string') { + if (open.test(content)) { + stackHeight++; + } else if (close.test(content)) { + stackHeight--; + + if (stackHeight === 0) { + return i; + } + } + } + } + + return -1; + } + + /** + * Adds an alias to the given token. + * + * @param {Token} token + * @param {string} alias + * @returns {void} + */ + function addAlias(token, alias) { + var aliases = token.alias; + if (!aliases) { + token.alias = aliases = []; + } else if (!Array.isArray(aliases)) { + token.alias = aliases = [aliases]; + } + aliases.push(alias); + } + + for (; currentIndex < validTokens.length; ) { + var startToken = validTokens[currentIndex++]; + + // add special aliases for mutation tokens + if (startToken.type === 'keyword' && startToken.content === 'mutation') { + // any array of the names of all input variables (if any) + var inputVariables = []; + + if ( + isTokenType(['definition-mutation', 'punctuation']) && + getToken(1).content === '(' + ) { + // definition + + currentIndex += 2; // skip 'definition-mutation' and 'punctuation' + + var definitionEnd = findClosingBracket(/^\($/, /^\)$/); + if (definitionEnd === -1) { + continue; + } + + // find all input variables + for (; currentIndex < definitionEnd; currentIndex++) { + var t = getToken(0); + if (t.type === 'variable') { + addAlias(t, 'variable-input'); + inputVariables.push(t.content); + } + } + + currentIndex = definitionEnd + 1; + } + + if ( + isTokenType(['punctuation', 'property-query']) && + getToken(0).content === '{' + ) { + currentIndex++; // skip opening bracket + + addAlias(getToken(0), 'property-mutation'); + + if (inputVariables.length > 0) { + var mutationEnd = findClosingBracket(/^\{$/, /^\}$/); + if (mutationEnd === -1) { + continue; + } + + // give references to input variables a special alias + for (var i = currentIndex; i < mutationEnd; i++) { + var varToken = validTokens[i]; + if ( + varToken.type === 'variable' && + inputVariables.indexOf(varToken.content) >= 0 + ) { + addAlias(varToken, 'variable-input'); + } + } + } + } + } + } +}); -- cgit v1.2.3