dart.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. ;(function (mod) {
  4. if (typeof exports == 'object' && typeof module == 'object')
  5. // CommonJS
  6. mod(require('../../lib/codemirror'), require('../clike/clike'))
  7. else if (typeof define == 'function' && define.amd)
  8. // AMD
  9. define(['../../lib/codemirror', '../clike/clike'], mod)
  10. // Plain browser env
  11. else mod(CodeMirror)
  12. })(function (CodeMirror) {
  13. 'use strict'
  14. var keywords = (
  15. 'this super static final const abstract class extends external factory ' +
  16. 'implements mixin get native set typedef with enum throw rethrow ' +
  17. 'assert break case continue default in return new deferred async await covariant ' +
  18. 'try catch finally do else for if switch while import library export ' +
  19. 'part of show hide is as extension on yield late required'
  20. ).split(' ')
  21. var blockKeywords = 'try catch finally do else for if switch while'.split(' ')
  22. var atoms = 'true false null'.split(' ')
  23. var builtins = 'void bool num int double dynamic var String Null Never'.split(' ')
  24. function set(words) {
  25. var obj = {}
  26. for (var i = 0; i < words.length; ++i) obj[words[i]] = true
  27. return obj
  28. }
  29. function pushInterpolationStack(state) {
  30. ;(state.interpolationStack || (state.interpolationStack = [])).push(state.tokenize)
  31. }
  32. function popInterpolationStack(state) {
  33. return (state.interpolationStack || (state.interpolationStack = [])).pop()
  34. }
  35. function sizeInterpolationStack(state) {
  36. return state.interpolationStack ? state.interpolationStack.length : 0
  37. }
  38. CodeMirror.defineMIME('application/dart', {
  39. name: 'clike',
  40. keywords: set(keywords),
  41. blockKeywords: set(blockKeywords),
  42. builtin: set(builtins),
  43. atoms: set(atoms),
  44. hooks: {
  45. '@': function (stream) {
  46. stream.eatWhile(/[\w\$_\.]/)
  47. return 'meta'
  48. },
  49. // custom string handling to deal with triple-quoted strings and string interpolation
  50. "'": function (stream, state) {
  51. return tokenString("'", stream, state, false)
  52. },
  53. '"': function (stream, state) {
  54. return tokenString('"', stream, state, false)
  55. },
  56. r: function (stream, state) {
  57. var peek = stream.peek()
  58. if (peek == "'" || peek == '"') {
  59. return tokenString(stream.next(), stream, state, true)
  60. }
  61. return false
  62. },
  63. '}': function (_stream, state) {
  64. // "}" is end of interpolation, if interpolation stack is non-empty
  65. if (sizeInterpolationStack(state) > 0) {
  66. state.tokenize = popInterpolationStack(state)
  67. return null
  68. }
  69. return false
  70. },
  71. '/': function (stream, state) {
  72. if (!stream.eat('*')) return false
  73. state.tokenize = tokenNestedComment(1)
  74. return state.tokenize(stream, state)
  75. },
  76. token: function (stream, _, style) {
  77. if (style == 'variable') {
  78. // Assume uppercase symbols are classes using variable-2
  79. var isUpper = RegExp('^[_$]*[A-Z][a-zA-Z0-9_$]*$', 'g')
  80. if (isUpper.test(stream.current())) {
  81. return 'variable-2'
  82. }
  83. }
  84. },
  85. },
  86. })
  87. function tokenString(quote, stream, state, raw) {
  88. var tripleQuoted = false
  89. if (stream.eat(quote)) {
  90. if (stream.eat(quote)) tripleQuoted = true
  91. else return 'string' //empty string
  92. }
  93. function tokenStringHelper(stream, state) {
  94. var escaped = false
  95. while (!stream.eol()) {
  96. if (!raw && !escaped && stream.peek() == '$') {
  97. pushInterpolationStack(state)
  98. state.tokenize = tokenInterpolation
  99. return 'string'
  100. }
  101. var next = stream.next()
  102. if (next == quote && !escaped && (!tripleQuoted || stream.match(quote + quote))) {
  103. state.tokenize = null
  104. break
  105. }
  106. escaped = !raw && !escaped && next == '\\'
  107. }
  108. return 'string'
  109. }
  110. state.tokenize = tokenStringHelper
  111. return tokenStringHelper(stream, state)
  112. }
  113. function tokenInterpolation(stream, state) {
  114. stream.eat('$')
  115. if (stream.eat('{')) {
  116. // let clike handle the content of ${...},
  117. // we take over again when "}" appears (see hooks).
  118. state.tokenize = null
  119. } else {
  120. state.tokenize = tokenInterpolationIdentifier
  121. }
  122. return null
  123. }
  124. function tokenInterpolationIdentifier(stream, state) {
  125. stream.eatWhile(/[\w_]/)
  126. state.tokenize = popInterpolationStack(state)
  127. return 'variable'
  128. }
  129. function tokenNestedComment(depth) {
  130. return function (stream, state) {
  131. var ch
  132. while ((ch = stream.next())) {
  133. if (ch == '*' && stream.eat('/')) {
  134. if (depth == 1) {
  135. state.tokenize = null
  136. break
  137. } else {
  138. state.tokenize = tokenNestedComment(depth - 1)
  139. return state.tokenize(stream, state)
  140. }
  141. } else if (ch == '/' && stream.eat('*')) {
  142. state.tokenize = tokenNestedComment(depth + 1)
  143. return state.tokenize(stream, state)
  144. }
  145. }
  146. return 'comment'
  147. }
  148. }
  149. CodeMirror.registerHelper('hintWords', 'application/dart', keywords.concat(atoms).concat(builtins))
  150. // This is needed to make loading through meta.js work.
  151. CodeMirror.defineMode(
  152. 'dart',
  153. function (conf) {
  154. return CodeMirror.getMode(conf, 'application/dart')
  155. },
  156. 'clike'
  157. )
  158. })