twig.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. define('vs/basic-languages/twig/twig',["require", "exports"], function (require, exports) {
  6. "use strict";
  7. Object.defineProperty(exports, "__esModule", { value: true });
  8. exports.language = exports.conf = void 0;
  9. exports.conf = {
  10. wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\$\^\&\*\(\)\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\s]+)/g,
  11. comments: {
  12. blockComment: ['{#', '#}']
  13. },
  14. brackets: [
  15. ['{#', '#}'],
  16. ['{%', '%}'],
  17. ['{{', '}}'],
  18. ['(', ')'],
  19. ['[', ']'],
  20. // HTML
  21. ['<!--', '-->'],
  22. ['<', '>']
  23. ],
  24. autoClosingPairs: [
  25. { open: '{# ', close: ' #}' },
  26. { open: '{% ', close: ' %}' },
  27. { open: '{{ ', close: ' }}' },
  28. { open: '[', close: ']' },
  29. { open: '(', close: ')' },
  30. { open: '"', close: '"' },
  31. { open: "'", close: "'" }
  32. ],
  33. surroundingPairs: [
  34. { open: '"', close: '"' },
  35. { open: "'", close: "'" },
  36. // HTML
  37. { open: '<', close: '>' }
  38. ]
  39. };
  40. exports.language = {
  41. defaultToken: '',
  42. tokenPostfix: '',
  43. ignoreCase: true,
  44. keywords: [
  45. // (opening) tags
  46. 'apply',
  47. 'autoescape',
  48. 'block',
  49. 'deprecated',
  50. 'do',
  51. 'embed',
  52. 'extends',
  53. 'flush',
  54. 'for',
  55. 'from',
  56. 'if',
  57. 'import',
  58. 'include',
  59. 'macro',
  60. 'sandbox',
  61. 'set',
  62. 'use',
  63. 'verbatim',
  64. 'with',
  65. // closing tags
  66. 'endapply',
  67. 'endautoescape',
  68. 'endblock',
  69. 'endembed',
  70. 'endfor',
  71. 'endif',
  72. 'endmacro',
  73. 'endsandbox',
  74. 'endset',
  75. 'endwith',
  76. // literals
  77. 'true',
  78. 'false'
  79. ],
  80. tokenizer: {
  81. root: [
  82. // whitespace
  83. [/\s+/],
  84. // Twig Tag Delimiters
  85. [/{#/, 'comment.twig', '@commentState'],
  86. [/{%[-~]?/, 'delimiter.twig', '@blockState'],
  87. [/{{[-~]?/, 'delimiter.twig', '@variableState'],
  88. // HTML
  89. [/<!DOCTYPE/, 'metatag.html', '@doctype'],
  90. [/<!--/, 'comment.html', '@comment'],
  91. [
  92. /(<)((?:[\w\-]+:)?[\w\-]+)(\s*)(\/>)/,
  93. ['delimiter.html', 'tag.html', '', 'delimiter.html']
  94. ],
  95. [/(<)(script)/, ['delimiter.html', { token: 'tag.html', next: '@script' }]],
  96. [/(<)(style)/, ['delimiter.html', { token: 'tag.html', next: '@style' }]],
  97. [
  98. /(<)((?:[\w\-]+:)?[\w\-]+)/,
  99. ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]
  100. ],
  101. [
  102. /(<\/)((?:[\w\-]+:)?[\w\-]+)/,
  103. ['delimiter.html', { token: 'tag.html', next: '@otherTag' }]
  104. ],
  105. [/</, 'delimiter.html'],
  106. [/[^<]+/] // text
  107. ],
  108. /**
  109. * Comment Tag Handling
  110. */
  111. commentState: [
  112. [/#}/, 'comment.twig', '@pop'],
  113. [/./, 'comment.twig']
  114. ],
  115. /**
  116. * Block Tag Handling
  117. */
  118. blockState: [
  119. [/[-~]?%}/, 'delimiter.twig', '@pop'],
  120. // whitespace
  121. [/\s+/],
  122. // verbatim
  123. // Unlike other blocks, verbatim ehas its own state
  124. // transition to ensure we mark its contents as strings.
  125. [
  126. /(verbatim)(\s*)([-~]?%})/,
  127. ['keyword.twig', '', { token: 'delimiter.twig', next: '@rawDataState' }]
  128. ],
  129. { include: 'expression' }
  130. ],
  131. rawDataState: [
  132. // endverbatim
  133. [
  134. /({%[-~]?)(\s*)(endverbatim)(\s*)([-~]?%})/,
  135. [
  136. 'delimiter.twig',
  137. '',
  138. 'keyword.twig',
  139. '',
  140. { token: 'delimiter.twig', next: '@popall' }
  141. ]
  142. ],
  143. [/./, 'string.twig']
  144. ],
  145. /**
  146. * Variable Tag Handling
  147. */
  148. variableState: [[/[-~]?}}/, 'delimiter.twig', '@pop'], { include: 'expression' }],
  149. stringState: [
  150. // closing double quoted string
  151. [/"/, 'string.twig', '@pop'],
  152. // interpolation start
  153. [/#{\s*/, 'string.twig', '@interpolationState'],
  154. // string part
  155. [/[^#"\\]*(?:(?:\\.|#(?!\{))[^#"\\]*)*/, 'string.twig']
  156. ],
  157. interpolationState: [
  158. // interpolation end
  159. [/}/, 'string.twig', '@pop'],
  160. { include: 'expression' }
  161. ],
  162. /**
  163. * Expression Handling
  164. */
  165. expression: [
  166. // whitespace
  167. [/\s+/],
  168. // operators - math
  169. [/\+|-|\/{1,2}|%|\*{1,2}/, 'operators.twig'],
  170. // operators - logic
  171. [/(and|or|not|b-and|b-xor|b-or)(\s+)/, ['operators.twig', '']],
  172. // operators - comparison (symbols)
  173. [/==|!=|<|>|>=|<=/, 'operators.twig'],
  174. // operators - comparison (words)
  175. [/(starts with|ends with|matches)(\s+)/, ['operators.twig', '']],
  176. // operators - containment
  177. [/(in)(\s+)/, ['operators.twig', '']],
  178. // operators - test
  179. [/(is)(\s+)/, ['operators.twig', '']],
  180. // operators - misc
  181. [/\||~|:|\.{1,2}|\?{1,2}/, 'operators.twig'],
  182. // names
  183. [
  184. /[^\W\d][\w]*/,
  185. {
  186. cases: {
  187. '@keywords': 'keyword.twig',
  188. '@default': 'variable.twig'
  189. }
  190. }
  191. ],
  192. // numbers
  193. [/\d+(\.\d+)?/, 'number.twig'],
  194. // punctuation
  195. [/\(|\)|\[|\]|{|}|,/, 'delimiter.twig'],
  196. // strings
  197. [/"([^#"\\]*(?:\\.[^#"\\]*)*)"|\'([^\'\\]*(?:\\.[^\'\\]*)*)\'/, 'string.twig'],
  198. // opening double quoted string
  199. [/"/, 'string.twig', '@stringState'],
  200. // misc syntactic constructs
  201. // These are not operators per se, but for the purposes of lexical analysis we
  202. // can treat them as such.
  203. // arrow functions
  204. [/=>/, 'operators.twig'],
  205. // assignment
  206. [/=/, 'operators.twig']
  207. ],
  208. /**
  209. * HTML
  210. */
  211. doctype: [
  212. [/[^>]+/, 'metatag.content.html'],
  213. [/>/, 'metatag.html', '@pop']
  214. ],
  215. comment: [
  216. [/-->/, 'comment.html', '@pop'],
  217. [/[^-]+/, 'comment.content.html'],
  218. [/./, 'comment.content.html']
  219. ],
  220. otherTag: [
  221. [/\/?>/, 'delimiter.html', '@pop'],
  222. [/"([^"]*)"/, 'attribute.value.html'],
  223. [/'([^']*)'/, 'attribute.value.html'],
  224. [/[\w\-]+/, 'attribute.name.html'],
  225. [/=/, 'delimiter.html'],
  226. [/[ \t\r\n]+/] // whitespace
  227. ],
  228. // -- BEGIN <script> tags handling
  229. // After <script
  230. script: [
  231. [/type/, 'attribute.name.html', '@scriptAfterType'],
  232. [/"([^"]*)"/, 'attribute.value.html'],
  233. [/'([^']*)'/, 'attribute.value.html'],
  234. [/[\w\-]+/, 'attribute.name.html'],
  235. [/=/, 'delimiter.html'],
  236. [
  237. />/,
  238. {
  239. token: 'delimiter.html',
  240. next: '@scriptEmbedded',
  241. nextEmbedded: 'text/javascript'
  242. }
  243. ],
  244. [/[ \t\r\n]+/],
  245. [
  246. /(<\/)(script\s*)(>)/,
  247. ['delimiter.html', 'tag.html', { token: 'delimiter.html', next: '@pop' }]
  248. ]
  249. ],
  250. // After <script ... type
  251. scriptAfterType: [
  252. [/=/, 'delimiter.html', '@scriptAfterTypeEquals'],
  253. [
  254. />/,
  255. {
  256. token: 'delimiter.html',
  257. next: '@scriptEmbedded',
  258. nextEmbedded: 'text/javascript'
  259. }
  260. ],
  261. [/[ \t\r\n]+/],
  262. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  263. ],
  264. // After <script ... type =
  265. scriptAfterTypeEquals: [
  266. [
  267. /"([^"]*)"/,
  268. {
  269. token: 'attribute.value.html',
  270. switchTo: '@scriptWithCustomType.$1'
  271. }
  272. ],
  273. [
  274. /'([^']*)'/,
  275. {
  276. token: 'attribute.value.html',
  277. switchTo: '@scriptWithCustomType.$1'
  278. }
  279. ],
  280. [
  281. />/,
  282. {
  283. token: 'delimiter.html',
  284. next: '@scriptEmbedded',
  285. nextEmbedded: 'text/javascript'
  286. }
  287. ],
  288. [/[ \t\r\n]+/],
  289. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  290. ],
  291. // After <script ... type = $S2
  292. scriptWithCustomType: [
  293. [
  294. />/,
  295. {
  296. token: 'delimiter.html',
  297. next: '@scriptEmbedded.$S2',
  298. nextEmbedded: '$S2'
  299. }
  300. ],
  301. [/"([^"]*)"/, 'attribute.value.html'],
  302. [/'([^']*)'/, 'attribute.value.html'],
  303. [/[\w\-]+/, 'attribute.name.html'],
  304. [/=/, 'delimiter.html'],
  305. [/[ \t\r\n]+/],
  306. [/<\/script\s*>/, { token: '@rematch', next: '@pop' }]
  307. ],
  308. scriptEmbedded: [
  309. [/<\/script/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  310. [/[^<]+/, '']
  311. ],
  312. // -- END <script> tags handling
  313. // -- BEGIN <style> tags handling
  314. // After <style
  315. style: [
  316. [/type/, 'attribute.name.html', '@styleAfterType'],
  317. [/"([^"]*)"/, 'attribute.value.html'],
  318. [/'([^']*)'/, 'attribute.value.html'],
  319. [/[\w\-]+/, 'attribute.name.html'],
  320. [/=/, 'delimiter.html'],
  321. [
  322. />/,
  323. {
  324. token: 'delimiter.html',
  325. next: '@styleEmbedded',
  326. nextEmbedded: 'text/css'
  327. }
  328. ],
  329. [/[ \t\r\n]+/],
  330. [
  331. /(<\/)(style\s*)(>)/,
  332. ['delimiter.html', 'tag.html', { token: 'delimiter.html', next: '@pop' }]
  333. ]
  334. ],
  335. // After <style ... type
  336. styleAfterType: [
  337. [/=/, 'delimiter.html', '@styleAfterTypeEquals'],
  338. [
  339. />/,
  340. {
  341. token: 'delimiter.html',
  342. next: '@styleEmbedded',
  343. nextEmbedded: 'text/css'
  344. }
  345. ],
  346. [/[ \t\r\n]+/],
  347. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  348. ],
  349. // After <style ... type =
  350. styleAfterTypeEquals: [
  351. [
  352. /"([^"]*)"/,
  353. {
  354. token: 'attribute.value.html',
  355. switchTo: '@styleWithCustomType.$1'
  356. }
  357. ],
  358. [
  359. /'([^']*)'/,
  360. {
  361. token: 'attribute.value.html',
  362. switchTo: '@styleWithCustomType.$1'
  363. }
  364. ],
  365. [
  366. />/,
  367. {
  368. token: 'delimiter.html',
  369. next: '@styleEmbedded',
  370. nextEmbedded: 'text/css'
  371. }
  372. ],
  373. [/[ \t\r\n]+/],
  374. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  375. ],
  376. // After <style ... type = $S2
  377. styleWithCustomType: [
  378. [
  379. />/,
  380. {
  381. token: 'delimiter.html',
  382. next: '@styleEmbedded.$S2',
  383. nextEmbedded: '$S2'
  384. }
  385. ],
  386. [/"([^"]*)"/, 'attribute.value.html'],
  387. [/'([^']*)'/, 'attribute.value.html'],
  388. [/[\w\-]+/, 'attribute.name.html'],
  389. [/=/, 'delimiter.html'],
  390. [/[ \t\r\n]+/],
  391. [/<\/style\s*>/, { token: '@rematch', next: '@pop' }]
  392. ],
  393. styleEmbedded: [
  394. [/<\/style/, { token: '@rematch', next: '@pop', nextEmbedded: '@pop' }],
  395. [/[^<]+/, '']
  396. ]
  397. }
  398. };
  399. });