groovy.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * @param {string} value
  3. * @returns {RegExp}
  4. * */
  5. /**
  6. * @param {RegExp | string } re
  7. * @returns {string}
  8. */
  9. function source(re) {
  10. if (!re) return null;
  11. if (typeof re === "string") return re;
  12. return re.source;
  13. }
  14. /**
  15. * @param {RegExp | string } re
  16. * @returns {string}
  17. */
  18. function lookahead(re) {
  19. return concat('(?=', re, ')');
  20. }
  21. /**
  22. * @param {...(RegExp | string) } args
  23. * @returns {string}
  24. */
  25. function concat(...args) {
  26. const joined = args.map((x) => source(x)).join("");
  27. return joined;
  28. }
  29. /*
  30. Language: Groovy
  31. Author: Guillaume Laforge <glaforge@gmail.com>
  32. Description: Groovy programming language implementation inspired from Vsevolod's Java mode
  33. Website: https://groovy-lang.org
  34. */
  35. function variants(variants, obj = {}) {
  36. obj.variants = variants;
  37. return obj;
  38. }
  39. function groovy(hljs) {
  40. const IDENT_RE = '[A-Za-z0-9_$]+';
  41. const COMMENT = variants([
  42. hljs.C_LINE_COMMENT_MODE,
  43. hljs.C_BLOCK_COMMENT_MODE,
  44. hljs.COMMENT(
  45. '/\\*\\*',
  46. '\\*/',
  47. {
  48. relevance: 0,
  49. contains: [
  50. {
  51. // eat up @'s in emails to prevent them to be recognized as doctags
  52. begin: /\w+@/,
  53. relevance: 0
  54. },
  55. {
  56. className: 'doctag',
  57. begin: '@[A-Za-z]+'
  58. }
  59. ]
  60. }
  61. )
  62. ]);
  63. const REGEXP = {
  64. className: 'regexp',
  65. begin: /~?\/[^\/\n]+\//,
  66. contains: [ hljs.BACKSLASH_ESCAPE ]
  67. };
  68. const NUMBER = variants([
  69. hljs.BINARY_NUMBER_MODE,
  70. hljs.C_NUMBER_MODE
  71. ]);
  72. const STRING = variants([
  73. {
  74. begin: /"""/,
  75. end: /"""/
  76. },
  77. {
  78. begin: /'''/,
  79. end: /'''/
  80. },
  81. {
  82. begin: "\\$/",
  83. end: "/\\$",
  84. relevance: 10
  85. },
  86. hljs.APOS_STRING_MODE,
  87. hljs.QUOTE_STRING_MODE
  88. ],
  89. {
  90. className: "string"
  91. }
  92. );
  93. return {
  94. name: 'Groovy',
  95. keywords: {
  96. built_in: 'this super',
  97. literal: 'true false null',
  98. keyword:
  99. 'byte short char int long boolean float double void ' +
  100. // groovy specific keywords
  101. 'def as in assert trait ' +
  102. // common keywords with Java
  103. 'abstract static volatile transient public private protected synchronized final ' +
  104. 'class interface enum if else for while switch case break default continue ' +
  105. 'throw throws try catch finally implements extends new import package return instanceof'
  106. },
  107. contains: [
  108. hljs.SHEBANG({
  109. binary: "groovy",
  110. relevance: 10
  111. }),
  112. COMMENT,
  113. STRING,
  114. REGEXP,
  115. NUMBER,
  116. {
  117. className: 'class',
  118. beginKeywords: 'class interface trait enum',
  119. end: /\{/,
  120. illegal: ':',
  121. contains: [
  122. {
  123. beginKeywords: 'extends implements'
  124. },
  125. hljs.UNDERSCORE_TITLE_MODE
  126. ]
  127. },
  128. {
  129. className: 'meta',
  130. begin: '@[A-Za-z]+',
  131. relevance: 0
  132. },
  133. {
  134. // highlight map keys and named parameters as attrs
  135. className: 'attr',
  136. begin: IDENT_RE + '[ \t]*:',
  137. relevance: 0
  138. },
  139. {
  140. // catch middle element of the ternary operator
  141. // to avoid highlight it as a label, named parameter, or map key
  142. begin: /\?/,
  143. end: /:/,
  144. relevance: 0,
  145. contains: [
  146. COMMENT,
  147. STRING,
  148. REGEXP,
  149. NUMBER,
  150. 'self'
  151. ]
  152. },
  153. {
  154. // highlight labeled statements
  155. className: 'symbol',
  156. begin: '^[ \t]*' + lookahead(IDENT_RE + ':'),
  157. excludeBegin: true,
  158. end: IDENT_RE + ':',
  159. relevance: 0
  160. }
  161. ],
  162. illegal: /#|<\//
  163. };
  164. }
  165. module.exports = groovy;