| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 | /** * @param {string} value * @returns {RegExp} * *//** * @param {RegExp | string } re * @returns {string} */function source(re) {  if (!re) return null;  if (typeof re === "string") return re;  return re.source;}/** * @param {RegExp | string } re * @returns {string} */function lookahead(re) {  return concat('(?=', re, ')');}/** * @param {...(RegExp | string) } args * @returns {string} */function concat(...args) {  const joined = args.map((x) => source(x)).join("");  return joined;}/* Language: Groovy Author: Guillaume Laforge <glaforge@gmail.com> Description: Groovy programming language implementation inspired from Vsevolod's Java mode Website: https://groovy-lang.org */function variants(variants, obj = {}) {  obj.variants = variants;  return obj;}function groovy(hljs) {  const IDENT_RE = '[A-Za-z0-9_$]+';  const COMMENT = variants([    hljs.C_LINE_COMMENT_MODE,    hljs.C_BLOCK_COMMENT_MODE,    hljs.COMMENT(      '/\\*\\*',      '\\*/',      {        relevance: 0,        contains: [          {            // eat up @'s in emails to prevent them to be recognized as doctags            begin: /\w+@/,            relevance: 0          },          {            className: 'doctag',            begin: '@[A-Za-z]+'          }        ]      }    )  ]);  const REGEXP = {    className: 'regexp',    begin: /~?\/[^\/\n]+\//,    contains: [ hljs.BACKSLASH_ESCAPE ]  };  const NUMBER = variants([    hljs.BINARY_NUMBER_MODE,    hljs.C_NUMBER_MODE  ]);  const STRING = variants([    {      begin: /"""/,      end: /"""/    },    {      begin: /'''/,      end: /'''/    },    {      begin: "\\$/",      end: "/\\$",      relevance: 10    },    hljs.APOS_STRING_MODE,    hljs.QUOTE_STRING_MODE  ],  {    className: "string"  }  );  return {    name: 'Groovy',    keywords: {      built_in: 'this super',      literal: 'true false null',      keyword:            'byte short char int long boolean float double void ' +            // groovy specific keywords            'def as in assert trait ' +            // common keywords with Java            'abstract static volatile transient public private protected synchronized final ' +            'class interface enum if else for while switch case break default continue ' +            'throw throws try catch finally implements extends new import package return instanceof'    },    contains: [      hljs.SHEBANG({        binary: "groovy",        relevance: 10      }),      COMMENT,      STRING,      REGEXP,      NUMBER,      {        className: 'class',        beginKeywords: 'class interface trait enum',        end: /\{/,        illegal: ':',        contains: [          {            beginKeywords: 'extends implements'          },          hljs.UNDERSCORE_TITLE_MODE        ]      },      {        className: 'meta',        begin: '@[A-Za-z]+',        relevance: 0      },      {        // highlight map keys and named parameters as attrs        className: 'attr',        begin: IDENT_RE + '[ \t]*:',        relevance: 0      },      {        // catch middle element of the ternary operator        // to avoid highlight it as a label, named parameter, or map key        begin: /\?/,        end: /:/,        relevance: 0,        contains: [          COMMENT,          STRING,          REGEXP,          NUMBER,          'self'        ]      },      {        // highlight labeled statements        className: 'symbol',        begin: '^[ \t]*' + lookahead(IDENT_RE + ':'),        excludeBegin: true,        end: IDENT_RE + ':',        relevance: 0      }    ],    illegal: /#|<\//  };}module.exports = groovy;
 |