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