jinja2.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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'))
  7. else if (typeof define == 'function' && define.amd)
  8. // AMD
  9. define(['../../lib/codemirror'], mod)
  10. // Plain browser env
  11. else mod(CodeMirror)
  12. })(function (CodeMirror) {
  13. 'use strict'
  14. CodeMirror.defineMode('jinja2', function () {
  15. var keywords = [
  16. 'and',
  17. 'as',
  18. 'block',
  19. 'endblock',
  20. 'by',
  21. 'cycle',
  22. 'debug',
  23. 'else',
  24. 'elif',
  25. 'extends',
  26. 'filter',
  27. 'endfilter',
  28. 'firstof',
  29. 'for',
  30. 'endfor',
  31. 'if',
  32. 'endif',
  33. 'ifchanged',
  34. 'endifchanged',
  35. 'ifequal',
  36. 'endifequal',
  37. 'ifnotequal',
  38. 'endifnotequal',
  39. 'in',
  40. 'include',
  41. 'load',
  42. 'not',
  43. 'now',
  44. 'or',
  45. 'parsed',
  46. 'regroup',
  47. 'reversed',
  48. 'spaceless',
  49. 'endspaceless',
  50. 'ssi',
  51. 'templatetag',
  52. 'openblock',
  53. 'closeblock',
  54. 'openvariable',
  55. 'closevariable',
  56. 'openbrace',
  57. 'closebrace',
  58. 'opencomment',
  59. 'closecomment',
  60. 'widthratio',
  61. 'url',
  62. 'with',
  63. 'endwith',
  64. 'get_current_language',
  65. 'trans',
  66. 'endtrans',
  67. 'noop',
  68. 'blocktrans',
  69. 'endblocktrans',
  70. 'get_available_languages',
  71. 'get_current_language_bidi',
  72. 'plural',
  73. ],
  74. operator = /^[+\-*&%=<>!?|~^]/,
  75. sign = /^[:\[\(\{]/,
  76. atom = ['true', 'false'],
  77. number = /^(\d[+\-\*\/])?\d+(\.\d+)?/
  78. keywords = new RegExp('((' + keywords.join(')|(') + '))\\b')
  79. atom = new RegExp('((' + atom.join(')|(') + '))\\b')
  80. function tokenBase(stream, state) {
  81. var ch = stream.peek()
  82. //Comment
  83. if (state.incomment) {
  84. if (!stream.skipTo('#}')) {
  85. stream.skipToEnd()
  86. } else {
  87. stream.eatWhile(/\#|}/)
  88. state.incomment = false
  89. }
  90. return 'comment'
  91. //Tag
  92. } else if (state.intag) {
  93. //After operator
  94. if (state.operator) {
  95. state.operator = false
  96. if (stream.match(atom)) {
  97. return 'atom'
  98. }
  99. if (stream.match(number)) {
  100. return 'number'
  101. }
  102. }
  103. //After sign
  104. if (state.sign) {
  105. state.sign = false
  106. if (stream.match(atom)) {
  107. return 'atom'
  108. }
  109. if (stream.match(number)) {
  110. return 'number'
  111. }
  112. }
  113. if (state.instring) {
  114. if (ch == state.instring) {
  115. state.instring = false
  116. }
  117. stream.next()
  118. return 'string'
  119. } else if (ch == "'" || ch == '"') {
  120. state.instring = ch
  121. stream.next()
  122. return 'string'
  123. } else if (stream.match(state.intag + '}') || (stream.eat('-') && stream.match(state.intag + '}'))) {
  124. state.intag = false
  125. return 'tag'
  126. } else if (stream.match(operator)) {
  127. state.operator = true
  128. return 'operator'
  129. } else if (stream.match(sign)) {
  130. state.sign = true
  131. } else {
  132. if (stream.eat(' ') || stream.sol()) {
  133. if (stream.match(keywords)) {
  134. return 'keyword'
  135. }
  136. if (stream.match(atom)) {
  137. return 'atom'
  138. }
  139. if (stream.match(number)) {
  140. return 'number'
  141. }
  142. if (stream.sol()) {
  143. stream.next()
  144. }
  145. } else {
  146. stream.next()
  147. }
  148. }
  149. return 'variable'
  150. } else if (stream.eat('{')) {
  151. if (stream.eat('#')) {
  152. state.incomment = true
  153. if (!stream.skipTo('#}')) {
  154. stream.skipToEnd()
  155. } else {
  156. stream.eatWhile(/\#|}/)
  157. state.incomment = false
  158. }
  159. return 'comment'
  160. //Open tag
  161. } else if ((ch = stream.eat(/\{|%/))) {
  162. //Cache close tag
  163. state.intag = ch
  164. if (ch == '{') {
  165. state.intag = '}'
  166. }
  167. stream.eat('-')
  168. return 'tag'
  169. }
  170. }
  171. stream.next()
  172. }
  173. return {
  174. startState: function () {
  175. return { tokenize: tokenBase }
  176. },
  177. token: function (stream, state) {
  178. return state.tokenize(stream, state)
  179. },
  180. blockCommentStart: '{#',
  181. blockCommentEnd: '#}',
  182. }
  183. })
  184. CodeMirror.defineMIME('text/jinja2', 'jinja2')
  185. })