scala.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /*
  2. Language: Scala
  3. Category: functional
  4. Author: Jan Berkel <jan.berkel@gmail.com>
  5. Contributors: Erik Osheim <d_m@plastic-idolatry.com>
  6. Website: https://www.scala-lang.org
  7. */
  8. function scala(hljs) {
  9. const regex = hljs.regex;
  10. const ANNOTATION = {
  11. className: 'meta',
  12. begin: '@[A-Za-z]+'
  13. };
  14. // used in strings for escaping/interpolation/substitution
  15. const SUBST = {
  16. className: 'subst',
  17. variants: [
  18. { begin: '\\$[A-Za-z0-9_]+' },
  19. {
  20. begin: /\$\{/,
  21. end: /\}/
  22. }
  23. ]
  24. };
  25. const STRING = {
  26. className: 'string',
  27. variants: [
  28. {
  29. begin: '"""',
  30. end: '"""'
  31. },
  32. {
  33. begin: '"',
  34. end: '"',
  35. illegal: '\\n',
  36. contains: [ hljs.BACKSLASH_ESCAPE ]
  37. },
  38. {
  39. begin: '[a-z]+"',
  40. end: '"',
  41. illegal: '\\n',
  42. contains: [
  43. hljs.BACKSLASH_ESCAPE,
  44. SUBST
  45. ]
  46. },
  47. {
  48. className: 'string',
  49. begin: '[a-z]+"""',
  50. end: '"""',
  51. contains: [ SUBST ],
  52. relevance: 10
  53. }
  54. ]
  55. };
  56. const TYPE = {
  57. className: 'type',
  58. begin: '\\b[A-Z][A-Za-z0-9_]*',
  59. relevance: 0
  60. };
  61. const NAME = {
  62. className: 'title',
  63. begin: /[^0-9\n\t "'(),.`{}\[\]:;][^\n\t "'(),.`{}\[\]:;]+|[^0-9\n\t "'(),.`{}\[\]:;=]/,
  64. relevance: 0
  65. };
  66. const CLASS = {
  67. className: 'class',
  68. beginKeywords: 'class object trait type',
  69. end: /[:={\[\n;]/,
  70. excludeEnd: true,
  71. contains: [
  72. hljs.C_LINE_COMMENT_MODE,
  73. hljs.C_BLOCK_COMMENT_MODE,
  74. {
  75. beginKeywords: 'extends with',
  76. relevance: 10
  77. },
  78. {
  79. begin: /\[/,
  80. end: /\]/,
  81. excludeBegin: true,
  82. excludeEnd: true,
  83. relevance: 0,
  84. contains: [
  85. TYPE,
  86. hljs.C_LINE_COMMENT_MODE,
  87. hljs.C_BLOCK_COMMENT_MODE,
  88. ]
  89. },
  90. {
  91. className: 'params',
  92. begin: /\(/,
  93. end: /\)/,
  94. excludeBegin: true,
  95. excludeEnd: true,
  96. relevance: 0,
  97. contains: [
  98. TYPE,
  99. hljs.C_LINE_COMMENT_MODE,
  100. hljs.C_BLOCK_COMMENT_MODE,
  101. ]
  102. },
  103. NAME
  104. ]
  105. };
  106. const METHOD = {
  107. className: 'function',
  108. beginKeywords: 'def',
  109. end: regex.lookahead(/[:={\[(\n;]/),
  110. contains: [ NAME ]
  111. };
  112. const EXTENSION = {
  113. begin: [
  114. /^\s*/, // Is first token on the line
  115. 'extension',
  116. /\s+(?=[[(])/, // followed by at least one space and `[` or `(`
  117. ],
  118. beginScope: { 2: "keyword", }
  119. };
  120. const END = {
  121. begin: [
  122. /^\s*/, // Is first token on the line
  123. /end/,
  124. /\s+/,
  125. /(extension\b)?/, // `extension` is the only marker that follows an `end` that cannot be captured by another rule.
  126. ],
  127. beginScope: {
  128. 2: "keyword",
  129. 4: "keyword",
  130. }
  131. };
  132. // TODO: use negative look-behind in future
  133. // /(?<!\.)\binline(?=\s)/
  134. const INLINE_MODES = [
  135. { match: /\.inline\b/ },
  136. {
  137. begin: /\binline(?=\s)/,
  138. keywords: 'inline'
  139. }
  140. ];
  141. const USING_PARAM_CLAUSE = {
  142. begin: [
  143. /\(\s*/, // Opening `(` of a parameter or argument list
  144. /using/,
  145. /\s+(?!\))/, // Spaces not followed by `)`
  146. ],
  147. beginScope: { 2: "keyword", }
  148. };
  149. // glob all non-whitespace characters as a "string"
  150. // sourced from https://github.com/scala/docs.scala-lang/pull/2845
  151. const DIRECTIVE_VALUE = {
  152. className: 'string',
  153. begin: /\S+/,
  154. };
  155. // directives
  156. // sourced from https://github.com/scala/docs.scala-lang/pull/2845
  157. const USING_DIRECTIVE = {
  158. begin: [
  159. '//>',
  160. /\s+/,
  161. /using/,
  162. /\s+/,
  163. /\S+/
  164. ],
  165. beginScope: {
  166. 1: "comment",
  167. 3: "keyword",
  168. 5: "type"
  169. },
  170. end: /$/,
  171. contains: [
  172. DIRECTIVE_VALUE,
  173. ]
  174. };
  175. return {
  176. name: 'Scala',
  177. keywords: {
  178. literal: 'true false null',
  179. keyword: 'type yield lazy override def with val var sealed abstract private trait object if then forSome for while do throw finally protected extends import final return else break new catch super class case package default try this match continue throws implicit export enum given transparent'
  180. },
  181. contains: [
  182. USING_DIRECTIVE,
  183. hljs.C_LINE_COMMENT_MODE,
  184. hljs.C_BLOCK_COMMENT_MODE,
  185. STRING,
  186. TYPE,
  187. METHOD,
  188. CLASS,
  189. hljs.C_NUMBER_MODE,
  190. EXTENSION,
  191. END,
  192. ...INLINE_MODES,
  193. USING_PARAM_CLAUSE,
  194. ANNOTATION
  195. ]
  196. };
  197. }
  198. export { scala as default };