less 3.0.0-pre.2 → 3.0.1

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 (205) hide show
  1. package/.eslintrc.json +88 -0
  2. package/.github/stale.yml +17 -0
  3. package/.project +17 -0
  4. package/.settings/org.eclipse.buildship.core.prefs +2 -0
  5. package/.travis.yml +22 -3
  6. package/.vscode/launch.json +14 -0
  7. package/CHANGELOG.md +27 -0
  8. package/Gruntfile.js +191 -86
  9. package/README.md +5 -7
  10. package/appveyor.yml +9 -10
  11. package/bin/lessc +37 -50
  12. package/dist/less.js +1357 -1269
  13. package/dist/less.min.js +7 -7
  14. package/lib/less/contexts.js +20 -16
  15. package/lib/less/default-options.js +65 -0
  16. package/lib/less/environment/abstract-file-manager.js +13 -14
  17. package/lib/less/environment/abstract-plugin-loader.js +45 -36
  18. package/lib/less/environment/environment.js +5 -0
  19. package/lib/less/functions/boolean.js +15 -0
  20. package/lib/less/functions/color.js +54 -24
  21. package/lib/less/functions/data-uri.js +5 -2
  22. package/lib/less/functions/function-registry.js +1 -1
  23. package/lib/less/functions/index.js +2 -1
  24. package/lib/less/functions/number.js +2 -2
  25. package/lib/less/functions/string.js +2 -2
  26. package/lib/less/functions/svg.js +4 -4
  27. package/lib/less/import-manager.js +41 -29
  28. package/lib/less/index.js +28 -3
  29. package/lib/less/less-error.js +112 -13
  30. package/lib/less/parse.js +18 -15
  31. package/lib/less/parser/parser-input.js +4 -4
  32. package/lib/less/parser/parser.js +208 -114
  33. package/lib/less/plugin-manager.js +8 -33
  34. package/lib/less/render.js +6 -2
  35. package/lib/less/source-map-builder.js +3 -0
  36. package/lib/less/source-map-output.js +13 -8
  37. package/lib/less/transform-tree.js +2 -2
  38. package/lib/less/tree/anonymous.js +4 -1
  39. package/lib/less/tree/atrule.js +7 -6
  40. package/lib/less/tree/call.js +25 -3
  41. package/lib/less/tree/color.js +2 -2
  42. package/lib/less/tree/debug-info.js +1 -1
  43. package/lib/less/tree/declaration.js +6 -5
  44. package/lib/less/tree/dimension.js +4 -1
  45. package/lib/less/tree/extend.js +2 -2
  46. package/lib/less/tree/import.js +17 -9
  47. package/lib/less/tree/index.js +3 -7
  48. package/lib/less/tree/js-eval-node.js +1 -1
  49. package/lib/less/tree/media.js +3 -14
  50. package/lib/less/tree/mixin-definition.js +3 -3
  51. package/lib/less/tree/node.js +9 -6
  52. package/lib/less/tree/operation.js +1 -1
  53. package/lib/less/tree/property.js +70 -0
  54. package/lib/less/tree/quoted.js +11 -10
  55. package/lib/less/tree/ruleset.js +115 -71
  56. package/lib/less/tree/selector.js +38 -23
  57. package/lib/less/tree/unit.js +1 -1
  58. package/lib/less/tree/value.js +6 -1
  59. package/lib/less/tree/{ruleset-call.js → variable-call.js} +5 -5
  60. package/lib/less/tree/variable.js +6 -6
  61. package/lib/less/utils.js +40 -0
  62. package/lib/less/visitors/extend-visitor.js +14 -14
  63. package/lib/less/visitors/import-visitor.js +2 -2
  64. package/lib/less/visitors/join-selector-visitor.js +1 -1
  65. package/lib/less/visitors/to-css-visitor.js +51 -84
  66. package/lib/less/visitors/visitor.js +15 -15
  67. package/lib/less-browser/bootstrap.js +21 -5
  68. package/lib/less-browser/cache.js +2 -2
  69. package/lib/less-browser/error-reporting.js +5 -5
  70. package/lib/less-browser/file-manager.js +27 -35
  71. package/lib/less-browser/index.js +12 -17
  72. package/lib/less-browser/plugin-loader.js +8 -45
  73. package/lib/less-browser/utils.js +1 -1
  74. package/lib/less-node/file-manager.js +99 -69
  75. package/lib/less-node/fs.js +1 -1
  76. package/lib/less-node/image-size.js +2 -2
  77. package/lib/less-node/index.js +7 -57
  78. package/lib/less-node/lessc-helper.js +38 -38
  79. package/lib/less-node/plugin-loader.js +18 -79
  80. package/lib/less-node/url-file-manager.js +1 -1
  81. package/lib/less-rhino/index.js +29 -44
  82. package/package.json +16 -9
  83. package/test/browser/common.js +54 -18
  84. package/test/browser/css/plugin/plugin.css +3 -0
  85. package/test/browser/jasmine-jsreporter.js +4 -4
  86. package/test/browser/less/plugin/plugin.js +7 -0
  87. package/test/browser/less/plugin/plugin.less +4 -0
  88. package/test/browser/less.js +11685 -13
  89. package/test/browser/runner-browser-options.js +6 -1
  90. package/test/browser/runner-filemanagerPlugin-options.js +3 -2
  91. package/test/browser/runner-legacy-options.js +2 -1
  92. package/test/browser/runner-main-options.js +0 -1
  93. package/test/browser/runner-modify-vars-spec.js +2 -2
  94. package/test/browser/test-runner-template.tmpl +38 -14
  95. package/test/copy-bom.js +1 -1
  96. package/test/css/calc.css +5 -0
  97. package/test/css/comments2.css +1 -1
  98. package/test/css/compression/compression.css +1 -1
  99. package/test/css/css-grid.css +11 -0
  100. package/test/css/debug/linenumbers-all.css +0 -1
  101. package/test/css/debug/linenumbers-comments.css +0 -1
  102. package/test/css/debug/linenumbers-mediaquery.css +0 -1
  103. package/test/css/functions.css +16 -3
  104. package/test/css/import-module.css +9 -0
  105. package/test/css/import.css +0 -1
  106. package/test/css/legacy/legacy.css +1 -1
  107. package/test/css/merge.css +5 -4
  108. package/test/css/plugin-module.css +1 -0
  109. package/test/css/plugin.css +20 -0
  110. package/test/css/property-accessors.css +49 -0
  111. package/test/css/{css.css → strict-math/css.css} +0 -0
  112. package/test/css/{mixins-args.css → strict-math/mixins-args.css} +0 -0
  113. package/test/css/{parens.css → strict-math/parens.css} +0 -0
  114. package/test/import-module/one/1.less +3 -0
  115. package/test/import-module/one/two/2.less +3 -0
  116. package/test/import-module/one/two/three/3.less +3 -0
  117. package/test/import-module/package.json +11 -0
  118. package/test/index.js +55 -49
  119. package/test/less/calc.less +7 -0
  120. package/test/less/css-grid.less +15 -0
  121. package/test/less/detached-rulesets.less +2 -2
  122. package/test/less/errors/color-invalid-hex-code.less +1 -0
  123. package/test/less/errors/color-invalid-hex-code.txt +1 -1
  124. package/test/less/errors/color-invalid-hex-code2.less +1 -0
  125. package/test/less/errors/color-invalid-hex-code2.txt +1 -1
  126. package/test/less/errors/import-missing.txt +1 -1
  127. package/test/less/errors/plugin/plugin-error-2.js +5 -0
  128. package/test/less/errors/plugin/plugin-error-3.js +5 -0
  129. package/test/less/errors/plugin/plugin-error.js +1 -0
  130. package/test/less/errors/plugin-1.less +1 -0
  131. package/test/less/errors/plugin-1.txt +2 -0
  132. package/test/less/errors/plugin-2.less +1 -0
  133. package/test/less/errors/plugin-2.txt +5 -0
  134. package/test/less/errors/plugin-3.less +1 -0
  135. package/test/less/errors/plugin-3.txt +5 -0
  136. package/test/less/functions.less +18 -0
  137. package/test/less/import-module.less +3 -0
  138. package/test/less/import.less +0 -2
  139. package/test/less/legacy/legacy.less +1 -1
  140. package/test/less/media.less +2 -2
  141. package/test/less/merge.less +6 -3
  142. package/test/less/plugin/plugin-collection.js +9 -0
  143. package/test/less/plugin/plugin-local.js +2 -2
  144. package/test/less/plugin/plugin-scope1.js +3 -0
  145. package/test/less/plugin/plugin-scope2.js +3 -0
  146. package/test/less/plugin/plugin-simple.js +7 -0
  147. package/test/less/plugin/plugin-tree-nodes.js +33 -31
  148. package/test/less/plugin-module.less +7 -0
  149. package/test/less/plugin.less +33 -3
  150. package/test/less/property-accessors.less +67 -0
  151. package/test/less/root-registry/file.less +1 -0
  152. package/test/less/root-registry/root.less +3 -0
  153. package/test/less/{css.less → strict-math/css.less} +0 -0
  154. package/test/less/{mixins-args.less → strict-math/mixins-args.less} +0 -0
  155. package/test/less/{parens.less → strict-math/parens.less} +0 -0
  156. package/test/less-bom/calc.less +7 -0
  157. package/test/less-bom/css-grid.less +15 -0
  158. package/test/less-bom/detached-rulesets.less +2 -2
  159. package/test/less-bom/errors/color-invalid-hex-code.less +1 -0
  160. package/test/less-bom/errors/color-invalid-hex-code.txt +1 -1
  161. package/test/less-bom/errors/color-invalid-hex-code2.less +1 -0
  162. package/test/less-bom/errors/color-invalid-hex-code2.txt +1 -1
  163. package/test/less-bom/errors/import-missing.txt +1 -1
  164. package/test/less-bom/errors/plugin/plugin-error-2.js +5 -0
  165. package/test/less-bom/errors/plugin/plugin-error-3.js +5 -0
  166. package/test/less-bom/errors/plugin/plugin-error.js +1 -0
  167. package/test/less-bom/errors/plugin-1.less +1 -0
  168. package/test/less-bom/errors/plugin-1.txt +2 -0
  169. package/test/less-bom/errors/plugin-2.less +1 -0
  170. package/test/less-bom/errors/plugin-2.txt +5 -0
  171. package/test/less-bom/errors/plugin-3.less +1 -0
  172. package/test/less-bom/errors/plugin-3.txt +5 -0
  173. package/test/less-bom/functions.less +18 -0
  174. package/test/less-bom/import-module.less +3 -0
  175. package/test/less-bom/import.less +0 -2
  176. package/test/less-bom/legacy/legacy.less +1 -1
  177. package/test/less-bom/media.less +2 -2
  178. package/test/less-bom/merge.less +6 -3
  179. package/test/less-bom/plugin/plugin-collection.js +9 -0
  180. package/test/less-bom/plugin/plugin-local.js +2 -2
  181. package/test/less-bom/plugin/plugin-scope1.js +3 -0
  182. package/test/less-bom/plugin/plugin-scope2.js +3 -0
  183. package/test/less-bom/plugin/plugin-simple.js +7 -0
  184. package/test/less-bom/plugin/plugin-tree-nodes.js +33 -31
  185. package/test/less-bom/plugin-module.less +7 -0
  186. package/test/less-bom/plugin.less +33 -3
  187. package/test/less-bom/property-accessors.less +67 -0
  188. package/test/less-bom/root-registry/file.less +1 -0
  189. package/test/less-bom/root-registry/root.less +3 -0
  190. package/test/less-bom/{css.less → strict-math/css.less} +0 -0
  191. package/test/less-bom/{mixins-args.less → strict-math/mixins-args.less} +0 -0
  192. package/test/less-bom/{parens.less → strict-math/parens.less} +0 -0
  193. package/test/less-test.js +75 -17
  194. package/test/modify-vars.js +1 -1
  195. package/test/plugins/visitor/index.js +1 -1
  196. package/.jscsrc +0 -73
  197. package/.jshintrc +0 -11
  198. package/lib/less/tree/alpha.js +0 -28
  199. package/lib/less/tree/directive.js +0 -12
  200. package/lib/less/tree/rule.js +0 -12
  201. package/test/less/errors/functions-2-alpha.less +0 -2
  202. package/test/less/errors/functions-2-alpha.txt +0 -3
  203. package/test/less-bom/errors/functions-2-alpha.less +0 -2
  204. package/test/less-bom/errors/functions-2-alpha.txt +0 -3
  205. package/test/sourcemaps/maps/import-map.map +0 -1
package/dist/less.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*!
2
- * Less - Leaner CSS v3.0.0-pre.2
2
+ * Less - Leaner CSS v3.0.1
3
3
  * http://lesscss.org
4
4
  *
5
- * Copyright (c) 2009-2016, Alexis Sellier <self@cloudhead.net>
5
+ * Copyright (c) 2009-2018, Alexis Sellier <self@cloudhead.net>
6
6
  * Licensed under the Apache-2.0 License.
7
7
  *
8
8
  */
@@ -66,14 +66,30 @@ module.exports = function(window, options) {
66
66
  * used in the browser distributed version of less
67
67
  * to kick-start less using the browser api
68
68
  */
69
- /*global window, document */
69
+ /* global window, document */
70
70
 
71
- // shim Promise if required
72
- require('promise/polyfill.js');
71
+ // TODO - consider switching this out for a recommendation for this polyfill?
72
+ // <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
73
+ // Browsers have good Promise support
74
+ require("promise/polyfill");
73
75
 
74
- var options = window.less || {};
76
+ var options = require('../less/default-options')();
77
+
78
+ if (window.less) {
79
+ for (key in window.less) {
80
+ if (window.less.hasOwnProperty(key)) {
81
+ options[key] = window.less[key];
82
+ }
83
+ }
84
+ }
75
85
  require("./add-default-options")(window, options);
76
86
 
87
+ options.plugins = options.plugins || [];
88
+
89
+ if (window.LESS_PLUGINS) {
90
+ options.plugins = options.plugins.concat(window.LESS_PLUGINS);
91
+ }
92
+
77
93
  var less = module.exports = require("./index")(window, options);
78
94
 
79
95
  window.less = less;
@@ -94,7 +110,7 @@ if (options.onReady) {
94
110
  if (/!watch/.test(window.location.hash)) {
95
111
  less.watch();
96
112
  }
97
- // Simulate synchronous stylesheet loading by blocking page rendering
113
+ // Simulate synchronous stylesheet loading by hiding page rendering
98
114
  if (!options.async) {
99
115
  css = 'body { display: none !important }';
100
116
  head = document.head || document.getElementsByTagName('head')[0];
@@ -113,7 +129,7 @@ if (options.onReady) {
113
129
  less.pageLoadFinished = less.refresh(less.env === 'development').then(resolveOrReject, resolveOrReject);
114
130
  }
115
131
 
116
- },{"./add-default-options":1,"./index":8,"promise/polyfill.js":102}],3:[function(require,module,exports){
132
+ },{"../less/default-options":16,"./add-default-options":1,"./index":8,"promise/polyfill":100}],3:[function(require,module,exports){
117
133
  var utils = require("./utils");
118
134
  module.exports = {
119
135
  createCSS: function (document, styles, sheet) {
@@ -199,8 +215,8 @@ module.exports = function(window, options, logger) {
199
215
  if (modifyVars) {
200
216
  cache.setItem(path + ':vars', JSON.stringify(modifyVars));
201
217
  }
202
- } catch(e) {
203
- //TODO - could do with adding more robust error handling
218
+ } catch (e) {
219
+ // TODO - could do with adding more robust error handling
204
220
  logger.error('failed to save "' + path + '" to local storage for caching.');
205
221
  }
206
222
  }
@@ -250,7 +266,7 @@ module.exports = function(window, less, options) {
250
266
  }
251
267
  };
252
268
 
253
- if (e.extract) {
269
+ if (e.line) {
254
270
  errorline(e, 0, '');
255
271
  errorline(e, 1, 'line');
256
272
  errorline(e, 2, '');
@@ -338,7 +354,7 @@ module.exports = function(window, less, options) {
338
354
  }
339
355
 
340
356
  function removeErrorConsole(path) {
341
- //no action
357
+ // no action
342
358
  }
343
359
 
344
360
  function removeError(path) {
@@ -356,7 +372,7 @@ module.exports = function(window, less, options) {
356
372
  var filename = e.filename || rootHref;
357
373
  var errors = [];
358
374
  var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
359
- " in " + filename + " ";
375
+ " in " + filename;
360
376
 
361
377
  var errorline = function (e, i, classname) {
362
378
  if (e.extract[i] !== undefined) {
@@ -366,11 +382,11 @@ module.exports = function(window, less, options) {
366
382
  }
367
383
  };
368
384
 
369
- if (e.extract) {
385
+ if (e.line) {
370
386
  errorline(e, 0, '');
371
387
  errorline(e, 1, 'line');
372
388
  errorline(e, 2, '');
373
- content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
389
+ content += ' on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
374
390
  errors.join('\n');
375
391
  }
376
392
  if (e.stack && (e.extract || options.logLevel >= 4)) {
@@ -396,7 +412,7 @@ module.exports = function(window, less, options) {
396
412
  };
397
413
 
398
414
  },{"./browser":3,"./utils":11}],6:[function(require,module,exports){
399
- /*global window, XMLHttpRequest */
415
+ /* global window, XMLHttpRequest */
400
416
 
401
417
  module.exports = function(options, logger) {
402
418
 
@@ -404,22 +420,7 @@ module.exports = function(options, logger) {
404
420
 
405
421
  var fileCache = {};
406
422
 
407
- //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
408
-
409
- function getXMLHttpRequest() {
410
- if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
411
- return new XMLHttpRequest();
412
- } else {
413
- try {
414
- /*global ActiveXObject */
415
- return new ActiveXObject("Microsoft.XMLHTTP");
416
- } catch (e) {
417
- logger.error("browser doesn't support AJAX.");
418
- return null;
419
- }
420
- }
421
- }
422
-
423
+ // TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
423
424
  var FileManager = function() {
424
425
  };
425
426
 
@@ -436,7 +437,7 @@ module.exports = function(options, logger) {
436
437
  };
437
438
  FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
438
439
 
439
- var xhr = getXMLHttpRequest();
440
+ var xhr = new XMLHttpRequest();
440
441
  var async = options.isFileProtocol ? options.fileAsync : true;
441
442
 
442
443
  if (typeof xhr.overrideMimeType === 'function') {
@@ -480,43 +481,50 @@ module.exports = function(options, logger) {
480
481
  fileCache = {};
481
482
  };
482
483
 
483
- FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
484
+ FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment) {
485
+ // TODO: Add prefix support like less-node?
486
+ // What about multiple paths?
487
+
484
488
  if (currentDirectory && !this.isPathAbsolute(filename)) {
485
489
  filename = currentDirectory + filename;
486
490
  }
487
491
 
492
+ filename = options.ext ? this.tryAppendExtension(filename, options.ext) : filename;
493
+
488
494
  options = options || {};
489
495
 
490
496
  // sheet may be set to the stylesheet for the initial load or a collection of properties including
491
497
  // some context variables for imports
492
498
  var hrefParts = this.extractUrlParts(filename, window.location.href);
493
499
  var href = hrefParts.url;
494
-
495
- if (options.useFileCache && fileCache[href]) {
496
- try {
497
- var lessText = fileCache[href];
498
- callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
499
- } catch (e) {
500
- callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
500
+ var self = this;
501
+
502
+ return new Promise(function(resolve, reject) {
503
+ if (options.useFileCache && fileCache[href]) {
504
+ try {
505
+ var lessText = fileCache[href];
506
+ return resolve({ contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
507
+ } catch (e) {
508
+ return reject({ filename: href, message: "Error loading file " + href + " error was " + e.message });
509
+ }
501
510
  }
502
- return;
503
- }
504
511
 
505
- this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
506
- // per file cache
507
- fileCache[href] = data;
512
+ self.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
513
+ // per file cache
514
+ fileCache[href] = data;
508
515
 
509
- // Use remote copy (re-parse)
510
- callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
511
- }, function doXHRError(status, url) {
512
- callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
516
+ // Use remote copy (re-parse)
517
+ resolve({ contents: data, filename: href, webInfo: { lastModified: lastModified }});
518
+ }, function doXHRError(status, url) {
519
+ reject({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
520
+ });
513
521
  });
514
522
  };
515
523
 
516
524
  return FileManager;
517
525
  };
518
526
 
519
- },{"../less/environment/abstract-file-manager.js":16}],7:[function(require,module,exports){
527
+ },{"../less/environment/abstract-file-manager.js":17}],7:[function(require,module,exports){
520
528
  module.exports = function() {
521
529
 
522
530
  var functionRegistry = require("./../less/functions/function-registry");
@@ -546,7 +554,7 @@ module.exports = function() {
546
554
  functionRegistry.addMultiple(imageFunctions);
547
555
  };
548
556
 
549
- },{"./../less/functions/function-registry":24}],8:[function(require,module,exports){
557
+ },{"./../less/functions/function-registry":26}],8:[function(require,module,exports){
550
558
  //
551
559
  // index.js
552
560
  // Should expose the additional browser functions on to the less object
@@ -571,7 +579,7 @@ module.exports = function(window, options) {
571
579
  var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
572
580
  require('./image-size')(less.environment);
573
581
 
574
- //Setup user functions - Deprecate?
582
+ // Setup user functions - Deprecate?
575
583
  if (options.functions) {
576
584
  less.functions.functionRegistry.addMultiple(options.functions);
577
585
  }
@@ -579,13 +587,7 @@ module.exports = function(window, options) {
579
587
  var typePattern = /^text\/(x-)?less$/;
580
588
 
581
589
  function clone(obj) {
582
- var cloned = {};
583
- for (var prop in obj) {
584
- if (obj.hasOwnProperty(prop)) {
585
- cloned[prop] = obj[prop];
586
- }
587
- }
588
- return cloned;
590
+ return JSON.parse(JSON.stringify(obj || {}));
589
591
  }
590
592
 
591
593
  // only really needed for phantom
@@ -609,7 +611,7 @@ module.exports = function(window, options) {
609
611
  var lessText = style.innerHTML || '';
610
612
  instanceOptions.filename = document.location.href.replace(/#.*$/, '');
611
613
 
612
- /*jshint loopfunc:true */
614
+ /* jshint loopfunc:true */
613
615
  // use closure to store current style
614
616
  less.render(lessText, instanceOptions,
615
617
  bind(function(style, e, result) {
@@ -665,7 +667,7 @@ module.exports = function(window, options) {
665
667
 
666
668
  }
667
669
 
668
- //TODO add tests around how this behaves when reloading
670
+ // TODO add tests around how this behaves when reloading
669
671
  errors.remove(path);
670
672
 
671
673
  instanceOptions.rootFileInfo = newFileInfo;
@@ -680,13 +682,14 @@ module.exports = function(window, options) {
680
682
  });
681
683
  }
682
684
 
683
- fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
684
- if (e) {
685
- callback(e);
686
- return;
687
- }
688
- loadInitialFileCallback(loadedFile);
689
- });
685
+ fileManager.loadFile(sheet.href, null, instanceOptions, environment)
686
+ .then(function(loadedFile) {
687
+ loadInitialFileCallback(loadedFile);
688
+ }).catch(function(err) {
689
+ console.log(err);
690
+ callback(err);
691
+ });
692
+
690
693
  }
691
694
 
692
695
  function loadStyleSheets(callback, reload, modifyVars) {
@@ -826,7 +829,7 @@ module.exports = function(window, options) {
826
829
  return less;
827
830
  };
828
831
 
829
- },{"../less":33,"./browser":3,"./cache":4,"./error-reporting":5,"./file-manager":6,"./image-size":7,"./log-listener":9,"./plugin-loader":10,"./utils":11}],9:[function(require,module,exports){
832
+ },{"../less":35,"./browser":3,"./cache":4,"./error-reporting":5,"./file-manager":6,"./image-size":7,"./log-listener":9,"./plugin-loader":10,"./utils":11}],9:[function(require,module,exports){
830
833
  module.exports = function(less, options) {
831
834
 
832
835
  var logLevel_debug = 4,
@@ -872,6 +875,9 @@ module.exports = function(less, options) {
872
875
  };
873
876
 
874
877
  },{}],10:[function(require,module,exports){
878
+ // TODO: Add tests for browser @plugin
879
+ /*global window */
880
+
875
881
  var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js");
876
882
 
877
883
  /**
@@ -879,63 +885,23 @@ var AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.j
879
885
  */
880
886
  var PluginLoader = function(less) {
881
887
  this.less = less;
888
+ // shim for browser require?
882
889
  this.require = require;
883
890
  };
884
891
 
885
892
  PluginLoader.prototype = new AbstractPluginLoader();
886
893
 
887
- PluginLoader.prototype.tryLoadPlugin = function(name, basePath, callback) {
888
- var self = this;
889
- var prefix = name.slice(0, 1);
890
- var explicit = prefix === "." || prefix === "/" || name.slice(-3).toLowerCase() === ".js";
891
- this.tryLoadFromEnvironment(name, basePath, explicit, function(err, data) {
892
- if (explicit) {
893
- callback(err, data);
894
- }
895
- else {
896
- if (!err) {
897
- callback(null, data);
898
- }
899
- else {
900
- self.tryLoadFromEnvironment('less-plugin-' + name, basePath, explicit, function(err2, data) {
901
- callback(err, data);
902
- });
903
- }
904
- }
894
+ PluginLoader.prototype.loadPlugin = function(filename, basePath, context, environment, fileManager) {
895
+ return new Promise(function(fulfill, reject) {
896
+ fileManager.loadFile(filename, basePath, context, environment)
897
+ .then(fulfill).catch(reject);
905
898
  });
906
-
907
- };
908
-
909
- PluginLoader.prototype.tryLoadFromEnvironment = function(filename, basePath, explicit, callback) {
910
- var fileManager = new this.less.FileManager();
911
-
912
- if (basePath) {
913
- filename = (fileManager.extractUrlParts(filename, basePath)).url;
914
- }
915
-
916
- if (filename) {
917
-
918
- filename = fileManager.tryAppendExtension(filename, '.js');
919
-
920
- var done = function(err, data) {
921
- if (err) {
922
- callback(err);
923
- } else {
924
- callback(null, data);
925
- }
926
- };
927
- fileManager.loadFile(filename, null, null, null, done);
928
-
929
- }
930
- else {
931
- callback({ message: 'Plugin could not be found.'});
932
- }
933
899
  };
934
900
 
935
901
  module.exports = PluginLoader;
936
902
 
937
903
 
938
- },{"../less/environment/abstract-plugin-loader.js":17}],11:[function(require,module,exports){
904
+ },{"../less/environment/abstract-plugin-loader.js":18}],11:[function(require,module,exports){
939
905
  module.exports = {
940
906
  extractId: function(href) {
941
907
  return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
@@ -954,7 +920,7 @@ module.exports = {
954
920
  try {
955
921
  options[opt] = JSON.parse(tag.dataset[opt]);
956
922
  }
957
- catch(_) {}
923
+ catch (_) {}
958
924
  }
959
925
  }
960
926
  }
@@ -1004,18 +970,18 @@ contexts.Parse = function(options) {
1004
970
  };
1005
971
 
1006
972
  var evalCopyProperties = [
1007
- 'paths', // additional include paths
1008
- 'compress', // whether to compress
1009
- 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
1010
- 'strictMath', // whether math has to be within parenthesis
1011
- 'strictUnits', // whether units need to evaluate correctly
1012
- 'sourceMap', // whether to output a source map
1013
- 'importMultiple', // whether we are currently importing multiple copies
1014
- 'urlArgs', // whether to add args into url tokens
1015
- 'javascriptEnabled',// option - whether Inline JavaScript is enabled. if undefined, defaults to false
1016
- 'pluginManager', // Used as the plugin manager for the session
1017
- 'importantScope' // used to bubble up !important statements
1018
- ];
973
+ 'paths', // additional include paths
974
+ 'compress', // whether to compress
975
+ 'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
976
+ 'strictMath', // whether math has to be within parenthesis
977
+ 'strictUnits', // whether units need to evaluate correctly
978
+ 'sourceMap', // whether to output a source map
979
+ 'importMultiple', // whether we are currently importing multiple copies
980
+ 'urlArgs', // whether to add args into url tokens
981
+ 'javascriptEnabled', // option - whether Inline JavaScript is enabled. if undefined, defaults to false
982
+ 'pluginManager', // Used as the plugin manager for the session
983
+ 'importantScope' // used to bubble up !important statements
984
+ ];
1019
985
 
1020
986
  contexts.Eval = function(options, frames) {
1021
987
  copyFromOriginal(options, this, evalCopyProperties);
@@ -1037,7 +1003,11 @@ contexts.Eval.prototype.outOfParenthesis = function () {
1037
1003
  this.parensStack.pop();
1038
1004
  };
1039
1005
 
1006
+ contexts.Eval.prototype.mathOn = true;
1040
1007
  contexts.Eval.prototype.isMathOn = function () {
1008
+ if (!this.mathOn) {
1009
+ return false;
1010
+ }
1041
1011
  return this.strictMath ? (this.parensStack && this.parensStack.length) : true;
1042
1012
  };
1043
1013
 
@@ -1047,13 +1017,13 @@ contexts.Eval.prototype.isPathRelative = function (path) {
1047
1017
 
1048
1018
  contexts.Eval.prototype.normalizePath = function( path ) {
1049
1019
  var
1050
- segments = path.split("/").reverse(),
1051
- segment;
1020
+ segments = path.split("/").reverse(),
1021
+ segment;
1052
1022
 
1053
1023
  path = [];
1054
1024
  while (segments.length !== 0 ) {
1055
1025
  segment = segments.pop();
1056
- switch( segment ) {
1026
+ switch ( segment ) {
1057
1027
  case ".":
1058
1028
  break;
1059
1029
  case "..":
@@ -1072,7 +1042,7 @@ contexts.Eval.prototype.normalizePath = function( path ) {
1072
1042
  return path.join("/");
1073
1043
  };
1074
1044
 
1075
- //todo - do the same for the toCSS ?
1045
+ // todo - do the same for the toCSS ?
1076
1046
 
1077
1047
  },{}],13:[function(require,module,exports){
1078
1048
  module.exports = {
@@ -1254,6 +1224,72 @@ module.exports = {
1254
1224
  }
1255
1225
  };
1256
1226
  },{}],16:[function(require,module,exports){
1227
+ // Export a new default each time
1228
+ module.exports = function() {
1229
+ return {
1230
+ /* Outputs a makefile import dependency list to stdout. */
1231
+ depends: false,
1232
+
1233
+ /* Compress using less built-in compression.
1234
+ * This does an okay job but does not utilise all the tricks of
1235
+ * dedicated css compression. */
1236
+ compress: false,
1237
+
1238
+ /* Runs the less parser and just reports errors without any output. */
1239
+ lint: false,
1240
+
1241
+ /* Sets available include paths.
1242
+ * If the file in an @import rule does not exist at that exact location,
1243
+ * less will look for it at the location(s) passed to this option.
1244
+ * You might use this for instance to specify a path to a library which
1245
+ * you want to be referenced simply and relatively in the less files. */
1246
+ paths: [],
1247
+
1248
+ /* color output in the terminal */
1249
+ color: true,
1250
+
1251
+ /* The strictImports controls whether the compiler will allow an @import inside of either
1252
+ * @media blocks or (a later addition) other selector blocks.
1253
+ * See: https://github.com/less/less.js/issues/656 */
1254
+ strictImports: false,
1255
+
1256
+ /* Allow Imports from Insecure HTTPS Hosts */
1257
+ insecure: false,
1258
+
1259
+ /* Allows you to add a path to every generated import and url in your css.
1260
+ * This does not affect less import statements that are processed, just ones
1261
+ * that are left in the output css. */
1262
+ rootpath: '',
1263
+
1264
+ /* By default URLs are kept as-is, so if you import a file in a sub-directory
1265
+ * that references an image, exactly the same URL will be output in the css.
1266
+ * This option allows you to re-write URL's in imported files so that the
1267
+ * URL is always relative to the base imported file */
1268
+ relativeUrls: false,
1269
+
1270
+ /* Compatibility with IE8. Used for limiting data-uri length */
1271
+ ieCompat: false, // true until 3.0
1272
+
1273
+ /* Without this option on, Less will try and process all math in your css */
1274
+ strictMath: false,
1275
+
1276
+ /* Without this option, less attempts to guess at the output unit when it does maths. */
1277
+ strictUnits: false,
1278
+
1279
+ /* Effectively the declaration is put at the top of your base Less file,
1280
+ * meaning it can be used but it also can be overridden if this variable
1281
+ * is defined in the file. */
1282
+ globalVars: null,
1283
+
1284
+ /* As opposed to the global variable option, this puts the declaration at the
1285
+ * end of your base file, meaning it will override anything defined in your Less file. */
1286
+ modifyVars: null,
1287
+
1288
+ /* This option allows you to specify a argument to go on to every URL. */
1289
+ urlArgs: ''
1290
+ }
1291
+ }
1292
+ },{}],17:[function(require,module,exports){
1257
1293
  var abstractFileManager = function() {
1258
1294
  };
1259
1295
 
@@ -1291,7 +1327,7 @@ abstractFileManager.prototype.alwaysMakePathsAbsolute = function() {
1291
1327
  abstractFileManager.prototype.isPathAbsolute = function(filename) {
1292
1328
  return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename);
1293
1329
  };
1294
- // TODO: pull out - this is part of Node & Browserify
1330
+ // TODO: pull out / replace?
1295
1331
  abstractFileManager.prototype.join = function(basePath, laterPath) {
1296
1332
  if (!basePath) {
1297
1333
  return laterPath;
@@ -1332,7 +1368,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1332
1368
 
1333
1369
  var urlPartsRegex = /^((?:[a-z-]+:)?\/{2}(?:[^\/\?#]*\/)|([\/\\]))?((?:[^\/\\\?#]*[\/\\])*)([^\/\\\?#]*)([#\?].*)?$/i,
1334
1370
  urlParts = url.match(urlPartsRegex),
1335
- returner = {}, directories = [], i, baseUrlParts;
1371
+ returner = {}, rawDirectories = [], directories = [], i, baseUrlParts;
1336
1372
 
1337
1373
  if (!urlParts) {
1338
1374
  throw new Error("Could not parse sheet href - '" + url + "'");
@@ -1351,27 +1387,26 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1351
1387
  }
1352
1388
 
1353
1389
  if (urlParts[3]) {
1354
- directories = urlParts[3].replace(/\\/g, "/").split("/");
1390
+ rawDirectories = urlParts[3].replace(/\\/g, "/").split("/");
1355
1391
 
1356
- // extract out . before .. so .. doesn't absorb a non-directory
1357
- for (i = 0; i < directories.length; i++) {
1358
- if (directories[i] === ".") {
1359
- directories.splice(i, 1);
1360
- i -= 1;
1361
- }
1362
- }
1392
+ // collapse '..' and skip '.'
1393
+ for (i = 0; i < rawDirectories.length; i++) {
1363
1394
 
1364
- for (i = 0; i < directories.length; i++) {
1365
- if (directories[i] === ".." && i > 0) {
1366
- directories.splice(i - 1, 2);
1367
- i -= 2;
1395
+ if (rawDirectories[i] === "..") {
1396
+ directories.pop();
1397
+ }
1398
+ else if (rawDirectories[i] !== ".") {
1399
+ directories.push(rawDirectories[i]);
1368
1400
  }
1401
+
1369
1402
  }
1370
1403
  }
1371
1404
 
1372
1405
  returner.hostPart = urlParts[1];
1373
1406
  returner.directories = directories;
1407
+ returner.rawPath = (urlParts[1] || "") + rawDirectories.join("/");
1374
1408
  returner.path = (urlParts[1] || "") + directories.join("/");
1409
+ returner.filename = urlParts[4];
1375
1410
  returner.fileUrl = returner.path + (urlParts[4] || "");
1376
1411
  returner.url = returner.fileUrl + (urlParts[5] || "");
1377
1412
  return returner;
@@ -1379,7 +1414,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1379
1414
 
1380
1415
  module.exports = abstractFileManager;
1381
1416
 
1382
- },{}],17:[function(require,module,exports){
1417
+ },{}],18:[function(require,module,exports){
1383
1418
  var functionRegistry = require("../functions/function-registry"),
1384
1419
  LessError = require('../less-error');
1385
1420
 
@@ -1394,13 +1429,12 @@ function error(msg, type) {
1394
1429
  }
1395
1430
  );
1396
1431
  }
1397
- AbstractPluginLoader.prototype.evalPlugin = function(contents, context, pluginOptions, fileInfo) {
1432
+ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, imports, pluginOptions, fileInfo) {
1398
1433
 
1399
1434
  var loader,
1400
1435
  registry,
1401
1436
  pluginObj,
1402
1437
  localModule,
1403
- localExports,
1404
1438
  pluginManager,
1405
1439
  filename;
1406
1440
 
@@ -1414,13 +1448,21 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, pluginOp
1414
1448
  filename = fileInfo.filename;
1415
1449
  }
1416
1450
  }
1451
+ var shortname = (new this.less.FileManager()).extractUrlParts(filename).filename;
1452
+
1417
1453
  if (filename) {
1418
1454
  pluginObj = pluginManager.get(filename);
1419
1455
 
1420
1456
  if (pluginObj) {
1421
- this.trySetOptions(pluginObj, filename, pluginOptions);
1422
- if (pluginObj.use) {
1423
- pluginObj.use(this.less);
1457
+ this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
1458
+ try {
1459
+ if (pluginObj.use) {
1460
+ pluginObj.use.call(this.context, pluginObj);
1461
+ }
1462
+ }
1463
+ catch (e) {
1464
+ e.message = 'Error during @plugin call';
1465
+ return new this.less.LessError(e, imports, filename);
1424
1466
  }
1425
1467
  return pluginObj;
1426
1468
  }
@@ -1430,52 +1472,54 @@ AbstractPluginLoader.prototype.evalPlugin = function(contents, context, pluginOp
1430
1472
  pluginManager: pluginManager,
1431
1473
  fileInfo: fileInfo
1432
1474
  };
1433
- localExports = localModule.exports;
1434
1475
  registry = functionRegistry.create();
1435
1476
 
1436
- try {
1437
- loader = new Function("module", "require", "functions", "tree", "fileInfo", contents);
1438
- pluginObj = loader(localModule, this.require, registry, this.less.tree, fileInfo);
1477
+ var registerPlugin = function(obj) {
1478
+ pluginObj = obj;
1479
+ };
1439
1480
 
1440
- if (!pluginObj) {
1441
- pluginObj = localModule.exports;
1442
- }
1481
+ try {
1482
+ loader = new Function("module", "require", "registerPlugin", "functions", "tree", "less", "fileInfo", contents);
1483
+ loader(localModule, this.require, registerPlugin, registry, this.less.tree, this.less, fileInfo);
1484
+ } catch (e) {
1485
+ return new this.less.LessError(e, imports, filename);
1486
+ }
1443
1487
 
1444
- pluginObj = this.validatePlugin(pluginObj, filename);
1488
+ if (!pluginObj) {
1489
+ pluginObj = localModule.exports;
1490
+ }
1491
+ pluginObj = this.validatePlugin(pluginObj, filename, shortname);
1445
1492
 
1446
- if (pluginObj) {
1447
- // Run on first load
1448
- pluginManager.addPlugin(pluginObj, fileInfo.filename);
1449
- pluginObj.functions = registry.getLocalFunctions();
1493
+ if (pluginObj) {
1494
+ // Run on first load
1495
+ pluginManager.addPlugin(pluginObj, fileInfo.filename, registry);
1496
+ pluginObj.functions = registry.getLocalFunctions();
1497
+ pluginObj.imports = imports;
1498
+ pluginObj.filename = filename;
1450
1499
 
1451
- this.trySetOptions(pluginObj, filename, pluginOptions);
1500
+ this.trySetOptions(pluginObj, filename, shortname, pluginOptions);
1452
1501
 
1453
- // Run every @plugin call
1502
+ // Run every @plugin call
1503
+ try {
1454
1504
  if (pluginObj.use) {
1455
- pluginObj.use(this.less);
1505
+ pluginObj.use.call(this.context, pluginObj);
1456
1506
  }
1457
1507
  }
1458
- else {
1459
- throw new SyntaxError("Not a valid plugin");
1508
+ catch (e) {
1509
+ e.message = 'Error during @plugin call';
1510
+ return new this.less.LessError(e, imports, filename);
1460
1511
  }
1461
1512
 
1462
- } catch(e) {
1463
- // TODO pass the error
1464
- console.log(e);
1465
- return new this.less.LessError({
1466
- message: "Plugin evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
1467
- filename: filename,
1468
- line: this.line,
1469
- col: this.column
1470
- });
1513
+ }
1514
+ else {
1515
+ return new this.less.LessError({ message: "Not a valid plugin" });
1471
1516
  }
1472
1517
 
1473
1518
  return pluginObj;
1474
1519
 
1475
1520
  };
1476
1521
 
1477
- AbstractPluginLoader.prototype.trySetOptions = function(plugin, filename, options) {
1478
- var name = require('path').basename(filename);
1522
+ AbstractPluginLoader.prototype.trySetOptions = function(plugin, filename, name, options) {
1479
1523
  if (options) {
1480
1524
  if (!plugin.setOptions) {
1481
1525
  error("Options have been provided but the plugin " + name + " does not support any options.");
@@ -1484,21 +1528,21 @@ AbstractPluginLoader.prototype.trySetOptions = function(plugin, filename, option
1484
1528
  try {
1485
1529
  plugin.setOptions(options);
1486
1530
  }
1487
- catch(e) {
1531
+ catch (e) {
1488
1532
  error("Error setting options on plugin " + name + '\n' + e.message);
1489
1533
  return null;
1490
1534
  }
1491
1535
  }
1492
1536
  };
1493
1537
 
1494
- AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename) {
1538
+ AbstractPluginLoader.prototype.validatePlugin = function(plugin, filename, name) {
1495
1539
  if (plugin) {
1496
1540
  // support plugins being a function
1497
1541
  // so that the plugin can be more usable programmatically
1498
1542
  if (typeof plugin === "function") {
1499
1543
  plugin = new plugin();
1500
1544
  }
1501
- var name = require('path').basename(filename);
1545
+
1502
1546
  if (plugin.minVersion) {
1503
1547
  if (this.compareVersion(plugin.minVersion, this.less.version) < 0) {
1504
1548
  error("Plugin " + name + " requires version " + this.versionToString(plugin.minVersion));
@@ -1541,7 +1585,12 @@ AbstractPluginLoader.prototype.printUsage = function(plugins) {
1541
1585
  module.exports = AbstractPluginLoader;
1542
1586
 
1543
1587
 
1544
- },{"../functions/function-registry":24,"../less-error":34,"path":97}],18:[function(require,module,exports){
1588
+ },{"../functions/function-registry":26,"../less-error":36}],19:[function(require,module,exports){
1589
+ /**
1590
+ * @todo Document why this abstraction exists, and the relationship between
1591
+ * environment, file managers, and plugin manager
1592
+ */
1593
+
1545
1594
  var logger = require("../logger");
1546
1595
  var environment = function(externalEnvironment, fileManagers) {
1547
1596
  this.fileManagers = fileManagers || [];
@@ -1594,7 +1643,24 @@ environment.prototype.clearFileManagers = function () {
1594
1643
 
1595
1644
  module.exports = environment;
1596
1645
 
1597
- },{"../logger":35}],19:[function(require,module,exports){
1646
+ },{"../logger":37}],20:[function(require,module,exports){
1647
+
1648
+ var functionRegistry = require("./function-registry"),
1649
+ Anonymous = require("../tree/anonymous"),
1650
+ Keyword = require("../tree/keyword");
1651
+
1652
+ functionRegistry.addMultiple({
1653
+ boolean: function(condition) {
1654
+ return condition ? Keyword.True : Keyword.False;
1655
+ },
1656
+
1657
+ 'if': function(condition, trueValue, falseValue) {
1658
+ return condition ? trueValue
1659
+ : (falseValue || new Anonymous);
1660
+ }
1661
+ });
1662
+
1663
+ },{"../tree/anonymous":48,"../tree/keyword":68,"./function-registry":26}],21:[function(require,module,exports){
1598
1664
  var Color = require("../tree/color"),
1599
1665
  functionRegistry = require("./function-registry");
1600
1666
 
@@ -1670,7 +1736,7 @@ for (var f in colorBlendModeFunctions) {
1670
1736
 
1671
1737
  functionRegistry.addMultiple(colorBlend);
1672
1738
 
1673
- },{"../tree/color":52,"./function-registry":24}],20:[function(require,module,exports){
1739
+ },{"../tree/color":53,"./function-registry":26}],22:[function(require,module,exports){
1674
1740
  var Dimension = require("../tree/dimension"),
1675
1741
  Color = require("../tree/color"),
1676
1742
  Quoted = require("../tree/quoted"),
@@ -1939,43 +2005,73 @@ colorFunctions = {
1939
2005
  greyscale: function (color) {
1940
2006
  return colorFunctions.desaturate(color, new Dimension(100));
1941
2007
  },
1942
- contrast: function (color, color1, color2, threshold) {
1943
- // Return which of `color1` and `color2` has the greatest contrast with `color`
1944
- // according to the standard WCAG contrast ratio calculation.
1945
- // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
1946
- // The threshold param is no longer used, in line with SASS.
2008
+ contrast: function (color, dark, light, threshold) {
1947
2009
  // filter: contrast(3.2);
1948
2010
  // should be kept as is, so check for color
1949
2011
  if (!color.rgb) {
1950
2012
  return null;
1951
2013
  }
1952
- if (typeof color1 === 'undefined') {
1953
- color1 = colorFunctions.rgba(0, 0, 0, 1.0);
2014
+ if (typeof light === 'undefined') {
2015
+ light = colorFunctions.rgba(255, 255, 255, 1.0);
1954
2016
  }
1955
- if (typeof color2 === 'undefined') {
1956
- color2 = colorFunctions.rgba(255, 255, 255, 1.0);
2017
+ if (typeof dark === 'undefined') {
2018
+ dark = colorFunctions.rgba(0, 0, 0, 1.0);
1957
2019
  }
1958
- var contrast1, contrast2;
1959
- var luma = color.luma();
1960
- var luma1 = color1.luma();
1961
- var luma2 = color2.luma();
1962
- // Calculate contrast ratios for each color
1963
- if (luma > luma1) {
1964
- contrast1 = (luma + 0.05) / (luma1 + 0.05);
1965
- } else {
1966
- contrast1 = (luma1 + 0.05) / (luma + 0.05);
2020
+ // Figure out which is actually light and dark:
2021
+ if (dark.luma() > light.luma()) {
2022
+ var t = light;
2023
+ light = dark;
2024
+ dark = t;
1967
2025
  }
1968
- if (luma > luma2) {
1969
- contrast2 = (luma + 0.05) / (luma2 + 0.05);
2026
+ if (typeof threshold === 'undefined') {
2027
+ threshold = 0.43;
1970
2028
  } else {
1971
- contrast2 = (luma2 + 0.05) / (luma + 0.05);
2029
+ threshold = number(threshold);
1972
2030
  }
1973
- if (contrast1 > contrast2) {
1974
- return color1;
2031
+ if (color.luma() < threshold) {
2032
+ return light;
1975
2033
  } else {
1976
- return color2;
1977
- }
1978
- },
2034
+ return dark;
2035
+ }
2036
+ },
2037
+ // Changes made in 2.7.0 - Reverted in 3.0.0
2038
+ // contrast: function (color, color1, color2, threshold) {
2039
+ // // Return which of `color1` and `color2` has the greatest contrast with `color`
2040
+ // // according to the standard WCAG contrast ratio calculation.
2041
+ // // http://www.w3.org/TR/WCAG20/#contrast-ratiodef
2042
+ // // The threshold param is no longer used, in line with SASS.
2043
+ // // filter: contrast(3.2);
2044
+ // // should be kept as is, so check for color
2045
+ // if (!color.rgb) {
2046
+ // return null;
2047
+ // }
2048
+ // if (typeof color1 === 'undefined') {
2049
+ // color1 = colorFunctions.rgba(0, 0, 0, 1.0);
2050
+ // }
2051
+ // if (typeof color2 === 'undefined') {
2052
+ // color2 = colorFunctions.rgba(255, 255, 255, 1.0);
2053
+ // }
2054
+ // var contrast1, contrast2;
2055
+ // var luma = color.luma();
2056
+ // var luma1 = color1.luma();
2057
+ // var luma2 = color2.luma();
2058
+ // // Calculate contrast ratios for each color
2059
+ // if (luma > luma1) {
2060
+ // contrast1 = (luma + 0.05) / (luma1 + 0.05);
2061
+ // } else {
2062
+ // contrast1 = (luma1 + 0.05) / (luma + 0.05);
2063
+ // }
2064
+ // if (luma > luma2) {
2065
+ // contrast2 = (luma + 0.05) / (luma2 + 0.05);
2066
+ // } else {
2067
+ // contrast2 = (luma2 + 0.05) / (luma + 0.05);
2068
+ // }
2069
+ // if (contrast1 > contrast2) {
2070
+ // return color1;
2071
+ // } else {
2072
+ // return color2;
2073
+ // }
2074
+ // },
1979
2075
  argb: function (color) {
1980
2076
  return new Anonymous(color.toARGB());
1981
2077
  },
@@ -2002,10 +2098,11 @@ colorFunctions = {
2002
2098
  };
2003
2099
  functionRegistry.addMultiple(colorFunctions);
2004
2100
 
2005
- },{"../tree/anonymous":47,"../tree/color":52,"../tree/dimension":59,"../tree/quoted":76,"./function-registry":24}],21:[function(require,module,exports){
2101
+ },{"../tree/anonymous":48,"../tree/color":53,"../tree/dimension":60,"../tree/quoted":77,"./function-registry":26}],23:[function(require,module,exports){
2006
2102
  module.exports = function(environment) {
2007
2103
  var Quoted = require("../tree/quoted"),
2008
2104
  URL = require("../tree/url"),
2105
+ utils = require('../utils'),
2009
2106
  functionRegistry = require("./function-registry"),
2010
2107
  fallback = function(functionThis, node) {
2011
2108
  return new URL(node, functionThis.index, functionThis.currentFileInfo).eval(functionThis.context);
@@ -2031,8 +2128,10 @@ module.exports = function(environment) {
2031
2128
  fragment = filePath.slice(fragmentStart);
2032
2129
  filePath = filePath.slice(0, fragmentStart);
2033
2130
  }
2131
+ var context = utils.clone(this.context);
2132
+ context.rawBuffer = true;
2034
2133
 
2035
- var fileManager = environment.getFileManager(filePath, currentDirectory, this.context, environment, true);
2134
+ var fileManager = environment.getFileManager(filePath, currentDirectory, context, environment, true);
2036
2135
 
2037
2136
  if (!fileManager) {
2038
2137
  return fallback(this, filePathNode);
@@ -2058,7 +2157,7 @@ module.exports = function(environment) {
2058
2157
  useBase64 = /;base64$/.test(mimetype);
2059
2158
  }
2060
2159
 
2061
- var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
2160
+ var fileSync = fileManager.loadFileSync(filePath, currentDirectory, context, environment);
2062
2161
  if (!fileSync.contents) {
2063
2162
  logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
2064
2163
  return fallback(this, filePathNode || mimetypeNode);
@@ -2089,7 +2188,7 @@ module.exports = function(environment) {
2089
2188
  });
2090
2189
  };
2091
2190
 
2092
- },{"../logger":35,"../tree/quoted":76,"../tree/url":83,"./function-registry":24}],22:[function(require,module,exports){
2191
+ },{"../logger":37,"../tree/quoted":77,"../tree/url":82,"../utils":86,"./function-registry":26}],24:[function(require,module,exports){
2093
2192
  var Keyword = require("../tree/keyword"),
2094
2193
  functionRegistry = require("./function-registry");
2095
2194
 
@@ -2118,7 +2217,7 @@ functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
2118
2217
 
2119
2218
  module.exports = defaultFunc;
2120
2219
 
2121
- },{"../tree/keyword":68,"./function-registry":24}],23:[function(require,module,exports){
2220
+ },{"../tree/keyword":68,"./function-registry":26}],25:[function(require,module,exports){
2122
2221
  var Expression = require("../tree/expression");
2123
2222
 
2124
2223
  var functionCaller = function(name, context, index, currentFileInfo) {
@@ -2166,7 +2265,7 @@ functionCaller.prototype.call = function(args) {
2166
2265
 
2167
2266
  module.exports = functionCaller;
2168
2267
 
2169
- },{"../tree/expression":62}],24:[function(require,module,exports){
2268
+ },{"../tree/expression":62}],26:[function(require,module,exports){
2170
2269
  function makeRegistry( base ) {
2171
2270
  return {
2172
2271
  _data: {},
@@ -2176,7 +2275,7 @@ function makeRegistry( base ) {
2176
2275
  name = name.toLowerCase();
2177
2276
 
2178
2277
  if (this._data.hasOwnProperty(name)) {
2179
- //TODO warn
2278
+ // TODO warn
2180
2279
  }
2181
2280
  this._data[name] = func;
2182
2281
  },
@@ -2202,14 +2301,15 @@ function makeRegistry( base ) {
2202
2301
  }
2203
2302
 
2204
2303
  module.exports = makeRegistry( null );
2205
- },{}],25:[function(require,module,exports){
2304
+ },{}],27:[function(require,module,exports){
2206
2305
  module.exports = function(environment) {
2207
2306
  var functions = {
2208
2307
  functionRegistry: require("./function-registry"),
2209
2308
  functionCaller: require("./function-caller")
2210
2309
  };
2211
2310
 
2212
- //register functions
2311
+ // register functions
2312
+ require("./boolean");
2213
2313
  require("./default");
2214
2314
  require("./color");
2215
2315
  require("./color-blending");
@@ -2223,7 +2323,7 @@ module.exports = function(environment) {
2223
2323
  return functions;
2224
2324
  };
2225
2325
 
2226
- },{"./color":20,"./color-blending":19,"./data-uri":21,"./default":22,"./function-caller":23,"./function-registry":24,"./math":27,"./number":28,"./string":29,"./svg":30,"./types":31}],26:[function(require,module,exports){
2326
+ },{"./boolean":20,"./color":22,"./color-blending":21,"./data-uri":23,"./default":24,"./function-caller":25,"./function-registry":26,"./math":29,"./number":30,"./string":31,"./svg":32,"./types":33}],28:[function(require,module,exports){
2227
2327
  var Dimension = require("../tree/dimension");
2228
2328
 
2229
2329
  var MathHelper = function() {
@@ -2240,7 +2340,7 @@ MathHelper._math = function (fn, unit, n) {
2240
2340
  return new Dimension(fn(parseFloat(n.value)), unit);
2241
2341
  };
2242
2342
  module.exports = MathHelper;
2243
- },{"../tree/dimension":59}],27:[function(require,module,exports){
2343
+ },{"../tree/dimension":60}],29:[function(require,module,exports){
2244
2344
  var functionRegistry = require("./function-registry"),
2245
2345
  mathHelper = require("./math-helper.js");
2246
2346
 
@@ -2271,7 +2371,7 @@ mathFunctions.round = function (n, f) {
2271
2371
 
2272
2372
  functionRegistry.addMultiple(mathFunctions);
2273
2373
 
2274
- },{"./function-registry":24,"./math-helper.js":26}],28:[function(require,module,exports){
2374
+ },{"./function-registry":26,"./math-helper.js":28}],30:[function(require,module,exports){
2275
2375
  var Dimension = require("../tree/dimension"),
2276
2376
  Anonymous = require("../tree/anonymous"),
2277
2377
  functionRegistry = require("./function-registry"),
@@ -2279,7 +2379,7 @@ var Dimension = require("../tree/dimension"),
2279
2379
 
2280
2380
  var minMax = function (isMin, args) {
2281
2381
  args = Array.prototype.slice.call(args);
2282
- switch(args.length) {
2382
+ switch (args.length) {
2283
2383
  case 0: throw { type: "Argument", message: "one or more arguments required" };
2284
2384
  }
2285
2385
  var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone,
@@ -2301,7 +2401,7 @@ var minMax = function (isMin, args) {
2301
2401
  j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
2302
2402
  if (j === undefined) {
2303
2403
  if (unitStatic !== undefined && unit !== unitStatic) {
2304
- throw{ type: "Argument", message: "incompatible types" };
2404
+ throw { type: "Argument", message: "incompatible types" };
2305
2405
  }
2306
2406
  values[unit] = order.length;
2307
2407
  order.push(current);
@@ -2354,7 +2454,7 @@ functionRegistry.addMultiple({
2354
2454
  }
2355
2455
  });
2356
2456
 
2357
- },{"../tree/anonymous":47,"../tree/dimension":59,"./function-registry":24,"./math-helper.js":26}],29:[function(require,module,exports){
2457
+ },{"../tree/anonymous":48,"../tree/dimension":60,"./function-registry":26,"./math-helper.js":28}],31:[function(require,module,exports){
2358
2458
  var Quoted = require("../tree/quoted"),
2359
2459
  Anonymous = require("../tree/anonymous"),
2360
2460
  JavaScript = require("../tree/javascript"),
@@ -2376,12 +2476,12 @@ functionRegistry.addMultiple({
2376
2476
  result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement);
2377
2477
  return new Quoted(string.quote || '', result, string.escaped);
2378
2478
  },
2379
- '%': function (string /* arg, arg, ...*/) {
2479
+ '%': function (string /* arg, arg, ... */) {
2380
2480
  var args = Array.prototype.slice.call(arguments, 1),
2381
2481
  result = string.value;
2382
2482
 
2383
2483
  for (var i = 0; i < args.length; i++) {
2384
- /*jshint loopfunc:true */
2484
+ /* jshint loopfunc:true */
2385
2485
  result = result.replace(/%[sda]/i, function(token) {
2386
2486
  var value = ((args[i].type === "Quoted") &&
2387
2487
  token.match(/s/i)) ? args[i].value : args[i].toCSS();
@@ -2393,7 +2493,7 @@ functionRegistry.addMultiple({
2393
2493
  }
2394
2494
  });
2395
2495
 
2396
- },{"../tree/anonymous":47,"../tree/javascript":66,"../tree/quoted":76,"./function-registry":24}],30:[function(require,module,exports){
2496
+ },{"../tree/anonymous":48,"../tree/javascript":66,"../tree/quoted":77,"./function-registry":26}],32:[function(require,module,exports){
2397
2497
  module.exports = function(environment) {
2398
2498
  var Dimension = require("../tree/dimension"),
2399
2499
  Color = require("../tree/color"),
@@ -2411,12 +2511,12 @@ module.exports = function(environment) {
2411
2511
  renderEnv = {compress: false},
2412
2512
  returner,
2413
2513
  directionValue = direction.toCSS(renderEnv),
2414
- i, color, position, positionValue, alpha;
2514
+ i, color, position, positionValue, alpha;
2415
2515
 
2416
2516
  function throwArgumentDescriptor() {
2417
2517
  throw { type: "Argument",
2418
- message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
2419
- " end_color [end_position] or direction, color list" };
2518
+ message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
2519
+ " end_color [end_position] or direction, color list" };
2420
2520
  }
2421
2521
 
2422
2522
  if (arguments.length == 2) {
@@ -2457,7 +2557,7 @@ module.exports = function(environment) {
2457
2557
  '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
2458
2558
  '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
2459
2559
 
2460
- for (i = 0; i < stops.length; i+= 1) {
2560
+ for (i = 0; i < stops.length; i += 1) {
2461
2561
  if (stops[i] instanceof Expression) {
2462
2562
  color = stops[i].value[0];
2463
2563
  position = stops[i].value[1];
@@ -2483,7 +2583,7 @@ module.exports = function(environment) {
2483
2583
  });
2484
2584
  };
2485
2585
 
2486
- },{"../tree/color":52,"../tree/dimension":59,"../tree/expression":62,"../tree/quoted":76,"../tree/url":83,"./function-registry":24}],31:[function(require,module,exports){
2586
+ },{"../tree/color":53,"../tree/dimension":60,"../tree/expression":62,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],33:[function(require,module,exports){
2487
2587
  var Keyword = require("../tree/keyword"),
2488
2588
  DetachedRuleset = require("../tree/detached-ruleset"),
2489
2589
  Dimension = require("../tree/dimension"),
@@ -2574,10 +2674,12 @@ functionRegistry.addMultiple({
2574
2674
  }
2575
2675
  });
2576
2676
 
2577
- },{"../tree/anonymous":47,"../tree/color":52,"../tree/detached-ruleset":58,"../tree/dimension":59,"../tree/keyword":68,"../tree/operation":74,"../tree/quoted":76,"../tree/url":83,"./function-registry":24}],32:[function(require,module,exports){
2677
+ },{"../tree/anonymous":48,"../tree/color":53,"../tree/detached-ruleset":59,"../tree/dimension":60,"../tree/keyword":68,"../tree/operation":74,"../tree/quoted":77,"../tree/url":82,"./function-registry":26}],34:[function(require,module,exports){
2578
2678
  var contexts = require("./contexts"),
2579
2679
  Parser = require('./parser/parser'),
2580
- LessError = require('./less-error');
2680
+ LessError = require('./less-error'),
2681
+ utils = require('./utils'),
2682
+ PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
2581
2683
 
2582
2684
  module.exports = function(environment) {
2583
2685
 
@@ -2603,6 +2705,7 @@ module.exports = function(environment) {
2603
2705
  this.queue = []; // Files which haven't been imported yet
2604
2706
  this.files = {}; // Holds the imported parse trees.
2605
2707
  };
2708
+
2606
2709
  /**
2607
2710
  * Add an import to be imported
2608
2711
  * @param path - the raw path
@@ -2625,7 +2728,9 @@ module.exports = function(environment) {
2625
2728
  callback(null, {rules:[]}, false, null);
2626
2729
  }
2627
2730
  else {
2628
- importManager.files[fullPath] = root;
2731
+ if (!importManager.files[fullPath]) {
2732
+ importManager.files[fullPath] = { root: root, options: importOptions };
2733
+ }
2629
2734
  if (e && !importManager.error) { importManager.error = e; }
2630
2735
  callback(e, root, importedEqualsRoot, fullPath);
2631
2736
  }
@@ -2645,10 +2750,6 @@ module.exports = function(environment) {
2645
2750
  return;
2646
2751
  }
2647
2752
 
2648
- if (tryAppendExtension) {
2649
- path = importOptions.isPlugin ? path : fileManager.tryAppendExtension(path, ".less");
2650
- }
2651
-
2652
2753
  var loadFileCallback = function(loadedFile) {
2653
2754
  var plugin,
2654
2755
  resolvedFilename = loadedFile.filename,
@@ -2684,7 +2785,7 @@ module.exports = function(environment) {
2684
2785
  }
2685
2786
 
2686
2787
  if (importOptions.isPlugin) {
2687
- plugin = pluginLoader.evalPlugin(contents, newEnv, importOptions.pluginArgs, newFileInfo);
2788
+ plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo);
2688
2789
  if (plugin instanceof LessError) {
2689
2790
  fileParsedFunc(plugin, null, resolvedFilename);
2690
2791
  }
@@ -2694,44 +2795,55 @@ module.exports = function(environment) {
2694
2795
  } else if (importOptions.inline) {
2695
2796
  fileParsedFunc(null, contents, resolvedFilename);
2696
2797
  } else {
2697
- new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
2698
- fileParsedFunc(e, root, resolvedFilename);
2699
- });
2700
- }
2701
- };
2702
- var promise;
2703
- var done = function(err, loadedFile) {
2704
- if (err) {
2705
- fileParsedFunc(err);
2706
- } else {
2707
- loadFileCallback(loadedFile);
2798
+
2799
+ // import (multiple) parse trees apparently get altered and can't be cached.
2800
+ // TODO: investigate why this is
2801
+ if (importManager.files[resolvedFilename]
2802
+ && !importManager.files[resolvedFilename].options.multiple
2803
+ && !importOptions.multiple) {
2804
+
2805
+ fileParsedFunc(null, importManager.files[resolvedFilename].root, resolvedFilename);
2806
+ }
2807
+ else {
2808
+ new Parser(newEnv, importManager, newFileInfo).parse(contents, function (e, root) {
2809
+ fileParsedFunc(e, root, resolvedFilename);
2810
+ });
2811
+ }
2708
2812
  }
2709
2813
  };
2814
+ var promise, context = utils.clone(this.context);
2815
+
2816
+ if (tryAppendExtension) {
2817
+ context.ext = importOptions.isPlugin ? ".js" : ".less";
2818
+ }
2819
+
2710
2820
  if (importOptions.isPlugin) {
2711
- try {
2712
- pluginLoader.tryLoadPlugin(path, currentFileInfo.currentDirectory, done);
2713
- }
2714
- catch(e) {
2715
- callback(e);
2716
- }
2821
+ promise = pluginLoader.loadPlugin(path, currentFileInfo.currentDirectory, context, environment, fileManager);
2717
2822
  }
2718
2823
  else {
2719
- promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment, done);
2720
- if (promise) {
2721
- promise.then(loadFileCallback, fileParsedFunc);
2722
- }
2824
+ promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, context, environment,
2825
+ function(err, loadedFile) {
2826
+ if (err) {
2827
+ fileParsedFunc(err);
2828
+ } else {
2829
+ loadFileCallback(loadedFile);
2830
+ }
2831
+ });
2723
2832
  }
2724
-
2833
+ if (promise) {
2834
+ promise.then(loadFileCallback, fileParsedFunc);
2835
+ }
2836
+
2725
2837
  };
2726
2838
  return ImportManager;
2727
2839
  };
2728
2840
 
2729
- },{"./contexts":12,"./less-error":34,"./parser/parser":40}],33:[function(require,module,exports){
2841
+ },{"./contexts":12,"./less-error":36,"./parser/parser":42,"./utils":86,"promise":undefined}],35:[function(require,module,exports){
2730
2842
  module.exports = function(environment, fileManagers) {
2731
2843
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2732
2844
 
2733
- var less = {
2734
- version: [3, 0, 0],
2845
+ var initial = {
2846
+ version: [3, 0, 1],
2735
2847
  data: require('./data'),
2736
2848
  tree: require('./tree'),
2737
2849
  Environment: (Environment = require("./environment/environment")),
@@ -2755,41 +2867,104 @@ module.exports = function(environment, fileManagers) {
2755
2867
  logger: require('./logger')
2756
2868
  };
2757
2869
 
2758
- return less;
2759
- };
2870
+ // Create a public API
2760
2871
 
2761
- },{"./contexts":12,"./data":14,"./environment/abstract-file-manager":16,"./environment/abstract-plugin-loader":17,"./environment/environment":18,"./functions":25,"./import-manager":32,"./less-error":34,"./logger":35,"./parse":37,"./parse-tree":36,"./parser/parser":40,"./plugin-manager":41,"./render":42,"./source-map-builder":43,"./source-map-output":44,"./transform-tree":45,"./tree":65,"./utils":86,"./visitors":90}],34:[function(require,module,exports){
2762
- var utils = require("./utils");
2872
+ var ctor = function(t) {
2873
+ return function() {
2874
+ var obj = Object.create(t.prototype);
2875
+ t.apply(obj, Array.prototype.slice.call(arguments, 0));
2876
+ return obj;
2877
+ };
2878
+ };
2879
+ var t, api = Object.create(initial);
2880
+ for (var n in initial.tree) {
2881
+ /* eslint guard-for-in: 0 */
2882
+ t = initial.tree[n];
2883
+ if (typeof t === "function") {
2884
+ api[n.toLowerCase()] = ctor(t);
2885
+ }
2886
+ else {
2887
+ api[n] = Object.create(null);
2888
+ for (var o in t) {
2889
+ /* eslint guard-for-in: 0 */
2890
+ api[n][o.toLowerCase()] = ctor(t[o]);
2891
+ }
2892
+ }
2893
+ }
2763
2894
 
2764
- var LessError = module.exports = function LessError(e, importManager, currentFilename) {
2895
+ return api;
2896
+ };
2765
2897
 
2898
+ },{"./contexts":12,"./data":14,"./environment/abstract-file-manager":17,"./environment/abstract-plugin-loader":18,"./environment/environment":19,"./functions":27,"./import-manager":34,"./less-error":36,"./logger":37,"./parse":39,"./parse-tree":38,"./parser/parser":42,"./plugin-manager":43,"./render":44,"./source-map-builder":45,"./source-map-output":46,"./transform-tree":47,"./tree":65,"./utils":86,"./visitors":90}],36:[function(require,module,exports){
2899
+ var utils = require('./utils');
2900
+ /**
2901
+ * This is a centralized class of any error that could be thrown internally (mostly by the parser).
2902
+ * Besides standard .message it keeps some additional data like a path to the file where the error
2903
+ * occurred along with line and column numbers.
2904
+ *
2905
+ * @class
2906
+ * @extends Error
2907
+ * @type {module.LessError}
2908
+ *
2909
+ * @prop {string} type
2910
+ * @prop {string} filename
2911
+ * @prop {number} index
2912
+ * @prop {number} line
2913
+ * @prop {number} column
2914
+ * @prop {number} callLine
2915
+ * @prop {number} callExtract
2916
+ * @prop {string[]} extract
2917
+ *
2918
+ * @param {Object} e - An error object to wrap around or just a descriptive object
2919
+ * @param {Object} fileContentMap - An object with file contents in 'contents' property (like importManager) @todo - move to fileManager?
2920
+ * @param {string} [currentFilename]
2921
+ */
2922
+ var LessError = module.exports = function LessError(e, fileContentMap, currentFilename) {
2766
2923
  Error.call(this);
2767
2924
 
2768
2925
  var filename = e.filename || currentFilename;
2769
2926
 
2770
- if (importManager && filename) {
2771
- var input = importManager.contents[filename],
2927
+ this.message = e.message;
2928
+ this.stack = e.stack;
2929
+
2930
+ if (fileContentMap && filename) {
2931
+ var input = fileContentMap.contents[filename],
2772
2932
  loc = utils.getLocation(e.index, input),
2773
2933
  line = loc.line,
2774
2934
  col = loc.column,
2775
2935
  callLine = e.call && utils.getLocation(e.call, input).line,
2776
- lines = input.split('\n');
2936
+ lines = input ? input.split('\n') : '';
2777
2937
 
2778
2938
  this.type = e.type || 'Syntax';
2779
2939
  this.filename = filename;
2780
2940
  this.index = e.index;
2781
2941
  this.line = typeof line === 'number' ? line + 1 : null;
2942
+ this.column = col;
2943
+
2944
+ if (!this.line && this.stack) {
2945
+ var found = this.stack.match(/(<anonymous>|Function):(\d+):(\d+)/);
2946
+
2947
+ if (found) {
2948
+ if (found[2]) {
2949
+ this.line = parseInt(found[2]) - 2;
2950
+ }
2951
+ if (found[3]) {
2952
+ this.column = parseInt(found[3]);
2953
+ }
2954
+ }
2955
+ }
2956
+
2782
2957
  this.callLine = callLine + 1;
2783
2958
  this.callExtract = lines[callLine];
2784
- this.column = col;
2959
+
2785
2960
  this.extract = [
2786
- lines[line - 1],
2787
- lines[line],
2788
- lines[line + 1]
2961
+ lines[this.line - 2],
2962
+ lines[this.line - 1],
2963
+ lines[this.line]
2789
2964
  ];
2965
+
2790
2966
  }
2791
- this.message = e.message;
2792
- this.stack = e.stack;
2967
+
2793
2968
  };
2794
2969
 
2795
2970
  if (typeof Object.create === 'undefined') {
@@ -2802,7 +2977,68 @@ if (typeof Object.create === 'undefined') {
2802
2977
 
2803
2978
  LessError.prototype.constructor = LessError;
2804
2979
 
2805
- },{"./utils":86}],35:[function(require,module,exports){
2980
+ /**
2981
+ * An overridden version of the default Object.prototype.toString
2982
+ * which uses additional information to create a helpful message.
2983
+ *
2984
+ * @param {Object} options
2985
+ * @returns {string}
2986
+ */
2987
+ LessError.prototype.toString = function(options) {
2988
+ options = options || {};
2989
+
2990
+ var message = '';
2991
+ var extract = this.extract || [];
2992
+ var error = [];
2993
+ var stylize = function (str) { return str; };
2994
+ if (options.stylize) {
2995
+ var type = typeof options.stylize;
2996
+ if (type !== 'function') {
2997
+ throw Error('options.stylize should be a function, got a ' + type + '!');
2998
+ }
2999
+ stylize = options.stylize;
3000
+ }
3001
+
3002
+ if (this.line !== null) {
3003
+ if (typeof extract[0] === 'string') {
3004
+ error.push(stylize((this.line - 1) + ' ' + extract[0], 'grey'));
3005
+ }
3006
+
3007
+ if (typeof extract[1] === 'string') {
3008
+ var errorTxt = this.line + ' ';
3009
+ if (extract[1]) {
3010
+ errorTxt += extract[1].slice(0, this.column) +
3011
+ stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') +
3012
+ extract[1].slice(this.column + 1), 'red'), 'inverse');
3013
+ }
3014
+ error.push(errorTxt);
3015
+ }
3016
+
3017
+ if (typeof extract[2] === 'string') {
3018
+ error.push(stylize((this.line + 1) + ' ' + extract[2], 'grey'));
3019
+ }
3020
+ error = error.join('\n') + stylize('', 'reset') + '\n';
3021
+ }
3022
+
3023
+ message += stylize(this.type + 'Error: ' + this.message, 'red');
3024
+ if (this.filename) {
3025
+ message += stylize(' in ', 'red') + this.filename;
3026
+ }
3027
+ if (this.line) {
3028
+ message += stylize(' on line ' + this.line + ', column ' + (this.column + 1) + ':', 'grey');
3029
+ }
3030
+
3031
+ message += '\n' + error;
3032
+
3033
+ if (this.callLine) {
3034
+ message += stylize('from ', 'red') + (this.filename || '') + '/n';
3035
+ message += stylize(this.callLine, 'grey') + ' ' + this.callExtract + '/n';
3036
+ }
3037
+
3038
+ return message;
3039
+ };
3040
+
3041
+ },{"./utils":86}],37:[function(require,module,exports){
2806
3042
  module.exports = {
2807
3043
  error: function(msg) {
2808
3044
  this._fireEvent("error", msg);
@@ -2838,7 +3074,7 @@ module.exports = {
2838
3074
  _listeners: []
2839
3075
  };
2840
3076
 
2841
- },{}],36:[function(require,module,exports){
3077
+ },{}],38:[function(require,module,exports){
2842
3078
  var LessError = require('./less-error'),
2843
3079
  transformTree = require("./transform-tree"),
2844
3080
  logger = require("./logger");
@@ -2900,20 +3136,23 @@ module.exports = function(SourceMapBuilder) {
2900
3136
  return ParseTree;
2901
3137
  };
2902
3138
 
2903
- },{"./less-error":34,"./logger":35,"./transform-tree":45}],37:[function(require,module,exports){
3139
+ },{"./less-error":36,"./logger":37,"./transform-tree":47}],39:[function(require,module,exports){
2904
3140
  var PromiseConstructor,
2905
3141
  contexts = require("./contexts"),
2906
3142
  Parser = require('./parser/parser'),
2907
3143
  PluginManager = require('./plugin-manager'),
2908
- LessError = require('./less-error');
3144
+ LessError = require('./less-error'),
3145
+ utils = require('./utils');
2909
3146
 
2910
3147
  module.exports = function(environment, ParseTree, ImportManager) {
2911
3148
  var parse = function (input, options, callback) {
2912
- options = options || {};
2913
3149
 
2914
3150
  if (typeof options === 'function') {
2915
3151
  callback = options;
2916
- options = {};
3152
+ options = utils.defaults(this.options, {});
3153
+ }
3154
+ else {
3155
+ options = utils.defaults(this.options, options || {});
2917
3156
  }
2918
3157
 
2919
3158
  if (!callback) {
@@ -2933,7 +3172,7 @@ module.exports = function(environment, ParseTree, ImportManager) {
2933
3172
  } else {
2934
3173
  var context,
2935
3174
  rootFileInfo,
2936
- pluginManager = new PluginManager(this, true);
3175
+ pluginManager = new PluginManager(this, !options.reUsePluginManager);
2937
3176
 
2938
3177
  options.pluginManager = pluginManager;
2939
3178
 
@@ -2959,38 +3198,38 @@ module.exports = function(environment, ParseTree, ImportManager) {
2959
3198
  }
2960
3199
 
2961
3200
  var imports = new ImportManager(this, context, rootFileInfo);
2962
-
3201
+ this.importManager = imports;
3202
+
3203
+ // TODO: allow the plugins to be just a list of paths or names
3204
+ // Do an async plugin queue like lessc
3205
+
2963
3206
  if (options.plugins) {
2964
3207
  options.plugins.forEach(function(plugin) {
2965
3208
  var evalResult, contents;
2966
3209
  if (plugin.fileContent) {
2967
3210
  contents = plugin.fileContent.replace(/^\uFEFF/, '');
2968
- evalResult = pluginManager.Loader.evalPlugin(contents, context, plugin.options, plugin.filename);
2969
- if (!(evalResult instanceof LessError)) {
2970
- pluginManager.addPlugin(plugin);
2971
- }
2972
- else {
3211
+ evalResult = pluginManager.Loader.evalPlugin(contents, context, imports, plugin.options, plugin.filename);
3212
+ if (evalResult instanceof LessError) {
2973
3213
  return callback(evalResult);
2974
3214
  }
2975
-
2976
3215
  }
2977
3216
  else {
2978
3217
  pluginManager.addPlugin(plugin);
2979
3218
  }
2980
3219
  });
2981
3220
  }
2982
-
3221
+
2983
3222
  new Parser(context, imports, rootFileInfo)
2984
3223
  .parse(input, function (e, root) {
2985
- if (e) { return callback(e); }
2986
- callback(null, root, imports, options);
2987
- }, options);
3224
+ if (e) { return callback(e); }
3225
+ callback(null, root, imports, options);
3226
+ }, options);
2988
3227
  }
2989
3228
  };
2990
3229
  return parse;
2991
3230
  };
2992
3231
 
2993
- },{"./contexts":12,"./less-error":34,"./parser/parser":40,"./plugin-manager":41,"promise":undefined}],38:[function(require,module,exports){
3232
+ },{"./contexts":12,"./less-error":36,"./parser/parser":42,"./plugin-manager":43,"./utils":86,"promise":undefined}],40:[function(require,module,exports){
2994
3233
  // Split the input into chunks.
2995
3234
  module.exports = function (input, fail) {
2996
3235
  var len = input.length, level = 0, parenLevel = 0,
@@ -3104,15 +3343,15 @@ module.exports = function (input, fail) {
3104
3343
  return chunks;
3105
3344
  };
3106
3345
 
3107
- },{}],39:[function(require,module,exports){
3346
+ },{}],41:[function(require,module,exports){
3108
3347
  var chunker = require('./chunker');
3109
3348
 
3110
3349
  module.exports = function() {
3111
- var input, // LeSS input string
3350
+ var input, // Less input string
3112
3351
  j, // current chunk
3113
3352
  saveStack = [], // holds state for backtracking
3114
3353
  furthest, // furthest index the parser has gone to
3115
- furthestPossibleErrorMessage,// if this is furthest we got to, this is the probably cause
3354
+ furthestPossibleErrorMessage, // if this is furthest we got to, this is the probably cause
3116
3355
  chunks, // chunkified input
3117
3356
  current, // current chunk
3118
3357
  currentPos, // index of current chunk, in `input`
@@ -3263,7 +3502,7 @@ module.exports = function() {
3263
3502
 
3264
3503
  for (var i = 1; i + currentPosition < length; i++) {
3265
3504
  var nextChar = input.charAt(i + currentPosition);
3266
- switch(nextChar) {
3505
+ switch (nextChar) {
3267
3506
  case "\\":
3268
3507
  i++;
3269
3508
  continue;
@@ -3316,7 +3555,7 @@ module.exports = function() {
3316
3555
 
3317
3556
  parserInput.peekNotNumeric = function() {
3318
3557
  var c = input.charCodeAt(parserInput.i);
3319
- //Is the first char of the dimension 0-9, '.', '+' or '-'
3558
+ // Is the first char of the dimension 0-9, '.', '+' or '-'
3320
3559
  return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA;
3321
3560
  };
3322
3561
 
@@ -3365,12 +3604,13 @@ module.exports = function() {
3365
3604
  return parserInput;
3366
3605
  };
3367
3606
 
3368
- },{"./chunker":38}],40:[function(require,module,exports){
3607
+ },{"./chunker":40}],42:[function(require,module,exports){
3369
3608
  var LessError = require('../less-error'),
3370
3609
  tree = require("../tree"),
3371
3610
  visitors = require("../visitors"),
3372
3611
  getParserInput = require("./parser-input"),
3373
- utils = require("../utils");
3612
+ utils = require("../utils"),
3613
+ functionRegistry = require('../functions/function-registry');
3374
3614
 
3375
3615
  //
3376
3616
  // less.js - parser
@@ -3403,8 +3643,8 @@ var LessError = require('../less-error'),
3403
3643
  // Token matching is done with the `$` function, which either takes
3404
3644
  // a terminal string or regexp, or a non-terminal function to call.
3405
3645
  // It also takes care of moving all the indices forwards.
3406
- //`
3407
3646
  //
3647
+
3408
3648
  var Parser = function Parser(context, imports, fileInfo) {
3409
3649
  var parsers,
3410
3650
  parserInput = getParserInput();
@@ -3448,11 +3688,61 @@ var Parser = function Parser(context, imports, fileInfo) {
3448
3688
  };
3449
3689
  }
3450
3690
 
3691
+ /**
3692
+ * Used after initial parsing to create nodes on the fly
3693
+ *
3694
+ * @param {String} str - string to parse
3695
+ * @param {Array} parseList - array of parsers to run input through e.g. ["value", "important"]
3696
+ * @param {Number} currentIndex - start number to begin indexing
3697
+ * @param {Object} fileInfo - fileInfo to attach to created nodes
3698
+ */
3699
+ function parseNode(str, parseList, currentIndex, fileInfo, callback) {
3700
+ var result, returnNodes = [];
3701
+ var parser = parserInput;
3702
+
3703
+ try {
3704
+ parser.start(str, false, function fail(msg, index) {
3705
+ callback({
3706
+ message: msg,
3707
+ index: index + currentIndex
3708
+ });
3709
+ });
3710
+ for (var x = 0, p, i; (p = parseList[x]); x++) {
3711
+ i = parser.i;
3712
+ result = parsers[p]();
3713
+ if (result) {
3714
+ result._index = i + currentIndex;
3715
+ result._fileInfo = fileInfo;
3716
+ returnNodes.push(result);
3717
+ }
3718
+ else {
3719
+ returnNodes.push(null);
3720
+ }
3721
+ }
3722
+
3723
+ var endInfo = parser.end();
3724
+ if (endInfo.isFinished) {
3725
+ callback(null, returnNodes);
3726
+ }
3727
+ else {
3728
+ callback(true, null);
3729
+ }
3730
+ } catch (e) {
3731
+ throw new LessError({
3732
+ index: e.index + currentIndex,
3733
+ message: e.message
3734
+ }, imports, fileInfo.filename);
3735
+ }
3736
+ }
3737
+
3451
3738
  //
3452
3739
  // The Parser
3453
3740
  //
3454
3741
  return {
3455
-
3742
+ parserInput: parserInput,
3743
+ imports: imports,
3744
+ fileInfo: fileInfo,
3745
+ parseNode: parseNode,
3456
3746
  //
3457
3747
  // Parse an input string into an abstract syntax tree,
3458
3748
  // @param str A string containing 'less' markup
@@ -3498,9 +3788,13 @@ var Parser = function Parser(context, imports, fileInfo) {
3498
3788
  }, imports);
3499
3789
  });
3500
3790
 
3501
- root = new(tree.Ruleset)(null, this.parsers.primary());
3791
+ tree.Node.prototype.parse = this;
3792
+ root = new tree.Ruleset(null, this.parsers.primary());
3793
+ tree.Node.prototype.rootNode = root;
3502
3794
  root.root = true;
3503
3795
  root.firstRoot = true;
3796
+ root.functionRegistry = functionRegistry.inherit();
3797
+
3504
3798
  } catch (e) {
3505
3799
  return callback(new LessError(e, imports, fileInfo.filename));
3506
3800
  }
@@ -3629,7 +3923,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3629
3923
  }
3630
3924
 
3631
3925
  node = mixin.definition() || this.declaration() || this.ruleset() ||
3632
- mixin.call() || this.rulesetCall() || this.entities.call() || this.atrule();
3926
+ mixin.call() || this.variableCall() || this.entities.call() || this.atrule();
3633
3927
  if (node) {
3634
3928
  root.push(node);
3635
3929
  } else {
@@ -3687,7 +3981,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3687
3981
  // black border-collapse
3688
3982
  //
3689
3983
  keyword: function () {
3690
- var k = parserInput.$char("%") || parserInput.$re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
3984
+ var k = parserInput.$char("%") || parserInput.$re(/^\[?[_A-Za-z-][_A-Za-z0-9-]*\]?/);
3691
3985
  if (k) {
3692
3986
  return tree.Color.fromKeyword(k) || new(tree.Keyword)(k);
3693
3987
  }
@@ -3698,13 +3992,10 @@ var Parser = function Parser(context, imports, fileInfo) {
3698
3992
  //
3699
3993
  // rgb(255, 0, 255)
3700
3994
  //
3701
- // We also try to catch IE's `alpha()`, but let the `alpha` parser
3702
- // deal with the details.
3703
- //
3704
3995
  // The arguments are parsed with the `entities.arguments` parser.
3705
3996
  //
3706
3997
  call: function () {
3707
- var name, nameLC, args, alpha, index = parserInput.i;
3998
+ var name, args, func, index = parserInput.i;
3708
3999
 
3709
4000
  // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
3710
4001
  if (parserInput.peek(/^url\(/i)) {
@@ -3714,70 +4005,98 @@ var Parser = function Parser(context, imports, fileInfo) {
3714
4005
  parserInput.save();
3715
4006
 
3716
4007
  name = parserInput.$re(/^([\w-]+|%|progid:[\w\.]+)\(/);
3717
- if (!name) { parserInput.forget(); return; }
4008
+ if (!name) {
4009
+ parserInput.forget();
4010
+ return;
4011
+ }
3718
4012
 
3719
4013
  name = name[1];
3720
- nameLC = name.toLowerCase();
3721
-
3722
- if (nameLC === 'alpha') {
3723
- alpha = parsers.alpha();
3724
- if (alpha) {
4014
+ func = this.customFuncCall(name);
4015
+ if (func) {
4016
+ args = func.parse();
4017
+ if (args && func.stop) {
3725
4018
  parserInput.forget();
3726
- return alpha;
4019
+ return args;
3727
4020
  }
3728
4021
  }
3729
4022
 
3730
- args = this.arguments();
4023
+ args = this.arguments(args);
3731
4024
 
3732
- if (! parserInput.$char(')')) {
4025
+ if (!parserInput.$char(')')) {
3733
4026
  parserInput.restore("Could not parse call arguments or missing ')'");
3734
4027
  return;
3735
4028
  }
3736
4029
 
3737
4030
  parserInput.forget();
4031
+
3738
4032
  return new(tree.Call)(name, args, index, fileInfo);
3739
4033
  },
3740
- arguments: function () {
3741
- var argsSemiColon = [], argsComma = [],
3742
- expressions = [],
3743
- isSemiColonSeparated, value, arg;
3744
-
3745
- parserInput.save();
4034
+
4035
+ //
4036
+ // Parsing rules for functions with non-standard args, e.g.:
4037
+ //
4038
+ // boolean(not(2 > 1))
4039
+ //
4040
+ // This is a quick prototype, to be modified/improved when
4041
+ // more custom-parsed funcs come (e.g. `selector(...)`)
4042
+ //
3746
4043
 
3747
- while (true) {
4044
+ customFuncCall: function (name) {
4045
+ /* Ideally the table is to be moved out of here for faster perf.,
4046
+ but it's quite tricky since it relies on all these `parsers`
4047
+ and `expect` available only here */
4048
+ return {
4049
+ alpha: f(parsers.ieAlpha, true),
4050
+ boolean: f(condition),
4051
+ 'if': f(condition)
4052
+ }[name.toLowerCase()];
4053
+
4054
+ function f(parse, stop) {
4055
+ return {
4056
+ parse: parse, // parsing function
4057
+ stop: stop // when true - stop after parse() and return its result,
4058
+ // otherwise continue for plain args
4059
+ };
4060
+ }
4061
+
4062
+ function condition() {
4063
+ return [expect(parsers.condition, 'expected condition')];
4064
+ }
4065
+ },
3748
4066
 
3749
- arg = parsers.detachedRuleset() || this.assignment() || parsers.expression();
4067
+ arguments: function (prevArgs) {
4068
+ var argsComma = prevArgs || [],
4069
+ argsSemiColon = [],
4070
+ isSemiColonSeparated, value;
3750
4071
 
3751
- if (!arg) {
3752
- break;
3753
- }
4072
+ parserInput.save();
3754
4073
 
3755
- value = arg;
4074
+ while (true) {
4075
+ if (prevArgs) {
4076
+ prevArgs = false;
4077
+ } else {
4078
+ value = parsers.detachedRuleset() || this.assignment() || parsers.expression();
4079
+ if (!value) {
4080
+ break;
4081
+ }
3756
4082
 
3757
- if (arg.value && arg.value.length == 1) {
3758
- value = arg.value[0];
3759
- }
4083
+ if (value.value && value.value.length == 1) {
4084
+ value = value.value[0];
4085
+ }
3760
4086
 
3761
- if (value) {
3762
- expressions.push(value);
4087
+ argsComma.push(value);
3763
4088
  }
3764
4089
 
3765
- argsComma.push(value);
3766
-
3767
4090
  if (parserInput.$char(',')) {
3768
4091
  continue;
3769
4092
  }
3770
4093
 
3771
4094
  if (parserInput.$char(';') || isSemiColonSeparated) {
3772
-
3773
4095
  isSemiColonSeparated = true;
3774
-
3775
- if (expressions.length > 1) {
3776
- value = new(tree.Value)(expressions);
3777
- }
4096
+ value = (argsComma.length < 1) ? argsComma[0]
4097
+ : new tree.Value(argsComma);
3778
4098
  argsSemiColon.push(value);
3779
-
3780
- expressions = [];
4099
+ argsComma = [];
3781
4100
  }
3782
4101
  }
3783
4102
 
@@ -3835,15 +4154,17 @@ var Parser = function Parser(context, imports, fileInfo) {
3835
4154
  return;
3836
4155
  }
3837
4156
 
3838
- value = this.quoted() || this.variable() ||
4157
+ value = this.quoted() || this.variable() || this.property() ||
3839
4158
  parserInput.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || "";
3840
4159
 
3841
4160
  parserInput.autoCommentAbsorb = true;
3842
4161
 
3843
4162
  expectChar(')');
3844
4163
 
3845
- return new(tree.URL)((value.value != null || value instanceof tree.Variable) ?
3846
- value : new(tree.Anonymous)(value), index, fileInfo);
4164
+ return new(tree.URL)((value.value != null ||
4165
+ value instanceof tree.Variable ||
4166
+ value instanceof tree.Property) ?
4167
+ value : new(tree.Anonymous)(value, index), index, fileInfo);
3847
4168
  },
3848
4169
 
3849
4170
  //
@@ -3870,7 +4191,27 @@ var Parser = function Parser(context, imports, fileInfo) {
3870
4191
  return new(tree.Variable)("@" + curly[1], index, fileInfo);
3871
4192
  }
3872
4193
  },
4194
+ //
4195
+ // A Property accessor, such as `$color`, in
4196
+ //
4197
+ // background-color: $color
4198
+ //
4199
+ property: function () {
4200
+ var name, index = parserInput.i;
4201
+
4202
+ if (parserInput.currentChar() === '$' && (name = parserInput.$re(/^\$[\w-]+/))) {
4203
+ return new(tree.Property)(name, index, fileInfo);
4204
+ }
4205
+ },
4206
+
4207
+ // A property entity useing the protective {} e.g. ${prop}
4208
+ propertyCurly: function () {
4209
+ var curly, index = parserInput.i;
3873
4210
 
4211
+ if (parserInput.currentChar() === '$' && (curly = parserInput.$re(/^\$\{([\w-]+)\}/))) {
4212
+ return new(tree.Property)("$" + curly[1], index, fileInfo);
4213
+ }
4214
+ },
3874
4215
  //
3875
4216
  // A Hexadecimal color
3876
4217
  //
@@ -3980,15 +4321,17 @@ var Parser = function Parser(context, imports, fileInfo) {
3980
4321
  },
3981
4322
 
3982
4323
  //
3983
- // The variable part of a variable definition. Used in the `rule` parser
4324
+ // Call a variable value
3984
4325
  //
3985
- // @fink();
4326
+ // @fink()
3986
4327
  //
3987
- rulesetCall: function () {
4328
+ variableCall: function () {
3988
4329
  var name;
3989
4330
 
3990
- if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) {
3991
- return new tree.RulesetCall(name[1]);
4331
+ if (parserInput.currentChar() === '@'
4332
+ && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)/))
4333
+ && parsers.end()) {
4334
+ return new tree.VariableCall(name[1]);
3992
4335
  }
3993
4336
  },
3994
4337
 
@@ -4005,7 +4348,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4005
4348
  do {
4006
4349
  option = null;
4007
4350
  elements = null;
4008
- while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
4351
+ while (!(option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
4009
4352
  e = this.element();
4010
4353
  if (!e) {
4011
4354
  break;
@@ -4124,7 +4467,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4124
4467
  .push({ variadic: true });
4125
4468
  break;
4126
4469
  }
4127
- arg = entities.variable() || entities.literal() || entities.keyword();
4470
+ arg = entities.variable() || entities.property() || entities.literal() || entities.keyword();
4128
4471
  }
4129
4472
 
4130
4473
  if (!arg) {
@@ -4147,7 +4490,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4147
4490
  val = arg;
4148
4491
  }
4149
4492
 
4150
- if (val && val instanceof tree.Variable) {
4493
+ if (val && (val instanceof tree.Variable || val instanceof tree.Property)) {
4151
4494
  if (parserInput.$char(':')) {
4152
4495
  if (expressions.length > 0) {
4153
4496
  if (isSemiColonSeparated) {
@@ -4293,7 +4636,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4293
4636
  var entities = this.entities;
4294
4637
 
4295
4638
  return this.comment() || entities.literal() || entities.variable() || entities.url() ||
4296
- entities.call() || entities.keyword() || entities.javascript();
4639
+ entities.property() || entities.call() || entities.keyword() || entities.javascript();
4297
4640
  },
4298
4641
 
4299
4642
  //
@@ -4310,17 +4653,18 @@ var Parser = function Parser(context, imports, fileInfo) {
4310
4653
  //
4311
4654
  // alpha(opacity=88)
4312
4655
  //
4313
- alpha: function () {
4656
+ ieAlpha: function () {
4314
4657
  var value;
4315
4658
 
4316
4659
  // http://jsperf.com/case-insensitive-regex-vs-strtolower-then-regex/18
4317
- if (! parserInput.$re(/^opacity=/i)) { return; }
4660
+ if (!parserInput.$re(/^opacity=/i)) { return; }
4318
4661
  value = parserInput.$re(/^\d+/);
4319
4662
  if (!value) {
4320
- value = expect(this.entities.variable, "Could not parse alpha");
4663
+ value = expect(parsers.entities.variable, "Could not parse alpha");
4664
+ value = '@{' + value.name.slice(1) + '}';
4321
4665
  }
4322
4666
  expectChar(')');
4323
- return new(tree.Alpha)(value);
4667
+ return new tree.Quoted('', 'alpha(opacity=' + value + ')');
4324
4668
  },
4325
4669
 
4326
4670
  //
@@ -4346,10 +4690,10 @@ var Parser = function Parser(context, imports, fileInfo) {
4346
4690
  parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
4347
4691
  this.entities.variableCurly();
4348
4692
 
4349
- if (! e) {
4693
+ if (!e) {
4350
4694
  parserInput.save();
4351
4695
  if (parserInput.$char('(')) {
4352
- if ((v = this.selector()) && parserInput.$char(')')) {
4696
+ if ((v = this.selector(false)) && parserInput.$char(')')) {
4353
4697
  e = new(tree.Paren)(v);
4354
4698
  parserInput.forget();
4355
4699
  } else {
@@ -4400,14 +4744,8 @@ var Parser = function Parser(context, imports, fileInfo) {
4400
4744
  }
4401
4745
  },
4402
4746
  //
4403
- // A CSS selector (see selector below)
4404
- // with less extensions e.g. the ability to extend and guard
4405
- //
4406
- lessSelector: function () {
4407
- return this.selector(true);
4408
- },
4409
- //
4410
4747
  // A CSS Selector
4748
+ // with less extensions e.g. the ability to extend and guard
4411
4749
  //
4412
4750
  // .class > div + h1
4413
4751
  // li a:hover
@@ -4416,7 +4754,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4416
4754
  //
4417
4755
  selector: function (isLess) {
4418
4756
  var index = parserInput.i, elements, extendList, c, e, allExtends, when, condition;
4419
-
4757
+ isLess = isLess !== false;
4420
4758
  while ((isLess && (extendList = this.extend())) || (isLess && (when = parserInput.$str("when"))) || (e = this.element())) {
4421
4759
  if (when) {
4422
4760
  condition = expect(this.conditions, 'expected condition');
@@ -4447,7 +4785,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4447
4785
  if (allExtends) { error("Extend must be used to extend a selector, it cannot be used on its own"); }
4448
4786
  },
4449
4787
  attribute: function () {
4450
- if (! parserInput.$char('[')) { return; }
4788
+ if (!parserInput.$char('[')) { return; }
4451
4789
 
4452
4790
  var entities = this.entities,
4453
4791
  key, val, op;
@@ -4506,7 +4844,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4506
4844
  }
4507
4845
 
4508
4846
  while (true) {
4509
- s = this.lessSelector();
4847
+ s = this.selector();
4510
4848
  if (!s) {
4511
4849
  break;
4512
4850
  }
@@ -4519,7 +4857,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4519
4857
  if (s.condition && selectors.length > 1) {
4520
4858
  error("Guards are only currently allowed on a single selector.");
4521
4859
  }
4522
- if (! parserInput.$char(',')) { break; }
4860
+ if (!parserInput.$char(',')) { break; }
4523
4861
  if (s.condition) {
4524
4862
  error("Guards are only currently allowed on a single selector.");
4525
4863
  }
@@ -4537,7 +4875,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4537
4875
  parserInput.restore();
4538
4876
  }
4539
4877
  },
4540
- declaration: function (tryAnonymous) {
4878
+ declaration: function () {
4541
4879
  var name, value, startOfRule = parserInput.i, c = parserInput.currentChar(), important, merge, isVariable;
4542
4880
 
4543
4881
  if (c === '.' || c === '#' || c === '&' || c === ':') { return; }
@@ -4559,22 +4897,16 @@ var Parser = function Parser(context, imports, fileInfo) {
4559
4897
  // where each item is a tree.Keyword or tree.Variable
4560
4898
  merge = !isVariable && name.length > 1 && name.pop().value;
4561
4899
 
4562
- // prefer to try to parse first if its a variable or we are compressing
4563
- // but always fallback on the other one
4564
- var tryValueFirst = !tryAnonymous && (context.compress || isVariable);
4565
-
4566
- if (tryValueFirst) {
4567
- value = this.value();
4900
+ // Try to store values as anonymous
4901
+ // If we need the value later we'll re-parse it in ruleset.parseValue
4902
+ value = this.anonymousValue();
4903
+ if (value) {
4904
+ parserInput.forget();
4905
+ // anonymous values absorb the end ';' which is required for them to work
4906
+ return new (tree.Declaration)(name, value, false, merge, startOfRule, fileInfo);
4568
4907
  }
4908
+
4569
4909
  if (!value) {
4570
- value = this.anonymousValue();
4571
- if (value) {
4572
- parserInput.forget();
4573
- // anonymous values absorb the end ';' which is required for them to work
4574
- return new (tree.Declaration)(name, value, false, merge, startOfRule, fileInfo);
4575
- }
4576
- }
4577
- if (!tryValueFirst && !value) {
4578
4910
  value = this.value();
4579
4911
  }
4580
4912
 
@@ -4584,20 +4916,19 @@ var Parser = function Parser(context, imports, fileInfo) {
4584
4916
  if (value && this.end()) {
4585
4917
  parserInput.forget();
4586
4918
  return new (tree.Declaration)(name, value, important, merge, startOfRule, fileInfo);
4587
- } else {
4919
+ }
4920
+ else {
4588
4921
  parserInput.restore();
4589
- if (value && !tryAnonymous) {
4590
- return this.declaration(true);
4591
- }
4592
4922
  }
4593
4923
  } else {
4594
- parserInput.forget();
4924
+ parserInput.restore();
4595
4925
  }
4596
4926
  },
4597
4927
  anonymousValue: function () {
4598
- var match = parserInput.$re(/^([^@+\/'"*`(;{}-]*);/);
4928
+ var index = parserInput.i;
4929
+ var match = parserInput.$re(/^([^@\$+\/'"*`(;{}-]*);/);
4599
4930
  if (match) {
4600
- return new(tree.Anonymous)(match[1]);
4931
+ return new(tree.Anonymous)(match[1], index);
4601
4932
  }
4602
4933
  },
4603
4934
 
@@ -4640,13 +4971,13 @@ var Parser = function Parser(context, imports, fileInfo) {
4640
4971
  var o, options = {}, optionName, value;
4641
4972
 
4642
4973
  // list of options, surrounded by parens
4643
- if (! parserInput.$char('(')) { return null; }
4974
+ if (!parserInput.$char('(')) { return null; }
4644
4975
  do {
4645
4976
  o = this.importOption();
4646
4977
  if (o) {
4647
4978
  optionName = o;
4648
4979
  value = true;
4649
- switch(optionName) {
4980
+ switch (optionName) {
4650
4981
  case "css":
4651
4982
  optionName = "less";
4652
4983
  value = false;
@@ -4657,7 +4988,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4657
4988
  break;
4658
4989
  }
4659
4990
  options[optionName] = value;
4660
- if (! parserInput.$char(',')) { break; }
4991
+ if (!parserInput.$char(',')) { break; }
4661
4992
  }
4662
4993
  } while (o);
4663
4994
  expectChar(')');
@@ -4707,12 +5038,12 @@ var Parser = function Parser(context, imports, fileInfo) {
4707
5038
  e = this.mediaFeature();
4708
5039
  if (e) {
4709
5040
  features.push(e);
4710
- if (! parserInput.$char(',')) { break; }
5041
+ if (!parserInput.$char(',')) { break; }
4711
5042
  } else {
4712
5043
  e = entities.variable();
4713
5044
  if (e) {
4714
5045
  features.push(e);
4715
- if (! parserInput.$char(',')) { break; }
5046
+ if (!parserInput.$char(',')) { break; }
4716
5047
  }
4717
5048
  }
4718
5049
  } while (e);
@@ -4793,7 +5124,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4793
5124
  pluginArgs: function() {
4794
5125
  // list of options, surrounded by parens
4795
5126
  parserInput.save();
4796
- if (! parserInput.$char('(')) {
5127
+ if (!parserInput.$char('(')) {
4797
5128
  parserInput.restore();
4798
5129
  return null;
4799
5130
  }
@@ -4835,7 +5166,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4835
5166
  nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
4836
5167
  }
4837
5168
 
4838
- switch(nonVendorSpecificName) {
5169
+ switch (nonVendorSpecificName) {
4839
5170
  case "@charset":
4840
5171
  hasIdentifier = true;
4841
5172
  hasBlock = false;
@@ -4902,18 +5233,18 @@ var Parser = function Parser(context, imports, fileInfo) {
4902
5233
  // and before the `;`.
4903
5234
  //
4904
5235
  value: function () {
4905
- var e, expressions = [];
5236
+ var e, expressions = [], index = parserInput.i;
4906
5237
 
4907
5238
  do {
4908
5239
  e = this.expression();
4909
5240
  if (e) {
4910
5241
  expressions.push(e);
4911
- if (! parserInput.$char(',')) { break; }
5242
+ if (!parserInput.$char(',')) { break; }
4912
5243
  }
4913
5244
  } while (e);
4914
5245
 
4915
5246
  if (expressions.length > 0) {
4916
- return new(tree.Value)(expressions);
5247
+ return new(tree.Value)(expressions, index);
4917
5248
  }
4918
5249
  },
4919
5250
  important: function () {
@@ -5152,13 +5483,14 @@ var Parser = function Parser(context, imports, fileInfo) {
5152
5483
  operand: function () {
5153
5484
  var entities = this.entities, negate;
5154
5485
 
5155
- if (parserInput.peek(/^-[@\(]/)) {
5486
+ if (parserInput.peek(/^-[@\$\(]/)) {
5156
5487
  negate = parserInput.$char('-');
5157
5488
  }
5158
5489
 
5159
5490
  var o = this.sub() || entities.dimension() ||
5160
5491
  entities.color() || entities.variable() ||
5161
- entities.call() || entities.colorKeyword();
5492
+ entities.property() || entities.call() ||
5493
+ entities.colorKeyword();
5162
5494
 
5163
5495
  if (negate) {
5164
5496
  o.parensInOp = true;
@@ -5176,7 +5508,7 @@ var Parser = function Parser(context, imports, fileInfo) {
5176
5508
  // @var * 2
5177
5509
  //
5178
5510
  expression: function () {
5179
- var entities = [], e, delim;
5511
+ var entities = [], e, delim, index = parserInput.i;
5180
5512
 
5181
5513
  do {
5182
5514
  e = this.comment();
@@ -5191,7 +5523,7 @@ var Parser = function Parser(context, imports, fileInfo) {
5191
5523
  if (!parserInput.peek(/^\/[\/*]/)) {
5192
5524
  delim = parserInput.$char('/');
5193
5525
  if (delim) {
5194
- entities.push(new(tree.Anonymous)(delim));
5526
+ entities.push(new(tree.Anonymous)(delim, index));
5195
5527
  }
5196
5528
  }
5197
5529
  }
@@ -5229,7 +5561,7 @@ var Parser = function Parser(context, imports, fileInfo) {
5229
5561
 
5230
5562
  match(/^(\*?)/);
5231
5563
  while (true) {
5232
- if (!match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)) {
5564
+ if (!match(/^((?:[\w-]+)|(?:[@\$]\{[\w-]+\}))/)) {
5233
5565
  break;
5234
5566
  }
5235
5567
  }
@@ -5245,10 +5577,11 @@ var Parser = function Parser(context, imports, fileInfo) {
5245
5577
  }
5246
5578
  for (k = 0; k < name.length; k++) {
5247
5579
  s = name[k];
5248
- name[k] = (s.charAt(0) !== '@') ?
5580
+ name[k] = (s.charAt(0) !== '@' && s.charAt(0) !== '$') ?
5249
5581
  new(tree.Keyword)(s) :
5250
- new(tree.Variable)('@' + s.slice(2, -1),
5251
- index[k], fileInfo);
5582
+ (s.charAt(0) === '@' ?
5583
+ new(tree.Variable)('@' + s.slice(2, -1), index[k], fileInfo) :
5584
+ new(tree.Property)('$' + s.slice(2, -1), index[k], fileInfo));
5252
5585
  }
5253
5586
  return name;
5254
5587
  }
@@ -5273,7 +5606,7 @@ Parser.serializeVars = function(vars) {
5273
5606
 
5274
5607
  module.exports = Parser;
5275
5608
 
5276
- },{"../less-error":34,"../tree":65,"../utils":86,"../visitors":90,"./parser-input":39}],41:[function(require,module,exports){
5609
+ },{"../functions/function-registry":26,"../less-error":36,"../tree":65,"../utils":86,"../visitors":90,"./parser-input":41}],43:[function(require,module,exports){
5277
5610
  /**
5278
5611
  * Plugin Manager
5279
5612
  */
@@ -5290,11 +5623,11 @@ var PluginManager = function(less) {
5290
5623
  };
5291
5624
 
5292
5625
  var pm, PluginManagerFactory = function(less, newFactory) {
5293
- if (newFactory || !pm) {
5294
- pm = new PluginManager(less);
5295
- }
5296
- return pm;
5297
- };
5626
+ if (newFactory || !pm) {
5627
+ pm = new PluginManager(less);
5628
+ }
5629
+ return pm;
5630
+ };
5298
5631
 
5299
5632
  /**
5300
5633
  * Adds all the plugins in the array
@@ -5312,13 +5645,13 @@ PluginManager.prototype.addPlugins = function(plugins) {
5312
5645
  * @param plugin
5313
5646
  * @param {String} filename
5314
5647
  */
5315
- PluginManager.prototype.addPlugin = function(plugin, filename) {
5648
+ PluginManager.prototype.addPlugin = function(plugin, filename, functionRegistry) {
5316
5649
  this.installedPlugins.push(plugin);
5317
5650
  if (filename) {
5318
5651
  this.pluginCache[filename] = plugin;
5319
5652
  }
5320
5653
  if (plugin.install) {
5321
- plugin.install(this.less, this);
5654
+ plugin.install(this.less, this, functionRegistry || this.less.functions.functionRegistry);
5322
5655
  }
5323
5656
  };
5324
5657
  /**
@@ -5329,37 +5662,12 @@ PluginManager.prototype.get = function(filename) {
5329
5662
  return this.pluginCache[filename];
5330
5663
  };
5331
5664
 
5332
- // Object.getPrototypeOf shim for visitor upgrade
5333
- if (!Object.getPrototypeOf) {
5334
- Object.getPrototypeOf = function getPrototypeOf(object) {
5335
- return object.constructor ? object.constructor.prototype : void 0;
5336
- };
5337
- }
5338
-
5339
- function upgradeVisitors(visitor, oldType, newType) {
5340
-
5341
- if (visitor['visit' + oldType] && !visitor['visit' + newType]) {
5342
- visitor['visit' + newType] = visitor['visit' + oldType];
5343
- }
5344
- if (visitor['visit' + oldType + 'Out'] && !visitor['visit' + newType + 'Out']) {
5345
- visitor['visit' + newType + 'Out'] = visitor['visit' + oldType + 'Out'];
5346
- }
5347
- }
5348
5665
  /**
5349
5666
  * Adds a visitor. The visitor object has options on itself to determine
5350
5667
  * when it should run.
5351
5668
  * @param visitor
5352
5669
  */
5353
5670
  PluginManager.prototype.addVisitor = function(visitor) {
5354
- var proto;
5355
- // 2.x to 3.x visitor compatibility
5356
- try {
5357
- proto = Object.getPrototypeOf(visitor);
5358
- upgradeVisitors(proto, 'Directive', 'AtRule');
5359
- upgradeVisitors(proto, 'Rule', 'Declaration');
5360
- }
5361
- catch(e) {}
5362
-
5363
5671
  this.visitors.push(visitor);
5364
5672
  };
5365
5673
  /**
@@ -5452,17 +5760,21 @@ PluginManager.prototype.getFileManagers = function() {
5452
5760
  return this.fileManagers;
5453
5761
  };
5454
5762
 
5455
- //
5763
+ //
5456
5764
  module.exports = PluginManagerFactory;
5457
5765
 
5458
- },{}],42:[function(require,module,exports){
5459
- var PromiseConstructor;
5766
+ },{}],44:[function(require,module,exports){
5767
+ var PromiseConstructor,
5768
+ utils = require('./utils');
5460
5769
 
5461
5770
  module.exports = function(environment, ParseTree, ImportManager) {
5462
5771
  var render = function (input, options, callback) {
5463
5772
  if (typeof options === 'function') {
5464
5773
  callback = options;
5465
- options = {};
5774
+ options = utils.defaults(this.options, {});
5775
+ }
5776
+ else {
5777
+ options = utils.defaults(this.options, options || {});
5466
5778
  }
5467
5779
 
5468
5780
  if (!callback) {
@@ -5498,7 +5810,7 @@ module.exports = function(environment, ParseTree, ImportManager) {
5498
5810
  return render;
5499
5811
  };
5500
5812
 
5501
- },{"promise":undefined}],43:[function(require,module,exports){
5813
+ },{"./utils":86,"promise":undefined}],45:[function(require,module,exports){
5502
5814
  module.exports = function (SourceMapOutput, environment) {
5503
5815
 
5504
5816
  var SourceMapBuilder = function (options) {
@@ -5527,6 +5839,9 @@ module.exports = function (SourceMapOutput, environment) {
5527
5839
  if (this.options.sourceMapInputFilename) {
5528
5840
  this.sourceMapInputFilename = sourceMapOutput.normalizeFilename(this.options.sourceMapInputFilename);
5529
5841
  }
5842
+ if (this.options.sourceMapBasepath !== undefined && this.sourceMapURL !== undefined) {
5843
+ this.sourceMapURL = sourceMapOutput.removeBasepath(this.sourceMapURL);
5844
+ }
5530
5845
  return css + this.getCSSAppendage();
5531
5846
  };
5532
5847
 
@@ -5569,7 +5884,7 @@ module.exports = function (SourceMapOutput, environment) {
5569
5884
  return SourceMapBuilder;
5570
5885
  };
5571
5886
 
5572
- },{}],44:[function(require,module,exports){
5887
+ },{}],46:[function(require,module,exports){
5573
5888
  module.exports = function (environment) {
5574
5889
 
5575
5890
  var SourceMapOutput = function (options) {
@@ -5600,21 +5915,26 @@ module.exports = function (environment) {
5600
5915
  this._column = 0;
5601
5916
  };
5602
5917
 
5603
- SourceMapOutput.prototype.normalizeFilename = function(filename) {
5604
- filename = filename.replace(/\\/g, '/');
5605
-
5606
- if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
5607
- filename = filename.substring(this._sourceMapBasepath.length);
5608
- if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
5609
- filename = filename.substring(1);
5918
+ SourceMapOutput.prototype.removeBasepath = function(path) {
5919
+ if (this._sourceMapBasepath && path.indexOf(this._sourceMapBasepath) === 0) {
5920
+ path = path.substring(this._sourceMapBasepath.length);
5921
+ if (path.charAt(0) === '\\' || path.charAt(0) === '/') {
5922
+ path = path.substring(1);
5610
5923
  }
5611
5924
  }
5925
+
5926
+ return path;
5927
+ };
5928
+
5929
+ SourceMapOutput.prototype.normalizeFilename = function(filename) {
5930
+ filename = filename.replace(/\\/g, '/');
5931
+ filename = this.removeBasepath(filename);
5612
5932
  return (this._sourceMapRootpath || "") + filename;
5613
5933
  };
5614
5934
 
5615
5935
  SourceMapOutput.prototype.add = function(chunk, fileInfo, index, mapLines) {
5616
5936
 
5617
- //ignore adding empty strings
5937
+ // ignore adding empty strings
5618
5938
  if (!chunk) {
5619
5939
  return;
5620
5940
  }
@@ -5709,7 +6029,7 @@ module.exports = function (environment) {
5709
6029
  return SourceMapOutput;
5710
6030
  };
5711
6031
 
5712
- },{}],45:[function(require,module,exports){
6032
+ },{}],47:[function(require,module,exports){
5713
6033
  var contexts = require("./contexts"),
5714
6034
  visitor = require("./visitors"),
5715
6035
  tree = require("./tree");
@@ -5737,8 +6057,8 @@ module.exports = function(root, options) {
5737
6057
  variables = Object.keys(variables).map(function (k) {
5738
6058
  var value = variables[k];
5739
6059
 
5740
- if (! (value instanceof tree.Value)) {
5741
- if (! (value instanceof tree.Expression)) {
6060
+ if (!(value instanceof tree.Value)) {
6061
+ if (!(value instanceof tree.Expression)) {
5742
6062
  value = new tree.Expression([value]);
5743
6063
  }
5744
6064
  value = new tree.Value([value]);
@@ -5784,37 +6104,7 @@ module.exports = function(root, options) {
5784
6104
  return evaldRoot;
5785
6105
  };
5786
6106
 
5787
- },{"./contexts":12,"./tree":65,"./visitors":90}],46:[function(require,module,exports){
5788
- var Node = require("./node");
5789
-
5790
- var Alpha = function (val) {
5791
- this.value = val;
5792
- };
5793
- Alpha.prototype = new Node();
5794
- Alpha.prototype.type = "Alpha";
5795
-
5796
- Alpha.prototype.accept = function (visitor) {
5797
- this.value = visitor.visit(this.value);
5798
- };
5799
- Alpha.prototype.eval = function (context) {
5800
- if (this.value.eval) { return new Alpha(this.value.eval(context)); }
5801
- return this;
5802
- };
5803
- Alpha.prototype.genCSS = function (context, output) {
5804
- output.add("alpha(opacity=");
5805
-
5806
- if (this.value.genCSS) {
5807
- this.value.genCSS(context, output);
5808
- } else {
5809
- output.add(this.value);
5810
- }
5811
-
5812
- output.add(")");
5813
- };
5814
-
5815
- module.exports = Alpha;
5816
-
5817
- },{"./node":73}],47:[function(require,module,exports){
6107
+ },{"./contexts":12,"./tree":65,"./visitors":90}],48:[function(require,module,exports){
5818
6108
  var Node = require("./node");
5819
6109
 
5820
6110
  var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) {
@@ -5838,11 +6128,14 @@ Anonymous.prototype.isRulesetLike = function() {
5838
6128
  return this.rulesetLike;
5839
6129
  };
5840
6130
  Anonymous.prototype.genCSS = function (context, output) {
5841
- output.add(this.value, this._fileInfo, this._index, this.mapLines);
6131
+ this.nodeVisible = Boolean(this.value);
6132
+ if (this.nodeVisible) {
6133
+ output.add(this.value, this._fileInfo, this._index, this.mapLines);
6134
+ }
5842
6135
  };
5843
6136
  module.exports = Anonymous;
5844
6137
 
5845
- },{"./node":73}],48:[function(require,module,exports){
6138
+ },{"./node":73}],49:[function(require,module,exports){
5846
6139
  var Node = require("./node");
5847
6140
 
5848
6141
  var Assignment = function (key, val) {
@@ -5871,16 +6164,17 @@ Assignment.prototype.genCSS = function (context, output) {
5871
6164
  };
5872
6165
  module.exports = Assignment;
5873
6166
 
5874
- },{"./node":73}],49:[function(require,module,exports){
6167
+ },{"./node":73}],50:[function(require,module,exports){
5875
6168
  var Node = require("./node"),
5876
6169
  Selector = require("./selector"),
5877
- Ruleset = require("./ruleset");
6170
+ Ruleset = require("./ruleset"),
6171
+ Anonymous = require('./anonymous');
5878
6172
 
5879
6173
  var AtRule = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
5880
6174
  var i;
5881
6175
 
5882
6176
  this.name = name;
5883
- this.value = value;
6177
+ this.value = (value instanceof Node) ? value : (value ? new Anonymous(value) : value);
5884
6178
  if (rules) {
5885
6179
  if (Array.isArray(rules)) {
5886
6180
  this.rules = rules;
@@ -5934,11 +6228,11 @@ AtRule.prototype.genCSS = function (context, output) {
5934
6228
  AtRule.prototype.eval = function (context) {
5935
6229
  var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules;
5936
6230
 
5937
- //media stored inside other atrule should not bubble over it
5938
- //backpup media bubbling information
6231
+ // media stored inside other atrule should not bubble over it
6232
+ // backpup media bubbling information
5939
6233
  mediaPathBackup = context.mediaPath;
5940
6234
  mediaBlocksBackup = context.mediaBlocks;
5941
- //deleted media bubbling information
6235
+ // deleted media bubbling information
5942
6236
  context.mediaPath = [];
5943
6237
  context.mediaBlocks = [];
5944
6238
 
@@ -5950,7 +6244,7 @@ AtRule.prototype.eval = function (context) {
5950
6244
  rules = [rules[0].eval(context)];
5951
6245
  rules[0].root = true;
5952
6246
  }
5953
- //restore media bubbling information
6247
+ // restore media bubbling information
5954
6248
  context.mediaPath = mediaPathBackup;
5955
6249
  context.mediaBlocks = mediaBlocksBackup;
5956
6250
 
@@ -6008,7 +6302,7 @@ AtRule.prototype.outputRuleset = function (context, output, rules) {
6008
6302
  };
6009
6303
  module.exports = AtRule;
6010
6304
 
6011
- },{"./node":73,"./ruleset":79,"./selector":80}],50:[function(require,module,exports){
6305
+ },{"./anonymous":48,"./node":73,"./ruleset":78,"./selector":79}],51:[function(require,module,exports){
6012
6306
  var Node = require("./node");
6013
6307
 
6014
6308
  var Attribute = function (key, op, value) {
@@ -6037,8 +6331,9 @@ Attribute.prototype.toCSS = function (context) {
6037
6331
  };
6038
6332
  module.exports = Attribute;
6039
6333
 
6040
- },{"./node":73}],51:[function(require,module,exports){
6334
+ },{"./node":73}],52:[function(require,module,exports){
6041
6335
  var Node = require("./node"),
6336
+ Anonymous = require("./anonymous"),
6042
6337
  FunctionCaller = require("../functions/function-caller");
6043
6338
  //
6044
6339
  // A function call node.
@@ -6046,6 +6341,7 @@ var Node = require("./node"),
6046
6341
  var Call = function (name, args, index, currentFileInfo) {
6047
6342
  this.name = name;
6048
6343
  this.args = args;
6344
+ this.mathOn = name === 'calc' ? false : true;
6049
6345
  this._index = index;
6050
6346
  this._fileInfo = currentFileInfo;
6051
6347
  };
@@ -6068,8 +6364,16 @@ Call.prototype.accept = function (visitor) {
6068
6364
  // The function should receive the value, not the variable.
6069
6365
  //
6070
6366
  Call.prototype.eval = function (context) {
6071
- var args = this.args.map(function (a) { return a.eval(context); }),
6072
- result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());
6367
+
6368
+ /**
6369
+ * Turn off math for calc(), and switch back on for evaluating nested functions
6370
+ */
6371
+ var currentMathContext = context.mathOn;
6372
+ context.mathOn = this.mathOn;
6373
+ var args = this.args.map(function (a) { return a.eval(context); });
6374
+ context.mathOn = currentMathContext;
6375
+
6376
+ var result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());
6073
6377
 
6074
6378
  if (funcCaller.isValid()) {
6075
6379
  try {
@@ -6086,11 +6390,23 @@ Call.prototype.eval = function (context) {
6086
6390
  };
6087
6391
  }
6088
6392
 
6089
- if (result != null) {
6393
+ if (result !== null && result !== undefined) {
6394
+ // Results that that are not nodes are cast as Anonymous nodes
6395
+ // Falsy values or booleans are returned as empty nodes
6396
+ if (!(result instanceof Node)) {
6397
+ if (!result || result === true) {
6398
+ result = new Anonymous(null);
6399
+ }
6400
+ else {
6401
+ result = new Anonymous(result.toString());
6402
+ }
6403
+
6404
+ }
6090
6405
  result._index = this._index;
6091
6406
  result._fileInfo = this._fileInfo;
6092
6407
  return result;
6093
6408
  }
6409
+
6094
6410
  }
6095
6411
 
6096
6412
  return new Call(this.name, args, this.getIndex(), this.fileInfo());
@@ -6109,7 +6425,7 @@ Call.prototype.genCSS = function (context, output) {
6109
6425
  };
6110
6426
  module.exports = Call;
6111
6427
 
6112
- },{"../functions/function-caller":23,"./node":73}],52:[function(require,module,exports){
6428
+ },{"../functions/function-caller":25,"./anonymous":48,"./node":73}],53:[function(require,module,exports){
6113
6429
  var Node = require("./node"),
6114
6430
  colors = require("../data/colors");
6115
6431
 
@@ -6244,7 +6560,7 @@ Color.prototype.toHSL = function () {
6244
6560
  }
6245
6561
  return { h: h * 360, s: s, l: l, a: a };
6246
6562
  };
6247
- //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
6563
+ // Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
6248
6564
  Color.prototype.toHSV = function () {
6249
6565
  var r = this.rgb[0] / 255,
6250
6566
  g = this.rgb[1] / 255,
@@ -6264,7 +6580,7 @@ Color.prototype.toHSV = function () {
6264
6580
  if (max === min) {
6265
6581
  h = 0;
6266
6582
  } else {
6267
- switch(max) {
6583
+ switch (max) {
6268
6584
  case r: h = (g - b) / d + (g < b ? 6 : 0); break;
6269
6585
  case g: h = (b - r) / d + 2; break;
6270
6586
  case b: h = (r - g) / d + 4; break;
@@ -6300,7 +6616,7 @@ Color.fromKeyword = function(keyword) {
6300
6616
  };
6301
6617
  module.exports = Color;
6302
6618
 
6303
- },{"../data/colors":13,"./node":73}],53:[function(require,module,exports){
6619
+ },{"../data/colors":13,"./node":73}],54:[function(require,module,exports){
6304
6620
  var Node = require("./node");
6305
6621
 
6306
6622
  var Combinator = function (value) {
@@ -6325,7 +6641,7 @@ Combinator.prototype.genCSS = function (context, output) {
6325
6641
  };
6326
6642
  module.exports = Combinator;
6327
6643
 
6328
- },{"./node":73}],54:[function(require,module,exports){
6644
+ },{"./node":73}],55:[function(require,module,exports){
6329
6645
  var Node = require("./node"),
6330
6646
  getDebugInfo = require("./debug-info");
6331
6647
 
@@ -6350,7 +6666,7 @@ Comment.prototype.isSilent = function(context) {
6350
6666
  };
6351
6667
  module.exports = Comment;
6352
6668
 
6353
- },{"./debug-info":56,"./node":73}],55:[function(require,module,exports){
6669
+ },{"./debug-info":57,"./node":73}],56:[function(require,module,exports){
6354
6670
  var Node = require("./node");
6355
6671
 
6356
6672
  var Condition = function (op, l, r, i, negate) {
@@ -6389,11 +6705,11 @@ Condition.prototype.eval = function (context) {
6389
6705
  };
6390
6706
  module.exports = Condition;
6391
6707
 
6392
- },{"./node":73}],56:[function(require,module,exports){
6708
+ },{"./node":73}],57:[function(require,module,exports){
6393
6709
  var debugInfo = function(context, ctx, lineSeparator) {
6394
6710
  var result = "";
6395
6711
  if (context.dumpLineNumbers && !context.compress) {
6396
- switch(context.dumpLineNumbers) {
6712
+ switch (context.dumpLineNumbers) {
6397
6713
  case 'comments':
6398
6714
  result = debugInfo.asComment(ctx);
6399
6715
  break;
@@ -6429,14 +6745,15 @@ debugInfo.asMediaQuery = function(ctx) {
6429
6745
 
6430
6746
  module.exports = debugInfo;
6431
6747
 
6432
- },{}],57:[function(require,module,exports){
6748
+ },{}],58:[function(require,module,exports){
6433
6749
  var Node = require("./node"),
6434
6750
  Value = require("./value"),
6435
- Keyword = require("./keyword");
6751
+ Keyword = require("./keyword"),
6752
+ Anonymous = require("./anonymous");
6436
6753
 
6437
6754
  var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
6438
6755
  this.name = name;
6439
- this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ??
6756
+ this.value = (value instanceof Node) ? value : new Value([value ? new Anonymous(value) : null]);
6440
6757
  this.important = important ? ' ' + important.trim() : '';
6441
6758
  this.merge = merge;
6442
6759
  this._index = index;
@@ -6464,7 +6781,7 @@ Declaration.prototype.genCSS = function (context, output) {
6464
6781
  try {
6465
6782
  this.value.genCSS(context, output);
6466
6783
  }
6467
- catch(e) {
6784
+ catch (e) {
6468
6785
  e.index = this._index;
6469
6786
  e.filename = this._fileInfo.filename;
6470
6787
  throw e;
@@ -6490,7 +6807,7 @@ Declaration.prototype.eval = function (context) {
6490
6807
 
6491
6808
  if (!this.variable && evaldValue.type === "DetachedRuleset") {
6492
6809
  throw { message: "Rulesets cannot be evaluated on a property.",
6493
- index: this.getIndex(), filename: this.fileInfo().filename };
6810
+ index: this.getIndex(), filename: this.fileInfo().filename };
6494
6811
  }
6495
6812
  var important = this.important,
6496
6813
  importantResult = context.importantScope.pop();
@@ -6505,7 +6822,7 @@ Declaration.prototype.eval = function (context) {
6505
6822
  this.getIndex(), this.fileInfo(), this.inline,
6506
6823
  variable);
6507
6824
  }
6508
- catch(e) {
6825
+ catch (e) {
6509
6826
  if (typeof e.index !== 'number') {
6510
6827
  e.index = this.getIndex();
6511
6828
  e.filename = this.fileInfo().filename;
@@ -6527,7 +6844,7 @@ Declaration.prototype.makeImportant = function () {
6527
6844
  };
6528
6845
 
6529
6846
  module.exports = Declaration;
6530
- },{"./keyword":68,"./node":73,"./value":84}],58:[function(require,module,exports){
6847
+ },{"./anonymous":48,"./keyword":68,"./node":73,"./value":83}],59:[function(require,module,exports){
6531
6848
  var Node = require("./node"),
6532
6849
  contexts = require("../contexts"),
6533
6850
  utils = require("../utils");
@@ -6552,7 +6869,7 @@ DetachedRuleset.prototype.callEval = function (context) {
6552
6869
  };
6553
6870
  module.exports = DetachedRuleset;
6554
6871
 
6555
- },{"../contexts":12,"../utils":86,"./node":73}],59:[function(require,module,exports){
6872
+ },{"../contexts":12,"../utils":86,"./node":73}],60:[function(require,module,exports){
6556
6873
  var Node = require("./node"),
6557
6874
  unitConversions = require("../data/unit-conversions"),
6558
6875
  Unit = require("./unit"),
@@ -6563,6 +6880,9 @@ var Node = require("./node"),
6563
6880
  //
6564
6881
  var Dimension = function (value, unit) {
6565
6882
  this.value = parseFloat(value);
6883
+ if (isNaN(this.value)) {
6884
+ throw new Error("Dimension is not a number.");
6885
+ }
6566
6886
  this.unit = (unit && unit instanceof Unit) ? unit :
6567
6887
  new Unit(unit ? [unit] : undefined);
6568
6888
  this.setParent(this.unit, this);
@@ -6613,7 +6933,7 @@ Dimension.prototype.genCSS = function (context, output) {
6613
6933
  // we default to the first Dimension's unit,
6614
6934
  // so `1px + 2` will yield `3px`.
6615
6935
  Dimension.prototype.operate = function (context, op, other) {
6616
- /*jshint noempty:false */
6936
+ /* jshint noempty:false */
6617
6937
  var value = this._operate(context, op, this.value, other.value),
6618
6938
  unit = this.unit.clone();
6619
6939
 
@@ -6712,20 +7032,7 @@ Dimension.prototype.convertTo = function (conversions) {
6712
7032
  };
6713
7033
  module.exports = Dimension;
6714
7034
 
6715
- },{"../data/unit-conversions":15,"./color":52,"./node":73,"./unit":82}],60:[function(require,module,exports){
6716
- // Backwards compatibility shim for Directive (AtRule)
6717
- var AtRule = require("./atrule");
6718
-
6719
- var Directive = function () {
6720
- var args = Array.prototype.slice.call(arguments);
6721
- AtRule.apply(this, args);
6722
- };
6723
-
6724
- Directive.prototype = Object.create(AtRule.prototype);
6725
- Directive.prototype.constructor = Directive;
6726
-
6727
- module.exports = Directive;
6728
- },{"./atrule":49}],61:[function(require,module,exports){
7035
+ },{"../data/unit-conversions":15,"./color":53,"./node":73,"./unit":81}],61:[function(require,module,exports){
6729
7036
  var Node = require("./node"),
6730
7037
  Paren = require("./paren"),
6731
7038
  Combinator = require("./combinator");
@@ -6788,7 +7095,7 @@ Element.prototype.toCSS = function (context) {
6788
7095
  };
6789
7096
  module.exports = Element;
6790
7097
 
6791
- },{"./combinator":53,"./node":73,"./paren":75}],62:[function(require,module,exports){
7098
+ },{"./combinator":54,"./node":73,"./paren":75}],62:[function(require,module,exports){
6792
7099
  var Node = require("./node"),
6793
7100
  Paren = require("./paren"),
6794
7101
  Comment = require("./comment");
@@ -6846,7 +7153,7 @@ Expression.prototype.throwAwayComments = function () {
6846
7153
  };
6847
7154
  module.exports = Expression;
6848
7155
 
6849
- },{"./comment":54,"./node":73,"./paren":75}],63:[function(require,module,exports){
7156
+ },{"./comment":55,"./node":73,"./paren":75}],63:[function(require,module,exports){
6850
7157
  var Node = require("./node"),
6851
7158
  Selector = require("./selector");
6852
7159
 
@@ -6860,7 +7167,7 @@ var Extend = function Extend(selector, option, index, currentFileInfo, visibilit
6860
7167
  this.copyVisibilityInfo(visibilityInfo);
6861
7168
  this.allowRoot = true;
6862
7169
 
6863
- switch(option) {
7170
+ switch (option) {
6864
7171
  case "all":
6865
7172
  this.allowBefore = true;
6866
7173
  this.allowAfter = true;
@@ -6885,7 +7192,7 @@ Extend.prototype.eval = function (context) {
6885
7192
  Extend.prototype.clone = function (context) {
6886
7193
  return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo());
6887
7194
  };
6888
- //it concatenates (joins) all selectors in selector array
7195
+ // it concatenates (joins) all selectors in selector array
6889
7196
  Extend.prototype.findSelfSelectors = function (selectors) {
6890
7197
  var selfElements = [],
6891
7198
  i,
@@ -6906,14 +7213,15 @@ Extend.prototype.findSelfSelectors = function (selectors) {
6906
7213
  };
6907
7214
  module.exports = Extend;
6908
7215
 
6909
- },{"./node":73,"./selector":80}],64:[function(require,module,exports){
7216
+ },{"./node":73,"./selector":79}],64:[function(require,module,exports){
6910
7217
  var Node = require("./node"),
6911
7218
  Media = require("./media"),
6912
7219
  URL = require("./url"),
6913
7220
  Quoted = require("./quoted"),
6914
7221
  Ruleset = require("./ruleset"),
6915
7222
  Anonymous = require("./anonymous"),
6916
- utils = require("../utils");
7223
+ utils = require("../utils"),
7224
+ LessError = require("../less-error");
6917
7225
 
6918
7226
  //
6919
7227
  // CSS @import node
@@ -6939,7 +7247,7 @@ var Import = function (path, features, options, index, currentFileInfo, visibili
6939
7247
  this.css = !this.options.less || this.options.inline;
6940
7248
  } else {
6941
7249
  var pathValue = this.getPath();
6942
- if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
7250
+ if (pathValue && /[#\.\&\?]css([\?;].*)?$/.test(pathValue)) {
6943
7251
  this.css = true;
6944
7252
  }
6945
7253
  }
@@ -7025,8 +7333,8 @@ Import.prototype.eval = function (context) {
7025
7333
  if (this.options.reference || this.blocksVisibility()) {
7026
7334
  if (result.length || result.length === 0) {
7027
7335
  result.forEach(function (node) {
7028
- node.addVisibilityBlock();
7029
- }
7336
+ node.addVisibilityBlock();
7337
+ }
7030
7338
  );
7031
7339
  } else {
7032
7340
  result.addVisibilityBlock();
@@ -7040,12 +7348,19 @@ Import.prototype.doEval = function (context) {
7040
7348
 
7041
7349
  if (this.options.isPlugin) {
7042
7350
  if (this.root && this.root.eval) {
7043
- this.root.eval(context);
7351
+ try {
7352
+ this.root.eval(context);
7353
+ }
7354
+ catch (e) {
7355
+ e.message = "Plugin error during evaluation";
7356
+ throw new LessError(e, this.root.imports, this.root.filename);
7357
+ }
7044
7358
  }
7045
7359
  registry = context.frames[0] && context.frames[0].functionRegistry;
7046
7360
  if ( registry && this.root && this.root.functions ) {
7047
7361
  registry.addMultiple( this.root.functions );
7048
7362
  }
7363
+
7049
7364
  return [];
7050
7365
  }
7051
7366
 
@@ -7059,10 +7374,10 @@ Import.prototype.doEval = function (context) {
7059
7374
  }
7060
7375
  if (this.options.inline) {
7061
7376
  var contents = new Anonymous(this.root, 0,
7062
- {
7063
- filename: this.importedFilename,
7064
- reference: this.path._fileInfo && this.path._fileInfo.reference
7065
- }, true, true);
7377
+ {
7378
+ filename: this.importedFilename,
7379
+ reference: this.path._fileInfo && this.path._fileInfo.reference
7380
+ }, true, true);
7066
7381
 
7067
7382
  return this.features ? new Media([contents], this.features.value) : [contents];
7068
7383
  } else if (this.css) {
@@ -7080,21 +7395,19 @@ Import.prototype.doEval = function (context) {
7080
7395
  };
7081
7396
  module.exports = Import;
7082
7397
 
7083
- },{"../utils":86,"./anonymous":47,"./media":69,"./node":73,"./quoted":76,"./ruleset":79,"./url":83}],65:[function(require,module,exports){
7084
- var tree = {};
7398
+ },{"../less-error":36,"../utils":86,"./anonymous":48,"./media":69,"./node":73,"./quoted":77,"./ruleset":78,"./url":82}],65:[function(require,module,exports){
7399
+ var tree = Object.create(null);
7085
7400
 
7086
7401
  tree.Node = require('./node');
7087
- tree.Alpha = require('./alpha');
7088
7402
  tree.Color = require('./color');
7089
7403
  tree.AtRule = require('./atrule');
7090
- // Backwards compatibility
7091
- tree.Directive = require('./directive');
7092
7404
  tree.DetachedRuleset = require('./detached-ruleset');
7093
7405
  tree.Operation = require('./operation');
7094
7406
  tree.Dimension = require('./dimension');
7095
7407
  tree.Unit = require('./unit');
7096
7408
  tree.Keyword = require('./keyword');
7097
7409
  tree.Variable = require('./variable');
7410
+ tree.Property = require('./property');
7098
7411
  tree.Ruleset = require('./ruleset');
7099
7412
  tree.Element = require('./element');
7100
7413
  tree.Attribute = require('./attribute');
@@ -7103,8 +7416,6 @@ tree.Selector = require('./selector');
7103
7416
  tree.Quoted = require('./quoted');
7104
7417
  tree.Expression = require('./expression');
7105
7418
  tree.Declaration = require('./declaration');
7106
- // Backwards compatibility
7107
- tree.Rule = require('./rule');
7108
7419
  tree.Call = require('./call');
7109
7420
  tree.URL = require('./url');
7110
7421
  tree.Import = require('./import');
@@ -7123,11 +7434,11 @@ tree.Media = require('./media');
7123
7434
  tree.UnicodeDescriptor = require('./unicode-descriptor');
7124
7435
  tree.Negative = require('./negative');
7125
7436
  tree.Extend = require('./extend');
7126
- tree.RulesetCall = require('./ruleset-call');
7437
+ tree.VariableCall = require('./variable-call');
7127
7438
 
7128
7439
  module.exports = tree;
7129
7440
 
7130
- },{"./alpha":46,"./anonymous":47,"./assignment":48,"./atrule":49,"./attribute":50,"./call":51,"./color":52,"./combinator":53,"./comment":54,"./condition":55,"./declaration":57,"./detached-ruleset":58,"./dimension":59,"./directive":60,"./element":61,"./expression":62,"./extend":63,"./import":64,"./javascript":66,"./keyword":68,"./media":69,"./mixin-call":70,"./mixin-definition":71,"./negative":72,"./node":73,"./operation":74,"./paren":75,"./quoted":76,"./rule":77,"./ruleset":79,"./ruleset-call":78,"./selector":80,"./unicode-descriptor":81,"./unit":82,"./url":83,"./value":84,"./variable":85}],66:[function(require,module,exports){
7441
+ },{"./anonymous":48,"./assignment":49,"./atrule":50,"./attribute":51,"./call":52,"./color":53,"./combinator":54,"./comment":55,"./condition":56,"./declaration":58,"./detached-ruleset":59,"./dimension":60,"./element":61,"./expression":62,"./extend":63,"./import":64,"./javascript":66,"./keyword":68,"./media":69,"./mixin-call":70,"./mixin-definition":71,"./negative":72,"./node":73,"./operation":74,"./paren":75,"./property":76,"./quoted":77,"./ruleset":78,"./selector":79,"./unicode-descriptor":80,"./unit":81,"./url":82,"./value":83,"./variable":85,"./variable-call":84}],66:[function(require,module,exports){
7131
7442
  var JsEvalNode = require("./js-eval-node"),
7132
7443
  Dimension = require("./dimension"),
7133
7444
  Quoted = require("./quoted"),
@@ -7157,7 +7468,7 @@ JavaScript.prototype.eval = function(context) {
7157
7468
 
7158
7469
  module.exports = JavaScript;
7159
7470
 
7160
- },{"./anonymous":47,"./dimension":59,"./js-eval-node":67,"./quoted":76}],67:[function(require,module,exports){
7471
+ },{"./anonymous":48,"./dimension":60,"./js-eval-node":67,"./quoted":77}],67:[function(require,module,exports){
7161
7472
  var Node = require("./node"),
7162
7473
  Variable = require("./variable");
7163
7474
 
@@ -7191,7 +7502,7 @@ JsEvalNode.prototype.evaluateJavaScript = function (expression, context) {
7191
7502
  var variables = context.frames[0].variables();
7192
7503
  for (var k in variables) {
7193
7504
  if (variables.hasOwnProperty(k)) {
7194
- /*jshint loopfunc:true */
7505
+ /* jshint loopfunc:true */
7195
7506
  evalContext[k.slice(1)] = {
7196
7507
  value: variables[k].value,
7197
7508
  toJS: function () {
@@ -7262,7 +7573,7 @@ var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
7262
7573
  };
7263
7574
  Media.prototype = new AtRule();
7264
7575
  Media.prototype.type = "Media";
7265
- Media.prototype.isRulesetLike = true;
7576
+ Media.prototype.isRulesetLike = function() { return true; };
7266
7577
  Media.prototype.accept = function (visitor) {
7267
7578
  if (this.features) {
7268
7579
  this.features = visitor.visit(this.features);
@@ -7287,19 +7598,8 @@ Media.prototype.eval = function (context) {
7287
7598
  this.rules[0].debugInfo = this.debugInfo;
7288
7599
  media.debugInfo = this.debugInfo;
7289
7600
  }
7290
- var strictMathBypass = false;
7291
- if (!context.strictMath) {
7292
- strictMathBypass = true;
7293
- context.strictMath = true;
7294
- }
7295
- try {
7296
- media.features = this.features.eval(context);
7297
- }
7298
- finally {
7299
- if (strictMathBypass) {
7300
- context.strictMath = false;
7301
- }
7302
- }
7601
+
7602
+ media.features = this.features.eval(context);
7303
7603
 
7304
7604
  context.mediaPath.push(media);
7305
7605
  context.mediaBlocks.push(media);
@@ -7390,7 +7690,7 @@ Media.prototype.bubbleSelectors = function (selectors) {
7390
7690
  };
7391
7691
  module.exports = Media;
7392
7692
 
7393
- },{"../utils":86,"./anonymous":47,"./atrule":49,"./expression":62,"./ruleset":79,"./selector":80,"./value":84}],70:[function(require,module,exports){
7693
+ },{"../utils":86,"./anonymous":48,"./atrule":50,"./expression":62,"./ruleset":78,"./selector":79,"./value":83}],70:[function(require,module,exports){
7394
7694
  var Node = require("./node"),
7395
7695
  Selector = require("./selector"),
7396
7696
  MixinDefinition = require("./mixin-definition"),
@@ -7576,7 +7876,7 @@ MixinCall.prototype.format = function (args) {
7576
7876
  };
7577
7877
  module.exports = MixinCall;
7578
7878
 
7579
- },{"../functions/default":22,"./mixin-definition":71,"./node":73,"./selector":80}],71:[function(require,module,exports){
7879
+ },{"../functions/default":24,"./mixin-definition":71,"./node":73,"./selector":79}],71:[function(require,module,exports){
7580
7880
  var Selector = require("./selector"),
7581
7881
  Element = require("./element"),
7582
7882
  Ruleset = require("./ruleset"),
@@ -7622,7 +7922,7 @@ Definition.prototype.accept = function (visitor) {
7622
7922
  }
7623
7923
  };
7624
7924
  Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArguments) {
7625
- /*jshint boss:true */
7925
+ /* jshint boss:true */
7626
7926
  var frame = new Ruleset(null, null),
7627
7927
  varargs, arg,
7628
7928
  params = utils.copyArray(this.params),
@@ -7735,7 +8035,7 @@ Definition.prototype.evalCall = function (context, args, important) {
7735
8035
  Definition.prototype.matchCondition = function (args, context) {
7736
8036
  if (this.condition && !this.condition.eval(
7737
8037
  new contexts.Eval(context,
7738
- [this.evalParams(context, /* the parameter variables*/
8038
+ [this.evalParams(context, /* the parameter variables */
7739
8039
  new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
7740
8040
  .concat(this.frames || []) // the parent namespace/mixin frames
7741
8041
  .concat(context.frames)))) { // the current environment frames
@@ -7753,7 +8053,7 @@ Definition.prototype.matchArgs = function (args, context) {
7753
8053
  }
7754
8054
  }, 0);
7755
8055
 
7756
- if (! this.variadic) {
8056
+ if (!this.variadic) {
7757
8057
  if (requiredArgsCnt < this.required) {
7758
8058
  return false;
7759
8059
  }
@@ -7780,7 +8080,7 @@ Definition.prototype.matchArgs = function (args, context) {
7780
8080
  };
7781
8081
  module.exports = Definition;
7782
8082
 
7783
- },{"../contexts":12,"../utils":86,"./declaration":57,"./element":61,"./expression":62,"./ruleset":79,"./selector":80}],72:[function(require,module,exports){
8083
+ },{"../contexts":12,"../utils":86,"./declaration":58,"./element":61,"./expression":62,"./ruleset":78,"./selector":79}],72:[function(require,module,exports){
7784
8084
  var Node = require("./node"),
7785
8085
  Operation = require("./operation"),
7786
8086
  Dimension = require("./dimension");
@@ -7802,11 +8102,13 @@ Negative.prototype.eval = function (context) {
7802
8102
  };
7803
8103
  module.exports = Negative;
7804
8104
 
7805
- },{"./dimension":59,"./node":73,"./operation":74}],73:[function(require,module,exports){
8105
+ },{"./dimension":60,"./node":73,"./operation":74}],73:[function(require,module,exports){
7806
8106
  var Node = function() {
7807
8107
  this.parent = null;
7808
8108
  this.visibilityBlocks = undefined;
7809
8109
  this.nodeVisible = undefined;
8110
+ this.rootNode = null;
8111
+ this.parsed = null;
7810
8112
 
7811
8113
  var self = this;
7812
8114
  Object.defineProperty(this, "currentFileInfo", {
@@ -7836,6 +8138,7 @@ Node.prototype.getIndex = function() {
7836
8138
  Node.prototype.fileInfo = function() {
7837
8139
  return this._fileInfo || (this.parent && this.parent.fileInfo()) || {};
7838
8140
  };
8141
+ Node.prototype.isRulesetLike = function() { return false; };
7839
8142
  Node.prototype.toCSS = function (context) {
7840
8143
  var strs = [];
7841
8144
  this.genCSS(context, {
@@ -7865,8 +8168,8 @@ Node.prototype._operate = function (context, op, a, b) {
7865
8168
  };
7866
8169
  Node.prototype.fround = function(context, value) {
7867
8170
  var precision = context && context.numPrecision;
7868
- //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
7869
- return (precision == null) ? value : Number((value + 2e-16).toFixed(precision));
8171
+ // add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999...) are properly rounded:
8172
+ return (precision) ? Number((value + 2e-16).toFixed(precision)) : value;
7870
8173
  };
7871
8174
  Node.compare = function (a, b) {
7872
8175
  /* returns:
@@ -7926,13 +8229,13 @@ Node.prototype.removeVisibilityBlock = function () {
7926
8229
  }
7927
8230
  this.visibilityBlocks = this.visibilityBlocks - 1;
7928
8231
  };
7929
- //Turns on node visibility - if called node will be shown in output regardless
7930
- //of whether it comes from import by reference or not
8232
+ // Turns on node visibility - if called node will be shown in output regardless
8233
+ // of whether it comes from import by reference or not
7931
8234
  Node.prototype.ensureVisibility = function () {
7932
8235
  this.nodeVisible = true;
7933
8236
  };
7934
- //Turns off node visibility - if called node will NOT be shown in output regardless
7935
- //of whether it comes from import by reference or not
8237
+ // Turns off node visibility - if called node will NOT be shown in output regardless
8238
+ // of whether it comes from import by reference or not
7936
8239
  Node.prototype.ensureInvisibility = function () {
7937
8240
  this.nodeVisible = false;
7938
8241
  };
@@ -7986,7 +8289,7 @@ Operation.prototype.eval = function (context) {
7986
8289
  }
7987
8290
  if (!a.operate) {
7988
8291
  throw { type: "Operation",
7989
- message: "Operation on an invalid type" };
8292
+ message: "Operation on an invalid type" };
7990
8293
  }
7991
8294
 
7992
8295
  return a.operate(context, this.op, b);
@@ -8008,7 +8311,7 @@ Operation.prototype.genCSS = function (context, output) {
8008
8311
 
8009
8312
  module.exports = Operation;
8010
8313
 
8011
- },{"./color":52,"./dimension":59,"./node":73}],75:[function(require,module,exports){
8314
+ },{"./color":53,"./dimension":60,"./node":73}],75:[function(require,module,exports){
8012
8315
  var Node = require("./node");
8013
8316
 
8014
8317
  var Paren = function (node) {
@@ -8028,8 +8331,80 @@ module.exports = Paren;
8028
8331
 
8029
8332
  },{"./node":73}],76:[function(require,module,exports){
8030
8333
  var Node = require("./node"),
8031
- JsEvalNode = require("./js-eval-node"),
8032
- Variable = require("./variable");
8334
+ Declaration = require("./declaration");
8335
+
8336
+ var Property = function (name, index, currentFileInfo) {
8337
+ this.name = name;
8338
+ this._index = index;
8339
+ this._fileInfo = currentFileInfo;
8340
+ };
8341
+ Property.prototype = new Node();
8342
+ Property.prototype.type = "Property";
8343
+ Property.prototype.eval = function (context) {
8344
+ var property, name = this.name;
8345
+ // TODO: shorten this reference
8346
+ var mergeRules = context.pluginManager.less.visitors.ToCSSVisitor.prototype._mergeRules;
8347
+
8348
+ if (this.evaluating) {
8349
+ throw { type: 'Name',
8350
+ message: "Recursive property reference for " + name,
8351
+ filename: this.fileInfo().filename,
8352
+ index: this.getIndex() };
8353
+ }
8354
+
8355
+ this.evaluating = true;
8356
+
8357
+ property = this.find(context.frames, function (frame) {
8358
+
8359
+ var v, vArr = frame.property(name);
8360
+ if (vArr) {
8361
+ for (var i = 0; i < vArr.length; i++) {
8362
+ v = vArr[i];
8363
+
8364
+ vArr[i] = new Declaration(v.name,
8365
+ v.value,
8366
+ v.important,
8367
+ v.merge,
8368
+ v.index,
8369
+ v.currentFileInfo,
8370
+ v.inline,
8371
+ v.variable
8372
+ );
8373
+ }
8374
+ mergeRules(vArr);
8375
+
8376
+ v = vArr[vArr.length - 1];
8377
+ if (v.important) {
8378
+ var importantScope = context.importantScope[context.importantScope.length - 1];
8379
+ importantScope.important = v.important;
8380
+ }
8381
+ v = v.value.eval(context);
8382
+ return v;
8383
+ }
8384
+ });
8385
+ if (property) {
8386
+ this.evaluating = false;
8387
+ return property;
8388
+ } else {
8389
+ throw { type: 'Name',
8390
+ message: "Property '" + name + "' is undefined",
8391
+ filename: this.currentFileInfo.filename,
8392
+ index: this.index };
8393
+ }
8394
+ };
8395
+ Property.prototype.find = function (obj, fun) {
8396
+ for (var i = 0, r; i < obj.length; i++) {
8397
+ r = fun.call(obj, obj[i]);
8398
+ if (r) { return r; }
8399
+ }
8400
+ return null;
8401
+ };
8402
+ module.exports = Property;
8403
+
8404
+ },{"./declaration":58,"./node":73}],77:[function(require,module,exports){
8405
+ var Node = require("./node"),
8406
+ Variable = require("./variable"),
8407
+ Property = require("./property");
8033
8408
 
8034
8409
  var Quoted = function (str, content, escaped, index, currentFileInfo) {
8035
8410
  this.escaped = (escaped == null) ? true : escaped;
@@ -8038,7 +8413,7 @@ var Quoted = function (str, content, escaped, index, currentFileInfo) {
8038
8413
  this._index = index;
8039
8414
  this._fileInfo = currentFileInfo;
8040
8415
  };
8041
- Quoted.prototype = new JsEvalNode();
8416
+ Quoted.prototype = new Node();
8042
8417
  Quoted.prototype.type = "Quoted";
8043
8418
  Quoted.prototype.genCSS = function (context, output) {
8044
8419
  if (!this.escaped) {
@@ -8050,17 +8425,18 @@ Quoted.prototype.genCSS = function (context, output) {
8050
8425
  }
8051
8426
  };
8052
8427
  Quoted.prototype.containsVariables = function() {
8053
- return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/);
8428
+ return this.value.match(/@\{([\w-]+)\}/);
8054
8429
  };
8055
8430
  Quoted.prototype.eval = function (context) {
8056
8431
  var that = this, value = this.value;
8057
- var javascriptReplacement = function (_, exp) {
8058
- return String(that.evaluateJavaScript(exp, context));
8059
- };
8060
- var interpolationReplacement = function (_, name) {
8432
+ var variableReplacement = function (_, name) {
8061
8433
  var v = new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context, true);
8062
8434
  return (v instanceof Quoted) ? v.value : v.toCSS();
8063
8435
  };
8436
+ var propertyReplacement = function (_, name) {
8437
+ var v = new Property('$' + name, that.getIndex(), that.fileInfo()).eval(context, true);
8438
+ return (v instanceof Quoted) ? v.value : v.toCSS();
8439
+ };
8064
8440
  function iterativeReplace(value, regexp, replacementFnc) {
8065
8441
  var evaluatedValue = value;
8066
8442
  do {
@@ -8069,8 +8445,8 @@ Quoted.prototype.eval = function (context) {
8069
8445
  } while (value !== evaluatedValue);
8070
8446
  return evaluatedValue;
8071
8447
  }
8072
- value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
8073
- value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement);
8448
+ value = iterativeReplace(value, /@\{([\w-]+)\}/g, variableReplacement);
8449
+ value = iterativeReplace(value, /\$\{([\w-]+)\}/g, propertyReplacement);
8074
8450
  return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo());
8075
8451
  };
8076
8452
  Quoted.prototype.compare = function (other) {
@@ -8083,41 +8459,15 @@ Quoted.prototype.compare = function (other) {
8083
8459
  };
8084
8460
  module.exports = Quoted;
8085
8461
 
8086
- },{"./js-eval-node":67,"./node":73,"./variable":85}],77:[function(require,module,exports){
8087
- // Backwards compatibility shim for Rule (Declaration)
8088
- var Declaration = require("./declaration");
8089
-
8090
- var Rule = function () {
8091
- var args = Array.prototype.slice.call(arguments);
8092
- Declaration.apply(this, args);
8093
- };
8094
-
8095
- Rule.prototype = Object.create(Declaration.prototype);
8096
- Rule.prototype.constructor = Rule;
8097
-
8098
- module.exports = Rule;
8099
- },{"./declaration":57}],78:[function(require,module,exports){
8100
- var Node = require("./node"),
8101
- Variable = require("./variable");
8102
-
8103
- var RulesetCall = function (variable) {
8104
- this.variable = variable;
8105
- this.allowRoot = true;
8106
- };
8107
- RulesetCall.prototype = new Node();
8108
- RulesetCall.prototype.type = "RulesetCall";
8109
- RulesetCall.prototype.eval = function (context) {
8110
- var detachedRuleset = new Variable(this.variable).eval(context);
8111
- return detachedRuleset.callEval(context);
8112
- };
8113
- module.exports = RulesetCall;
8114
-
8115
- },{"./node":73,"./variable":85}],79:[function(require,module,exports){
8462
+ },{"./node":73,"./property":76,"./variable":85}],78:[function(require,module,exports){
8116
8463
  var Node = require("./node"),
8117
8464
  Declaration = require("./declaration"),
8465
+ Keyword = require("./keyword"),
8466
+ Comment = require("./comment"),
8467
+ Paren = require("./paren"),
8118
8468
  Selector = require("./selector"),
8119
8469
  Element = require("./element"),
8120
- Paren = require("./paren"),
8470
+ Anonymous = require("./anonymous"),
8121
8471
  contexts = require("../contexts"),
8122
8472
  globalFunctionRegistry = require("../functions/function-registry"),
8123
8473
  defaultFunc = require("../functions/default"),
@@ -8128,9 +8478,12 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {
8128
8478
  this.selectors = selectors;
8129
8479
  this.rules = rules;
8130
8480
  this._lookups = {};
8481
+ this._variables = null;
8482
+ this._properties = null;
8131
8483
  this.strictImports = strictImports;
8132
8484
  this.copyVisibilityInfo(visibilityInfo);
8133
8485
  this.allowRoot = true;
8486
+
8134
8487
  this.setParent(this.selectors, this);
8135
8488
  this.setParent(this.rules, this);
8136
8489
 
@@ -8138,7 +8491,7 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {
8138
8491
  Ruleset.prototype = new Node();
8139
8492
  Ruleset.prototype.type = "Ruleset";
8140
8493
  Ruleset.prototype.isRuleset = true;
8141
- Ruleset.prototype.isRulesetLike = true;
8494
+ Ruleset.prototype.isRulesetLike = function() { return true; };
8142
8495
  Ruleset.prototype.accept = function (visitor) {
8143
8496
  if (this.paths) {
8144
8497
  this.paths = visitor.visitArray(this.paths, true);
@@ -8219,20 +8572,20 @@ Ruleset.prototype.eval = function (context) {
8219
8572
 
8220
8573
  // Store the frames around mixin definitions,
8221
8574
  // so they can be evaluated like closures when the time comes.
8222
- var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0;
8223
- for (i = 0; i < rsRuleCnt; i++) {
8224
- if (rsRules[i].evalFirst) {
8225
- rsRules[i] = rsRules[i].eval(context);
8575
+ var rsRules = ruleset.rules;
8576
+ for (i = 0; (rule = rsRules[i]); i++) {
8577
+ if (rule.evalFirst) {
8578
+ rsRules[i] = rule.eval(context);
8226
8579
  }
8227
8580
  }
8228
8581
 
8229
8582
  var mediaBlockCount = (context.mediaBlocks && context.mediaBlocks.length) || 0;
8230
8583
 
8231
8584
  // Evaluate mixin calls.
8232
- for (i = 0; i < rsRuleCnt; i++) {
8233
- if (rsRules[i].type === "MixinCall") {
8234
- /*jshint loopfunc:true */
8235
- rules = rsRules[i].eval(context).filter(function(r) {
8585
+ for (i = 0; (rule = rsRules[i]); i++) {
8586
+ if (rule.type === "MixinCall") {
8587
+ /* jshint loopfunc:true */
8588
+ rules = rule.eval(context).filter(function(r) {
8236
8589
  if ((r instanceof Declaration) && r.variable) {
8237
8590
  // do not pollute the scope if the variable is
8238
8591
  // already there. consider returning false here
@@ -8242,12 +8595,11 @@ Ruleset.prototype.eval = function (context) {
8242
8595
  return true;
8243
8596
  });
8244
8597
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
8245
- rsRuleCnt += rules.length - 1;
8246
8598
  i += rules.length - 1;
8247
8599
  ruleset.resetCache();
8248
- } else if (rsRules[i].type === "RulesetCall") {
8249
- /*jshint loopfunc:true */
8250
- rules = rsRules[i].eval(context).rules.filter(function(r) {
8600
+ } else if (rule.type === "VariableCall") {
8601
+ /* jshint loopfunc:true */
8602
+ rules = rule.eval(context).rules.filter(function(r) {
8251
8603
  if ((r instanceof Declaration) && r.variable) {
8252
8604
  // do not pollute the scope at all
8253
8605
  return false;
@@ -8255,31 +8607,27 @@ Ruleset.prototype.eval = function (context) {
8255
8607
  return true;
8256
8608
  });
8257
8609
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
8258
- rsRuleCnt += rules.length - 1;
8259
8610
  i += rules.length - 1;
8260
8611
  ruleset.resetCache();
8261
8612
  }
8262
8613
  }
8263
8614
 
8264
8615
  // Evaluate everything else
8265
- for (i = 0; i < rsRules.length; i++) {
8266
- rule = rsRules[i];
8616
+ for (i = 0; (rule = rsRules[i]); i++) {
8267
8617
  if (!rule.evalFirst) {
8268
8618
  rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;
8269
8619
  }
8270
8620
  }
8271
8621
 
8272
8622
  // Evaluate everything else
8273
- for (i = 0; i < rsRules.length; i++) {
8274
- rule = rsRules[i];
8623
+ for (i = 0; (rule = rsRules[i]); i++) {
8275
8624
  // for rulesets, check if it is a css guard and can be removed
8276
8625
  if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {
8277
8626
  // check if it can be folded in (e.g. & where)
8278
8627
  if (rule.selectors[0].isJustParentSelector()) {
8279
8628
  rsRules.splice(i--, 1);
8280
8629
 
8281
- for (var j = 0; j < rule.rules.length; j++) {
8282
- subRule = rule.rules[j];
8630
+ for (var j = 0; (subRule = rule.rules[j]); j++) {
8283
8631
  if (subRule instanceof Node) {
8284
8632
  subRule.copyVisibilityInfo(rule.visibilityInfo());
8285
8633
  if (!(subRule instanceof Declaration) || !subRule.variable) {
@@ -8312,7 +8660,7 @@ Ruleset.prototype.evalImports = function(context) {
8312
8660
  importRules = rules[i].eval(context);
8313
8661
  if (importRules && (importRules.length || importRules.length === 0)) {
8314
8662
  rules.splice.apply(rules, [i, 1].concat(importRules));
8315
- i+= importRules.length - 1;
8663
+ i += importRules.length - 1;
8316
8664
  } else {
8317
8665
  rules.splice(i, 1, importRules);
8318
8666
  }
@@ -8351,6 +8699,7 @@ Ruleset.prototype.matchCondition = function (args, context) {
8351
8699
  Ruleset.prototype.resetCache = function () {
8352
8700
  this._rulesets = null;
8353
8701
  this._variables = null;
8702
+ this._properties = null;
8354
8703
  this._lookups = {};
8355
8704
  };
8356
8705
  Ruleset.prototype.variables = function () {
@@ -8375,17 +8724,81 @@ Ruleset.prototype.variables = function () {
8375
8724
  }
8376
8725
  return this._variables;
8377
8726
  };
8727
+ Ruleset.prototype.properties = function () {
8728
+ if (!this._properties) {
8729
+ this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) {
8730
+ if (r instanceof Declaration && r.variable !== true) {
8731
+ var name = (r.name.length === 1) && (r.name[0] instanceof Keyword) ?
8732
+ r.name[0].value : r.name;
8733
+ // Properties don't overwrite as they can merge
8734
+ if (!hash['$' + name]) {
8735
+ hash['$' + name] = [ r ];
8736
+ }
8737
+ else {
8738
+ hash['$' + name].push(r);
8739
+ }
8740
+ }
8741
+ return hash;
8742
+ }, {});
8743
+ }
8744
+ return this._properties;
8745
+ };
8378
8746
  Ruleset.prototype.variable = function (name) {
8379
- return this.variables()[name];
8747
+ var decl = this.variables()[name];
8748
+ if (decl) {
8749
+ return this.parseValue(decl);
8750
+ }
8751
+ };
8752
+ Ruleset.prototype.property = function (name) {
8753
+ var decl = this.properties()[name];
8754
+ if (decl) {
8755
+ return this.parseValue(decl);
8756
+ }
8757
+ };
8758
+ Ruleset.prototype.parseValue = function(toParse) {
8759
+ var self = this;
8760
+ function transformDeclaration(decl) {
8761
+ if (decl.value instanceof Anonymous && !decl.parsed) {
8762
+ this.parse.parseNode(
8763
+ decl.value.value,
8764
+ ["value", "important"],
8765
+ decl.value.getIndex(),
8766
+ decl.fileInfo(),
8767
+ function(err, result) {
8768
+ if (err) {
8769
+ decl.parsed = true;
8770
+ }
8771
+ if (result) {
8772
+ decl.value = result[0];
8773
+ decl.important = result[1] || '';
8774
+ decl.parsed = true;
8775
+ }
8776
+ });
8777
+
8778
+ return decl;
8779
+ }
8780
+ else {
8781
+ return decl;
8782
+ }
8783
+ }
8784
+ if (!Array.isArray(toParse)) {
8785
+ return transformDeclaration.call(self, toParse);
8786
+ }
8787
+ else {
8788
+ var nodes = [];
8789
+ toParse.forEach(function(n) {
8790
+ nodes.push(transformDeclaration.call(self, n));
8791
+ });
8792
+ return nodes;
8793
+ }
8380
8794
  };
8381
8795
  Ruleset.prototype.rulesets = function () {
8382
8796
  if (!this.rules) { return []; }
8383
8797
 
8384
- var filtRules = [], rules = this.rules, cnt = rules.length,
8798
+ var filtRules = [], rules = this.rules,
8385
8799
  i, rule;
8386
8800
 
8387
- for (i = 0; i < cnt; i++) {
8388
- rule = rules[i];
8801
+ for (i = 0; (rule = rules[i]); i++) {
8389
8802
  if (rule.isRuleset) {
8390
8803
  filtRules.push(rule);
8391
8804
  }
@@ -8451,41 +8864,23 @@ Ruleset.prototype.genCSS = function (context, output) {
8451
8864
  tabSetStr = context.compress ? '' : Array(context.tabLevel).join(" "),
8452
8865
  sep;
8453
8866
 
8454
- function isRulesetLikeNode(rule) {
8455
- // if it has nested rules, then it should be treated like a ruleset
8456
- // medias and comments do not have nested rules, but should be treated like rulesets anyway
8457
- // some atrules and anonymous nodes are ruleset like, others are not
8458
- if (typeof rule.isRulesetLike === "boolean") {
8459
- return rule.isRulesetLike;
8460
- } else if (typeof rule.isRulesetLike === "function") {
8461
- return rule.isRulesetLike();
8462
- }
8463
-
8464
- //anything else is assumed to be a rule
8465
- return false;
8466
- }
8467
-
8468
8867
  var charsetNodeIndex = 0;
8469
8868
  var importNodeIndex = 0;
8470
- for (i = 0; i < this.rules.length; i++) {
8471
- rule = this.rules[i];
8472
- // Plugins may return something other than Nodes
8473
- if (rule instanceof Node) {
8474
- if (rule.type === "Comment") {
8475
- if (importNodeIndex === i) {
8476
- importNodeIndex++;
8477
- }
8478
- ruleNodes.push(rule);
8479
- } else if (rule.isCharset && rule.isCharset()) {
8480
- ruleNodes.splice(charsetNodeIndex, 0, rule);
8481
- charsetNodeIndex++;
8869
+ for (i = 0; (rule = this.rules[i]); i++) {
8870
+ if (rule instanceof Comment) {
8871
+ if (importNodeIndex === i) {
8482
8872
  importNodeIndex++;
8483
- } else if (rule.type === "Import") {
8484
- ruleNodes.splice(importNodeIndex, 0, rule);
8485
- importNodeIndex++;
8486
- } else {
8487
- ruleNodes.push(rule);
8488
8873
  }
8874
+ ruleNodes.push(rule);
8875
+ } else if (rule.isCharset && rule.isCharset()) {
8876
+ ruleNodes.splice(charsetNodeIndex, 0, rule);
8877
+ charsetNodeIndex++;
8878
+ importNodeIndex++;
8879
+ } else if (rule.type === "Import") {
8880
+ ruleNodes.splice(importNodeIndex, 0, rule);
8881
+ importNodeIndex++;
8882
+ } else {
8883
+ ruleNodes.push(rule);
8489
8884
  }
8490
8885
  }
8491
8886
  ruleNodes = charsetRuleNodes.concat(ruleNodes);
@@ -8523,15 +8918,14 @@ Ruleset.prototype.genCSS = function (context, output) {
8523
8918
  }
8524
8919
 
8525
8920
  // Compile rules and rulesets
8526
- for (i = 0; i < ruleNodes.length; i++) {
8527
- rule = ruleNodes[i];
8921
+ for (i = 0; (rule = ruleNodes[i]); i++) {
8528
8922
 
8529
8923
  if (i + 1 === ruleNodes.length) {
8530
8924
  context.lastRule = true;
8531
8925
  }
8532
8926
 
8533
8927
  var currentLastRule = context.lastRule;
8534
- if (isRulesetLikeNode(rule)) {
8928
+ if (rule.isRulesetLike(rule)) {
8535
8929
  context.lastRule = false;
8536
8930
  }
8537
8931
 
@@ -8543,7 +8937,7 @@ Ruleset.prototype.genCSS = function (context, output) {
8543
8937
 
8544
8938
  context.lastRule = currentLastRule;
8545
8939
 
8546
- if (!context.lastRule) {
8940
+ if (!context.lastRule && rule.isVisible()) {
8547
8941
  output.add(context.compress ? '' : ('\n' + tabRuleStr));
8548
8942
  } else {
8549
8943
  context.lastRule = false;
@@ -8597,7 +8991,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8597
8991
  // our new selector path
8598
8992
  newSelectorPath = [];
8599
8993
 
8600
- //construct the joined selector - if & is the first thing this will be empty,
8994
+ // construct the joined selector - if & is the first thing this will be empty,
8601
8995
  // if not newJoinedSelector will be the last set of elements in the selector
8602
8996
  if (beginningPath.length > 0) {
8603
8997
  newSelectorPath = utils.copyArray(beginningPath);
@@ -8627,7 +9021,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8627
9021
  newSelectorPath.push(newJoinedSelector);
8628
9022
  }
8629
9023
 
8630
- //put together the parent selectors after the join (e.g. the rest of the parent)
9024
+ // put together the parent selectors after the join (e.g. the rest of the parent)
8631
9025
  if (addPath.length > 1) {
8632
9026
  var restOfPath = addPath.slice(1);
8633
9027
  restOfPath = restOfPath.map(function (selector) {
@@ -8661,9 +9055,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8661
9055
  return;
8662
9056
  }
8663
9057
 
8664
- for (i = 0; i < selectors.length; i++) {
8665
- sel = selectors[i];
8666
-
9058
+ for (i = 0; (sel = selectors[i]); i++) {
8667
9059
  // if the previous thing in sel is a parent this needs to join on to it
8668
9060
  if (sel.length > 0) {
8669
9061
  sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
@@ -8691,12 +9083,12 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8691
9083
  var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
8692
9084
  function findNestedSelector(element) {
8693
9085
  var maybeSelector;
8694
- if (element.value.type !== 'Paren') {
9086
+ if (!(element.value instanceof Paren)) {
8695
9087
  return null;
8696
9088
  }
8697
9089
 
8698
9090
  maybeSelector = element.value.value;
8699
- if (maybeSelector.type !== 'Selector') {
9091
+ if (!(maybeSelector instanceof Selector)) {
8700
9092
  return null;
8701
9093
  }
8702
9094
 
@@ -8712,8 +9104,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8712
9104
  []
8713
9105
  ];
8714
9106
 
8715
- for (i = 0; i < inSelector.elements.length; i++) {
8716
- el = inSelector.elements[i];
9107
+ for (i = 0; (el = inSelector.elements[i]); i++) {
8717
9108
  // non parent reference elements just get added
8718
9109
  if (el.value !== "&") {
8719
9110
  var nestedSelector = findNestedSelector(el);
@@ -8725,7 +9116,7 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8725
9116
  var nestedPaths = [], replaced, replacedNewSelectors = [];
8726
9117
  replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
8727
9118
  hadParentSelector = hadParentSelector || replaced;
8728
- //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
9119
+ // the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
8729
9120
  for (k = 0; k < nestedPaths.length; k++) {
8730
9121
  var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
8731
9122
  addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
@@ -8828,19 +9219,19 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
8828
9219
  };
8829
9220
  module.exports = Ruleset;
8830
9221
 
8831
- },{"../contexts":12,"../functions/default":22,"../functions/function-registry":24,"../utils":86,"./debug-info":56,"./declaration":57,"./element":61,"./node":73,"./paren":75,"./selector":80}],80:[function(require,module,exports){
9222
+ },{"../contexts":12,"../functions/default":24,"../functions/function-registry":26,"../utils":86,"./anonymous":48,"./comment":55,"./debug-info":57,"./declaration":58,"./element":61,"./keyword":68,"./node":73,"./paren":75,"./selector":79}],79:[function(require,module,exports){
8832
9223
  var Node = require("./node"),
8833
- Element = require("./element");
9224
+ Element = require("./element"),
9225
+ LessError = require("../less-error");
8834
9226
 
8835
9227
  var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) {
8836
- this.elements = elements;
8837
9228
  this.extendList = extendList;
8838
9229
  this.condition = condition;
9230
+ this.evaldCondition = !condition;
8839
9231
  this._index = index;
8840
9232
  this._fileInfo = currentFileInfo;
8841
- if (!condition) {
8842
- this.evaldCondition = true;
8843
- }
9233
+ this.elements = this.getElements(elements);
9234
+ this.mixinElements_ = undefined;
8844
9235
  this.copyVisibilityInfo(visibilityInfo);
8845
9236
  this.setParent(this.elements, this);
8846
9237
  };
@@ -8858,13 +9249,32 @@ Selector.prototype.accept = function (visitor) {
8858
9249
  }
8859
9250
  };
8860
9251
  Selector.prototype.createDerived = function(elements, extendList, evaldCondition) {
8861
- var info = this.visibilityInfo();
8862
- evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
8863
- var newSelector = new Selector(elements, extendList || this.extendList, null, this.getIndex(), this.fileInfo(), info);
8864
- newSelector.evaldCondition = evaldCondition;
9252
+ elements = this.getElements(elements);
9253
+ var newSelector = new Selector(elements, extendList || this.extendList,
9254
+ null, this.getIndex(), this.fileInfo(), this.visibilityInfo());
9255
+ newSelector.evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
8865
9256
  newSelector.mediaEmpty = this.mediaEmpty;
8866
9257
  return newSelector;
8867
9258
  };
9259
+ Selector.prototype.getElements = function(els) {
9260
+ if (typeof els === "string") {
9261
+ this.parse.parseNode(
9262
+ els,
9263
+ ["selector"],
9264
+ this._index,
9265
+ this._fileInfo,
9266
+ function(err, result) {
9267
+ if (err) {
9268
+ throw new LessError({
9269
+ index: err.index,
9270
+ message: err.message
9271
+ }, this.parse.imports, this._fileInfo.filename);
9272
+ }
9273
+ els = result[0].elements;
9274
+ });
9275
+ }
9276
+ return els;
9277
+ };
8868
9278
  Selector.prototype.createEmptySelectors = function() {
8869
9279
  var el = new Element('', '&', this._index, this._fileInfo),
8870
9280
  sels = [new Selector([el], null, null, this._index, this._fileInfo)];
@@ -8876,14 +9286,13 @@ Selector.prototype.match = function (other) {
8876
9286
  len = elements.length,
8877
9287
  olen, i;
8878
9288
 
8879
- other.CacheElements();
8880
-
8881
- olen = other._elements.length;
9289
+ other = other.mixinElements();
9290
+ olen = other.length;
8882
9291
  if (olen === 0 || len < olen) {
8883
9292
  return 0;
8884
9293
  } else {
8885
9294
  for (i = 0; i < olen; i++) {
8886
- if (elements[i].value !== other._elements[i]) {
9295
+ if (elements[i].value !== other[i]) {
8887
9296
  return 0;
8888
9297
  }
8889
9298
  }
@@ -8891,9 +9300,9 @@ Selector.prototype.match = function (other) {
8891
9300
 
8892
9301
  return olen; // return number of matched elements
8893
9302
  };
8894
- Selector.prototype.CacheElements = function() {
8895
- if (this._elements) {
8896
- return;
9303
+ Selector.prototype.mixinElements = function() {
9304
+ if (this.mixinElements_) {
9305
+ return this.mixinElements_;
8897
9306
  }
8898
9307
 
8899
9308
  var elements = this.elements.map( function(v) {
@@ -8908,7 +9317,7 @@ Selector.prototype.CacheElements = function() {
8908
9317
  elements = [];
8909
9318
  }
8910
9319
 
8911
- this._elements = elements;
9320
+ return (this.mixinElements_ = elements);
8912
9321
  };
8913
9322
  Selector.prototype.isJustParentSelector = function() {
8914
9323
  return !this.mediaEmpty &&
@@ -8930,12 +9339,9 @@ Selector.prototype.genCSS = function (context, output) {
8930
9339
  if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") {
8931
9340
  output.add(' ', this.fileInfo(), this.getIndex());
8932
9341
  }
8933
- if (!this._css) {
8934
- //TODO caching? speed comparison?
8935
- for (i = 0; i < this.elements.length; i++) {
8936
- element = this.elements[i];
8937
- element.genCSS(context, output);
8938
- }
9342
+ for (i = 0; i < this.elements.length; i++) {
9343
+ element = this.elements[i];
9344
+ element.genCSS(context, output);
8939
9345
  }
8940
9346
  };
8941
9347
  Selector.prototype.getIsOutput = function() {
@@ -8943,7 +9349,7 @@ Selector.prototype.getIsOutput = function() {
8943
9349
  };
8944
9350
  module.exports = Selector;
8945
9351
 
8946
- },{"./element":61,"./node":73}],81:[function(require,module,exports){
9352
+ },{"../less-error":36,"./element":61,"./node":73}],80:[function(require,module,exports){
8947
9353
  var Node = require("./node");
8948
9354
 
8949
9355
  var UnicodeDescriptor = function (value) {
@@ -8954,7 +9360,7 @@ UnicodeDescriptor.prototype.type = "UnicodeDescriptor";
8954
9360
 
8955
9361
  module.exports = UnicodeDescriptor;
8956
9362
 
8957
- },{"./node":73}],82:[function(require,module,exports){
9363
+ },{"./node":73}],81:[function(require,module,exports){
8958
9364
  var Node = require("./node"),
8959
9365
  unitConversions = require("../data/unit-conversions"),
8960
9366
  utils = require("../utils");
@@ -9022,7 +9428,7 @@ Unit.prototype.usedUnits = function() {
9022
9428
  var group, result = {}, mapUnit, groupName;
9023
9429
 
9024
9430
  mapUnit = function (atomicUnit) {
9025
- /*jshint loopfunc:true */
9431
+ /* jshint loopfunc:true */
9026
9432
  if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
9027
9433
  result[groupName] = atomicUnit;
9028
9434
  }
@@ -9077,7 +9483,7 @@ Unit.prototype.cancel = function () {
9077
9483
  };
9078
9484
  module.exports = Unit;
9079
9485
 
9080
- },{"../data/unit-conversions":15,"../utils":86,"./node":73}],83:[function(require,module,exports){
9486
+ },{"../data/unit-conversions":15,"../utils":86,"./node":73}],82:[function(require,module,exports){
9081
9487
  var Node = require("./node");
9082
9488
 
9083
9489
  var URL = function (val, index, currentFileInfo, isEvald) {
@@ -9133,14 +9539,19 @@ URL.prototype.eval = function (context) {
9133
9539
  };
9134
9540
  module.exports = URL;
9135
9541
 
9136
- },{"./node":73}],84:[function(require,module,exports){
9542
+ },{"./node":73}],83:[function(require,module,exports){
9137
9543
  var Node = require("./node");
9138
9544
 
9139
9545
  var Value = function (value) {
9140
- this.value = value;
9141
9546
  if (!value) {
9142
9547
  throw new Error("Value requires an array argument");
9143
9548
  }
9549
+ if (!Array.isArray(value)) {
9550
+ this.value = [ value ];
9551
+ }
9552
+ else {
9553
+ this.value = value;
9554
+ }
9144
9555
  };
9145
9556
  Value.prototype = new Node();
9146
9557
  Value.prototype.type = "Value";
@@ -9169,7 +9580,23 @@ Value.prototype.genCSS = function (context, output) {
9169
9580
  };
9170
9581
  module.exports = Value;
9171
9582
 
9172
- },{"./node":73}],85:[function(require,module,exports){
9583
+ },{"./node":73}],84:[function(require,module,exports){
9584
+ var Node = require("./node"),
9585
+ Variable = require("./variable");
9586
+
9587
+ var VariableCall = function (variable) {
9588
+ this.variable = variable;
9589
+ this.allowRoot = true;
9590
+ };
9591
+ VariableCall.prototype = new Node();
9592
+ VariableCall.prototype.type = "VariableCall";
9593
+ VariableCall.prototype.eval = function (context) {
9594
+ var detachedRuleset = new Variable(this.variable).eval(context);
9595
+ return detachedRuleset.callEval(context);
9596
+ };
9597
+ module.exports = VariableCall;
9598
+
9599
+ },{"./node":73,"./variable":85}],85:[function(require,module,exports){
9173
9600
  var Node = require("./node");
9174
9601
 
9175
9602
  var Variable = function (name, index, currentFileInfo) {
@@ -9188,9 +9615,9 @@ Variable.prototype.eval = function (context) {
9188
9615
 
9189
9616
  if (this.evaluating) {
9190
9617
  throw { type: 'Name',
9191
- message: "Recursive variable definition for " + name,
9192
- filename: this.fileInfo().filename,
9193
- index: this.getIndex() };
9618
+ message: "Recursive variable definition for " + name,
9619
+ filename: this.fileInfo().filename,
9620
+ index: this.getIndex() };
9194
9621
  }
9195
9622
 
9196
9623
  this.evaluating = true;
@@ -9210,9 +9637,9 @@ Variable.prototype.eval = function (context) {
9210
9637
  return variable;
9211
9638
  } else {
9212
9639
  throw { type: 'Name',
9213
- message: "variable " + name + " is undefined",
9214
- filename: this.fileInfo().filename,
9215
- index: this.getIndex() };
9640
+ message: "variable " + name + " is undefined",
9641
+ filename: this.fileInfo().filename,
9642
+ index: this.getIndex() };
9216
9643
  }
9217
9644
  };
9218
9645
  Variable.prototype.find = function (obj, fun) {
@@ -9225,6 +9652,7 @@ Variable.prototype.find = function (obj, fun) {
9225
9652
  module.exports = Variable;
9226
9653
 
9227
9654
  },{"./node":73}],86:[function(require,module,exports){
9655
+ /* jshint proto: true */
9228
9656
  module.exports = {
9229
9657
  getLocation: function(index, inputStream) {
9230
9658
  var n = index + 1,
@@ -9252,6 +9680,45 @@ module.exports = {
9252
9680
  copy[i] = arr[i];
9253
9681
  }
9254
9682
  return copy;
9683
+ },
9684
+ clone: function (obj) {
9685
+ var cloned = {};
9686
+ for (var prop in obj) {
9687
+ if (obj.hasOwnProperty(prop)) {
9688
+ cloned[prop] = obj[prop];
9689
+ }
9690
+ }
9691
+ return cloned;
9692
+ },
9693
+ defaults: function(obj1, obj2) {
9694
+ if (!obj2._defaults || obj2._defaults !== obj1) {
9695
+ for (var prop in obj1) {
9696
+ if (obj1.hasOwnProperty(prop)) {
9697
+ if (!obj2.hasOwnProperty(prop)) {
9698
+ obj2[prop] = obj1[prop];
9699
+ }
9700
+ else if (Array.isArray(obj1[prop])
9701
+ && Array.isArray(obj2[prop])) {
9702
+
9703
+ obj1[prop].forEach(function(p) {
9704
+ if (obj2[prop].indexOf(p) === -1) {
9705
+ obj2[prop].push(p);
9706
+ }
9707
+ });
9708
+ }
9709
+ }
9710
+ }
9711
+ }
9712
+ obj2._defaults = obj1;
9713
+ return obj2;
9714
+ },
9715
+ merge: function(obj1, obj2) {
9716
+ for (var prop in obj2) {
9717
+ if (obj2.hasOwnProperty(prop)) {
9718
+ obj1[prop] = obj2[prop];
9719
+ }
9720
+ }
9721
+ return obj1;
9255
9722
  }
9256
9723
  };
9257
9724
 
@@ -9261,7 +9728,7 @@ var tree = require("../tree"),
9261
9728
  logger = require("../logger"),
9262
9729
  utils = require("../utils");
9263
9730
 
9264
- /*jshint loopfunc:true */
9731
+ /* jshint loopfunc:true */
9265
9732
 
9266
9733
  var ExtendFinderVisitor = function() {
9267
9734
  this._visitor = new Visitor(this);
@@ -9368,17 +9835,17 @@ ProcessExtendsVisitor.prototype = {
9368
9835
  extendList.filter(function(extend) {
9369
9836
  return !extend.hasFoundMatches && extend.parent_ids.length == 1;
9370
9837
  }).forEach(function(extend) {
9371
- var selector = "_unknown_";
9372
- try {
9373
- selector = extend.selector.toCSS({});
9374
- }
9375
- catch(_) {}
9838
+ var selector = "_unknown_";
9839
+ try {
9840
+ selector = extend.selector.toCSS({});
9841
+ }
9842
+ catch (_) {}
9376
9843
 
9377
- if (!indices[extend.index + ' ' + selector]) {
9378
- indices[extend.index + ' ' + selector] = true;
9379
- logger.warn("extend '" + selector + "' has no matches");
9380
- }
9381
- });
9844
+ if (!indices[extend.index + ' ' + selector]) {
9845
+ indices[extend.index + ' ' + selector] = true;
9846
+ logger.warn("extend '" + selector + "' has no matches");
9847
+ }
9848
+ });
9382
9849
  },
9383
9850
  doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
9384
9851
  //
@@ -9395,7 +9862,7 @@ ProcessExtendsVisitor.prototype = {
9395
9862
 
9396
9863
  iterationCount = iterationCount || 0;
9397
9864
 
9398
- //loop through comparing every extend with every target extend.
9865
+ // loop through comparing every extend with every target extend.
9399
9866
  // a target extend is the one on the ruleset we are looking at copy/edit/pasting in place
9400
9867
  // e.g. .a:extend(.b) {} and .b:extend(.c) {} then the first extend extends the second one
9401
9868
  // and the second is the target.
@@ -9461,7 +9928,7 @@ ProcessExtendsVisitor.prototype = {
9461
9928
  selectorOne = extendsToAdd[0].selfSelectors[0].toCSS();
9462
9929
  selectorTwo = extendsToAdd[0].selector.toCSS();
9463
9930
  }
9464
- catch(e) {}
9931
+ catch (e) {}
9465
9932
  throw { message: "extend circular reference detected. One of the circular extends is currently:" +
9466
9933
  selectorOne + ":extend(" + selectorTwo + ")"};
9467
9934
  }
@@ -9626,7 +10093,7 @@ ProcessExtendsVisitor.prototype = {
9626
10093
  },
9627
10094
  extendSelector:function (matches, selectorPath, replacementSelector, isVisible) {
9628
10095
 
9629
- //for a set of matches, replace each match with the replacement selector
10096
+ // for a set of matches, replace each match with the replacement selector
9630
10097
 
9631
10098
  var currentSelectorPathIndex = 0,
9632
10099
  currentSelectorPathElementIndex = 0,
@@ -9718,7 +10185,7 @@ ProcessExtendsVisitor.prototype = {
9718
10185
 
9719
10186
  module.exports = ProcessExtendsVisitor;
9720
10187
 
9721
- },{"../logger":35,"../tree":65,"../utils":86,"./visitor":94}],88:[function(require,module,exports){
10188
+ },{"../logger":37,"../tree":65,"../utils":86,"./visitor":94}],88:[function(require,module,exports){
9722
10189
  function ImportSequencer(onSequencerEmpty) {
9723
10190
  this.imports = [];
9724
10191
  this.variableImports = [];
@@ -9799,7 +10266,7 @@ ImportVisitor.prototype = {
9799
10266
  // process the contents
9800
10267
  this._visitor.visit(root);
9801
10268
  }
9802
- catch(e) {
10269
+ catch (e) {
9803
10270
  this.error = e;
9804
10271
  }
9805
10272
 
@@ -9835,7 +10302,7 @@ ImportVisitor.prototype = {
9835
10302
 
9836
10303
  try {
9837
10304
  evaldImportNode = importNode.evalForImport(context);
9838
- } catch(e) {
10305
+ } catch (e) {
9839
10306
  if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; }
9840
10307
  // attempt to eval properly and treat as css
9841
10308
  importNode.css = true;
@@ -10003,7 +10470,7 @@ JoinSelectorVisitor.prototype = {
10003
10470
 
10004
10471
  this.contexts.push(paths);
10005
10472
 
10006
- if (! rulesetNode.root) {
10473
+ if (!rulesetNode.root) {
10007
10474
  selectors = rulesetNode.selectors;
10008
10475
  if (selectors) {
10009
10476
  selectors = selectors.filter(function(selector) { return selector.getIsOutput(); });
@@ -10082,14 +10549,14 @@ var CSSVisitorUtils = function(context) {
10082
10549
  CSSVisitorUtils.prototype = {
10083
10550
  containsSilentNonBlockedChild: function(bodyRules) {
10084
10551
  var rule;
10085
- if (bodyRules == null) {
10552
+ if (!bodyRules) {
10086
10553
  return false;
10087
10554
  }
10088
10555
  for (var r = 0; r < bodyRules.length; r++) {
10089
10556
  rule = bodyRules[r];
10090
10557
  if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) {
10091
- //the atrule contains something that was referenced (likely by extend)
10092
- //therefore it needs to be shown in output too
10558
+ // the atrule contains something that was referenced (likely by extend)
10559
+ // therefore it needs to be shown in output too
10093
10560
  return true;
10094
10561
  }
10095
10562
  }
@@ -10097,28 +10564,21 @@ CSSVisitorUtils.prototype = {
10097
10564
  },
10098
10565
 
10099
10566
  keepOnlyVisibleChilds: function(owner) {
10100
- if (owner == null || owner.rules == null) {
10101
- return ;
10102
- }
10103
-
10104
- owner.rules = owner.rules.filter(function(thing) {
10567
+ if (owner && owner.rules) {
10568
+ owner.rules = owner.rules.filter(function(thing) {
10105
10569
  return thing.isVisible();
10106
- }
10107
- );
10570
+ });
10571
+ }
10108
10572
  },
10109
10573
 
10110
10574
  isEmpty: function(owner) {
10111
- if (owner == null || owner.rules == null) {
10112
- return true;
10113
- }
10114
- return owner.rules.length === 0;
10575
+ return (owner && owner.rules)
10576
+ ? (owner.rules.length === 0) : true;
10115
10577
  },
10116
10578
 
10117
10579
  hasVisibleSelector: function(rulesetNode) {
10118
- if (rulesetNode == null || rulesetNode.paths == null) {
10119
- return false;
10120
- }
10121
- return rulesetNode.paths.length > 0;
10580
+ return (rulesetNode && rulesetNode.paths)
10581
+ ? (rulesetNode.paths.length > 0) : false;
10122
10582
  },
10123
10583
 
10124
10584
  resolveVisibility: function (node, originalRules) {
@@ -10219,9 +10679,16 @@ ToCSSVisitor.prototype = {
10219
10679
  }
10220
10680
  },
10221
10681
 
10682
+ visitAnonymous: function(anonymousNode, visitArgs) {
10683
+ if (!anonymousNode.blocksVisibility()) {
10684
+ anonymousNode.accept(this._visitor);
10685
+ return anonymousNode;
10686
+ }
10687
+ },
10688
+
10222
10689
  visitAtRuleWithBody: function(atRuleNode, visitArgs) {
10223
- //if there is only one nested ruleset and that one has no path, then it is
10224
- //just fake ruleset
10690
+ // if there is only one nested ruleset and that one has no path, then it is
10691
+ // just fake ruleset
10225
10692
  function hasFakeRuleset(atRuleNode) {
10226
10693
  var bodyRules = atRuleNode.rules;
10227
10694
  return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0);
@@ -10234,9 +10701,9 @@ ToCSSVisitor.prototype = {
10234
10701
 
10235
10702
  return nodeRules;
10236
10703
  }
10237
- //it is still true that it is only one ruleset in array
10238
- //this is last such moment
10239
- //process childs
10704
+ // it is still true that it is only one ruleset in array
10705
+ // this is last such moment
10706
+ // process childs
10240
10707
  var originalRules = getBodyRules(atRuleNode);
10241
10708
  atRuleNode.accept(this._visitor);
10242
10709
  visitArgs.visitDeeper = false;
@@ -10294,13 +10761,13 @@ ToCSSVisitor.prototype = {
10294
10761
  },
10295
10762
 
10296
10763
  visitRuleset: function (rulesetNode, visitArgs) {
10297
- //at this point rulesets are nested into each other
10764
+ // at this point rulesets are nested into each other
10298
10765
  var rule, rulesets = [];
10299
10766
 
10300
10767
  this.checkValidNodes(rulesetNode.rules, rulesetNode.firstRoot);
10301
10768
 
10302
- if (! rulesetNode.root) {
10303
- //remove invisible paths
10769
+ if (!rulesetNode.root) {
10770
+ // remove invisible paths
10304
10771
  this._compileRulesetPaths(rulesetNode);
10305
10772
 
10306
10773
  // remove rulesets from this ruleset body and compile them separately
@@ -10326,7 +10793,7 @@ ToCSSVisitor.prototype = {
10326
10793
  }
10327
10794
  visitArgs.visitDeeper = false;
10328
10795
 
10329
- } else { //if (! rulesetNode.root) {
10796
+ } else { // if (! rulesetNode.root) {
10330
10797
  rulesetNode.accept(this._visitor);
10331
10798
  visitArgs.visitDeeper = false;
10332
10799
  }
@@ -10336,7 +10803,7 @@ ToCSSVisitor.prototype = {
10336
10803
  this._removeDuplicateRules(rulesetNode.rules);
10337
10804
  }
10338
10805
 
10339
- //now decide whether we keep the ruleset
10806
+ // now decide whether we keep the ruleset
10340
10807
  if (this.utils.isVisibleRuleset(rulesetNode)) {
10341
10808
  rulesetNode.ensureVisibility();
10342
10809
  rulesets.splice(0, 0, rulesetNode);
@@ -10394,72 +10861,39 @@ ToCSSVisitor.prototype = {
10394
10861
  }
10395
10862
  },
10396
10863
 
10397
- _mergeRules: function (rules) {
10398
- if (!rules) { return; }
10399
-
10400
- var groups = {},
10401
- parts,
10402
- rule,
10403
- key;
10864
+ _mergeRules: function(rules) {
10865
+ if (!rules) {
10866
+ return;
10867
+ }
10404
10868
 
10869
+ var groups = {},
10870
+ groupsArr = [];
10871
+
10405
10872
  for (var i = 0; i < rules.length; i++) {
10406
- rule = rules[i];
10407
-
10408
- if ((rule instanceof tree.Declaration) && rule.merge) {
10409
- key = [rule.name,
10410
- rule.important ? "!" : ""].join(",");
10411
-
10412
- if (!groups[key]) {
10413
- groups[key] = [];
10414
- } else {
10415
- rules.splice(i--, 1);
10416
- }
10417
-
10873
+ var rule = rules[i];
10874
+ if (rule.merge) {
10875
+ var key = rule.name;
10876
+ groups[key] ? rules.splice(i--, 1) :
10877
+ groupsArr.push(groups[key] = []);
10418
10878
  groups[key].push(rule);
10419
10879
  }
10420
10880
  }
10421
10881
 
10422
- Object.keys(groups).map(function (k) {
10423
-
10424
- function toExpression(values) {
10425
- return new (tree.Expression)(values.map(function (p) {
10426
- return p.value;
10427
- }));
10428
- }
10429
-
10430
- function toValue(values) {
10431
- return new (tree.Value)(values.map(function (p) {
10432
- return p;
10433
- }));
10434
- }
10435
-
10436
- parts = groups[k];
10437
-
10438
- if (parts.length > 1) {
10439
- rule = parts[0];
10440
- var spacedGroups = [];
10441
- var lastSpacedGroup = [];
10442
- parts.map(function (p) {
10443
- if (p.merge === "+") {
10444
- if (lastSpacedGroup.length > 0) {
10445
- spacedGroups.push(toExpression(lastSpacedGroup));
10446
- }
10447
- lastSpacedGroup = [];
10882
+ groupsArr.forEach(function(group) {
10883
+ if (group.length > 0) {
10884
+ var result = group[0],
10885
+ space = [],
10886
+ comma = [new tree.Expression(space)];
10887
+ group.forEach(function(rule) {
10888
+ if ((rule.merge === '+') && (space.length > 0)) {
10889
+ comma.push(new tree.Expression(space = []));
10448
10890
  }
10449
- lastSpacedGroup.push(p);
10891
+ space.push(rule.value);
10892
+ result.important = result.important || rule.important;
10450
10893
  });
10451
- spacedGroups.push(toExpression(lastSpacedGroup));
10452
- rule.value = toValue(spacedGroups);
10894
+ result.value = new tree.Value(comma);
10453
10895
  }
10454
10896
  });
10455
- },
10456
-
10457
- visitAnonymous: function(anonymousNode, visitArgs) {
10458
- if (anonymousNode.blocksVisibility()) {
10459
- return ;
10460
- }
10461
- anonymousNode.accept(this._visitor);
10462
- return anonymousNode;
10463
10897
  }
10464
10898
  };
10465
10899
 
@@ -10478,21 +10912,21 @@ function _noop(node) {
10478
10912
  function indexNodeTypes(parent, ticker) {
10479
10913
  // add .typeIndex to tree node types for lookup table
10480
10914
  var key, child;
10481
- for (key in parent) {
10482
- if (parent.hasOwnProperty(key)) {
10483
- child = parent[key];
10484
- switch (typeof child) {
10485
- case "function":
10486
- // ignore bound functions directly on tree which do not have a prototype
10487
- // or aren't nodes
10488
- if (child.prototype && child.prototype.type) {
10489
- child.prototype.typeIndex = ticker++;
10490
- }
10491
- break;
10492
- case "object":
10493
- ticker = indexNodeTypes(child, ticker);
10494
- break;
10495
- }
10915
+ for (key in parent) {
10916
+ /* eslint guard-for-in: 0 */
10917
+ child = parent[key];
10918
+ switch (typeof child) {
10919
+ case "function":
10920
+ // ignore bound functions directly on tree which do not have a prototype
10921
+ // or aren't nodes
10922
+ if (child.prototype && child.prototype.type) {
10923
+ child.prototype.typeIndex = ticker++;
10924
+ }
10925
+ break;
10926
+ case "object":
10927
+ ticker = indexNodeTypes(child, ticker);
10928
+ break;
10929
+
10496
10930
  }
10497
10931
  }
10498
10932
  return ticker;
@@ -10767,9 +11201,12 @@ function flush() {
10767
11201
 
10768
11202
  // Safari 6 and 6.1 for desktop, iPad, and iPhone are the only browsers that
10769
11203
  // have WebKitMutationObserver but not un-prefixed MutationObserver.
10770
- // Must use `global` instead of `window` to work in both frames and web
11204
+ // Must use `global` or `self` instead of `window` to work in both frames and web
10771
11205
  // workers. `global` is a provision of Browserify, Mr, Mrs, or Mop.
10772
- var BrowserMutationObserver = global.MutationObserver || global.WebKitMutationObserver;
11206
+
11207
+ /* globals self */
11208
+ var scope = typeof global !== "undefined" ? global : self;
11209
+ var BrowserMutationObserver = scope.MutationObserver || scope.WebKitMutationObserver;
10773
11210
 
10774
11211
  // MutationObservers are desirable because they have high priority and work
10775
11212
  // reliably everywhere they are implemented.
@@ -10912,355 +11349,6 @@ rawAsap.makeRequestCallFromTimer = makeRequestCallFromTimer;
10912
11349
 
10913
11350
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
10914
11351
  },{}],97:[function(require,module,exports){
10915
- (function (process){
10916
- // Copyright Joyent, Inc. and other Node contributors.
10917
- //
10918
- // Permission is hereby granted, free of charge, to any person obtaining a
10919
- // copy of this software and associated documentation files (the
10920
- // "Software"), to deal in the Software without restriction, including
10921
- // without limitation the rights to use, copy, modify, merge, publish,
10922
- // distribute, sublicense, and/or sell copies of the Software, and to permit
10923
- // persons to whom the Software is furnished to do so, subject to the
10924
- // following conditions:
10925
- //
10926
- // The above copyright notice and this permission notice shall be included
10927
- // in all copies or substantial portions of the Software.
10928
- //
10929
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10930
- // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
10931
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
10932
- // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
10933
- // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
10934
- // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
10935
- // USE OR OTHER DEALINGS IN THE SOFTWARE.
10936
-
10937
- // resolves . and .. elements in a path array with directory names there
10938
- // must be no slashes, empty elements, or device names (c:\) in the array
10939
- // (so also no leading and trailing slashes - it does not distinguish
10940
- // relative and absolute paths)
10941
- function normalizeArray(parts, allowAboveRoot) {
10942
- // if the path tries to go above the root, `up` ends up > 0
10943
- var up = 0;
10944
- for (var i = parts.length - 1; i >= 0; i--) {
10945
- var last = parts[i];
10946
- if (last === '.') {
10947
- parts.splice(i, 1);
10948
- } else if (last === '..') {
10949
- parts.splice(i, 1);
10950
- up++;
10951
- } else if (up) {
10952
- parts.splice(i, 1);
10953
- up--;
10954
- }
10955
- }
10956
-
10957
- // if the path is allowed to go above the root, restore leading ..s
10958
- if (allowAboveRoot) {
10959
- for (; up--; up) {
10960
- parts.unshift('..');
10961
- }
10962
- }
10963
-
10964
- return parts;
10965
- }
10966
-
10967
- // Split a filename into [root, dir, basename, ext], unix version
10968
- // 'root' is just a slash, or nothing.
10969
- var splitPathRe =
10970
- /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
10971
- var splitPath = function(filename) {
10972
- return splitPathRe.exec(filename).slice(1);
10973
- };
10974
-
10975
- // path.resolve([from ...], to)
10976
- // posix version
10977
- exports.resolve = function() {
10978
- var resolvedPath = '',
10979
- resolvedAbsolute = false;
10980
-
10981
- for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
10982
- var path = (i >= 0) ? arguments[i] : process.cwd();
10983
-
10984
- // Skip empty and invalid entries
10985
- if (typeof path !== 'string') {
10986
- throw new TypeError('Arguments to path.resolve must be strings');
10987
- } else if (!path) {
10988
- continue;
10989
- }
10990
-
10991
- resolvedPath = path + '/' + resolvedPath;
10992
- resolvedAbsolute = path.charAt(0) === '/';
10993
- }
10994
-
10995
- // At this point the path should be resolved to a full absolute path, but
10996
- // handle relative paths to be safe (might happen when process.cwd() fails)
10997
-
10998
- // Normalize the path
10999
- resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
11000
- return !!p;
11001
- }), !resolvedAbsolute).join('/');
11002
-
11003
- return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
11004
- };
11005
-
11006
- // path.normalize(path)
11007
- // posix version
11008
- exports.normalize = function(path) {
11009
- var isAbsolute = exports.isAbsolute(path),
11010
- trailingSlash = substr(path, -1) === '/';
11011
-
11012
- // Normalize the path
11013
- path = normalizeArray(filter(path.split('/'), function(p) {
11014
- return !!p;
11015
- }), !isAbsolute).join('/');
11016
-
11017
- if (!path && !isAbsolute) {
11018
- path = '.';
11019
- }
11020
- if (path && trailingSlash) {
11021
- path += '/';
11022
- }
11023
-
11024
- return (isAbsolute ? '/' : '') + path;
11025
- };
11026
-
11027
- // posix version
11028
- exports.isAbsolute = function(path) {
11029
- return path.charAt(0) === '/';
11030
- };
11031
-
11032
- // posix version
11033
- exports.join = function() {
11034
- var paths = Array.prototype.slice.call(arguments, 0);
11035
- return exports.normalize(filter(paths, function(p, index) {
11036
- if (typeof p !== 'string') {
11037
- throw new TypeError('Arguments to path.join must be strings');
11038
- }
11039
- return p;
11040
- }).join('/'));
11041
- };
11042
-
11043
-
11044
- // path.relative(from, to)
11045
- // posix version
11046
- exports.relative = function(from, to) {
11047
- from = exports.resolve(from).substr(1);
11048
- to = exports.resolve(to).substr(1);
11049
-
11050
- function trim(arr) {
11051
- var start = 0;
11052
- for (; start < arr.length; start++) {
11053
- if (arr[start] !== '') break;
11054
- }
11055
-
11056
- var end = arr.length - 1;
11057
- for (; end >= 0; end--) {
11058
- if (arr[end] !== '') break;
11059
- }
11060
-
11061
- if (start > end) return [];
11062
- return arr.slice(start, end - start + 1);
11063
- }
11064
-
11065
- var fromParts = trim(from.split('/'));
11066
- var toParts = trim(to.split('/'));
11067
-
11068
- var length = Math.min(fromParts.length, toParts.length);
11069
- var samePartsLength = length;
11070
- for (var i = 0; i < length; i++) {
11071
- if (fromParts[i] !== toParts[i]) {
11072
- samePartsLength = i;
11073
- break;
11074
- }
11075
- }
11076
-
11077
- var outputParts = [];
11078
- for (var i = samePartsLength; i < fromParts.length; i++) {
11079
- outputParts.push('..');
11080
- }
11081
-
11082
- outputParts = outputParts.concat(toParts.slice(samePartsLength));
11083
-
11084
- return outputParts.join('/');
11085
- };
11086
-
11087
- exports.sep = '/';
11088
- exports.delimiter = ':';
11089
-
11090
- exports.dirname = function(path) {
11091
- var result = splitPath(path),
11092
- root = result[0],
11093
- dir = result[1];
11094
-
11095
- if (!root && !dir) {
11096
- // No dirname whatsoever
11097
- return '.';
11098
- }
11099
-
11100
- if (dir) {
11101
- // It has a dirname, strip trailing slash
11102
- dir = dir.substr(0, dir.length - 1);
11103
- }
11104
-
11105
- return root + dir;
11106
- };
11107
-
11108
-
11109
- exports.basename = function(path, ext) {
11110
- var f = splitPath(path)[2];
11111
- // TODO: make this comparison case-insensitive on windows?
11112
- if (ext && f.substr(-1 * ext.length) === ext) {
11113
- f = f.substr(0, f.length - ext.length);
11114
- }
11115
- return f;
11116
- };
11117
-
11118
-
11119
- exports.extname = function(path) {
11120
- return splitPath(path)[3];
11121
- };
11122
-
11123
- function filter (xs, f) {
11124
- if (xs.filter) return xs.filter(f);
11125
- var res = [];
11126
- for (var i = 0; i < xs.length; i++) {
11127
- if (f(xs[i], i, xs)) res.push(xs[i]);
11128
- }
11129
- return res;
11130
- }
11131
-
11132
- // String.prototype.substr - negative index don't work in IE8
11133
- var substr = 'ab'.substr(-1) === 'b'
11134
- ? function (str, start, len) { return str.substr(start, len) }
11135
- : function (str, start, len) {
11136
- if (start < 0) start = str.length + start;
11137
- return str.substr(start, len);
11138
- }
11139
- ;
11140
-
11141
- }).call(this,require('_process'))
11142
- },{"_process":98}],98:[function(require,module,exports){
11143
- // shim for using process in browser
11144
-
11145
- var process = module.exports = {};
11146
-
11147
- // cached from whatever global is present so that test runners that stub it
11148
- // don't break things. But we need to wrap it in a try catch in case it is
11149
- // wrapped in strict mode code which doesn't define any globals. It's inside a
11150
- // function because try/catches deoptimize in certain engines.
11151
-
11152
- var cachedSetTimeout;
11153
- var cachedClearTimeout;
11154
-
11155
- (function () {
11156
- try {
11157
- cachedSetTimeout = setTimeout;
11158
- } catch (e) {
11159
- cachedSetTimeout = function () {
11160
- throw new Error('setTimeout is not defined');
11161
- }
11162
- }
11163
- try {
11164
- cachedClearTimeout = clearTimeout;
11165
- } catch (e) {
11166
- cachedClearTimeout = function () {
11167
- throw new Error('clearTimeout is not defined');
11168
- }
11169
- }
11170
- } ())
11171
- var queue = [];
11172
- var draining = false;
11173
- var currentQueue;
11174
- var queueIndex = -1;
11175
-
11176
- function cleanUpNextTick() {
11177
- if (!draining || !currentQueue) {
11178
- return;
11179
- }
11180
- draining = false;
11181
- if (currentQueue.length) {
11182
- queue = currentQueue.concat(queue);
11183
- } else {
11184
- queueIndex = -1;
11185
- }
11186
- if (queue.length) {
11187
- drainQueue();
11188
- }
11189
- }
11190
-
11191
- function drainQueue() {
11192
- if (draining) {
11193
- return;
11194
- }
11195
- var timeout = cachedSetTimeout(cleanUpNextTick);
11196
- draining = true;
11197
-
11198
- var len = queue.length;
11199
- while(len) {
11200
- currentQueue = queue;
11201
- queue = [];
11202
- while (++queueIndex < len) {
11203
- if (currentQueue) {
11204
- currentQueue[queueIndex].run();
11205
- }
11206
- }
11207
- queueIndex = -1;
11208
- len = queue.length;
11209
- }
11210
- currentQueue = null;
11211
- draining = false;
11212
- cachedClearTimeout(timeout);
11213
- }
11214
-
11215
- process.nextTick = function (fun) {
11216
- var args = new Array(arguments.length - 1);
11217
- if (arguments.length > 1) {
11218
- for (var i = 1; i < arguments.length; i++) {
11219
- args[i - 1] = arguments[i];
11220
- }
11221
- }
11222
- queue.push(new Item(fun, args));
11223
- if (queue.length === 1 && !draining) {
11224
- cachedSetTimeout(drainQueue, 0);
11225
- }
11226
- };
11227
-
11228
- // v8 likes predictible objects
11229
- function Item(fun, array) {
11230
- this.fun = fun;
11231
- this.array = array;
11232
- }
11233
- Item.prototype.run = function () {
11234
- this.fun.apply(null, this.array);
11235
- };
11236
- process.title = 'browser';
11237
- process.browser = true;
11238
- process.env = {};
11239
- process.argv = [];
11240
- process.version = ''; // empty string to avoid regexp issues
11241
- process.versions = {};
11242
-
11243
- function noop() {}
11244
-
11245
- process.on = noop;
11246
- process.addListener = noop;
11247
- process.once = noop;
11248
- process.off = noop;
11249
- process.removeListener = noop;
11250
- process.removeAllListeners = noop;
11251
- process.emit = noop;
11252
-
11253
- process.binding = function (name) {
11254
- throw new Error('process.binding is not supported');
11255
- };
11256
-
11257
- process.cwd = function () { return '/' };
11258
- process.chdir = function (dir) {
11259
- throw new Error('process.chdir is not supported');
11260
- };
11261
- process.umask = function() { return 0; };
11262
-
11263
- },{}],99:[function(require,module,exports){
11264
11352
  'use strict';
11265
11353
 
11266
11354
  var asap = require('asap/raw');
@@ -11319,17 +11407,17 @@ function Promise(fn) {
11319
11407
  throw new TypeError('Promises must be constructed via new');
11320
11408
  }
11321
11409
  if (typeof fn !== 'function') {
11322
- throw new TypeError('not a function');
11410
+ throw new TypeError('Promise constructor\'s argument is not a function');
11323
11411
  }
11324
- this._45 = 0;
11325
- this._81 = 0;
11326
- this._65 = null;
11327
- this._54 = null;
11412
+ this._40 = 0;
11413
+ this._65 = 0;
11414
+ this._55 = null;
11415
+ this._72 = null;
11328
11416
  if (fn === noop) return;
11329
11417
  doResolve(fn, this);
11330
11418
  }
11331
- Promise._10 = null;
11332
- Promise._97 = null;
11419
+ Promise._37 = null;
11420
+ Promise._87 = null;
11333
11421
  Promise._61 = noop;
11334
11422
 
11335
11423
  Promise.prototype.then = function(onFulfilled, onRejected) {
@@ -11347,26 +11435,26 @@ function safeThen(self, onFulfilled, onRejected) {
11347
11435
  res.then(resolve, reject);
11348
11436
  handle(self, new Handler(onFulfilled, onRejected, res));
11349
11437
  });
11350
- };
11438
+ }
11351
11439
  function handle(self, deferred) {
11352
- while (self._81 === 3) {
11353
- self = self._65;
11440
+ while (self._65 === 3) {
11441
+ self = self._55;
11354
11442
  }
11355
- if (Promise._10) {
11356
- Promise._10(self);
11443
+ if (Promise._37) {
11444
+ Promise._37(self);
11357
11445
  }
11358
- if (self._81 === 0) {
11359
- if (self._45 === 0) {
11360
- self._45 = 1;
11361
- self._54 = deferred;
11446
+ if (self._65 === 0) {
11447
+ if (self._40 === 0) {
11448
+ self._40 = 1;
11449
+ self._72 = deferred;
11362
11450
  return;
11363
11451
  }
11364
- if (self._45 === 1) {
11365
- self._45 = 2;
11366
- self._54 = [self._54, deferred];
11452
+ if (self._40 === 1) {
11453
+ self._40 = 2;
11454
+ self._72 = [self._72, deferred];
11367
11455
  return;
11368
11456
  }
11369
- self._54.push(deferred);
11457
+ self._72.push(deferred);
11370
11458
  return;
11371
11459
  }
11372
11460
  handleResolved(self, deferred);
@@ -11374,16 +11462,16 @@ function handle(self, deferred) {
11374
11462
 
11375
11463
  function handleResolved(self, deferred) {
11376
11464
  asap(function() {
11377
- var cb = self._81 === 1 ? deferred.onFulfilled : deferred.onRejected;
11465
+ var cb = self._65 === 1 ? deferred.onFulfilled : deferred.onRejected;
11378
11466
  if (cb === null) {
11379
- if (self._81 === 1) {
11380
- resolve(deferred.promise, self._65);
11467
+ if (self._65 === 1) {
11468
+ resolve(deferred.promise, self._55);
11381
11469
  } else {
11382
- reject(deferred.promise, self._65);
11470
+ reject(deferred.promise, self._55);
11383
11471
  }
11384
11472
  return;
11385
11473
  }
11386
- var ret = tryCallOne(cb, self._65);
11474
+ var ret = tryCallOne(cb, self._55);
11387
11475
  if (ret === IS_ERROR) {
11388
11476
  reject(deferred.promise, LAST_ERROR);
11389
11477
  } else {
@@ -11411,8 +11499,8 @@ function resolve(self, newValue) {
11411
11499
  then === self.then &&
11412
11500
  newValue instanceof Promise
11413
11501
  ) {
11414
- self._81 = 3;
11415
- self._65 = newValue;
11502
+ self._65 = 3;
11503
+ self._55 = newValue;
11416
11504
  finale(self);
11417
11505
  return;
11418
11506
  } else if (typeof then === 'function') {
@@ -11420,29 +11508,29 @@ function resolve(self, newValue) {
11420
11508
  return;
11421
11509
  }
11422
11510
  }
11423
- self._81 = 1;
11424
- self._65 = newValue;
11511
+ self._65 = 1;
11512
+ self._55 = newValue;
11425
11513
  finale(self);
11426
11514
  }
11427
11515
 
11428
11516
  function reject(self, newValue) {
11429
- self._81 = 2;
11430
- self._65 = newValue;
11431
- if (Promise._97) {
11432
- Promise._97(self, newValue);
11517
+ self._65 = 2;
11518
+ self._55 = newValue;
11519
+ if (Promise._87) {
11520
+ Promise._87(self, newValue);
11433
11521
  }
11434
11522
  finale(self);
11435
11523
  }
11436
11524
  function finale(self) {
11437
- if (self._45 === 1) {
11438
- handle(self, self._54);
11439
- self._54 = null;
11525
+ if (self._40 === 1) {
11526
+ handle(self, self._72);
11527
+ self._72 = null;
11440
11528
  }
11441
- if (self._45 === 2) {
11442
- for (var i = 0; i < self._54.length; i++) {
11443
- handle(self, self._54[i]);
11529
+ if (self._40 === 2) {
11530
+ for (var i = 0; i < self._72.length; i++) {
11531
+ handle(self, self._72[i]);
11444
11532
  }
11445
- self._54 = null;
11533
+ self._72 = null;
11446
11534
  }
11447
11535
  }
11448
11536
 
@@ -11468,14 +11556,14 @@ function doResolve(fn, promise) {
11468
11556
  if (done) return;
11469
11557
  done = true;
11470
11558
  reject(promise, reason);
11471
- })
11559
+ });
11472
11560
  if (!done && res === IS_ERROR) {
11473
11561
  done = true;
11474
11562
  reject(promise, LAST_ERROR);
11475
11563
  }
11476
11564
  }
11477
11565
 
11478
- },{"asap/raw":96}],100:[function(require,module,exports){
11566
+ },{"asap/raw":96}],98:[function(require,module,exports){
11479
11567
  'use strict';
11480
11568
 
11481
11569
  //This file contains the ES6 extensions to the core Promises/A+ API
@@ -11495,8 +11583,8 @@ var EMPTYSTRING = valuePromise('');
11495
11583
 
11496
11584
  function valuePromise(value) {
11497
11585
  var p = new Promise(Promise._61);
11498
- p._81 = 1;
11499
- p._65 = value;
11586
+ p._65 = 1;
11587
+ p._55 = value;
11500
11588
  return p;
11501
11589
  }
11502
11590
  Promise.resolve = function (value) {
@@ -11533,11 +11621,11 @@ Promise.all = function (arr) {
11533
11621
  function res(i, val) {
11534
11622
  if (val && (typeof val === 'object' || typeof val === 'function')) {
11535
11623
  if (val instanceof Promise && val.then === Promise.prototype.then) {
11536
- while (val._81 === 3) {
11537
- val = val._65;
11624
+ while (val._65 === 3) {
11625
+ val = val._55;
11538
11626
  }
11539
- if (val._81 === 1) return res(i, val._65);
11540
- if (val._81 === 2) reject(val._65);
11627
+ if (val._65 === 1) return res(i, val._55);
11628
+ if (val._65 === 2) reject(val._55);
11541
11629
  val.then(function (val) {
11542
11630
  res(i, val);
11543
11631
  }, reject);
@@ -11584,7 +11672,7 @@ Promise.prototype['catch'] = function (onRejected) {
11584
11672
  return this.then(null, onRejected);
11585
11673
  };
11586
11674
 
11587
- },{"./core.js":99}],101:[function(require,module,exports){
11675
+ },{"./core.js":97}],99:[function(require,module,exports){
11588
11676
  // should work in any browser without browserify
11589
11677
 
11590
11678
  if (typeof Promise.prototype.done !== 'function') {
@@ -11597,7 +11685,7 @@ if (typeof Promise.prototype.done !== 'function') {
11597
11685
  })
11598
11686
  }
11599
11687
  }
11600
- },{}],102:[function(require,module,exports){
11688
+ },{}],100:[function(require,module,exports){
11601
11689
  // not "use strict" so we can declare global "Promise"
11602
11690
 
11603
11691
  var asap = require('asap');
@@ -11609,5 +11697,5 @@ if (typeof Promise === 'undefined') {
11609
11697
 
11610
11698
  require('./polyfill-done.js');
11611
11699
 
11612
- },{"./lib/core.js":99,"./lib/es6-extensions.js":100,"./polyfill-done.js":101,"asap":95}]},{},[2])(2)
11700
+ },{"./lib/core.js":97,"./lib/es6-extensions.js":98,"./polyfill-done.js":99,"asap":95}]},{},[2])(2)
11613
11701
  });