groovy.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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+@/, relevance: 0
  53. }, {
  54. className : 'doctag',
  55. begin : '@[A-Za-z]+'
  56. }
  57. ]
  58. }
  59. )
  60. ]);
  61. const REGEXP = {
  62. className: 'regexp',
  63. begin: /~?\/[^\/\n]+\//,
  64. contains: [
  65. hljs.BACKSLASH_ESCAPE
  66. ]
  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. begin: /'''/,
  78. end: /'''/
  79. }, {
  80. begin: "\\$/",
  81. end: "/\\$",
  82. relevance: 10
  83. },
  84. hljs.APOS_STRING_MODE,
  85. hljs.QUOTE_STRING_MODE,
  86. ],
  87. { className: "string" }
  88. );
  89. return {
  90. name: 'Groovy',
  91. keywords: {
  92. built_in: 'this super',
  93. literal: 'true false null',
  94. keyword:
  95. 'byte short char int long boolean float double void ' +
  96. // groovy specific keywords
  97. 'def as in assert trait ' +
  98. // common keywords with Java
  99. 'abstract static volatile transient public private protected synchronized final ' +
  100. 'class interface enum if else for while switch case break default continue ' +
  101. 'throw throws try catch finally implements extends new import package return instanceof'
  102. },
  103. contains: [
  104. hljs.SHEBANG(),
  105. COMMENT,
  106. STRING,
  107. REGEXP,
  108. NUMBER,
  109. {
  110. className: 'class',
  111. beginKeywords: 'class interface trait enum', end: '{',
  112. illegal: ':',
  113. contains: [
  114. {beginKeywords: 'extends implements'},
  115. hljs.UNDERSCORE_TITLE_MODE
  116. ]
  117. },
  118. {
  119. className: 'meta', begin: '@[A-Za-z]+'
  120. },
  121. {
  122. // highlight map keys and named parameters as attrs
  123. className: 'attr', begin: IDENT_RE + '[ \t]*:'
  124. },
  125. {
  126. // catch middle element of the ternary operator
  127. // to avoid highlight it as a label, named parameter, or map key
  128. begin: /\?/,
  129. end: /:/,
  130. contains: [
  131. COMMENT,
  132. STRING,
  133. REGEXP,
  134. NUMBER,
  135. 'self'
  136. ]
  137. },
  138. {
  139. // highlight labeled statements
  140. className: 'symbol',
  141. begin: '^[ \t]*' + lookahead(IDENT_RE + ':'),
  142. excludeBegin: true,
  143. end: IDENT_RE + ':',
  144. relevance: 0
  145. }
  146. ],
  147. illegal: /#|<\//
  148. };
  149. }
  150. module.exports = groovy;