scss.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. export var conf = {
  6. wordPattern: /(#?-?\d*\.\d\w*%?)|([@$#!.:]?[\w-?]+%?)|[@#!.]/g,
  7. comments: {
  8. blockComment: ['/*', '*/'],
  9. lineComment: '//'
  10. },
  11. brackets: [
  12. ['{', '}'],
  13. ['[', ']'],
  14. ['(', ')']
  15. ],
  16. autoClosingPairs: [
  17. { open: '{', close: '}', notIn: ['string', 'comment'] },
  18. { open: '[', close: ']', notIn: ['string', 'comment'] },
  19. { open: '(', close: ')', notIn: ['string', 'comment'] },
  20. { open: '"', close: '"', notIn: ['string', 'comment'] },
  21. { open: "'", close: "'", notIn: ['string', 'comment'] }
  22. ],
  23. surroundingPairs: [
  24. { open: '{', close: '}' },
  25. { open: '[', close: ']' },
  26. { open: '(', close: ')' },
  27. { open: '"', close: '"' },
  28. { open: "'", close: "'" }
  29. ],
  30. folding: {
  31. markers: {
  32. start: new RegExp('^\\s*\\/\\*\\s*#region\\b\\s*(.*?)\\s*\\*\\/'),
  33. end: new RegExp('^\\s*\\/\\*\\s*#endregion\\b.*\\*\\/')
  34. }
  35. }
  36. };
  37. export var language = {
  38. defaultToken: '',
  39. tokenPostfix: '.scss',
  40. ws: '[ \t\n\r\f]*',
  41. identifier: '-?-?([a-zA-Z]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))([\\w\\-]|(\\\\(([0-9a-fA-F]{1,6}\\s?)|[^[0-9a-fA-F])))*',
  42. brackets: [
  43. { open: '{', close: '}', token: 'delimiter.curly' },
  44. { open: '[', close: ']', token: 'delimiter.bracket' },
  45. { open: '(', close: ')', token: 'delimiter.parenthesis' },
  46. { open: '<', close: '>', token: 'delimiter.angle' }
  47. ],
  48. tokenizer: {
  49. root: [{ include: '@selector' }],
  50. selector: [
  51. { include: '@comments' },
  52. { include: '@import' },
  53. { include: '@variabledeclaration' },
  54. { include: '@warndebug' },
  55. ['[@](include)', { token: 'keyword', next: '@includedeclaration' }],
  56. [
  57. '[@](keyframes|-webkit-keyframes|-moz-keyframes|-o-keyframes)',
  58. { token: 'keyword', next: '@keyframedeclaration' }
  59. ],
  60. ['[@](page|content|font-face|-moz-document)', { token: 'keyword' }],
  61. ['[@](charset|namespace)', { token: 'keyword', next: '@declarationbody' }],
  62. ['[@](function)', { token: 'keyword', next: '@functiondeclaration' }],
  63. ['[@](mixin)', { token: 'keyword', next: '@mixindeclaration' }],
  64. ['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
  65. { include: '@controlstatement' },
  66. { include: '@selectorname' },
  67. ['[&\\*]', 'tag'],
  68. ['[>\\+,]', 'delimiter'],
  69. ['\\[', { token: 'delimiter.bracket', next: '@selectorattribute' }],
  70. ['{', { token: 'delimiter.curly', next: '@selectorbody' }]
  71. ],
  72. selectorbody: [
  73. ['[*_]?@identifier@ws:(?=(\\s|\\d|[^{;}]*[;}]))', 'attribute.name', '@rulevalue'],
  74. { include: '@selector' },
  75. ['[@](extend)', { token: 'keyword', next: '@extendbody' }],
  76. ['[@](return)', { token: 'keyword', next: '@declarationbody' }],
  77. ['}', { token: 'delimiter.curly', next: '@pop' }]
  78. ],
  79. selectorname: [
  80. ['#{', { token: 'meta', next: '@variableinterpolation' }],
  81. ['(\\.|#(?=[^{])|%|(@identifier)|:)+', 'tag'] // selector (.foo, div, ...)
  82. ],
  83. selectorattribute: [
  84. { include: '@term' },
  85. [']', { token: 'delimiter.bracket', next: '@pop' }]
  86. ],
  87. term: [
  88. { include: '@comments' },
  89. ['url(\\-prefix)?\\(', { token: 'meta', next: '@urldeclaration' }],
  90. { include: '@functioninvocation' },
  91. { include: '@numbers' },
  92. { include: '@strings' },
  93. { include: '@variablereference' },
  94. ['(and\\b|or\\b|not\\b)', 'operator'],
  95. { include: '@name' },
  96. ['([<>=\\+\\-\\*\\/\\^\\|\\~,])', 'operator'],
  97. [',', 'delimiter'],
  98. ['!default', 'literal'],
  99. ['\\(', { token: 'delimiter.parenthesis', next: '@parenthizedterm' }]
  100. ],
  101. rulevalue: [
  102. { include: '@term' },
  103. ['!important', 'literal'],
  104. [';', 'delimiter', '@pop'],
  105. ['{', { token: 'delimiter.curly', switchTo: '@nestedproperty' }],
  106. ['(?=})', { token: '', next: '@pop' }] // missing semicolon
  107. ],
  108. nestedproperty: [
  109. ['[*_]?@identifier@ws:', 'attribute.name', '@rulevalue'],
  110. { include: '@comments' },
  111. ['}', { token: 'delimiter.curly', next: '@pop' }]
  112. ],
  113. warndebug: [['[@](warn|debug)', { token: 'keyword', next: '@declarationbody' }]],
  114. import: [['[@](import)', { token: 'keyword', next: '@declarationbody' }]],
  115. variabledeclaration: [
  116. // sass variables
  117. ['\\$@identifier@ws:', 'variable.decl', '@declarationbody']
  118. ],
  119. urldeclaration: [
  120. { include: '@strings' },
  121. ['[^)\r\n]+', 'string'],
  122. ['\\)', { token: 'meta', next: '@pop' }]
  123. ],
  124. parenthizedterm: [
  125. { include: '@term' },
  126. ['\\)', { token: 'delimiter.parenthesis', next: '@pop' }]
  127. ],
  128. declarationbody: [
  129. { include: '@term' },
  130. [';', 'delimiter', '@pop'],
  131. ['(?=})', { token: '', next: '@pop' }] // missing semicolon
  132. ],
  133. extendbody: [
  134. { include: '@selectorname' },
  135. ['!optional', 'literal'],
  136. [';', 'delimiter', '@pop'],
  137. ['(?=})', { token: '', next: '@pop' }] // missing semicolon
  138. ],
  139. variablereference: [
  140. // sass variable reference
  141. ['\\$@identifier', 'variable.ref'],
  142. ['\\.\\.\\.', 'operator'],
  143. ['#{', { token: 'meta', next: '@variableinterpolation' }] // sass var resolve
  144. ],
  145. variableinterpolation: [
  146. { include: '@variablereference' },
  147. ['}', { token: 'meta', next: '@pop' }]
  148. ],
  149. comments: [
  150. ['\\/\\*', 'comment', '@comment'],
  151. ['\\/\\/+.*', 'comment']
  152. ],
  153. comment: [
  154. ['\\*\\/', 'comment', '@pop'],
  155. ['.', 'comment']
  156. ],
  157. name: [['@identifier', 'attribute.value']],
  158. numbers: [
  159. ['(\\d*\\.)?\\d+([eE][\\-+]?\\d+)?', { token: 'number', next: '@units' }],
  160. ['#[0-9a-fA-F_]+(?!\\w)', 'number.hex']
  161. ],
  162. units: [
  163. [
  164. '(em|ex|ch|rem|vmin|vmax|vw|vh|vm|cm|mm|in|px|pt|pc|deg|grad|rad|turn|s|ms|Hz|kHz|%)?',
  165. 'number',
  166. '@pop'
  167. ]
  168. ],
  169. functiondeclaration: [
  170. ['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
  171. ['{', { token: 'delimiter.curly', switchTo: '@functionbody' }]
  172. ],
  173. mixindeclaration: [
  174. // mixin with parameters
  175. ['@identifier@ws\\(', { token: 'meta', next: '@parameterdeclaration' }],
  176. // mixin without parameters
  177. ['@identifier', 'meta'],
  178. ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }]
  179. ],
  180. parameterdeclaration: [
  181. ['\\$@identifier@ws:', 'variable.decl'],
  182. ['\\.\\.\\.', 'operator'],
  183. [',', 'delimiter'],
  184. { include: '@term' },
  185. ['\\)', { token: 'meta', next: '@pop' }]
  186. ],
  187. includedeclaration: [
  188. { include: '@functioninvocation' },
  189. ['@identifier', 'meta'],
  190. [';', 'delimiter', '@pop'],
  191. ['(?=})', { token: '', next: '@pop' }],
  192. ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }]
  193. ],
  194. keyframedeclaration: [
  195. ['@identifier', 'meta'],
  196. ['{', { token: 'delimiter.curly', switchTo: '@keyframebody' }]
  197. ],
  198. keyframebody: [
  199. { include: '@term' },
  200. ['{', { token: 'delimiter.curly', next: '@selectorbody' }],
  201. ['}', { token: 'delimiter.curly', next: '@pop' }]
  202. ],
  203. controlstatement: [
  204. [
  205. '[@](if|else|for|while|each|media)',
  206. { token: 'keyword.flow', next: '@controlstatementdeclaration' }
  207. ]
  208. ],
  209. controlstatementdeclaration: [
  210. ['(in|from|through|if|to)\\b', { token: 'keyword.flow' }],
  211. { include: '@term' },
  212. ['{', { token: 'delimiter.curly', switchTo: '@selectorbody' }]
  213. ],
  214. functionbody: [
  215. ['[@](return)', { token: 'keyword' }],
  216. { include: '@variabledeclaration' },
  217. { include: '@term' },
  218. { include: '@controlstatement' },
  219. [';', 'delimiter'],
  220. ['}', { token: 'delimiter.curly', next: '@pop' }]
  221. ],
  222. functioninvocation: [['@identifier\\(', { token: 'meta', next: '@functionarguments' }]],
  223. functionarguments: [
  224. ['\\$@identifier@ws:', 'attribute.name'],
  225. ['[,]', 'delimiter'],
  226. { include: '@term' },
  227. ['\\)', { token: 'meta', next: '@pop' }]
  228. ],
  229. strings: [
  230. ['~?"', { token: 'string.delimiter', next: '@stringenddoublequote' }],
  231. ["~?'", { token: 'string.delimiter', next: '@stringendquote' }]
  232. ],
  233. stringenddoublequote: [
  234. ['\\\\.', 'string'],
  235. ['"', { token: 'string.delimiter', next: '@pop' }],
  236. ['.', 'string']
  237. ],
  238. stringendquote: [
  239. ['\\\\.', 'string'],
  240. ["'", { token: 'string.delimiter', next: '@pop' }],
  241. ['.', 'string']
  242. ]
  243. }
  244. };