less 4.4.2 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (333) hide show
  1. package/bin/lessc +67 -58
  2. package/dist/less.js +14496 -11811
  3. package/dist/less.min.js +4 -4
  4. package/dist/less.min.js.map +1 -1
  5. package/lib/less/constants.js +5 -7
  6. package/lib/less/contexts.js +71 -56
  7. package/lib/less/data/colors.js +150 -153
  8. package/lib/less/data/index.js +4 -7
  9. package/lib/less/data/unit-conversions.js +2 -5
  10. package/lib/less/default-options.js +52 -23
  11. package/lib/less/deprecation.js +67 -0
  12. package/lib/less/environment/abstract-file-manager.js +62 -50
  13. package/lib/less/environment/abstract-plugin-loader.js +69 -46
  14. package/lib/less/environment/environment-api.ts +21 -0
  15. package/lib/less/environment/environment.js +34 -30
  16. package/lib/less/environment/file-manager-api.ts +77 -0
  17. package/lib/less/functions/boolean.js +13 -13
  18. package/lib/less/functions/color-blending.js +39 -31
  19. package/lib/less/functions/color.js +153 -137
  20. package/lib/less/functions/data-uri.js +73 -64
  21. package/lib/less/functions/default.js +9 -11
  22. package/lib/less/functions/function-caller.js +35 -34
  23. package/lib/less/functions/function-registry.js +16 -17
  24. package/lib/less/functions/index.js +33 -33
  25. package/lib/less/functions/list.js +88 -75
  26. package/lib/less/functions/math-helper.js +8 -11
  27. package/lib/less/functions/math.js +21 -21
  28. package/lib/less/functions/number.js +42 -53
  29. package/lib/less/functions/string.js +18 -22
  30. package/lib/less/functions/style.js +21 -20
  31. package/lib/less/functions/svg.js +83 -82
  32. package/lib/less/functions/types.js +28 -32
  33. package/lib/less/import-manager.js +73 -64
  34. package/lib/less/index.js +65 -65
  35. package/lib/less/less-error.js +65 -46
  36. package/lib/less/logger.js +11 -14
  37. package/lib/less/parse-tree.js +94 -38
  38. package/lib/less/parse.js +44 -44
  39. package/lib/less/parser/parser-input.js +152 -131
  40. package/lib/less/parser/parser.js +866 -672
  41. package/lib/less/plugin-manager.js +57 -46
  42. package/lib/less/render.js +17 -23
  43. package/lib/less/source-map-builder.js +52 -43
  44. package/lib/less/source-map-output.js +57 -44
  45. package/lib/less/transform-tree.js +40 -30
  46. package/lib/less/tree/anonymous.js +52 -28
  47. package/lib/less/tree/assignment.js +44 -27
  48. package/lib/less/tree/atrule-syntax.js +4 -6
  49. package/lib/less/tree/atrule.js +247 -140
  50. package/lib/less/tree/attribute.js +55 -24
  51. package/lib/less/tree/call.js +70 -42
  52. package/lib/less/tree/color.js +194 -145
  53. package/lib/less/tree/combinator.js +31 -21
  54. package/lib/less/tree/comment.js +44 -23
  55. package/lib/less/tree/condition.js +61 -36
  56. package/lib/less/tree/container.js +90 -34
  57. package/lib/less/tree/debug-info.js +53 -11
  58. package/lib/less/tree/declaration.js +97 -52
  59. package/lib/less/tree/detached-ruleset.js +42 -24
  60. package/lib/less/tree/dimension.js +127 -71
  61. package/lib/less/tree/element.js +82 -52
  62. package/lib/less/tree/expression.js +75 -50
  63. package/lib/less/tree/extend.js +71 -42
  64. package/lib/less/tree/import.js +184 -110
  65. package/lib/less/tree/index.js +52 -81
  66. package/lib/less/tree/javascript.js +43 -32
  67. package/lib/less/tree/js-eval-node.js +46 -32
  68. package/lib/less/tree/keyword.js +25 -17
  69. package/lib/less/tree/media.js +77 -35
  70. package/lib/less/tree/merge-rules.js +47 -0
  71. package/lib/less/tree/mixin-call.js +181 -98
  72. package/lib/less/tree/mixin-definition.js +211 -117
  73. package/lib/less/tree/namespace-value.js +63 -44
  74. package/lib/less/tree/negative.js +34 -21
  75. package/lib/less/tree/nested-at-rule.js +149 -66
  76. package/lib/less/tree/node.js +225 -90
  77. package/lib/less/tree/operation.js +59 -34
  78. package/lib/less/tree/paren.js +34 -17
  79. package/lib/less/tree/property.js +66 -35
  80. package/lib/less/tree/query-in-parens.js +52 -60
  81. package/lib/less/tree/quoted.js +93 -44
  82. package/lib/less/tree/ruleset.js +632 -318
  83. package/lib/less/tree/selector.js +151 -77
  84. package/lib/less/tree/unicode-descriptor.js +14 -12
  85. package/lib/less/tree/unit.js +111 -63
  86. package/lib/less/tree/url.js +62 -38
  87. package/lib/less/tree/value.js +50 -34
  88. package/lib/less/tree/variable-call.js +47 -30
  89. package/lib/less/tree/variable.js +53 -31
  90. package/lib/less/utils.js +44 -47
  91. package/lib/less/visitors/extend-visitor.js +233 -172
  92. package/lib/less/visitors/import-sequencer.js +24 -24
  93. package/lib/less/visitors/import-visitor.js +62 -52
  94. package/lib/less/visitors/index.js +14 -17
  95. package/lib/less/visitors/join-selector-visitor.js +40 -37
  96. package/lib/less/visitors/set-tree-visibility-visitor.js +32 -18
  97. package/lib/less/visitors/to-css-visitor.js +135 -128
  98. package/lib/less/visitors/visitor.js +60 -45
  99. package/lib/less-browser/add-default-options.js +23 -13
  100. package/lib/less-browser/bootstrap.js +23 -17
  101. package/lib/less-browser/browser.js +24 -21
  102. package/lib/less-browser/cache.js +17 -19
  103. package/lib/less-browser/error-reporting.js +52 -44
  104. package/lib/less-browser/file-manager.js +52 -42
  105. package/lib/less-browser/image-size.js +12 -12
  106. package/lib/less-browser/index.js +131 -105
  107. package/lib/less-browser/log-listener.js +30 -31
  108. package/lib/less-browser/plugin-loader.js +10 -10
  109. package/lib/less-browser/utils.js +19 -21
  110. package/lib/less-node/environment.js +32 -8
  111. package/lib/less-node/file-manager.js +62 -45
  112. package/lib/less-node/fs.js +11 -8
  113. package/lib/less-node/image-size.js +40 -31
  114. package/lib/less-node/index.js +28 -19
  115. package/lib/less-node/lessc-helper.js +28 -28
  116. package/lib/less-node/plugin-loader.js +35 -27
  117. package/lib/less-node/url-file-manager.js +33 -31
  118. package/package.json +31 -19
  119. package/.eslintignore +0 -6
  120. package/.eslintrc.js +0 -63
  121. package/Gruntfile.js +0 -404
  122. package/bower.json +0 -22
  123. package/lib/less/constants.js.map +0 -1
  124. package/lib/less/contexts.js.map +0 -1
  125. package/lib/less/data/colors.js.map +0 -1
  126. package/lib/less/data/index.js.map +0 -1
  127. package/lib/less/data/unit-conversions.js.map +0 -1
  128. package/lib/less/default-options.js.map +0 -1
  129. package/lib/less/environment/abstract-file-manager.js.map +0 -1
  130. package/lib/less/environment/abstract-plugin-loader.js.map +0 -1
  131. package/lib/less/environment/environment-api.js +0 -3
  132. package/lib/less/environment/environment-api.js.map +0 -1
  133. package/lib/less/environment/environment.js.map +0 -1
  134. package/lib/less/environment/file-manager-api.js +0 -3
  135. package/lib/less/environment/file-manager-api.js.map +0 -1
  136. package/lib/less/functions/boolean.js.map +0 -1
  137. package/lib/less/functions/color-blending.js.map +0 -1
  138. package/lib/less/functions/color.js.map +0 -1
  139. package/lib/less/functions/data-uri.js.map +0 -1
  140. package/lib/less/functions/default.js.map +0 -1
  141. package/lib/less/functions/function-caller.js.map +0 -1
  142. package/lib/less/functions/function-registry.js.map +0 -1
  143. package/lib/less/functions/index.js.map +0 -1
  144. package/lib/less/functions/list.js.map +0 -1
  145. package/lib/less/functions/math-helper.js.map +0 -1
  146. package/lib/less/functions/math.js.map +0 -1
  147. package/lib/less/functions/number.js.map +0 -1
  148. package/lib/less/functions/string.js.map +0 -1
  149. package/lib/less/functions/style.js.map +0 -1
  150. package/lib/less/functions/svg.js.map +0 -1
  151. package/lib/less/functions/types.js.map +0 -1
  152. package/lib/less/import-manager.js.map +0 -1
  153. package/lib/less/index.js.map +0 -1
  154. package/lib/less/less-error.js.map +0 -1
  155. package/lib/less/logger.js.map +0 -1
  156. package/lib/less/parse-tree.js.map +0 -1
  157. package/lib/less/parse.js.map +0 -1
  158. package/lib/less/parser/chunker.js +0 -148
  159. package/lib/less/parser/chunker.js.map +0 -1
  160. package/lib/less/parser/parser-input.js.map +0 -1
  161. package/lib/less/parser/parser.js.map +0 -1
  162. package/lib/less/plugin-manager.js.map +0 -1
  163. package/lib/less/render.js.map +0 -1
  164. package/lib/less/source-map-builder.js.map +0 -1
  165. package/lib/less/source-map-output.js.map +0 -1
  166. package/lib/less/transform-tree.js.map +0 -1
  167. package/lib/less/tree/anonymous.js.map +0 -1
  168. package/lib/less/tree/assignment.js.map +0 -1
  169. package/lib/less/tree/atrule-syntax.js.map +0 -1
  170. package/lib/less/tree/atrule.js.map +0 -1
  171. package/lib/less/tree/attribute.js.map +0 -1
  172. package/lib/less/tree/call.js.map +0 -1
  173. package/lib/less/tree/color.js.map +0 -1
  174. package/lib/less/tree/combinator.js.map +0 -1
  175. package/lib/less/tree/comment.js.map +0 -1
  176. package/lib/less/tree/condition.js.map +0 -1
  177. package/lib/less/tree/container.js.map +0 -1
  178. package/lib/less/tree/debug-info.js.map +0 -1
  179. package/lib/less/tree/declaration.js.map +0 -1
  180. package/lib/less/tree/detached-ruleset.js.map +0 -1
  181. package/lib/less/tree/dimension.js.map +0 -1
  182. package/lib/less/tree/element.js.map +0 -1
  183. package/lib/less/tree/expression.js.map +0 -1
  184. package/lib/less/tree/extend.js.map +0 -1
  185. package/lib/less/tree/import.js.map +0 -1
  186. package/lib/less/tree/index.js.map +0 -1
  187. package/lib/less/tree/javascript.js.map +0 -1
  188. package/lib/less/tree/js-eval-node.js.map +0 -1
  189. package/lib/less/tree/keyword.js.map +0 -1
  190. package/lib/less/tree/media.js.map +0 -1
  191. package/lib/less/tree/mixin-call.js.map +0 -1
  192. package/lib/less/tree/mixin-definition.js.map +0 -1
  193. package/lib/less/tree/namespace-value.js.map +0 -1
  194. package/lib/less/tree/negative.js.map +0 -1
  195. package/lib/less/tree/nested-at-rule.js.map +0 -1
  196. package/lib/less/tree/node.js.map +0 -1
  197. package/lib/less/tree/operation.js.map +0 -1
  198. package/lib/less/tree/paren.js.map +0 -1
  199. package/lib/less/tree/property.js.map +0 -1
  200. package/lib/less/tree/query-in-parens.js.map +0 -1
  201. package/lib/less/tree/quoted.js.map +0 -1
  202. package/lib/less/tree/ruleset.js.map +0 -1
  203. package/lib/less/tree/selector.js.map +0 -1
  204. package/lib/less/tree/unicode-descriptor.js.map +0 -1
  205. package/lib/less/tree/unit.js.map +0 -1
  206. package/lib/less/tree/url.js.map +0 -1
  207. package/lib/less/tree/value.js.map +0 -1
  208. package/lib/less/tree/variable-call.js.map +0 -1
  209. package/lib/less/tree/variable.js.map +0 -1
  210. package/lib/less/utils.js.map +0 -1
  211. package/lib/less/visitors/extend-visitor.js.map +0 -1
  212. package/lib/less/visitors/import-sequencer.js.map +0 -1
  213. package/lib/less/visitors/import-visitor.js.map +0 -1
  214. package/lib/less/visitors/index.js.map +0 -1
  215. package/lib/less/visitors/join-selector-visitor.js.map +0 -1
  216. package/lib/less/visitors/set-tree-visibility-visitor.js.map +0 -1
  217. package/lib/less/visitors/to-css-visitor.js.map +0 -1
  218. package/lib/less/visitors/visitor.js.map +0 -1
  219. package/lib/less-browser/add-default-options.js.map +0 -1
  220. package/lib/less-browser/bootstrap.js.map +0 -1
  221. package/lib/less-browser/browser.js.map +0 -1
  222. package/lib/less-browser/cache.js.map +0 -1
  223. package/lib/less-browser/error-reporting.js.map +0 -1
  224. package/lib/less-browser/file-manager.js.map +0 -1
  225. package/lib/less-browser/image-size.js.map +0 -1
  226. package/lib/less-browser/index.js.map +0 -1
  227. package/lib/less-browser/log-listener.js.map +0 -1
  228. package/lib/less-browser/plugin-loader.js.map +0 -1
  229. package/lib/less-browser/utils.js.map +0 -1
  230. package/lib/less-node/environment.js.map +0 -1
  231. package/lib/less-node/file-manager.js.map +0 -1
  232. package/lib/less-node/fs.js.map +0 -1
  233. package/lib/less-node/image-size.js.map +0 -1
  234. package/lib/less-node/index.js.map +0 -1
  235. package/lib/less-node/lessc-helper.js.map +0 -1
  236. package/lib/less-node/plugin-loader.js.map +0 -1
  237. package/lib/less-node/url-file-manager.js.map +0 -1
  238. package/test/.eslintrc.json +0 -9
  239. package/test/README.md +0 -3
  240. package/test/browser/common.js +0 -230
  241. package/test/browser/css/global-vars/simple.css +0 -3
  242. package/test/browser/css/modify-vars/simple.css +0 -8
  243. package/test/browser/css/plugin/plugin.css +0 -3
  244. package/test/browser/css/postProcessor/postProcessor.css +0 -4
  245. package/test/browser/css/relative-urls/urls.css +0 -36
  246. package/test/browser/css/rewrite-urls/urls.css +0 -36
  247. package/test/browser/css/rootpath/urls.css +0 -35
  248. package/test/browser/css/rootpath-relative/urls.css +0 -35
  249. package/test/browser/css/rootpath-rewrite-urls/urls.css +0 -35
  250. package/test/browser/css/urls.css +0 -54
  251. package/test/browser/generator/benchmark.config.js +0 -50
  252. package/test/browser/generator/generate.js +0 -78
  253. package/test/browser/generator/runner.config.js +0 -188
  254. package/test/browser/generator/runner.js +0 -2
  255. package/test/browser/generator/template.js +0 -93
  256. package/test/browser/generator/utils.js +0 -14
  257. package/test/browser/less/console-errors/test-error.less +0 -3
  258. package/test/browser/less/console-errors/test-error.txt +0 -2
  259. package/test/browser/less/errors/image-height-error.less +0 -3
  260. package/test/browser/less/errors/image-height-error.txt +0 -4
  261. package/test/browser/less/errors/image-size-error.less +0 -3
  262. package/test/browser/less/errors/image-size-error.txt +0 -4
  263. package/test/browser/less/errors/image-width-error.less +0 -3
  264. package/test/browser/less/errors/image-width-error.txt +0 -4
  265. package/test/browser/less/global-vars/simple.less +0 -3
  266. package/test/browser/less/imports/urls.less +0 -4
  267. package/test/browser/less/imports/urls2.less +0 -4
  268. package/test/browser/less/modify-vars/imports/simple2.less +0 -4
  269. package/test/browser/less/modify-vars/simple.less +0 -8
  270. package/test/browser/less/nested-gradient-with-svg-gradient/mixin-consumer.less +0 -5
  271. package/test/browser/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +0 -15
  272. package/test/browser/less/plugin/plugin.js +0 -4
  273. package/test/browser/less/plugin/plugin.less +0 -4
  274. package/test/browser/less/postProcessor/postProcessor.less +0 -4
  275. package/test/browser/less/relative-urls/urls.less +0 -34
  276. package/test/browser/less/rewrite-urls/urls.less +0 -34
  277. package/test/browser/less/rootpath/urls.less +0 -33
  278. package/test/browser/less/rootpath-relative/urls.less +0 -33
  279. package/test/browser/less/rootpath-rewrite-urls/urls.less +0 -33
  280. package/test/browser/less/urls.less +0 -62
  281. package/test/browser/runner-VisitorPlugin-options.js +0 -3
  282. package/test/browser/runner-VisitorPlugin.js +0 -3
  283. package/test/browser/runner-browser-options.js +0 -51
  284. package/test/browser/runner-browser-spec.js +0 -12
  285. package/test/browser/runner-console-errors.js +0 -5
  286. package/test/browser/runner-errors-options.js +0 -6
  287. package/test/browser/runner-errors-spec.js +0 -3
  288. package/test/browser/runner-filemanagerPlugin-options.js +0 -5
  289. package/test/browser/runner-filemanagerPlugin.js +0 -3
  290. package/test/browser/runner-global-vars-options.js +0 -7
  291. package/test/browser/runner-global-vars-spec.js +0 -3
  292. package/test/browser/runner-legacy-options.js +0 -6
  293. package/test/browser/runner-legacy-spec.js +0 -3
  294. package/test/browser/runner-main-options.js +0 -17
  295. package/test/browser/runner-main-spec.js +0 -7
  296. package/test/browser/runner-modify-vars-options.js +0 -5
  297. package/test/browser/runner-modify-vars-spec.js +0 -33
  298. package/test/browser/runner-no-js-errors-options.js +0 -4
  299. package/test/browser/runner-no-js-errors-spec.js +0 -3
  300. package/test/browser/runner-postProcessorPlugin-options.js +0 -3
  301. package/test/browser/runner-postProcessorPlugin.js +0 -3
  302. package/test/browser/runner-preProcessorPlugin-options.js +0 -3
  303. package/test/browser/runner-preProcessorPlugin.js +0 -3
  304. package/test/browser/runner-production-options.js +0 -3
  305. package/test/browser/runner-production-spec.js +0 -5
  306. package/test/browser/runner-relative-urls-options.js +0 -3
  307. package/test/browser/runner-relative-urls-spec.js +0 -3
  308. package/test/browser/runner-rewrite-urls-options.js +0 -3
  309. package/test/browser/runner-rewrite-urls-spec.js +0 -3
  310. package/test/browser/runner-rootpath-options.js +0 -3
  311. package/test/browser/runner-rootpath-relative-options.js +0 -4
  312. package/test/browser/runner-rootpath-relative-spec.js +0 -3
  313. package/test/browser/runner-rootpath-rewrite-urls-options.js +0 -4
  314. package/test/browser/runner-rootpath-rewrite-urls-spec.js +0 -3
  315. package/test/browser/runner-rootpath-spec.js +0 -3
  316. package/test/browser/runner-strict-units-options.js +0 -5
  317. package/test/browser/runner-strict-units-spec.js +0 -3
  318. package/test/index.js +0 -112
  319. package/test/less-test.js +0 -625
  320. package/test/mocha-playwright/runner.js +0 -210
  321. package/test/modify-vars.js +0 -28
  322. package/test/plugins/filemanager/index.js +0 -19
  323. package/test/plugins/postprocess/index.js +0 -14
  324. package/test/plugins/preprocess/index.js +0 -19
  325. package/test/plugins/visitor/index.js +0 -24
  326. package/test/sourcemaps/basic.json +0 -1
  327. package/test/sourcemaps/custom-props.json +0 -1
  328. package/test/sourcemaps/index.html +0 -17
  329. package/test/sourcemaps-disable-annotation/basic.json +0 -1
  330. package/test/sourcemaps-variable-selector/basic.json +0 -1
  331. package/test/test-es6.ts +0 -17
  332. package/tsconfig.build.json +0 -7
  333. package/tsconfig.json +0 -21
@@ -1,16 +1,15 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- var tslib_1 = require("tslib");
4
- var less_error_1 = tslib_1.__importDefault(require("../less-error"));
5
- var tree_1 = tslib_1.__importDefault(require("../tree"));
6
- var visitors_1 = tslib_1.__importDefault(require("../visitors"));
7
- var parser_input_1 = tslib_1.__importDefault(require("./parser-input"));
8
- var utils = tslib_1.__importStar(require("../utils"));
9
- var function_registry_1 = tslib_1.__importDefault(require("../functions/function-registry"));
10
- var atrule_syntax_1 = require("../tree/atrule-syntax");
11
- var logger_1 = tslib_1.__importDefault(require("../logger"));
12
- var selector_1 = tslib_1.__importDefault(require("../tree/selector"));
13
- var anonymous_1 = tslib_1.__importDefault(require("../tree/anonymous"));
1
+ import LessError from '../less-error.js';
2
+ import tree from '../tree/index.js';
3
+ import visitors from '../visitors/index.js';
4
+ import getParserInput from './parser-input.js';
5
+ import * as utils from '../utils.js';
6
+ import functionRegistry from '../functions/function-registry.js';
7
+ import { ContainerSyntaxOptions, MediaSyntaxOptions } from '../tree/atrule-syntax.js';
8
+ import logger from '../logger.js';
9
+ import { DeprecationHandler } from '../deprecation.js';
10
+ import Selector from '../tree/selector.js';
11
+ import Anonymous from '../tree/anonymous.js';
12
+
14
13
  //
15
14
  // less.js - parser
16
15
  //
@@ -43,58 +42,79 @@ var anonymous_1 = tslib_1.__importDefault(require("../tree/anonymous"));
43
42
  // a terminal string or regexp, or a non-terminal function to call.
44
43
  // It also takes care of moving all the indices forwards.
45
44
  //
46
- var Parser = function Parser(context, imports, fileInfo, currentIndex) {
45
+
46
+ const Parser = function Parser(context, imports, fileInfo, currentIndex) {
47
47
  currentIndex = currentIndex || 0;
48
- var parsers;
49
- var parserInput = (0, parser_input_1.default)();
48
+ let parsers;
49
+ const parserInput = getParserInput();
50
+
50
51
  function error(msg, type) {
51
- throw new less_error_1.default({
52
- index: parserInput.i,
53
- filename: fileInfo.filename,
54
- type: type || 'Syntax',
55
- message: msg
56
- }, imports);
52
+ throw new LessError(
53
+ {
54
+ index: parserInput.i,
55
+ filename: fileInfo.filename,
56
+ type: type || 'Syntax',
57
+ message: msg
58
+ },
59
+ imports
60
+ );
57
61
  }
62
+
63
+ const deprecationHandler = new DeprecationHandler();
64
+
58
65
  /**
59
- *
60
66
  * @param {string} msg
61
67
  * @param {number} index
62
68
  * @param {string} type
69
+ * @param {string} [deprecationId] - stable deprecation ID for repetition limiting
63
70
  */
64
- function warn(msg, index, type) {
65
- if (!context.quiet) {
66
- logger_1.default.warn((new less_error_1.default({
67
- index: index !== null && index !== void 0 ? index : parserInput.i,
68
- filename: fileInfo.filename,
69
- type: type ? "".concat(type.toUpperCase(), " WARNING") : 'WARNING',
70
- message: msg
71
- }, imports)).toString());
72
- }
71
+ function warn(msg, index, type, deprecationId) {
72
+ if (context.quiet) { return; }
73
+ if (deprecationId && context.quietDeprecations) { return; }
74
+ if (deprecationId && !deprecationHandler.shouldWarn(deprecationId)) { return; }
75
+
76
+ logger.warn(
77
+ (new LessError(
78
+ {
79
+ index: index ?? parserInput.i,
80
+ filename: fileInfo.filename,
81
+ type: type ? `${type.toUpperCase()} WARNING` : 'WARNING',
82
+ message: msg
83
+ },
84
+ imports
85
+ )).toString()
86
+ );
73
87
  }
88
+
74
89
  function expect(arg, msg) {
75
90
  // some older browsers return typeof 'function' for RegExp
76
- var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
91
+ const result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
77
92
  if (result) {
78
93
  return result;
79
94
  }
95
+
80
96
  error(msg || (typeof arg === 'string'
81
- ? "expected '".concat(arg, "' got '").concat(parserInput.currentChar(), "'")
97
+ ? `expected '${arg}' got '${parserInput.currentChar()}'`
82
98
  : 'unexpected token'));
83
99
  }
100
+
84
101
  // Specialization of expect()
85
102
  function expectChar(arg, msg) {
86
103
  if (parserInput.$char(arg)) {
87
104
  return arg;
88
105
  }
89
- error(msg || "expected '".concat(arg, "' got '").concat(parserInput.currentChar(), "'"));
106
+ error(msg || `expected '${arg}' got '${parserInput.currentChar()}'`);
90
107
  }
108
+
91
109
  function getDebugInfo(index) {
92
- var filename = fileInfo.filename;
110
+ const filename = fileInfo.filename;
111
+
93
112
  return {
94
113
  lineNumber: utils.getLocation(index, parserInput.getInput()).line + 1,
95
114
  fileName: filename
96
115
  };
97
116
  }
117
+
98
118
  /**
99
119
  * Used after initial parsing to create nodes on the fly
100
120
  *
@@ -104,43 +124,40 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
104
124
  * @param {Object} fileInfo - fileInfo to attach to created nodes
105
125
  */
106
126
  function parseNode(str, parseList, callback) {
107
- var result;
108
- var returnNodes = [];
109
- var parser = parserInput;
127
+ let result;
128
+ const returnNodes = [];
129
+ const parser = parserInput;
130
+
110
131
  try {
111
- parser.start(str, false, function fail(msg, index) {
112
- callback({
113
- message: msg,
114
- index: index + currentIndex
115
- });
116
- });
117
- for (var x = 0, p = void 0; (p = parseList[x]); x++) {
132
+ parser.start(str);
133
+ for (let x = 0, p; (p = parseList[x]); x++) {
118
134
  result = parsers[p]();
119
135
  returnNodes.push(result || null);
120
136
  }
121
- var endInfo = parser.end();
137
+
138
+ const endInfo = parser.end();
122
139
  if (endInfo.isFinished) {
123
140
  callback(null, returnNodes);
124
141
  }
125
142
  else {
126
143
  callback(true, null);
127
144
  }
128
- }
129
- catch (e) {
130
- throw new less_error_1.default({
145
+ } catch (e) {
146
+ throw new LessError({
131
147
  index: e.index + currentIndex,
132
148
  message: e.message
133
149
  }, imports, fileInfo.filename);
134
150
  }
135
151
  }
152
+
136
153
  //
137
154
  // The Parser
138
155
  //
139
156
  return {
140
- parserInput: parserInput,
141
- imports: imports,
142
- fileInfo: fileInfo,
143
- parseNode: parseNode,
157
+ parserInput,
158
+ imports,
159
+ fileInfo,
160
+ parseNode,
144
161
  //
145
162
  // Parse an input string into an abstract syntax tree,
146
163
  // @param str A string containing 'less' markup
@@ -148,62 +165,63 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
148
165
  // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
149
166
  //
150
167
  parse: function (str, callback, additionalData) {
151
- var root;
152
- var err = null;
153
- var globalVars;
154
- var modifyVars;
155
- var ignored;
156
- var preText = '';
168
+ let root;
169
+ let err = null;
170
+ let globalVars;
171
+ let modifyVars;
172
+ let ignored;
173
+ let preText = '';
174
+
157
175
  // Optionally disable @plugin parsing
158
176
  if (additionalData && additionalData.disablePluginRule) {
159
- parsers.plugin = function () {
177
+ parsers.plugin = function() {
160
178
  var dir = parserInput.$re(/^@plugin?\s+/);
161
179
  if (dir) {
162
180
  error('@plugin statements are not allowed when disablePluginRule is set to true');
163
181
  }
164
- };
182
+ }
165
183
  }
166
- globalVars = (additionalData && additionalData.globalVars) ? "".concat(Parser.serializeVars(additionalData.globalVars), "\n") : '';
167
- modifyVars = (additionalData && additionalData.modifyVars) ? "\n".concat(Parser.serializeVars(additionalData.modifyVars)) : '';
184
+
185
+ globalVars = (additionalData && additionalData.globalVars) ? `${Parser.serializeVars(additionalData.globalVars)}\n` : '';
186
+ modifyVars = (additionalData && additionalData.modifyVars) ? `\n${Parser.serializeVars(additionalData.modifyVars)}` : '';
187
+
168
188
  if (context.pluginManager) {
169
- var preProcessors = context.pluginManager.getPreProcessors();
170
- for (var i = 0; i < preProcessors.length; i++) {
171
- str = preProcessors[i].process(str, { context: context, imports: imports, fileInfo: fileInfo });
189
+ const preProcessors = context.pluginManager.getPreProcessors();
190
+ for (let i = 0; i < preProcessors.length; i++) {
191
+ str = preProcessors[i].process(str, { context, imports, fileInfo });
172
192
  }
173
193
  }
194
+
174
195
  if (globalVars || (additionalData && additionalData.banner)) {
175
196
  preText = ((additionalData && additionalData.banner) ? additionalData.banner : '') + globalVars;
176
197
  ignored = imports.contentsIgnoredChars;
177
198
  ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0;
178
199
  ignored[fileInfo.filename] += preText.length;
179
200
  }
201
+
180
202
  str = str.replace(/\r\n?/g, '\n');
181
203
  // Remove potential UTF Byte Order Mark
182
204
  str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
183
205
  imports.contents[fileInfo.filename] = str;
206
+
184
207
  // Start with the primary rule.
185
208
  // The whole syntax tree is held under a Ruleset node,
186
209
  // with the `root` property set to true, so no `{}` are
187
210
  // output. The callback is called when the input is parsed.
188
211
  try {
189
- parserInput.start(str, context.chunkInput, function fail(msg, index) {
190
- throw new less_error_1.default({
191
- index: index,
192
- type: 'Parse',
193
- message: msg,
194
- filename: fileInfo.filename
195
- }, imports);
196
- });
197
- tree_1.default.Node.prototype.parse = this;
198
- root = new tree_1.default.Ruleset(null, this.parsers.primary());
199
- tree_1.default.Node.prototype.rootNode = root;
212
+ parserInput.start(str);
213
+
214
+ tree.Node.prototype.parse = this;
215
+ root = new tree.Ruleset(null, this.parsers.primary());
216
+ tree.Node.prototype.rootNode = root;
200
217
  root.root = true;
201
218
  root.firstRoot = true;
202
- root.functionRegistry = function_registry_1.default.inherit();
203
- }
204
- catch (e) {
205
- return callback(new less_error_1.default(e, imports, fileInfo.filename));
219
+ root.functionRegistry = functionRegistry.inherit();
220
+
221
+ } catch (e) {
222
+ return callback(new LessError(e, imports, fileInfo.filename));
206
223
  }
224
+
207
225
  // If `i` is smaller than the `input.length - 1`,
208
226
  // it means the parser wasn't able to parse the whole
209
227
  // string, so we've got a parsing error.
@@ -212,48 +230,53 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
212
230
  // showing the line where the parse error occurred.
213
231
  // We split it up into two parts (the part which parsed,
214
232
  // and the part which didn't), so we can color them differently.
215
- var endInfo = parserInput.end();
233
+ const endInfo = parserInput.end();
216
234
  if (!endInfo.isFinished) {
217
- var message = endInfo.furthestPossibleErrorMessage;
235
+
236
+ let message = endInfo.furthestPossibleErrorMessage;
237
+
218
238
  if (!message) {
219
239
  message = 'Unrecognised input';
220
240
  if (endInfo.furthestChar === '}') {
221
241
  message += '. Possibly missing opening \'{\'';
222
- }
223
- else if (endInfo.furthestChar === ')') {
242
+ } else if (endInfo.furthestChar === ')') {
224
243
  message += '. Possibly missing opening \'(\'';
225
- }
226
- else if (endInfo.furthestReachedEnd) {
244
+ } else if (endInfo.furthestReachedEnd) {
227
245
  message += '. Possibly missing something';
228
246
  }
229
247
  }
230
- err = new less_error_1.default({
248
+
249
+ err = new LessError({
231
250
  type: 'Parse',
232
- message: message,
251
+ message,
233
252
  index: endInfo.furthest,
234
253
  filename: fileInfo.filename
235
254
  }, imports);
236
255
  }
237
- var finish = function (e) {
256
+
257
+ const finish = e => {
238
258
  e = err || e || imports.error;
259
+
239
260
  if (e) {
240
- if (!(e instanceof less_error_1.default)) {
241
- e = new less_error_1.default(e, imports, fileInfo.filename);
261
+ if (!(e instanceof LessError)) {
262
+ e = new LessError(e, imports, fileInfo.filename);
242
263
  }
264
+
243
265
  return callback(e);
244
266
  }
245
267
  else {
246
268
  return callback(null, root);
247
269
  }
248
270
  };
271
+
249
272
  if (context.processImports !== false) {
250
- new visitors_1.default.ImportVisitor(imports, finish)
273
+ new visitors.ImportVisitor(imports, finish)
251
274
  .run(root);
252
- }
253
- else {
275
+ } else {
254
276
  return finish();
255
277
  }
256
278
  },
279
+
257
280
  //
258
281
  // Here in, the parsing rules/functions
259
282
  //
@@ -300,15 +323,14 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
300
323
  // block rule: at the root level.
301
324
  //
302
325
  primary: function () {
303
- var mixin = this.mixin;
304
- var root = [];
305
- var node;
326
+ const mixin = this.mixin;
327
+ let root = [];
328
+ let node;
329
+
306
330
  while (true) {
307
331
  while (true) {
308
332
  node = this.comment();
309
- if (!node) {
310
- break;
311
- }
333
+ if (!node) { break; }
312
334
  root.push(node);
313
335
  }
314
336
  // always process comments before deciding if finished
@@ -318,18 +340,19 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
318
340
  if (parserInput.peek('}')) {
319
341
  break;
320
342
  }
343
+
321
344
  node = this.extendRule();
322
345
  if (node) {
323
346
  root = root.concat(node);
324
347
  continue;
325
348
  }
349
+
326
350
  node = mixin.definition() || this.declaration() || mixin.call(false, false) ||
327
351
  this.ruleset() || this.variableCall() || this.entities.call() || this.atrule();
328
352
  if (node) {
329
353
  root.push(node);
330
- }
331
- else {
332
- var foundSemiColon = false;
354
+ } else {
355
+ let foundSemiColon = false;
333
356
  while (parserInput.$char(';')) {
334
357
  foundSemiColon = true;
335
358
  }
@@ -338,21 +361,24 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
338
361
  }
339
362
  }
340
363
  }
364
+
341
365
  return root;
342
366
  },
367
+
343
368
  // comments are collected by the main parsing mechanism and then assigned to nodes
344
369
  // where the current structure allows it
345
370
  comment: function () {
346
371
  if (parserInput.commentStore.length) {
347
- var comment = parserInput.commentStore.shift();
348
- return new (tree_1.default.Comment)(comment.text, comment.isLineComment, comment.index + currentIndex, fileInfo);
372
+ const comment = parserInput.commentStore.shift();
373
+ return new(tree.Comment)(comment.text, comment.isLineComment, comment.index + currentIndex, fileInfo);
349
374
  }
350
375
  },
376
+
351
377
  //
352
378
  // Entities are tokens which can be found inside an Expression
353
379
  //
354
380
  entities: {
355
- mixinLookup: function () {
381
+ mixinLookup: function() {
356
382
  return parsers.mixin.call(true, true);
357
383
  },
358
384
  //
@@ -361,36 +387,40 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
361
387
  // "milky way" 'he\'s the one!'
362
388
  //
363
389
  quoted: function (forceEscaped) {
364
- var str;
365
- var index = parserInput.i;
366
- var isEscaped = false;
390
+ let str;
391
+ const index = parserInput.i;
392
+ let isEscaped = false;
393
+
367
394
  parserInput.save();
368
395
  if (parserInput.$char('~')) {
369
396
  isEscaped = true;
370
- }
371
- else if (forceEscaped) {
397
+ } else if (forceEscaped) {
372
398
  parserInput.restore();
373
399
  return;
374
400
  }
401
+
375
402
  str = parserInput.$quoted();
376
403
  if (!str) {
377
404
  parserInput.restore();
378
405
  return;
379
406
  }
380
407
  parserInput.forget();
381
- return new (tree_1.default.Quoted)(str.charAt(0), str.substr(1, str.length - 2), isEscaped, index + currentIndex, fileInfo);
408
+
409
+ return new(tree.Quoted)(str.charAt(0), str.slice(1, -1), isEscaped, index + currentIndex, fileInfo);
382
410
  },
411
+
383
412
  //
384
413
  // A catch-all word, such as:
385
414
  //
386
415
  // black border-collapse
387
416
  //
388
417
  keyword: function () {
389
- var k = parserInput.$char('%') || parserInput.$re(/^\[?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+\]?/);
418
+ const k = parserInput.$char('%') || parserInput.$re(/^\[?(?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+\]?/);
390
419
  if (k) {
391
- return tree_1.default.Color.fromKeyword(k) || new (tree_1.default.Keyword)(k);
420
+ return tree.Color.fromKeyword(k) || new(tree.Keyword)(k);
392
421
  }
393
422
  },
423
+
394
424
  //
395
425
  // A function call
396
426
  //
@@ -399,20 +429,24 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
399
429
  // The arguments are parsed with the `entities.arguments` parser.
400
430
  //
401
431
  call: function () {
402
- var name;
403
- var args;
404
- var func;
405
- var index = parserInput.i;
432
+ let name;
433
+ let args;
434
+ let func;
435
+ const index = parserInput.i;
436
+
406
437
  // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
407
438
  if (parserInput.peek(/^url\(/i)) {
408
439
  return;
409
440
  }
441
+
410
442
  parserInput.save();
443
+
411
444
  name = parserInput.$re(/^([\w-]+|%|~|progid:[\w.]+)\(/);
412
445
  if (!name) {
413
446
  parserInput.forget();
414
447
  return;
415
448
  }
449
+
416
450
  name = name[1];
417
451
  func = this.customFuncCall(name);
418
452
  if (func) {
@@ -422,40 +456,61 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
422
456
  return args;
423
457
  }
424
458
  }
459
+
425
460
  args = this.arguments(args);
461
+
426
462
  if (!parserInput.$char(')')) {
427
463
  parserInput.restore('Could not parse call arguments or missing \')\'');
428
464
  return;
429
465
  }
466
+
430
467
  parserInput.forget();
431
- return new (tree_1.default.Call)(name, args, index + currentIndex, fileInfo);
468
+
469
+ return new(tree.Call)(name, args, index + currentIndex, fileInfo);
432
470
  },
471
+
433
472
  declarationCall: function () {
434
- var validCall;
435
- var args;
436
- var index = parserInput.i;
473
+ let validCall;
474
+ let args;
475
+ const index = parserInput.i;
476
+
437
477
  parserInput.save();
478
+
438
479
  validCall = parserInput.$re(/^[\w]+\(/);
439
480
  if (!validCall) {
440
481
  parserInput.forget();
441
482
  return;
442
483
  }
484
+
443
485
  validCall = validCall.substring(0, validCall.length - 1);
444
- var rule = this.ruleProperty();
445
- var value;
486
+
487
+ // CSS at-rule keywords should never be parsed as declaration calls
488
+ if (/^(and|or|not|only|layer)$/i.test(validCall)) {
489
+ parserInput.restore();
490
+ return;
491
+ }
492
+
493
+ let rule = this.ruleProperty();
494
+ let value;
495
+
446
496
  if (rule) {
447
497
  value = this.value();
448
498
  }
499
+
449
500
  if (rule && value) {
450
- args = [new (tree_1.default.Declaration)(rule, value, null, null, parserInput.i + currentIndex, fileInfo, true)];
501
+ args = [new (tree.Declaration)(rule, value, null, null, parserInput.i + currentIndex, fileInfo, true)];
451
502
  }
503
+
452
504
  if (!parserInput.$char(')')) {
453
505
  parserInput.restore('Could not parse call arguments or missing \')\'');
454
506
  return;
455
507
  }
508
+
456
509
  parserInput.forget();
457
- return new (tree_1.default.Call)(validCall, args, index + currentIndex, fileInfo);
510
+
511
+ return new(tree.Call)(validCall, args, index + currentIndex, fileInfo);
458
512
  },
513
+
459
514
  //
460
515
  // Parsing rules for functions with non-standard args, e.g.:
461
516
  //
@@ -464,74 +519,86 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
464
519
  // This is a quick prototype, to be modified/improved when
465
520
  // more custom-parsed funcs come (e.g. `selector(...)`)
466
521
  //
522
+
467
523
  customFuncCall: function (name) {
468
524
  /* Ideally the table is to be moved out of here for faster perf.,
469
525
  but it's quite tricky since it relies on all these `parsers`
470
526
  and `expect` available only here */
471
527
  return {
472
- alpha: f(parsers.ieAlpha, true),
528
+ alpha: f(parsers.ieAlpha, true),
473
529
  boolean: f(condition),
474
- 'if': f(condition)
530
+ 'if': f(condition)
475
531
  }[name.toLowerCase()];
532
+
476
533
  function f(parse, stop) {
477
534
  return {
478
- parse: parse,
479
- stop: stop // when true - stop after parse() and return its result,
535
+ parse, // parsing function
536
+ stop // when true - stop after parse() and return its result,
480
537
  // otherwise continue for plain args
481
538
  };
482
539
  }
540
+
483
541
  function condition() {
484
542
  return [expect(parsers.condition, 'expected condition')];
485
543
  }
486
544
  },
545
+
487
546
  arguments: function (prevArgs) {
488
- var argsComma = prevArgs || [];
489
- var argsSemiColon = [];
490
- var isSemiColonSeparated;
491
- var value;
547
+ let argsComma = prevArgs || [];
548
+ const argsSemiColon = [];
549
+ let isSemiColonSeparated;
550
+ let value;
551
+
492
552
  parserInput.save();
553
+
493
554
  while (true) {
494
555
  if (prevArgs) {
495
556
  prevArgs = false;
496
- }
497
- else {
557
+ } else {
498
558
  value = parsers.detachedRuleset() || this.assignment() || parsers.expression();
499
559
  if (!value) {
500
560
  break;
501
561
  }
562
+
502
563
  if (value.value && value.value.length == 1) {
503
564
  value = value.value[0];
504
565
  }
566
+
505
567
  argsComma.push(value);
506
568
  }
569
+
507
570
  if (parserInput.$char(',')) {
508
571
  continue;
509
572
  }
573
+
510
574
  if (parserInput.$char(';') || isSemiColonSeparated) {
511
575
  isSemiColonSeparated = true;
512
576
  value = (argsComma.length < 1) ? argsComma[0]
513
- : new tree_1.default.Value(argsComma);
577
+ : new tree.Value(argsComma);
514
578
  argsSemiColon.push(value);
515
579
  argsComma = [];
516
580
  }
517
581
  }
582
+
518
583
  parserInput.forget();
519
584
  return isSemiColonSeparated ? argsSemiColon : argsComma;
520
585
  },
521
586
  literal: function () {
522
587
  return this.dimension() ||
523
- this.color() ||
524
- this.quoted() ||
525
- this.unicodeDescriptor();
588
+ this.color() ||
589
+ this.quoted() ||
590
+ this.unicodeDescriptor();
526
591
  },
592
+
527
593
  // Assignments are argument entities for calls.
528
594
  // They are present in ie filter properties as shown below.
529
595
  //
530
596
  // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* )
531
597
  //
598
+
532
599
  assignment: function () {
533
- var key;
534
- var value;
600
+ let key;
601
+ let value;
535
602
  parserInput.save();
536
603
  key = parserInput.$re(/^\w+(?=\s?=)/i);
537
604
  if (!key) {
@@ -545,12 +612,12 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
545
612
  value = parsers.entity();
546
613
  if (value) {
547
614
  parserInput.forget();
548
- return new (tree_1.default.Assignment)(key, value);
549
- }
550
- else {
615
+ return new(tree.Assignment)(key, value);
616
+ } else {
551
617
  parserInput.restore();
552
618
  }
553
619
  },
620
+
554
621
  //
555
622
  // Parse url() tokens
556
623
  //
@@ -559,22 +626,29 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
559
626
  // to be enclosed within a string, so it can't be parsed as an Expression.
560
627
  //
561
628
  url: function () {
562
- var value;
563
- var index = parserInput.i;
629
+ let value;
630
+ const index = parserInput.i;
631
+
564
632
  parserInput.autoCommentAbsorb = false;
633
+
565
634
  if (!parserInput.$str('url(')) {
566
635
  parserInput.autoCommentAbsorb = true;
567
636
  return;
568
637
  }
638
+
569
639
  value = this.quoted() || this.variable() || this.property() ||
570
- parserInput.$re(/^(?:(?:\\[()'"])|[^()'"])+/) || '';
640
+ parserInput.$re(/^(?:(?:\\[()'"])|[^()'"])+/) || '';
641
+
571
642
  parserInput.autoCommentAbsorb = true;
643
+
572
644
  expectChar(')');
573
- return new (tree_1.default.URL)((value.value !== undefined ||
574
- value instanceof tree_1.default.Variable ||
575
- value instanceof tree_1.default.Property) ?
576
- value : new (tree_1.default.Anonymous)(value, index), index + currentIndex, fileInfo);
645
+
646
+ return new(tree.URL)((value.value !== undefined ||
647
+ value instanceof tree.Variable ||
648
+ value instanceof tree.Property) ?
649
+ value : new(tree.Anonymous)(value, index), index + currentIndex, fileInfo);
577
650
  },
651
+
578
652
  //
579
653
  // A Variable entity, such as `@fink`, in
580
654
  //
@@ -584,31 +658,35 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
584
658
  // see `parsers.variable`.
585
659
  //
586
660
  variable: function () {
587
- var ch;
588
- var name;
589
- var index = parserInput.i;
661
+ let ch;
662
+ let name;
663
+ const index = parserInput.i;
664
+
590
665
  parserInput.save();
591
666
  if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^@@?[\w-]+/))) {
592
667
  ch = parserInput.currentChar();
593
- if (ch === '(' || ch === '[' && !parserInput.prevChar().match(/^\s/)) {
668
+ if ((ch === '(' && !parserInput.prevChar().match(/^\s/))
669
+ || (ch === '[' && !parserInput.prevChar().match(/^\s/))) {
594
670
  // this may be a VariableCall lookup
595
- var result = parsers.variableCall(name);
671
+ const result = parsers.variableCall(name);
596
672
  if (result) {
597
673
  parserInput.forget();
598
674
  return result;
599
675
  }
600
676
  }
601
677
  parserInput.forget();
602
- return new (tree_1.default.Variable)(name, index + currentIndex, fileInfo);
678
+ return new(tree.Variable)(name, index + currentIndex, fileInfo);
603
679
  }
604
680
  parserInput.restore();
605
681
  },
682
+
606
683
  // A variable entity using the protective {} e.g. @{var}
607
684
  variableCurly: function () {
608
- var curly;
609
- var index = parserInput.i;
685
+ let curly;
686
+ const index = parserInput.i;
687
+
610
688
  if (parserInput.currentChar() === '@' && (curly = parserInput.$re(/^@\{([\w-]+)\}/))) {
611
- return new (tree_1.default.Variable)("@".concat(curly[1]), index + currentIndex, fileInfo);
689
+ return new(tree.Variable)(`@${curly[1]}`, index + currentIndex, fileInfo);
612
690
  }
613
691
  },
614
692
  //
@@ -617,20 +695,14 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
617
695
  // background-color: $color
618
696
  //
619
697
  property: function () {
620
- var name;
621
- var index = parserInput.i;
698
+ let name;
699
+ const index = parserInput.i;
700
+
622
701
  if (parserInput.currentChar() === '$' && (name = parserInput.$re(/^\$[\w-]+/))) {
623
- return new (tree_1.default.Property)(name, index + currentIndex, fileInfo);
624
- }
625
- },
626
- // A property entity useing the protective {} e.g. ${prop}
627
- propertyCurly: function () {
628
- var curly;
629
- var index = parserInput.i;
630
- if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) {
631
- return new (tree_1.default.Property)("$".concat(curly[1]), index + currentIndex, fileInfo);
702
+ return new(tree.Property)(name, index + currentIndex, fileInfo);
632
703
  }
633
704
  },
705
+
634
706
  //
635
707
  // A Hexadecimal color
636
708
  //
@@ -639,33 +711,36 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
639
711
  // `rgb` and `hsl` colors are parsed through the `entities.call` parser.
640
712
  //
641
713
  color: function () {
642
- var rgb;
714
+ let rgb;
643
715
  parserInput.save();
716
+
644
717
  if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})([\w.#[])?/))) {
645
718
  if (!rgb[2]) {
646
719
  parserInput.forget();
647
- return new (tree_1.default.Color)(rgb[1], undefined, rgb[0]);
720
+ return new(tree.Color)(rgb[1], undefined, rgb[0]);
648
721
  }
649
722
  }
650
723
  parserInput.restore();
651
724
  },
725
+
652
726
  colorKeyword: function () {
653
727
  parserInput.save();
654
- var autoCommentAbsorb = parserInput.autoCommentAbsorb;
728
+ const autoCommentAbsorb = parserInput.autoCommentAbsorb;
655
729
  parserInput.autoCommentAbsorb = false;
656
- var k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);
730
+ const k = parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);
657
731
  parserInput.autoCommentAbsorb = autoCommentAbsorb;
658
732
  if (!k) {
659
733
  parserInput.forget();
660
734
  return;
661
735
  }
662
736
  parserInput.restore();
663
- var color = tree_1.default.Color.fromKeyword(k);
737
+ const color = tree.Color.fromKeyword(k);
664
738
  if (color) {
665
739
  parserInput.$str(k);
666
740
  return color;
667
741
  }
668
742
  },
743
+
669
744
  //
670
745
  // A Dimension, that is, a number and a unit
671
746
  //
@@ -675,57 +750,67 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
675
750
  if (parserInput.peekNotNumeric()) {
676
751
  return;
677
752
  }
678
- var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);
753
+
754
+ const value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);
679
755
  if (value) {
680
- return new (tree_1.default.Dimension)(value[1], value[2]);
756
+ return new(tree.Dimension)(value[1], value[2]);
681
757
  }
682
758
  },
759
+
683
760
  //
684
761
  // A unicode descriptor, as is used in unicode-range
685
762
  //
686
763
  // U+0?? or U+00A1-00A9
687
764
  //
688
765
  unicodeDescriptor: function () {
689
- var ud;
766
+ let ud;
767
+
690
768
  ud = parserInput.$re(/^U\+[0-9a-fA-F?]+(-[0-9a-fA-F?]+)?/);
691
769
  if (ud) {
692
- return new (tree_1.default.UnicodeDescriptor)(ud[0]);
770
+ return new(tree.UnicodeDescriptor)(ud[0]);
693
771
  }
694
772
  },
773
+
695
774
  //
696
775
  // JavaScript code to be evaluated
697
776
  //
698
777
  // `window.location.href`
699
778
  //
700
779
  javascript: function () {
701
- var js;
702
- var index = parserInput.i;
780
+ let js;
781
+ const index = parserInput.i;
782
+
703
783
  parserInput.save();
704
- var escape = parserInput.$char('~');
705
- var jsQuote = parserInput.$char('`');
784
+
785
+ const escape = parserInput.$char('~');
786
+ const jsQuote = parserInput.$char('`');
787
+
706
788
  if (!jsQuote) {
707
789
  parserInput.restore();
708
790
  return;
709
791
  }
792
+
710
793
  js = parserInput.$re(/^[^`]*`/);
711
794
  if (js) {
795
+ warn('Inline JavaScript evaluation (backtick expressions) is deprecated and will be removed in Less 5.x. Use Less functions or custom plugins instead.', index, 'DEPRECATED', 'js-eval');
712
796
  parserInput.forget();
713
- return new (tree_1.default.JavaScript)(js.substr(0, js.length - 1), Boolean(escape), index + currentIndex, fileInfo);
797
+ return new(tree.JavaScript)(js.slice(0, -1), Boolean(escape), index + currentIndex, fileInfo);
714
798
  }
715
799
  parserInput.restore('invalid javascript definition');
716
800
  }
717
801
  },
802
+
718
803
  //
719
804
  // The variable part of a variable definition. Used in the `rule` parser
720
805
  //
721
806
  // @fink:
722
807
  //
723
808
  variable: function () {
724
- var name;
725
- if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) {
726
- return name[1];
727
- }
809
+ let name;
810
+
811
+ if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\s*:/))) { return name[1]; }
728
812
  },
813
+
729
814
  //
730
815
  // Call a variable value to retrieve a detached ruleset
731
816
  // or a value from a detached ruleset's rules.
@@ -735,52 +820,63 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
735
820
  // color: @fink[@color];
736
821
  //
737
822
  variableCall: function (parsedName) {
738
- var lookups;
739
- var i = parserInput.i;
740
- var inValue = !!parsedName;
741
- var name = parsedName;
823
+ let lookups;
824
+ const i = parserInput.i;
825
+ const inValue = !!parsedName;
826
+ let name = parsedName;
827
+
742
828
  parserInput.save();
829
+
743
830
  if (name || (parserInput.currentChar() === '@'
744
831
  && (name = parserInput.$re(/^(@[\w-]+)(\(\s*\))?/)))) {
832
+
745
833
  lookups = this.mixin.ruleLookups();
834
+
746
835
  if (!lookups && ((inValue && parserInput.$str('()') !== '()') || (name[2] !== '()'))) {
747
836
  parserInput.restore('Missing \'[...]\' lookup in variable call');
748
837
  return;
749
838
  }
839
+
750
840
  if (!inValue) {
751
841
  name = name[1];
752
842
  }
753
- var call = new tree_1.default.VariableCall(name, i, fileInfo);
843
+
844
+ const call = new tree.VariableCall(name, i, fileInfo);
754
845
  if (!inValue && parsers.end()) {
755
846
  parserInput.forget();
756
847
  return call;
757
848
  }
758
849
  else {
759
850
  parserInput.forget();
760
- return new tree_1.default.NamespaceValue(call, lookups, i, fileInfo);
851
+ return new tree.NamespaceValue(call, lookups, i, fileInfo);
761
852
  }
762
853
  }
854
+
763
855
  parserInput.restore();
764
856
  },
857
+
765
858
  //
766
859
  // extend syntax - used to extend selectors
767
860
  //
768
- extend: function (isRule) {
769
- var elements;
770
- var e;
771
- var index = parserInput.i;
772
- var option;
773
- var extendList;
774
- var extend;
861
+ extend: function(isRule) {
862
+ let elements;
863
+ let e;
864
+ const index = parserInput.i;
865
+ let option;
866
+ let extendList;
867
+ let extend;
868
+
775
869
  if (!parserInput.$str(isRule ? '&:extend(' : ':extend(')) {
776
870
  return;
777
871
  }
872
+
778
873
  do {
779
874
  option = null;
780
875
  elements = null;
781
- var first = true;
876
+ let first = true;
782
877
  while (!(option = parserInput.$re(/^(!?all)(?=\s*(\)|,))/))) {
783
878
  e = this.element();
879
+
784
880
  if (!e) {
785
881
  break;
786
882
  }
@@ -789,40 +885,45 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
789
885
  * they don't currently parse their contents as selectors.
790
886
  */
791
887
  if (!first && e.combinator.value) {
792
- warn('Targeting complex selectors can have unexpected behavior, and this behavior may change in the future.', index);
888
+ warn('Targeting complex selectors can have unexpected behavior, and this behavior may change in the future.', index)
793
889
  }
890
+
794
891
  first = false;
795
892
  if (elements) {
796
893
  elements.push(e);
797
- }
798
- else {
799
- elements = [e];
894
+ } else {
895
+ elements = [ e ];
800
896
  }
801
897
  }
898
+
802
899
  option = option && option[1];
803
900
  if (!elements) {
804
901
  error('Missing target selector for :extend().');
805
902
  }
806
- extend = new (tree_1.default.Extend)(new (tree_1.default.Selector)(elements), option, index + currentIndex, fileInfo);
903
+ extend = new(tree.Extend)(new(tree.Selector)(elements), option, index + currentIndex, fileInfo);
807
904
  if (extendList) {
808
905
  extendList.push(extend);
809
- }
810
- else {
811
- extendList = [extend];
906
+ } else {
907
+ extendList = [ extend ];
812
908
  }
813
909
  } while (parserInput.$char(','));
910
+
814
911
  expect(/^\)/);
912
+
815
913
  if (isRule) {
816
914
  expect(/^;/);
817
915
  }
916
+
818
917
  return extendList;
819
918
  },
919
+
820
920
  //
821
921
  // extendRule - used in a rule to extend all the parent selectors
822
922
  //
823
- extendRule: function () {
923
+ extendRule: function() {
824
924
  return this.extend(true);
825
925
  },
926
+
826
927
  //
827
928
  // Mixins
828
929
  //
@@ -844,31 +945,34 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
844
945
  // selector for now.
845
946
  //
846
947
  call: function (inValue, getLookup) {
847
- var s = parserInput.currentChar();
848
- var important = false;
849
- var lookups;
850
- var index = parserInput.i;
851
- var elements;
852
- var args;
853
- var hasParens;
854
- var parensIndex;
855
- var parensWS = false;
856
- if (s !== '.' && s !== '#') {
857
- return;
858
- }
948
+ const s = parserInput.currentChar();
949
+ let important = false;
950
+ let lookups;
951
+ const index = parserInput.i;
952
+ let elements;
953
+ let args;
954
+ let hasParens;
955
+ let parensIndex;
956
+ let parensWS = false;
957
+
958
+ if (s !== '.' && s !== '#') { return; }
959
+
859
960
  parserInput.save(); // stop us absorbing part of an invalid selector
961
+
860
962
  elements = this.elements();
963
+
861
964
  if (elements) {
862
965
  parensIndex = parserInput.i;
863
- if (parserInput.$char('(')) {
864
- parensWS = parserInput.isWhitespace(-2);
966
+ parensWS = parserInput.isWhitespace(-1);
967
+ if (parserInput.$char('(')) {
865
968
  args = this.args(true).args;
866
969
  expectChar(')');
867
970
  hasParens = true;
868
971
  if (parensWS) {
869
- warn('Whitespace between a mixin name and parentheses for a mixin call is deprecated', parensIndex, 'DEPRECATED');
972
+ warn('Whitespace between a mixin name and parentheses for a mixin call is deprecated', parensIndex, 'DEPRECATED', 'mixin-call-whitespace');
870
973
  }
871
974
  }
975
+
872
976
  if (getLookup !== false) {
873
977
  lookups = this.ruleLookups();
874
978
  }
@@ -876,78 +980,83 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
876
980
  parserInput.restore();
877
981
  return;
878
982
  }
983
+
879
984
  if (inValue && !lookups && !hasParens) {
880
985
  // This isn't a valid in-value mixin call
881
986
  parserInput.restore();
882
987
  return;
883
988
  }
989
+
884
990
  if (!inValue && parsers.important()) {
885
991
  important = true;
886
992
  }
993
+
887
994
  if (inValue || parsers.end()) {
888
995
  parserInput.forget();
889
- var mixin = new (tree_1.default.mixin.Call)(elements, args, index + currentIndex, fileInfo, !lookups && important);
996
+ const mixin = new(tree.mixin.Call)(elements, args, index + currentIndex, fileInfo, !lookups && important);
890
997
  if (lookups) {
891
- return new tree_1.default.NamespaceValue(mixin, lookups);
998
+ return new tree.NamespaceValue(mixin, lookups);
892
999
  }
893
1000
  else {
894
1001
  if (!hasParens) {
895
- warn('Calling a mixin without parentheses is deprecated', parensIndex, 'DEPRECATED');
1002
+ warn('Calling a mixin without parentheses is deprecated', parensIndex, 'DEPRECATED', 'mixin-call-no-parens');
896
1003
  }
897
1004
  return mixin;
898
1005
  }
899
1006
  }
900
1007
  }
1008
+
901
1009
  parserInput.restore();
902
1010
  },
903
1011
  /**
904
1012
  * Matching elements for mixins
905
1013
  * (Start with . or # and can have > )
906
1014
  */
907
- elements: function () {
908
- var elements;
909
- var e;
910
- var c;
911
- var elem;
912
- var elemIndex;
913
- var re = /^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/;
1015
+ elements: function() {
1016
+ let elements;
1017
+ let e;
1018
+ let c;
1019
+ let elem;
1020
+ let elemIndex;
1021
+ const re = /^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/;
914
1022
  while (true) {
915
1023
  elemIndex = parserInput.i;
916
1024
  e = parserInput.$re(re);
1025
+
917
1026
  if (!e) {
918
1027
  break;
919
1028
  }
920
- elem = new (tree_1.default.Element)(c, e, false, elemIndex + currentIndex, fileInfo);
1029
+ elem = new(tree.Element)(c, e, false, elemIndex + currentIndex, fileInfo);
921
1030
  if (elements) {
922
1031
  elements.push(elem);
923
- }
924
- else {
925
- elements = [elem];
1032
+ } else {
1033
+ elements = [ elem ];
926
1034
  }
927
1035
  c = parserInput.$char('>');
928
1036
  }
929
1037
  return elements;
930
1038
  },
931
1039
  args: function (isCall) {
932
- var entities = parsers.entities;
933
- var returner = { args: null, variadic: false };
934
- var expressions = [];
935
- var argsSemiColon = [];
936
- var argsComma = [];
937
- var isSemiColonSeparated;
938
- var expressionContainsNamed;
939
- var name;
940
- var nameLoop;
941
- var value;
942
- var arg;
943
- var expand;
944
- var hasSep = true;
1040
+ const entities = parsers.entities;
1041
+ const returner = { args:null, variadic: false };
1042
+ let expressions = [];
1043
+ const argsSemiColon = [];
1044
+ const argsComma = [];
1045
+ let isSemiColonSeparated;
1046
+ let expressionContainsNamed;
1047
+ let name;
1048
+ let nameLoop;
1049
+ let value;
1050
+ let arg;
1051
+ let expand;
1052
+ let hasSep = true;
1053
+
945
1054
  parserInput.save();
1055
+
946
1056
  while (true) {
947
1057
  if (isCall) {
948
1058
  arg = parsers.detachedRuleset() || parsers.expression();
949
- }
950
- else {
1059
+ } else {
951
1060
  parserInput.commentStore.length = 0;
952
1061
  if (parserInput.$str('...')) {
953
1062
  returner.variadic = true;
@@ -960,25 +1069,28 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
960
1069
  }
961
1070
  arg = entities.variable() || entities.property() || entities.literal() || entities.keyword() || this.call(true);
962
1071
  }
1072
+
963
1073
  if (!arg || !hasSep) {
964
1074
  break;
965
1075
  }
1076
+
966
1077
  nameLoop = null;
967
1078
  if (arg.throwAwayComments) {
968
1079
  arg.throwAwayComments();
969
1080
  }
970
1081
  value = arg;
971
- var val = null;
1082
+ let val = null;
1083
+
972
1084
  if (isCall) {
973
1085
  // Variable
974
1086
  if (arg.value && arg.value.length == 1) {
975
1087
  val = arg.value[0];
976
1088
  }
977
- }
978
- else {
1089
+ } else {
979
1090
  val = arg;
980
1091
  }
981
- if (val && (val instanceof tree_1.default.Variable || val instanceof tree_1.default.Property)) {
1092
+
1093
+ if (val && (val instanceof tree.Variable || val instanceof tree.Property)) {
982
1094
  if (parserInput.$char(':')) {
983
1095
  if (expressions.length > 0) {
984
1096
  if (isSemiColonSeparated) {
@@ -986,20 +1098,20 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
986
1098
  }
987
1099
  expressionContainsNamed = true;
988
1100
  }
1101
+
989
1102
  value = parsers.detachedRuleset() || parsers.expression();
1103
+
990
1104
  if (!value) {
991
1105
  if (isCall) {
992
1106
  error('could not understand value for named argument');
993
- }
994
- else {
1107
+ } else {
995
1108
  parserInput.restore();
996
1109
  returner.args = [];
997
1110
  return returner;
998
1111
  }
999
1112
  }
1000
1113
  nameLoop = (name = val.name);
1001
- }
1002
- else if (parserInput.$str('...')) {
1114
+ } else if (parserInput.$str('...')) {
1003
1115
  if (!isCall) {
1004
1116
  returner.variadic = true;
1005
1117
  if (parserInput.$char(';') && !isSemiColonSeparated) {
@@ -1008,39 +1120,46 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1008
1120
  (isSemiColonSeparated ? argsSemiColon : argsComma)
1009
1121
  .push({ name: arg.name, variadic: true });
1010
1122
  break;
1011
- }
1012
- else {
1123
+ } else {
1013
1124
  expand = true;
1014
1125
  }
1015
- }
1016
- else if (!isCall) {
1126
+ } else if (!isCall) {
1017
1127
  name = nameLoop = val.name;
1018
1128
  value = null;
1019
1129
  }
1020
1130
  }
1131
+
1021
1132
  if (value) {
1022
1133
  expressions.push(value);
1023
1134
  }
1024
- argsComma.push({ name: nameLoop, value: value, expand: expand });
1135
+
1136
+ argsComma.push({ name:nameLoop, value, expand });
1137
+
1025
1138
  if (parserInput.$char(',')) {
1026
1139
  hasSep = true;
1027
1140
  continue;
1028
1141
  }
1029
1142
  hasSep = parserInput.$char(';') === ';';
1143
+
1030
1144
  if (hasSep || isSemiColonSeparated) {
1145
+
1031
1146
  if (expressionContainsNamed) {
1032
1147
  error('Cannot mix ; and , as delimiter types');
1033
1148
  }
1149
+
1034
1150
  isSemiColonSeparated = true;
1151
+
1035
1152
  if (expressions.length > 1) {
1036
- value = new (tree_1.default.Value)(expressions);
1153
+ value = new(tree.Value)(expressions);
1037
1154
  }
1038
- argsSemiColon.push({ name: name, value: value, expand: expand });
1155
+ argsSemiColon.push({ name, value, expand });
1156
+
1039
1157
  name = null;
1040
1158
  expressions = [];
1041
1159
  expressionContainsNamed = false;
1042
1160
  }
1043
1161
  }
1162
+
1044
1163
  parserInput.forget();
1045
1164
  returner.args = isSemiColonSeparated ? argsSemiColon : argsComma;
1046
1165
  return returner;
@@ -1065,23 +1184,27 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1065
1184
  // the `{...}` block.
1066
1185
  //
1067
1186
  definition: function () {
1068
- var name;
1069
- var params = [];
1070
- var match;
1071
- var ruleset;
1072
- var cond;
1073
- var variadic = false;
1187
+ let name;
1188
+ let params = [];
1189
+ let match;
1190
+ let ruleset;
1191
+ let cond;
1192
+ let variadic = false;
1074
1193
  if ((parserInput.currentChar() !== '.' && parserInput.currentChar() !== '#') ||
1075
1194
  parserInput.peek(/^[^{]*\}/)) {
1076
1195
  return;
1077
1196
  }
1197
+
1078
1198
  parserInput.save();
1199
+
1079
1200
  match = parserInput.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/);
1080
1201
  if (match) {
1081
1202
  name = match[1];
1082
- var argInfo = this.args(false);
1203
+
1204
+ const argInfo = this.args(false);
1083
1205
  params = argInfo.args;
1084
1206
  variadic = argInfo.variadic;
1207
+
1085
1208
  // .mixincall("@{a}");
1086
1209
  // looks a bit like a mixin definition..
1087
1210
  // also
@@ -1091,29 +1214,34 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1091
1214
  parserInput.restore('Missing closing \')\'');
1092
1215
  return;
1093
1216
  }
1217
+
1094
1218
  parserInput.commentStore.length = 0;
1219
+
1095
1220
  if (parserInput.$str('when')) { // Guard
1096
1221
  cond = expect(parsers.conditions, 'expected condition');
1097
1222
  }
1223
+
1098
1224
  ruleset = parsers.block();
1225
+
1099
1226
  if (ruleset) {
1100
1227
  parserInput.forget();
1101
- return new (tree_1.default.mixin.Definition)(name, params, ruleset, cond, variadic);
1102
- }
1103
- else {
1228
+ return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
1229
+ } else {
1104
1230
  parserInput.restore();
1105
1231
  }
1106
- }
1107
- else {
1232
+ } else {
1108
1233
  parserInput.restore();
1109
1234
  }
1110
1235
  },
1111
- ruleLookups: function () {
1112
- var rule;
1113
- var lookups = [];
1236
+
1237
+ ruleLookups: function() {
1238
+ let rule;
1239
+ const lookups = [];
1240
+
1114
1241
  if (parserInput.currentChar() !== '[') {
1115
1242
  return;
1116
1243
  }
1244
+
1117
1245
  while (true) {
1118
1246
  parserInput.save();
1119
1247
  rule = this.lookupValue();
@@ -1128,21 +1256,27 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1128
1256
  return lookups;
1129
1257
  }
1130
1258
  },
1131
- lookupValue: function () {
1259
+
1260
+ lookupValue: function() {
1132
1261
  parserInput.save();
1262
+
1133
1263
  if (!parserInput.$char('[')) {
1134
1264
  parserInput.restore();
1135
1265
  return;
1136
1266
  }
1137
- var name = parserInput.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/);
1267
+
1268
+ const name = parserInput.$re(/^(?:[@$]{0,2})[_a-zA-Z0-9-]*/);
1269
+
1138
1270
  if (!parserInput.$char(']')) {
1139
1271
  parserInput.restore();
1140
1272
  return;
1141
1273
  }
1274
+
1142
1275
  if (name || name === '') {
1143
1276
  parserInput.forget();
1144
1277
  return name;
1145
1278
  }
1279
+
1146
1280
  parserInput.restore();
1147
1281
  }
1148
1282
  },
@@ -1151,11 +1285,13 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1151
1285
  // and can be found inside a rule's value.
1152
1286
  //
1153
1287
  entity: function () {
1154
- var entities = this.entities;
1288
+ const entities = this.entities;
1289
+
1155
1290
  return this.comment() || entities.literal() || entities.variable() || entities.url() ||
1156
1291
  entities.property() || entities.call() || entities.keyword() || this.mixin.call(true) ||
1157
1292
  entities.javascript();
1158
1293
  },
1294
+
1159
1295
  //
1160
1296
  // A Declaration terminator. Note that we use `peek()` to check for '}',
1161
1297
  // because the `block` rule will be expecting it, but we still need to make sure
@@ -1164,26 +1300,27 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1164
1300
  end: function () {
1165
1301
  return parserInput.$char(';') || parserInput.peek('}');
1166
1302
  },
1303
+
1167
1304
  //
1168
1305
  // IE's alpha function
1169
1306
  //
1170
1307
  // alpha(opacity=88)
1171
1308
  //
1172
1309
  ieAlpha: function () {
1173
- var value;
1310
+ let value;
1311
+
1174
1312
  // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
1175
- if (!parserInput.$re(/^opacity=/i)) {
1176
- return;
1177
- }
1313
+ if (!parserInput.$re(/^opacity=/i)) { return; }
1178
1314
  value = parserInput.$re(/^\d+/);
1179
1315
  if (!value) {
1180
1316
  value = expect(parsers.entities.variable, 'Could not parse alpha');
1181
- value = "@{".concat(value.name.slice(1), "}");
1317
+ value = `@{${value.name.slice(1)}}`;
1182
1318
  }
1183
1319
  expectChar(')');
1184
- return new tree_1.default.Quoted('', "alpha(opacity=".concat(value, ")"));
1320
+ return new tree.Quoted('', `alpha(opacity=${value})`);
1185
1321
  },
1186
- /**
1322
+
1323
+ /**
1187
1324
  * A Selector Element
1188
1325
  *
1189
1326
  * div
@@ -1196,54 +1333,54 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1196
1333
  * and an element name, such as a tag a class, or `*`.
1197
1334
  */
1198
1335
  element: function () {
1199
- var e;
1200
- var c;
1201
- var v;
1202
- var index = parserInput.i;
1336
+ let e;
1337
+ let c;
1338
+ let v;
1339
+ const index = parserInput.i;
1340
+
1203
1341
  c = this.combinator();
1342
+
1204
1343
  /** This selector parser is quite simplistic and will pass a number of invalid selectors. */
1205
1344
  e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
1206
1345
  // eslint-disable-next-line no-control-regex
1207
1346
  parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
1208
1347
  parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
1209
- parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[.#:](?=@)/) ||
1348
+ parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[.#:](?=@)/) ||
1210
1349
  this.entities.variableCurly();
1350
+
1211
1351
  if (!e) {
1212
1352
  parserInput.save();
1213
1353
  if (parserInput.$char('(')) {
1214
1354
  if ((v = this.selector(false))) {
1215
- var selectors = [];
1355
+ let selectors = [];
1216
1356
  while (parserInput.$char(',')) {
1217
1357
  selectors.push(v);
1218
- selectors.push(new anonymous_1.default(','));
1358
+ selectors.push(new Anonymous(','));
1219
1359
  v = this.selector(false);
1220
1360
  }
1221
1361
  selectors.push(v);
1362
+
1222
1363
  if (parserInput.$char(')')) {
1223
1364
  if (selectors.length > 1) {
1224
- e = new (tree_1.default.Paren)(new selector_1.default(selectors));
1225
- }
1226
- else {
1227
- e = new (tree_1.default.Paren)(v);
1365
+ e = new (tree.Paren)(new Selector(selectors));
1366
+ } else {
1367
+ e = new(tree.Paren)(v);
1228
1368
  }
1229
1369
  parserInput.forget();
1230
- }
1231
- else {
1370
+ } else {
1232
1371
  parserInput.restore('Missing closing \')\'');
1233
1372
  }
1234
- }
1235
- else {
1373
+ } else {
1236
1374
  parserInput.restore('Missing closing \')\'');
1237
1375
  }
1238
- }
1239
- else {
1376
+ } else {
1240
1377
  parserInput.forget();
1241
1378
  }
1242
1379
  }
1243
- if (e) {
1244
- return new (tree_1.default.Element)(c, e, e instanceof tree_1.default.Variable, index + currentIndex, fileInfo);
1245
- }
1380
+
1381
+ if (e) { return new(tree.Element)(c, e, e instanceof tree.Variable, index + currentIndex, fileInfo); }
1246
1382
  },
1383
+
1247
1384
  //
1248
1385
  // Combinators combine elements together, in a Selector.
1249
1386
  //
@@ -1254,32 +1391,30 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1254
1391
  // we deal with this in *combinator.js*.
1255
1392
  //
1256
1393
  combinator: function () {
1257
- var c = parserInput.currentChar();
1394
+ let c = parserInput.currentChar();
1395
+
1258
1396
  if (c === '/') {
1259
1397
  parserInput.save();
1260
- var slashedCombinator = parserInput.$re(/^\/[a-z]+\//i);
1398
+ const slashedCombinator = parserInput.$re(/^\/[a-z]+\//i);
1261
1399
  if (slashedCombinator) {
1262
1400
  parserInput.forget();
1263
- return new (tree_1.default.Combinator)(slashedCombinator);
1401
+ return new(tree.Combinator)(slashedCombinator);
1264
1402
  }
1265
1403
  parserInput.restore();
1266
1404
  }
1405
+
1267
1406
  if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
1268
1407
  parserInput.i++;
1269
1408
  if (c === '^' && parserInput.currentChar() === '^') {
1270
1409
  c = '^^';
1271
1410
  parserInput.i++;
1272
1411
  }
1273
- while (parserInput.isWhitespace()) {
1274
- parserInput.i++;
1275
- }
1276
- return new (tree_1.default.Combinator)(c);
1277
- }
1278
- else if (parserInput.isWhitespace(-1)) {
1279
- return new (tree_1.default.Combinator)(' ');
1280
- }
1281
- else {
1282
- return new (tree_1.default.Combinator)(null);
1412
+ while (parserInput.isWhitespace()) { parserInput.i++; }
1413
+ return new(tree.Combinator)(c);
1414
+ } else if (parserInput.isWhitespace(-1)) {
1415
+ return new(tree.Combinator)(' ');
1416
+ } else {
1417
+ return new(tree.Combinator)(null);
1283
1418
  }
1284
1419
  },
1285
1420
  //
@@ -1292,43 +1427,35 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1292
1427
  // Selectors are made out of one or more Elements, see above.
1293
1428
  //
1294
1429
  selector: function (isLess) {
1295
- var index = parserInput.i;
1296
- var elements;
1297
- var extendList;
1298
- var c;
1299
- var e;
1300
- var allExtends;
1301
- var when;
1302
- var condition;
1430
+ const index = parserInput.i;
1431
+ let elements;
1432
+ let extendList;
1433
+ let c;
1434
+ let e;
1435
+ let allExtends;
1436
+ let when;
1437
+ let condition;
1303
1438
  isLess = isLess !== false;
1304
1439
  while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str('when'))) || (e = this.element())) {
1305
1440
  if (when) {
1306
1441
  condition = expect(this.conditions, 'expected condition');
1307
- }
1308
- else if (condition) {
1442
+ } else if (condition) {
1309
1443
  error('CSS guard can only be used at the end of selector');
1310
- }
1311
- else if (extendList) {
1444
+ } else if (extendList) {
1312
1445
  if (allExtends) {
1313
1446
  allExtends = allExtends.concat(extendList);
1314
- }
1315
- else {
1447
+ } else {
1316
1448
  allExtends = extendList;
1317
1449
  }
1318
- }
1319
- else {
1320
- if (allExtends) {
1321
- error('Extend can only be used at the end of selector');
1322
- }
1450
+ } else {
1451
+ if (allExtends) { error('Extend can only be used at the end of selector'); }
1323
1452
  c = parserInput.currentChar();
1324
- if (Array.isArray(e)) {
1325
- e.forEach(function (ele) { return elements.push(ele); });
1326
- }
1327
- if (elements) {
1453
+ if (Array.isArray(e)){
1454
+ e.forEach(ele => elements.push(ele));
1455
+ } if (elements) {
1328
1456
  elements.push(e);
1329
- }
1330
- else {
1331
- elements = [e];
1457
+ } else {
1458
+ elements = [ e ];
1332
1459
  }
1333
1460
  e = null;
1334
1461
  }
@@ -1336,16 +1463,13 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1336
1463
  break;
1337
1464
  }
1338
1465
  }
1339
- if (elements) {
1340
- return new (tree_1.default.Selector)(elements, allExtends, condition, index + currentIndex, fileInfo);
1341
- }
1342
- if (allExtends) {
1343
- error('Extend must be used to extend a selector, it cannot be used on its own');
1344
- }
1466
+
1467
+ if (elements) { return new(tree.Selector)(elements, allExtends, condition, index + currentIndex, fileInfo); }
1468
+ if (allExtends) { error('Extend must be used to extend a selector, it cannot be used on its own'); }
1345
1469
  },
1346
1470
  selectors: function () {
1347
- var s;
1348
- var selectors;
1471
+ let s;
1472
+ let selectors;
1349
1473
  while (true) {
1350
1474
  s = this.selector();
1351
1475
  if (!s) {
@@ -1353,17 +1477,14 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1353
1477
  }
1354
1478
  if (selectors) {
1355
1479
  selectors.push(s);
1356
- }
1357
- else {
1358
- selectors = [s];
1480
+ } else {
1481
+ selectors = [ s ];
1359
1482
  }
1360
1483
  parserInput.commentStore.length = 0;
1361
1484
  if (s.condition && selectors.length > 1) {
1362
1485
  error('Guards are only currently allowed on a single selector.');
1363
1486
  }
1364
- if (!parserInput.$char(',')) {
1365
- break;
1366
- }
1487
+ if (!parserInput.$char(',')) { break; }
1367
1488
  if (s.condition) {
1368
1489
  error('Guards are only currently allowed on a single selector.');
1369
1490
  }
@@ -1372,21 +1493,22 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1372
1493
  return selectors;
1373
1494
  },
1374
1495
  attribute: function () {
1375
- if (!parserInput.$char('[')) {
1376
- return;
1377
- }
1378
- var entities = this.entities;
1379
- var key;
1380
- var val;
1381
- var op;
1496
+ if (!parserInput.$char('[')) { return; }
1497
+
1498
+ const entities = this.entities;
1499
+ let key;
1500
+ let val;
1501
+ let op;
1382
1502
  //
1383
1503
  // case-insensitive flag
1384
1504
  // e.g. [attr operator value i]
1385
1505
  //
1386
- var cif;
1506
+ let cif;
1507
+
1387
1508
  if (!(key = entities.variableCurly())) {
1388
1509
  key = expect(/^(?:[_A-Za-z0-9-*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/);
1389
1510
  }
1511
+
1390
1512
  op = parserInput.$re(/^[|~*$^]?=/);
1391
1513
  if (op) {
1392
1514
  val = entities.quoted() || parserInput.$re(/^[0-9]+%/) || parserInput.$re(/^[\w-]+/) || entities.variableCurly();
@@ -1394,30 +1516,35 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1394
1516
  cif = parserInput.$re(/^[iIsS]/);
1395
1517
  }
1396
1518
  }
1519
+
1397
1520
  expectChar(']');
1398
- return new (tree_1.default.Attribute)(key, op, val, cif);
1521
+
1522
+ return new(tree.Attribute)(key, op, val, cif);
1399
1523
  },
1524
+
1400
1525
  //
1401
1526
  // The `block` rule is used by `ruleset` and `mixin.definition`.
1402
1527
  // It's a wrapper around the `primary` rule, with added `{}`.
1403
1528
  //
1404
1529
  block: function () {
1405
- var content;
1530
+ let content;
1406
1531
  if (parserInput.$char('{') && (content = this.primary()) && parserInput.$char('}')) {
1407
1532
  return content;
1408
1533
  }
1409
1534
  },
1410
- blockRuleset: function () {
1411
- var block = this.block();
1535
+
1536
+ blockRuleset: function() {
1537
+ let block = this.block();
1412
1538
  if (block) {
1413
- block = new tree_1.default.Ruleset(null, block);
1539
+ return new tree.Ruleset(null, block);
1414
1540
  }
1415
- return block;
1416
1541
  },
1417
- detachedRuleset: function () {
1418
- var argInfo;
1419
- var params;
1420
- var variadic;
1542
+
1543
+ detachedRuleset: function() {
1544
+ let argInfo;
1545
+ let params;
1546
+ let variadic;
1547
+
1421
1548
  parserInput.save();
1422
1549
  if (parserInput.$re(/^[.#]\(/)) {
1423
1550
  /**
@@ -1434,74 +1561,81 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1434
1561
  return;
1435
1562
  }
1436
1563
  }
1437
- var blockRuleset = this.blockRuleset();
1564
+ const blockRuleset = this.blockRuleset();
1438
1565
  if (blockRuleset) {
1439
1566
  parserInput.forget();
1440
1567
  if (params) {
1441
- return new tree_1.default.mixin.Definition(null, params, blockRuleset, null, variadic);
1568
+ return new tree.mixin.Definition(null, params, blockRuleset, null, variadic);
1442
1569
  }
1443
- return new tree_1.default.DetachedRuleset(blockRuleset);
1570
+ return new tree.DetachedRuleset(blockRuleset);
1444
1571
  }
1445
1572
  parserInput.restore();
1446
1573
  },
1574
+
1447
1575
  //
1448
1576
  // div, .class, body > p {...}
1449
1577
  //
1450
1578
  ruleset: function () {
1451
- var selectors;
1452
- var rules;
1453
- var debugInfo;
1579
+ let selectors;
1580
+ let rules;
1581
+ let debugInfo;
1582
+
1454
1583
  parserInput.save();
1584
+
1455
1585
  if (context.dumpLineNumbers) {
1456
1586
  debugInfo = getDebugInfo(parserInput.i);
1457
1587
  }
1588
+
1458
1589
  selectors = this.selectors();
1590
+
1459
1591
  if (selectors && (rules = this.block())) {
1460
1592
  parserInput.forget();
1461
- var ruleset = new (tree_1.default.Ruleset)(selectors, rules, context.strictImports);
1593
+ const ruleset = new(tree.Ruleset)(selectors, rules, context.strictImports);
1462
1594
  if (context.dumpLineNumbers) {
1463
1595
  ruleset.debugInfo = debugInfo;
1464
1596
  }
1465
1597
  return ruleset;
1466
- }
1467
- else {
1598
+ } else {
1468
1599
  parserInput.restore();
1469
1600
  }
1470
1601
  },
1471
1602
  declaration: function () {
1472
- var name;
1473
- var value;
1474
- var index = parserInput.i;
1475
- var hasDR;
1476
- var c = parserInput.currentChar();
1477
- var important;
1478
- var merge;
1479
- var isVariable;
1480
- if (c === '.' || c === '#' || c === '&' || c === ':') {
1481
- return;
1482
- }
1603
+ let name;
1604
+ let value;
1605
+ const index = parserInput.i;
1606
+ let hasDR;
1607
+ const c = parserInput.currentChar();
1608
+ let important;
1609
+ let merge;
1610
+ let isVariable;
1611
+
1612
+ if (c === '.' || c === '#' || c === '&' || c === ':') { return; }
1613
+
1483
1614
  parserInput.save();
1615
+
1484
1616
  name = this.variable() || this.ruleProperty();
1485
1617
  if (name) {
1486
1618
  isVariable = typeof name === 'string';
1619
+
1487
1620
  if (isVariable) {
1488
1621
  value = this.detachedRuleset();
1489
1622
  if (value) {
1490
1623
  hasDR = true;
1491
1624
  }
1492
1625
  }
1626
+
1493
1627
  parserInput.commentStore.length = 0;
1494
1628
  if (!value) {
1495
1629
  // a name returned by this.ruleProperty() is always an array of the form:
1496
1630
  // [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
1497
1631
  // where each item is a tree.Keyword or tree.Variable
1498
1632
  merge = !isVariable && name.length > 1 && name.pop().value;
1633
+
1499
1634
  // Custom property values get permissive parsing
1500
1635
  if (name[0].value && name[0].value.slice(0, 2) === '--') {
1501
1636
  if (parserInput.$char(';')) {
1502
- value = new anonymous_1.default('');
1503
- }
1504
- else {
1637
+ value = new Anonymous('');
1638
+ } else {
1505
1639
  value = this.permissiveValue(/[;}]/, true);
1506
1640
  }
1507
1641
  }
@@ -1513,15 +1647,16 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1513
1647
  if (value) {
1514
1648
  parserInput.forget();
1515
1649
  // anonymous values absorb the end ';' which is required for them to work
1516
- return new (tree_1.default.Declaration)(name, value, false, merge, index + currentIndex, fileInfo);
1650
+ return new(tree.Declaration)(name, value, false, merge, index + currentIndex, fileInfo);
1517
1651
  }
1652
+
1518
1653
  if (!value) {
1519
1654
  value = this.value();
1520
1655
  }
1656
+
1521
1657
  if (value) {
1522
1658
  important = this.important();
1523
- }
1524
- else if (isVariable) {
1659
+ } else if (isVariable) {
1525
1660
  /**
1526
1661
  * As a last resort, try permissiveValue
1527
1662
  *
@@ -1531,23 +1666,23 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1531
1666
  value = this.permissiveValue();
1532
1667
  }
1533
1668
  }
1669
+
1534
1670
  if (value && (this.end() || hasDR)) {
1535
1671
  parserInput.forget();
1536
- return new (tree_1.default.Declaration)(name, value, important, merge, index + currentIndex, fileInfo);
1672
+ return new(tree.Declaration)(name, value, important, merge, index + currentIndex, fileInfo);
1537
1673
  }
1538
1674
  else {
1539
1675
  parserInput.restore();
1540
1676
  }
1541
- }
1542
- else {
1677
+ } else {
1543
1678
  parserInput.restore();
1544
1679
  }
1545
1680
  },
1546
1681
  anonymousValue: function () {
1547
- var index = parserInput.i;
1548
- var match = parserInput.$re(/^([^.#@$+/'"*`(;{}-]*);/);
1682
+ const index = parserInput.i;
1683
+ const match = parserInput.$re(/^([^.#@$+/'"*`(;{}-]*);/);
1549
1684
  if (match) {
1550
- return new (tree_1.default.Anonymous)(match[1], index + currentIndex);
1685
+ return new(tree.Anonymous)(match[1], index + currentIndex);
1551
1686
  }
1552
1687
  },
1553
1688
  /**
@@ -1558,23 +1693,23 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1558
1693
  * First, it will try to parse comments and entities to reach
1559
1694
  * the end. This is mostly like the Expression parser except no
1560
1695
  * math is allowed.
1561
- *
1696
+ *
1562
1697
  * @param {RexExp} untilTokens - Characters to stop parsing at
1563
1698
  */
1564
1699
  permissiveValue: function (untilTokens) {
1565
- var i;
1566
- var e;
1567
- var done;
1568
- var value;
1569
- var tok = untilTokens || ';';
1570
- var index = parserInput.i;
1571
- var result = [];
1700
+ let i;
1701
+ let e;
1702
+ let done;
1703
+ let value;
1704
+ const tok = untilTokens || ';';
1705
+ const index = parserInput.i;
1706
+ const result = [];
1707
+
1572
1708
  function testCurrentChar() {
1573
- var char = parserInput.currentChar();
1709
+ const char = parserInput.currentChar();
1574
1710
  if (typeof tok === 'string') {
1575
1711
  return char === tok;
1576
- }
1577
- else {
1712
+ } else {
1578
1713
  return tok.test(char);
1579
1714
  }
1580
1715
  }
@@ -1593,13 +1728,15 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1593
1728
  value.push(e);
1594
1729
  }
1595
1730
  if (parserInput.peek(',')) {
1596
- value.push(new (tree_1.default.Anonymous)(',', parserInput.i));
1731
+ value.push(new (tree.Anonymous)(',', parserInput.i));
1597
1732
  parserInput.$char(',');
1598
1733
  }
1599
1734
  } while (e);
1735
+
1600
1736
  done = testCurrentChar();
1737
+
1601
1738
  if (value.length > 0) {
1602
- value = new (tree_1.default.Expression)(value);
1739
+ value = new(tree.Expression)(value);
1603
1740
  if (done) {
1604
1741
  return value;
1605
1742
  }
@@ -1608,40 +1745,42 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1608
1745
  }
1609
1746
  // Preserve space before $parseUntil as it will not
1610
1747
  if (parserInput.prevChar() === ' ') {
1611
- result.push(new tree_1.default.Anonymous(' ', index));
1748
+ result.push(new tree.Anonymous(' ', index));
1612
1749
  }
1613
1750
  }
1614
1751
  parserInput.save();
1752
+
1615
1753
  value = parserInput.$parseUntil(tok);
1754
+
1616
1755
  if (value) {
1617
1756
  if (typeof value === 'string') {
1618
- error("Expected '".concat(value, "'"), 'Parse');
1757
+ error(`Expected '${value}'`, 'Parse');
1619
1758
  }
1620
1759
  if (value.length === 1 && value[0] === ' ') {
1621
1760
  parserInput.forget();
1622
- return new tree_1.default.Anonymous('', index);
1761
+ return new tree.Anonymous('', index);
1623
1762
  }
1624
1763
  /** @type {string} */
1625
- var item = void 0;
1764
+ let item;
1626
1765
  for (i = 0; i < value.length; i++) {
1627
1766
  item = value[i];
1628
1767
  if (Array.isArray(item)) {
1629
1768
  // Treat actual quotes as normal quoted values
1630
- result.push(new tree_1.default.Quoted(item[0], item[1], true, index, fileInfo));
1769
+ result.push(new tree.Quoted(item[0], item[1], true, index, fileInfo));
1631
1770
  }
1632
1771
  else {
1633
1772
  if (i === value.length - 1) {
1634
1773
  item = item.trim();
1635
1774
  }
1636
1775
  // Treat like quoted values, but replace vars like unquoted expressions
1637
- var quote = new tree_1.default.Quoted('\'', item, true, index, fileInfo);
1638
- var variableRegex = /@([\w-]+)/g;
1639
- var propRegex = /\$([\w-]+)/g;
1776
+ const quote = new tree.Quoted('\'', item, true, index, fileInfo);
1777
+ const variableRegex = /@([\w-]+)/g;
1778
+ const propRegex = /\$([\w-]+)/g;
1640
1779
  if (variableRegex.test(item)) {
1641
- warn('@[ident] in unknown values will not be evaluated as variables in the future. Use @{[ident]}', index, 'DEPRECATED');
1780
+ warn('@[ident] in unknown values will not be evaluated as variables in the future. Use @{[ident]}', index, 'DEPRECATED', 'variable-in-unknown-value');
1642
1781
  }
1643
1782
  if (propRegex.test(item)) {
1644
- warn('$[ident] in unknown values will not be evaluated as property references in the future. Use ${[ident]}', index, 'DEPRECATED');
1783
+ warn('$[ident] in unknown values will not be evaluated as property references in the future. Use ${[ident]}', index, 'DEPRECATED', 'property-in-unknown-value');
1645
1784
  }
1646
1785
  quote.variableRegex = /@([\w-]+)|@{([\w-]+)}/g;
1647
1786
  quote.propRegex = /\$([\w-]+)|\${([\w-]+)}/g;
@@ -1649,10 +1788,11 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1649
1788
  }
1650
1789
  }
1651
1790
  parserInput.forget();
1652
- return new tree_1.default.Expression(result, true);
1791
+ return new tree.Expression(result, true);
1653
1792
  }
1654
1793
  parserInput.restore();
1655
1794
  },
1795
+
1656
1796
  //
1657
1797
  // An @import atrule
1658
1798
  //
@@ -1664,20 +1804,24 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1664
1804
  // stored in `import`, which we pass to the Import constructor.
1665
1805
  //
1666
1806
  'import': function () {
1667
- var path;
1668
- var features;
1669
- var index = parserInput.i;
1670
- var dir = parserInput.$re(/^@import\s+/);
1807
+ let path;
1808
+ let features;
1809
+ const index = parserInput.i;
1810
+
1811
+ const dir = parserInput.$re(/^@import\s+/);
1812
+
1671
1813
  if (dir) {
1672
- var options = (dir ? this.importOptions() : null) || {};
1814
+ const options = (dir ? this.importOptions() : null) || {};
1815
+
1673
1816
  if ((path = this.entities.quoted() || this.entities.url())) {
1674
1817
  features = this.mediaFeatures({});
1818
+
1675
1819
  if (!parserInput.$char(';')) {
1676
1820
  parserInput.i = index;
1677
1821
  error('missing semi-colon or unrecognised media features on import');
1678
1822
  }
1679
- features = features && new (tree_1.default.Value)(features);
1680
- return new (tree_1.default.Import)(path, features, options, index + currentIndex, fileInfo);
1823
+ features = features && new(tree.Value)(features);
1824
+ return new(tree.Import)(path, features, options, index + currentIndex, fileInfo);
1681
1825
  }
1682
1826
  else {
1683
1827
  parserInput.i = index;
@@ -1685,15 +1829,15 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1685
1829
  }
1686
1830
  }
1687
1831
  },
1688
- importOptions: function () {
1689
- var o;
1690
- var options = {};
1691
- var optionName;
1692
- var value;
1832
+
1833
+ importOptions: function() {
1834
+ let o;
1835
+ const options = {};
1836
+ let optionName;
1837
+ let value;
1838
+
1693
1839
  // list of options, surrounded by parens
1694
- if (!parserInput.$char('(')) {
1695
- return null;
1696
- }
1840
+ if (!parserInput.$char('(')) { return null; }
1697
1841
  do {
1698
1842
  o = this.importOption();
1699
1843
  if (o) {
@@ -1710,27 +1854,27 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1710
1854
  break;
1711
1855
  }
1712
1856
  options[optionName] = value;
1713
- if (!parserInput.$char(',')) {
1714
- break;
1715
- }
1857
+ if (!parserInput.$char(',')) { break; }
1716
1858
  }
1717
1859
  } while (o);
1718
1860
  expectChar(')');
1719
1861
  return options;
1720
1862
  },
1721
- importOption: function () {
1722
- var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
1863
+
1864
+ importOption: function() {
1865
+ const opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
1723
1866
  if (opt) {
1724
1867
  return opt[1];
1725
1868
  }
1726
1869
  },
1870
+
1727
1871
  mediaFeature: function (syntaxOptions) {
1728
- var entities = this.entities;
1729
- var nodes = [];
1730
- var e;
1731
- var p;
1732
- var rangeP;
1733
- var spacing = false;
1872
+ const entities = this.entities;
1873
+ const nodes = [];
1874
+ let e;
1875
+ let p;
1876
+ let rangeP;
1877
+ let spacing = false;
1734
1878
  parserInput.save();
1735
1879
  do {
1736
1880
  parserInput.save();
@@ -1738,129 +1882,143 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1738
1882
  spacing = true;
1739
1883
  }
1740
1884
  parserInput.restore();
1741
- e = entities.declarationCall.bind(this)() || entities.keyword() || entities.variable() || entities.mixinLookup();
1885
+
1886
+ e = entities.declarationCall.bind(this)() || entities.keyword() || entities.variable() || entities.mixinLookup()
1742
1887
  if (e) {
1743
1888
  nodes.push(e);
1744
- }
1745
- else if (parserInput.$char('(')) {
1889
+ if (e.type === 'Variable' ||
1890
+ (e.type === 'Keyword' && /^(and|or|not|only)$/i.test(e.value))) {
1891
+ spacing = true;
1892
+ }
1893
+ } else if (parserInput.$char('(')) {
1746
1894
  p = this.property();
1747
1895
  parserInput.save();
1748
1896
  if (!p && syntaxOptions.queryInParens && parserInput.$re(/^[0-9a-z-]*\s*([<>]=|<=|>=|[<>]|=)/)) {
1749
1897
  parserInput.restore();
1750
1898
  p = this.condition();
1899
+
1751
1900
  parserInput.save();
1752
1901
  rangeP = this.atomicCondition(null, p.rvalue);
1753
1902
  if (!rangeP) {
1754
1903
  parserInput.restore();
1755
1904
  }
1756
- }
1757
- else {
1905
+ } else {
1758
1906
  parserInput.restore();
1759
1907
  e = this.value();
1760
1908
  }
1761
1909
  if (parserInput.$char(')')) {
1762
1910
  if (p && !e) {
1763
- nodes.push(new (tree_1.default.Paren)(new (tree_1.default.QueryInParens)(p.op, p.lvalue, p.rvalue, rangeP ? rangeP.op : null, rangeP ? rangeP.rvalue : null, p._index)));
1911
+ nodes.push(new (tree.Paren)(new (tree.QueryInParens)(p.op, p.lvalue, p.rvalue, rangeP ? rangeP.op : null, rangeP ? rangeP.rvalue : null, p._index)));
1764
1912
  e = p;
1765
- }
1766
- else if (p && e) {
1767
- nodes.push(new (tree_1.default.Paren)(new (tree_1.default.Declaration)(p, e, null, null, parserInput.i + currentIndex, fileInfo, true)));
1913
+ } else if (p && e) {
1914
+ nodes.push(new (tree.Paren)(new (tree.Declaration)(p, e, null, null, parserInput.i + currentIndex, fileInfo, true)));
1768
1915
  if (!spacing) {
1769
1916
  nodes[nodes.length - 1].noSpacing = true;
1770
1917
  }
1771
1918
  spacing = false;
1772
- }
1773
- else if (e) {
1774
- nodes.push(new (tree_1.default.Paren)(e));
1919
+ } else if (e) {
1920
+ nodes.push(new(tree.Paren)(e));
1775
1921
  spacing = false;
1776
- }
1777
- else {
1922
+ } else {
1778
1923
  error('badly formed media feature definition');
1779
1924
  }
1780
- }
1781
- else {
1925
+ } else {
1782
1926
  error('Missing closing \')\'', 'Parse');
1783
1927
  }
1784
1928
  }
1785
1929
  } while (e);
1930
+
1786
1931
  parserInput.forget();
1787
1932
  if (nodes.length > 0) {
1788
- return new (tree_1.default.Expression)(nodes);
1933
+ return new(tree.Expression)(nodes);
1789
1934
  }
1790
1935
  },
1936
+
1791
1937
  mediaFeatures: function (syntaxOptions) {
1792
- var entities = this.entities;
1793
- var features = [];
1794
- var e;
1938
+ const entities = this.entities;
1939
+ const features = [];
1940
+ let e;
1795
1941
  do {
1796
1942
  e = this.mediaFeature(syntaxOptions);
1797
1943
  if (e) {
1798
1944
  features.push(e);
1799
- if (!parserInput.$char(',')) {
1800
- break;
1801
- }
1945
+ if (!parserInput.$char(',')) { break; }
1802
1946
  else if (!features[features.length - 1].noSpacing) {
1803
1947
  features[features.length - 1].noSpacing = false;
1804
1948
  }
1805
- }
1806
- else {
1949
+ } else {
1807
1950
  e = entities.variable() || entities.mixinLookup();
1808
1951
  if (e) {
1809
1952
  features.push(e);
1810
- if (!parserInput.$char(',')) {
1811
- break;
1812
- }
1953
+ if (!parserInput.$char(',')) { break; }
1813
1954
  else if (!features[features.length - 1].noSpacing) {
1814
1955
  features[features.length - 1].noSpacing = false;
1815
1956
  }
1816
1957
  }
1817
1958
  }
1818
1959
  } while (e);
1960
+
1819
1961
  return features.length > 0 ? features : null;
1820
1962
  },
1963
+
1821
1964
  prepareAndGetNestableAtRule: function (treeType, index, debugInfo, syntaxOptions) {
1822
- var features = this.mediaFeatures(syntaxOptions);
1823
- var rules = this.block();
1965
+ const features = this.mediaFeatures(syntaxOptions);
1966
+
1967
+ const rules = this.block();
1968
+
1824
1969
  if (!rules) {
1825
1970
  error('media definitions require block statements after any features');
1826
1971
  }
1972
+
1827
1973
  parserInput.forget();
1828
- var atRule = new (treeType)(rules, features, index + currentIndex, fileInfo);
1974
+
1975
+ const atRule = new (treeType)(rules, features, index + currentIndex, fileInfo);
1829
1976
  if (context.dumpLineNumbers) {
1830
1977
  atRule.debugInfo = debugInfo;
1831
1978
  }
1979
+
1832
1980
  return atRule;
1833
1981
  },
1982
+
1834
1983
  nestableAtRule: function () {
1835
- var debugInfo;
1836
- var index = parserInput.i;
1984
+ let debugInfo;
1985
+ const index = parserInput.i;
1986
+
1837
1987
  if (context.dumpLineNumbers) {
1838
1988
  debugInfo = getDebugInfo(index);
1839
1989
  }
1840
1990
  parserInput.save();
1991
+
1841
1992
  if (parserInput.$peekChar('@')) {
1842
1993
  if (parserInput.$str('@media')) {
1843
- return this.prepareAndGetNestableAtRule(tree_1.default.Media, index, debugInfo, atrule_syntax_1.MediaSyntaxOptions);
1994
+ return this.prepareAndGetNestableAtRule(tree.Media, index, debugInfo, MediaSyntaxOptions);
1844
1995
  }
1996
+
1845
1997
  if (parserInput.$str('@container')) {
1846
- return this.prepareAndGetNestableAtRule(tree_1.default.Container, index, debugInfo, atrule_syntax_1.ContainerSyntaxOptions);
1998
+ return this.prepareAndGetNestableAtRule(tree.Container, index, debugInfo, ContainerSyntaxOptions);
1847
1999
  }
1848
2000
  }
2001
+
1849
2002
  parserInput.restore();
1850
2003
  },
2004
+
1851
2005
  //
2006
+
1852
2007
  // A @plugin directive, used to import plugins dynamically.
1853
2008
  //
1854
2009
  // @plugin (args) "lib";
1855
2010
  //
1856
2011
  plugin: function () {
1857
- var path;
1858
- var args;
1859
- var options;
1860
- var index = parserInput.i;
1861
- var dir = parserInput.$re(/^@plugin\s+/);
2012
+ let path;
2013
+ let args;
2014
+ let options;
2015
+ const index = parserInput.i;
2016
+ const dir = parserInput.$re(/^@plugin\s+/);
2017
+
1862
2018
  if (dir) {
2019
+ warn('The @plugin directive is deprecated and will be replaced in Less 5.x. Use --plugin CLI option or the programmatic plugin API instead.', index, 'DEPRECATED', 'at-plugin');
1863
2020
  args = this.pluginArgs();
2021
+
1864
2022
  if (args) {
1865
2023
  options = {
1866
2024
  pluginArgs: args,
@@ -1870,12 +2028,14 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1870
2028
  else {
1871
2029
  options = { isPlugin: true };
1872
2030
  }
2031
+
1873
2032
  if ((path = this.entities.quoted() || this.entities.url())) {
2033
+
1874
2034
  if (!parserInput.$char(';')) {
1875
2035
  parserInput.i = index;
1876
2036
  error('missing semi-colon on @plugin');
1877
2037
  }
1878
- return new (tree_1.default.Import)(path, null, options, index + currentIndex, fileInfo);
2038
+ return new(tree.Import)(path, null, options, index + currentIndex, fileInfo);
1879
2039
  }
1880
2040
  else {
1881
2041
  parserInput.i = index;
@@ -1883,14 +2043,15 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1883
2043
  }
1884
2044
  }
1885
2045
  },
1886
- pluginArgs: function () {
2046
+
2047
+ pluginArgs: function() {
1887
2048
  // list of options, surrounded by parens
1888
2049
  parserInput.save();
1889
2050
  if (!parserInput.$char('(')) {
1890
2051
  parserInput.restore();
1891
2052
  return null;
1892
2053
  }
1893
- var args = parserInput.$re(/^\s*([^);]+)\)\s*/);
2054
+ const args = parserInput.$re(/^\s*([^);]+)\)\s*/);
1894
2055
  if (args[1]) {
1895
2056
  parserInput.forget();
1896
2057
  return args[1].trim();
@@ -1940,6 +2101,7 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1940
2101
  else {
1941
2102
  parserInput.forget();
1942
2103
  }
2104
+
1943
2105
  return [rules, value, isKeywordList];
1944
2106
  },
1945
2107
  //
@@ -1948,33 +2110,36 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
1948
2110
  // @charset "utf-8";
1949
2111
  //
1950
2112
  atrule: function () {
1951
- var index = parserInput.i;
1952
- var name;
1953
- var value;
1954
- var rules;
1955
- var nonVendorSpecificName;
1956
- var hasIdentifier;
1957
- var hasExpression;
1958
- var hasUnknown;
1959
- var hasBlock = true;
1960
- var isRooted = true;
1961
- var isKeywordList = false;
1962
- if (parserInput.currentChar() !== '@') {
1963
- return;
1964
- }
2113
+ const index = parserInput.i;
2114
+ let name;
2115
+ let value;
2116
+ let rules;
2117
+ let nonVendorSpecificName;
2118
+ let hasIdentifier;
2119
+ let hasExpression;
2120
+ let hasUnknown;
2121
+ let hasBlock = true;
2122
+ let isRooted = true;
2123
+ let isKeywordList = false;
2124
+
2125
+ if (parserInput.currentChar() !== '@') { return; }
2126
+
1965
2127
  value = this['import']() || this.plugin() || this.nestableAtRule();
1966
2128
  if (value) {
1967
2129
  return value;
1968
2130
  }
2131
+
1969
2132
  parserInput.save();
2133
+
1970
2134
  name = parserInput.$re(/^@[a-z-]+/);
1971
- if (!name) {
1972
- return;
1973
- }
2135
+
2136
+ if (!name) { return; }
2137
+
1974
2138
  nonVendorSpecificName = name;
1975
2139
  if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
1976
- nonVendorSpecificName = "@".concat(name.slice(name.indexOf('-', 2) + 1));
2140
+ nonVendorSpecificName = `@${name.slice(name.indexOf('-', 2) + 1)}`;
1977
2141
  }
2142
+
1978
2143
  switch (nonVendorSpecificName) {
1979
2144
  case '@charset':
1980
2145
  hasIdentifier = true;
@@ -2003,33 +2168,35 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2003
2168
  hasUnknown = true;
2004
2169
  break;
2005
2170
  }
2171
+
2006
2172
  parserInput.commentStore.length = 0;
2173
+
2007
2174
  if (hasIdentifier) {
2008
2175
  value = this.entity();
2009
2176
  if (!value) {
2010
- error("expected ".concat(name, " identifier"));
2177
+ error(`expected ${name} identifier`);
2011
2178
  }
2012
- }
2013
- else if (hasExpression) {
2179
+ } else if (hasExpression) {
2014
2180
  value = this.expression();
2015
2181
  if (!value) {
2016
- error("expected ".concat(name, " expression"));
2182
+ error(`expected ${name} expression`);
2017
2183
  }
2018
- }
2019
- else if (hasUnknown) {
2020
- var unknownPackage = this.atruleUnknown(value, name, hasBlock);
2184
+ } else if (hasUnknown) {
2185
+ const unknownPackage = this.atruleUnknown(value, name, hasBlock);
2021
2186
  value = unknownPackage[0];
2022
2187
  hasBlock = unknownPackage[1];
2023
2188
  }
2189
+
2024
2190
  if (hasBlock) {
2025
- var blockPackage = this.atruleBlock(rules, value, isRooted, isKeywordList);
2191
+ let blockPackage = this.atruleBlock(rules, value, isRooted, isKeywordList);
2026
2192
  rules = blockPackage[0];
2027
2193
  value = blockPackage[1];
2028
2194
  isKeywordList = blockPackage[2];
2195
+
2029
2196
  if (!rules && !hasUnknown) {
2030
2197
  parserInput.restore();
2031
2198
  name = parserInput.$re(/^@[a-z-]+/);
2032
- var unknownPackage = this.atruleUnknown(value, name, hasBlock);
2199
+ const unknownPackage = this.atruleUnknown(value, name, hasBlock);
2033
2200
  value = unknownPackage[0];
2034
2201
  hasBlock = unknownPackage[1];
2035
2202
  if (hasBlock) {
@@ -2040,12 +2207,18 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2040
2207
  }
2041
2208
  }
2042
2209
  }
2210
+
2043
2211
  if (rules || isKeywordList || (!hasBlock && value && parserInput.$char(';'))) {
2044
2212
  parserInput.forget();
2045
- return new (tree_1.default.AtRule)(name, value, rules, index + currentIndex, fileInfo, context.dumpLineNumbers ? getDebugInfo(index) : null, isRooted);
2213
+ return new(tree.AtRule)(name, value, rules, index + currentIndex, fileInfo,
2214
+ context.dumpLineNumbers ? getDebugInfo(index) : null,
2215
+ isRooted
2216
+ );
2046
2217
  }
2218
+
2047
2219
  parserInput.restore('at-rule options not recognised');
2048
2220
  },
2221
+
2049
2222
  //
2050
2223
  // A Value is a comma-delimited list of Expressions
2051
2224
  //
@@ -2055,20 +2228,20 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2055
2228
  // and before the `;`.
2056
2229
  //
2057
2230
  value: function () {
2058
- var e;
2059
- var expressions = [];
2060
- var index = parserInput.i;
2231
+ let e;
2232
+ const expressions = [];
2233
+ const index = parserInput.i;
2234
+
2061
2235
  do {
2062
2236
  e = this.expression();
2063
2237
  if (e) {
2064
2238
  expressions.push(e);
2065
- if (!parserInput.$char(',')) {
2066
- break;
2067
- }
2239
+ if (!parserInput.$char(',')) { break; }
2068
2240
  }
2069
2241
  } while (e);
2242
+
2070
2243
  if (expressions.length > 0) {
2071
- return new (tree_1.default.Value)(expressions, index + currentIndex);
2244
+ return new(tree.Value)(expressions, index + currentIndex);
2072
2245
  }
2073
2246
  },
2074
2247
  important: function () {
@@ -2077,14 +2250,15 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2077
2250
  }
2078
2251
  },
2079
2252
  sub: function () {
2080
- var a;
2081
- var e;
2253
+ let a;
2254
+ let e;
2255
+
2082
2256
  parserInput.save();
2083
2257
  if (parserInput.$char('(')) {
2084
2258
  a = this.addition();
2085
2259
  if (a && parserInput.$char(')')) {
2086
2260
  parserInput.forget();
2087
- e = new (tree_1.default.Expression)([a]);
2261
+ e = new(tree.Expression)([a]);
2088
2262
  e.parens = true;
2089
2263
  return e;
2090
2264
  }
@@ -2095,19 +2269,22 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2095
2269
  },
2096
2270
  colorOperand: function () {
2097
2271
  parserInput.save();
2272
+
2098
2273
  // hsl or rgb or lch operand
2099
- var match = parserInput.$re(/^[lchrgbs]\s+/);
2274
+ const match = parserInput.$re(/^[lchrgbs]\s+/);
2100
2275
  if (match) {
2101
- return new tree_1.default.Keyword(match[0]);
2276
+ parserInput.forget();
2277
+ return new tree.Keyword(match[0]);
2102
2278
  }
2279
+
2103
2280
  parserInput.restore();
2104
2281
  },
2105
2282
  multiplication: function () {
2106
- var m;
2107
- var a;
2108
- var op;
2109
- var operation;
2110
- var isSpaced;
2283
+ let m;
2284
+ let a;
2285
+ let op;
2286
+ let operation;
2287
+ let isSpaced;
2111
2288
  m = this.operand();
2112
2289
  if (m) {
2113
2290
  isSpaced = parserInput.isWhitespace(-1);
@@ -2115,39 +2292,39 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2115
2292
  if (parserInput.peek(/^\/[*/]/)) {
2116
2293
  break;
2117
2294
  }
2295
+
2118
2296
  parserInput.save();
2297
+
2119
2298
  op = parserInput.$char('/') || parserInput.$char('*');
2120
2299
  if (!op) {
2121
- var index = parserInput.i;
2300
+ let index = parserInput.i;
2122
2301
  op = parserInput.$str('./');
2123
2302
  if (op) {
2124
- warn('./ operator is deprecated', index, 'DEPRECATED');
2303
+ warn('./ operator is deprecated', index, 'DEPRECATED', 'dot-slash-operator');
2125
2304
  }
2126
2305
  }
2127
- if (!op) {
2128
- parserInput.forget();
2129
- break;
2130
- }
2306
+
2307
+ if (!op) { parserInput.forget(); break; }
2308
+
2131
2309
  a = this.operand();
2132
- if (!a) {
2133
- parserInput.restore();
2134
- break;
2135
- }
2310
+
2311
+ if (!a) { parserInput.restore(); break; }
2136
2312
  parserInput.forget();
2313
+
2137
2314
  m.parensInOp = true;
2138
2315
  a.parensInOp = true;
2139
- operation = new (tree_1.default.Operation)(op, [operation || m, a], isSpaced);
2316
+ operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
2140
2317
  isSpaced = parserInput.isWhitespace(-1);
2141
2318
  }
2142
2319
  return operation || m;
2143
2320
  }
2144
2321
  },
2145
2322
  addition: function () {
2146
- var m;
2147
- var a;
2148
- var op;
2149
- var operation;
2150
- var isSpaced;
2323
+ let m;
2324
+ let a;
2325
+ let op;
2326
+ let operation;
2327
+ let isSpaced;
2151
2328
  m = this.multiplication();
2152
2329
  if (m) {
2153
2330
  isSpaced = parserInput.isWhitespace(-1);
@@ -2160,19 +2337,21 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2160
2337
  if (!a) {
2161
2338
  break;
2162
2339
  }
2340
+
2163
2341
  m.parensInOp = true;
2164
2342
  a.parensInOp = true;
2165
- operation = new (tree_1.default.Operation)(op, [operation || m, a], isSpaced);
2343
+ operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
2166
2344
  isSpaced = parserInput.isWhitespace(-1);
2167
2345
  }
2168
2346
  return operation || m;
2169
2347
  }
2170
2348
  },
2171
2349
  conditions: function () {
2172
- var a;
2173
- var b;
2174
- var index = parserInput.i;
2175
- var condition;
2350
+ let a;
2351
+ let b;
2352
+ const index = parserInput.i;
2353
+ let condition;
2354
+
2176
2355
  a = this.condition(true);
2177
2356
  if (a) {
2178
2357
  while (true) {
@@ -2183,41 +2362,41 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2183
2362
  if (!b) {
2184
2363
  break;
2185
2364
  }
2186
- condition = new (tree_1.default.Condition)('or', condition || a, b, index + currentIndex);
2365
+ condition = new(tree.Condition)('or', condition || a, b, index + currentIndex);
2187
2366
  }
2188
2367
  return condition || a;
2189
2368
  }
2190
2369
  },
2191
2370
  condition: function (needsParens) {
2192
- var result;
2193
- var logical;
2194
- var next;
2371
+ let result;
2372
+ let logical;
2373
+ let next;
2195
2374
  function or() {
2196
2375
  return parserInput.$str('or');
2197
2376
  }
2377
+
2198
2378
  result = this.conditionAnd(needsParens);
2199
2379
  if (!result) {
2200
- return;
2380
+ return ;
2201
2381
  }
2202
2382
  logical = or();
2203
2383
  if (logical) {
2204
2384
  next = this.condition(needsParens);
2205
2385
  if (next) {
2206
- result = new (tree_1.default.Condition)(logical, result, next);
2207
- }
2208
- else {
2209
- return;
2386
+ result = new(tree.Condition)(logical, result, next);
2387
+ } else {
2388
+ return ;
2210
2389
  }
2211
2390
  }
2212
2391
  return result;
2213
2392
  },
2214
2393
  conditionAnd: function (needsParens) {
2215
- var result;
2216
- var logical;
2217
- var next;
2218
- var self = this;
2394
+ let result;
2395
+ let logical;
2396
+ let next;
2397
+ const self = this;
2219
2398
  function insideCondition() {
2220
- var cond = self.negatedCondition(needsParens) || self.parenthesisCondition(needsParens);
2399
+ const cond = self.negatedCondition(needsParens) || self.parenthesisCondition(needsParens);
2221
2400
  if (!cond && !needsParens) {
2222
2401
  return self.atomicCondition(needsParens);
2223
2402
  }
@@ -2226,25 +2405,25 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2226
2405
  function and() {
2227
2406
  return parserInput.$str('and');
2228
2407
  }
2408
+
2229
2409
  result = insideCondition();
2230
2410
  if (!result) {
2231
- return;
2411
+ return ;
2232
2412
  }
2233
2413
  logical = and();
2234
2414
  if (logical) {
2235
2415
  next = this.conditionAnd(needsParens);
2236
2416
  if (next) {
2237
- result = new (tree_1.default.Condition)(logical, result, next);
2238
- }
2239
- else {
2240
- return;
2417
+ result = new(tree.Condition)(logical, result, next);
2418
+ } else {
2419
+ return ;
2241
2420
  }
2242
2421
  }
2243
2422
  return result;
2244
2423
  },
2245
2424
  negatedCondition: function (needsParens) {
2246
2425
  if (parserInput.$str('not')) {
2247
- var result = this.parenthesisCondition(needsParens);
2426
+ const result = this.parenthesisCondition(needsParens);
2248
2427
  if (result) {
2249
2428
  result.negate = !result.negate;
2250
2429
  }
@@ -2253,123 +2432,127 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2253
2432
  },
2254
2433
  parenthesisCondition: function (needsParens) {
2255
2434
  function tryConditionFollowedByParenthesis(me) {
2256
- var body;
2435
+ let body;
2257
2436
  parserInput.save();
2258
2437
  body = me.condition(needsParens);
2259
2438
  if (!body) {
2260
2439
  parserInput.restore();
2261
- return;
2440
+ return ;
2262
2441
  }
2263
2442
  if (!parserInput.$char(')')) {
2264
2443
  parserInput.restore();
2265
- return;
2444
+ return ;
2266
2445
  }
2267
2446
  parserInput.forget();
2268
2447
  return body;
2269
2448
  }
2270
- var body;
2449
+
2450
+ let body;
2271
2451
  parserInput.save();
2272
2452
  if (!parserInput.$str('(')) {
2273
2453
  parserInput.restore();
2274
- return;
2454
+ return ;
2275
2455
  }
2276
2456
  body = tryConditionFollowedByParenthesis(this);
2277
2457
  if (body) {
2278
2458
  parserInput.forget();
2279
2459
  return body;
2280
2460
  }
2461
+
2281
2462
  body = this.atomicCondition(needsParens);
2282
2463
  if (!body) {
2283
2464
  parserInput.restore();
2284
- return;
2465
+ return ;
2285
2466
  }
2286
2467
  if (!parserInput.$char(')')) {
2287
- parserInput.restore("expected ')' got '".concat(parserInput.currentChar(), "'"));
2288
- return;
2468
+ parserInput.restore(`expected ')' got '${parserInput.currentChar()}'`);
2469
+ return ;
2289
2470
  }
2290
2471
  parserInput.forget();
2291
2472
  return body;
2292
2473
  },
2293
2474
  atomicCondition: function (needsParens, preparsedCond) {
2294
- var entities = this.entities;
2295
- var index = parserInput.i;
2296
- var a;
2297
- var b;
2298
- var c;
2299
- var op;
2300
- var cond = (function () {
2475
+ const entities = this.entities;
2476
+ const index = parserInput.i;
2477
+ let a;
2478
+ let b;
2479
+ let c;
2480
+ let op;
2481
+
2482
+ const cond = (function() {
2301
2483
  return this.addition() || entities.keyword() || entities.quoted() || entities.mixinLookup();
2302
- }).bind(this);
2484
+ }).bind(this)
2485
+
2303
2486
  if (preparsedCond) {
2304
2487
  a = preparsedCond;
2305
- }
2306
- else {
2488
+ } else {
2307
2489
  a = cond();
2308
2490
  }
2491
+
2309
2492
  if (a) {
2310
2493
  if (parserInput.$char('>')) {
2311
2494
  if (parserInput.$char('=')) {
2312
2495
  op = '>=';
2313
- }
2314
- else {
2496
+ } else {
2315
2497
  op = '>';
2316
2498
  }
2317
- }
2318
- else if (parserInput.$char('<')) {
2499
+ } else
2500
+ if (parserInput.$char('<')) {
2319
2501
  if (parserInput.$char('=')) {
2320
2502
  op = '<=';
2321
- }
2322
- else {
2503
+ } else {
2323
2504
  op = '<';
2324
2505
  }
2325
- }
2326
- else if (parserInput.$char('=')) {
2506
+ } else
2507
+ if (parserInput.$char('=')) {
2327
2508
  if (parserInput.$char('>')) {
2328
2509
  op = '=>';
2329
- }
2330
- else if (parserInput.$char('<')) {
2510
+ } else if (parserInput.$char('<')) {
2331
2511
  op = '=<';
2332
- }
2333
- else {
2512
+ } else {
2334
2513
  op = '=';
2335
2514
  }
2336
2515
  }
2337
2516
  if (op) {
2338
2517
  b = cond();
2339
2518
  if (b) {
2340
- c = new (tree_1.default.Condition)(op, a, b, index + currentIndex, false);
2341
- }
2342
- else {
2519
+ c = new(tree.Condition)(op, a, b, index + currentIndex, false);
2520
+ } else {
2343
2521
  error('expected expression');
2344
2522
  }
2345
- }
2346
- else if (!preparsedCond) {
2347
- c = new (tree_1.default.Condition)('=', a, new (tree_1.default.Keyword)('true'), index + currentIndex, false);
2523
+ } else if (!preparsedCond) {
2524
+ c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index + currentIndex, false);
2348
2525
  }
2349
2526
  return c;
2350
2527
  }
2351
2528
  },
2529
+
2352
2530
  //
2353
2531
  // An operand is anything that can be part of an operation,
2354
2532
  // such as a Color, or a Variable
2355
2533
  //
2356
2534
  operand: function () {
2357
- var entities = this.entities;
2358
- var negate;
2535
+ const entities = this.entities;
2536
+ let negate;
2537
+
2359
2538
  if (parserInput.peek(/^-[@$(]/)) {
2360
2539
  negate = parserInput.$char('-');
2361
2540
  }
2362
- var o = this.sub() || entities.dimension() ||
2363
- entities.color() || entities.variable() ||
2364
- entities.property() || entities.call() ||
2365
- entities.quoted(true) || entities.colorKeyword() ||
2366
- this.colorOperand() || entities.mixinLookup();
2541
+
2542
+ let o = this.sub() || entities.dimension() ||
2543
+ entities.color() || entities.variable() ||
2544
+ entities.property() || entities.call() ||
2545
+ entities.quoted(true) || entities.colorKeyword() ||
2546
+ this.colorOperand() || entities.mixinLookup();
2547
+
2367
2548
  if (negate) {
2368
2549
  o.parensInOp = true;
2369
- o = new (tree_1.default.Negative)(o);
2550
+ o = new(tree.Negative)(o);
2370
2551
  }
2552
+
2371
2553
  return o;
2372
2554
  },
2555
+
2373
2556
  //
2374
2557
  // Expressions either represent mathematical operations,
2375
2558
  // or white-space delimited Entities.
@@ -2378,10 +2561,11 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2378
2561
  // @var * 2
2379
2562
  //
2380
2563
  expression: function () {
2381
- var entities = [];
2382
- var e;
2383
- var delim;
2384
- var index = parserInput.i;
2564
+ const entities = [];
2565
+ let e;
2566
+ let delim;
2567
+ const index = parserInput.i;
2568
+
2385
2569
  do {
2386
2570
  e = this.comment();
2387
2571
  if (e && !e.isLineComment) {
@@ -2389,58 +2573,66 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2389
2573
  continue;
2390
2574
  }
2391
2575
  e = this.addition() || this.entity();
2392
- if (e instanceof tree_1.default.Comment) {
2576
+
2577
+ if (e instanceof tree.Comment) {
2393
2578
  e = null;
2394
2579
  }
2580
+
2395
2581
  if (e) {
2396
2582
  entities.push(e);
2397
2583
  // operations do not allow keyword "/" dimension (e.g. small/20px) so we support that here
2398
2584
  if (!parserInput.peek(/^\/[/*]/)) {
2399
2585
  delim = parserInput.$char('/');
2400
2586
  if (delim) {
2401
- entities.push(new (tree_1.default.Anonymous)(delim, index + currentIndex));
2587
+ entities.push(new(tree.Anonymous)(delim, index + currentIndex));
2402
2588
  }
2403
2589
  }
2404
2590
  }
2405
2591
  } while (e);
2406
2592
  if (entities.length > 0) {
2407
- return new (tree_1.default.Expression)(entities);
2593
+ return new(tree.Expression)(entities);
2408
2594
  }
2409
2595
  },
2410
2596
  property: function () {
2411
- var name = parserInput.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
2597
+ const name = parserInput.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);
2412
2598
  if (name) {
2413
2599
  return name[1];
2414
2600
  }
2415
2601
  },
2416
2602
  ruleProperty: function () {
2417
- var name = [];
2418
- var index = [];
2419
- var s;
2420
- var k;
2603
+ let name = [];
2604
+ const index = [];
2605
+ let s;
2606
+ let k;
2607
+
2421
2608
  parserInput.save();
2422
- var simpleProperty = parserInput.$re(/^([_a-zA-Z0-9-]+)\s*:/);
2609
+
2610
+ const simpleProperty = parserInput.$re(/^([_a-zA-Z0-9-]+)\s*:/);
2423
2611
  if (simpleProperty) {
2424
- name = [new (tree_1.default.Keyword)(simpleProperty[1])];
2612
+ name = [new(tree.Keyword)(simpleProperty[1])];
2425
2613
  parserInput.forget();
2426
2614
  return name;
2427
2615
  }
2616
+
2428
2617
  function match(re) {
2429
- var i = parserInput.i;
2430
- var chunk = parserInput.$re(re);
2618
+ const i = parserInput.i;
2619
+ const chunk = parserInput.$re(re);
2431
2620
  if (chunk) {
2432
2621
  index.push(i);
2433
2622
  return name.push(chunk[1]);
2434
2623
  }
2435
2624
  }
2625
+
2436
2626
  match(/^(\*?)/);
2437
2627
  while (true) {
2438
2628
  if (!match(/^((?:[\w-]+)|(?:[@$]\{[\w-]+\}))/)) {
2439
2629
  break;
2440
2630
  }
2441
2631
  }
2632
+
2442
2633
  if ((name.length > 1) && match(/^((?:\+_|\+)?)\s*:/)) {
2443
2634
  parserInput.forget();
2635
+
2444
2636
  // at last, we have the complete match now. move forward,
2445
2637
  // convert name particles to tree objects and return:
2446
2638
  if (name[0] === '') {
@@ -2450,10 +2642,10 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2450
2642
  for (k = 0; k < name.length; k++) {
2451
2643
  s = name[k];
2452
2644
  name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ?
2453
- new (tree_1.default.Keyword)(s) :
2645
+ new(tree.Keyword)(s) :
2454
2646
  (s.charAt(0) === '@' ?
2455
- new (tree_1.default.Variable)("@".concat(s.slice(2, -1)), index[k] + currentIndex, fileInfo) :
2456
- new (tree_1.default.Property)("$".concat(s.slice(2, -1)), index[k] + currentIndex, fileInfo));
2647
+ new(tree.Variable)(`@${s.slice(2, -1)}`, index[k] + currentIndex, fileInfo) :
2648
+ new(tree.Property)(`$${s.slice(2, -1)}`, index[k] + currentIndex, fileInfo));
2457
2649
  }
2458
2650
  return name;
2459
2651
  }
@@ -2462,15 +2654,17 @@ var Parser = function Parser(context, imports, fileInfo, currentIndex) {
2462
2654
  }
2463
2655
  };
2464
2656
  };
2465
- Parser.serializeVars = function (vars) {
2466
- var s = '';
2467
- for (var name_1 in vars) {
2468
- if (Object.hasOwnProperty.call(vars, name_1)) {
2469
- var value = vars[name_1];
2470
- s += "".concat(((name_1[0] === '@') ? '' : '@') + name_1, ": ").concat(value).concat((String(value).slice(-1) === ';') ? '' : ';');
2657
+ Parser.serializeVars = vars => {
2658
+ let s = '';
2659
+
2660
+ for (const name in vars) {
2661
+ if (Object.hasOwnProperty.call(vars, name)) {
2662
+ const value = vars[name];
2663
+ s += `${((name[0] === '@') ? '' : '@') + name}: ${value}${(String(value).slice(-1) === ';') ? '' : ';'}`;
2471
2664
  }
2472
2665
  }
2666
+
2473
2667
  return s;
2474
2668
  };
2475
- exports.default = Parser;
2476
- //# sourceMappingURL=parser.js.map
2669
+
2670
+ export default Parser;