less 2.1.2 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/.idea/inspectionProfiles/Project_Default.xml +1 -0
  2. package/.idea/jsLinters/jscs.xml +4 -0
  3. package/.idea/jsLinters/jshint.xml +58 -4
  4. package/.idea/workspace.xml +499 -760
  5. package/.jscsrc +73 -0
  6. package/.jshintrc +0 -2
  7. package/.travis.yml +1 -0
  8. package/CHANGELOG.md +59 -0
  9. package/Gruntfile.js +37 -3
  10. package/appveyor.yml +5 -0
  11. package/bin/lessc +383 -316
  12. package/bower.json +1 -1
  13. package/dist/less.js +1638 -1244
  14. package/dist/less.min.js +7 -7
  15. package/lib/less/contexts.js +3 -3
  16. package/lib/less/data/unit-conversions.js +3 -3
  17. package/lib/less/environment/abstract-file-manager.js +8 -8
  18. package/lib/less/environment/environment.js +2 -2
  19. package/lib/less/functions/color-blending.js +3 -3
  20. package/lib/less/functions/color.js +20 -12
  21. package/lib/less/functions/data-uri.js +26 -18
  22. package/lib/less/functions/math.js +1 -1
  23. package/lib/less/functions/number.js +2 -2
  24. package/lib/less/functions/string.js +3 -1
  25. package/lib/less/functions/svg.js +12 -15
  26. package/lib/less/functions/types.js +33 -10
  27. package/lib/less/import-manager.js +14 -9
  28. package/lib/less/index.js +2 -1
  29. package/lib/less/less-error.js +1 -1
  30. package/lib/less/logger.js +2 -2
  31. package/lib/less/parse-tree.js +48 -42
  32. package/lib/less/parse.js +68 -0
  33. package/lib/less/parser/parser-input.js +6 -5
  34. package/lib/less/parser/parser.js +76 -29
  35. package/lib/less/plugin-manager.js +30 -3
  36. package/lib/less/render.js +11 -37
  37. package/lib/less/source-map-builder.js +4 -0
  38. package/lib/less/source-map-output.js +6 -6
  39. package/lib/less/transform-tree.js +4 -4
  40. package/lib/less/tree/anonymous.js +1 -1
  41. package/lib/less/tree/assignment.js +0 -1
  42. package/lib/less/tree/call.js +1 -1
  43. package/lib/less/tree/color.js +6 -6
  44. package/lib/less/tree/condition.js +9 -5
  45. package/lib/less/tree/debug-info.js +6 -2
  46. package/lib/less/tree/dimension.js +5 -5
  47. package/lib/less/tree/directive.js +25 -6
  48. package/lib/less/tree/element.js +1 -1
  49. package/lib/less/tree/expression.js +2 -2
  50. package/lib/less/tree/extend.js +3 -3
  51. package/lib/less/tree/import.js +2 -2
  52. package/lib/less/tree/index.js +1 -0
  53. package/lib/less/tree/javascript.js +2 -2
  54. package/lib/less/tree/media.js +20 -19
  55. package/lib/less/tree/mixin-call.js +5 -6
  56. package/lib/less/tree/mixin-definition.js +33 -11
  57. package/lib/less/tree/quoted.js +3 -3
  58. package/lib/less/tree/rule.js +3 -4
  59. package/lib/less/tree/ruleset.js +290 -177
  60. package/lib/less/tree/selector.js +3 -2
  61. package/lib/less/tree/unit.js +2 -0
  62. package/lib/less/tree/url.js +5 -2
  63. package/lib/less/tree/value.js +2 -2
  64. package/lib/less/tree/variable.js +1 -1
  65. package/lib/less/visitors/extend-visitor.js +72 -36
  66. package/lib/less/visitors/import-sequencer.js +20 -14
  67. package/lib/less/visitors/import-visitor.js +15 -12
  68. package/lib/less/visitors/to-css-visitor.js +41 -9
  69. package/lib/less-browser/add-default-options.js +5 -1
  70. package/lib/less-browser/bootstrap.js +10 -8
  71. package/lib/less-browser/cache.js +3 -3
  72. package/lib/less-browser/file-manager.js +96 -96
  73. package/lib/less-browser/index.js +206 -205
  74. package/lib/less-browser/log-listener.js +2 -2
  75. package/lib/less-browser/utils.js +6 -6
  76. package/lib/less-node/file-manager.js +58 -30
  77. package/lib/less-node/image-size.js +34 -0
  78. package/lib/less-node/index.js +6 -3
  79. package/lib/less-node/lessc-helper.js +3 -2
  80. package/lib/less-node/plugin-loader.js +3 -3
  81. package/lib/less-node/url-file-manager.js +6 -3
  82. package/lib/less-rhino/index.js +15 -13
  83. package/lib/source-map/source-map-0.1.31.js +1 -1
  84. package/package.json +10 -7
  85. package/test/browser/common.js +13 -11
  86. package/test/browser/css/relative-urls/urls.css +1 -0
  87. package/test/browser/css/urls.css +6 -3
  88. package/test/browser/jasmine-jsreporter.js +2 -3
  89. package/test/browser/less/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  90. package/test/browser/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  91. package/test/browser/less/relative-urls/urls.less +1 -0
  92. package/test/browser/less/urls.less +1 -0
  93. package/test/browser/runner-browser-options.js +23 -23
  94. package/test/browser/runner-errors-options.js +0 -1
  95. package/test/browser/runner-errors-spec.js +1 -2
  96. package/test/browser/runner-global-vars-spec.js +1 -1
  97. package/test/browser/runner-legacy-options.js +0 -1
  98. package/test/browser/runner-main-options.js +5 -5
  99. package/test/browser/runner-main-spec.js +1 -1
  100. package/test/browser/runner-no-js-errors-spec.js +0 -1
  101. package/test/browser/runner-production-options.js +0 -1
  102. package/test/browser/runner-relative-urls-options.js +0 -1
  103. package/test/browser/runner-rootpath-options.js +0 -1
  104. package/test/browser/runner-rootpath-relative-options.js +0 -1
  105. package/test/browser/runner-strict-units-options.js +0 -1
  106. package/test/copy-bom.js +72 -0
  107. package/test/css/comments.css +1 -0
  108. package/test/css/css-3.css +2 -0
  109. package/test/css/functions.css +10 -0
  110. package/test/css/import-interpolation.css +7 -0
  111. package/test/css/import-reference.css +25 -0
  112. package/test/css/include-path/include-path.css +6 -0
  113. package/test/css/mixins-important.css +12 -0
  114. package/test/css/selectors.css +15 -1
  115. package/test/css/static-urls/urls.css +1 -0
  116. package/test/css/url-args/urls.css +3 -3
  117. package/test/css/urls.css +13 -4
  118. package/test/css/variables.css +7 -1
  119. package/test/data/image.svg +3 -0
  120. package/test/index.js +15 -10
  121. package/test/less/comments.less +1 -0
  122. package/test/less/css-3.less +3 -0
  123. package/test/less/css-guards.less +2 -1
  124. package/test/less/errors/detached-ruleset-2.txt +1 -1
  125. package/test/less/errors/import-missing.txt +1 -1
  126. package/test/less/errors/parens-error-1.txt +1 -1
  127. package/test/less/errors/parens-error-2.txt +1 -1
  128. package/test/less/errors/parens-error-3.txt +1 -1
  129. package/test/less/errors/single-character.less +1 -0
  130. package/test/less/errors/single-character.txt +2 -0
  131. package/test/less/functions.less +18 -0
  132. package/test/less/import/import-interpolation.less +1 -0
  133. package/test/less/import/import-reference.less +38 -0
  134. package/test/less/import/imports/logo.less +1 -0
  135. package/test/less/import-reference.less +3 -1
  136. package/test/less/import.less +2 -0
  137. package/test/less/include-path/include-path.less +6 -0
  138. package/test/less/mixins-important.less +28 -0
  139. package/test/less/nested-gradient-with-svg-gradient/mixin-consumer.less +5 -0
  140. package/test/less/nested-gradient-with-svg-gradient/svg-gradient-mixin.less +15 -0
  141. package/test/less/selectors.less +29 -4
  142. package/test/less/sourcemaps-empty/empty.less +0 -0
  143. package/test/less/sourcemaps-empty/var-defs.less +1 -0
  144. package/test/less/urls.less +10 -1
  145. package/test/less/variables.less +17 -3
  146. package/test/less-test.js +133 -52
  147. package/test/modify-vars.js +14 -12
  148. package/test/browser/less.js +0 -9473
package/dist/less.js CHANGED
@@ -1,8 +1,8 @@
1
1
  /*!
2
- * Less - Leaner CSS v2.1.2
2
+ * Less - Leaner CSS v2.4.0
3
3
  * http://lesscss.org
4
4
  *
5
- * Copyright (c) 2009-2014, Alexis Sellier <self@cloudhead.net>
5
+ * Copyright (c) 2009-2015, Alexis Sellier <self@cloudhead.net>
6
6
  * Licensed under the Apache v2 License.
7
7
  *
8
8
  */
@@ -20,7 +20,7 @@ module.exports = function(window, options) {
20
20
  addDataAttr(options, browser.currentScript(window));
21
21
 
22
22
  if (options.isFileProtocol === undefined) {
23
- options.isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(window.location.protocol);
23
+ options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
24
24
  }
25
25
 
26
26
  // Load styles asynchronously (default: false)
@@ -52,6 +52,10 @@ module.exports = function(window, options) {
52
52
  options.useFileCache = true;
53
53
  }
54
54
 
55
+ if (options.onReady === undefined) {
56
+ options.onReady = true;
57
+ }
58
+
55
59
  };
56
60
 
57
61
  },{"./browser":3,"./utils":9}],2:[function(require,module,exports){
@@ -70,17 +74,18 @@ require("./add-default-options")(window, options);
70
74
 
71
75
  var less = module.exports = require("./index")(window, options);
72
76
 
73
- if (/!watch/.test(window.location.hash)) {
74
- less.watch();
75
- }
76
-
77
- less.pageLoadFinished = less.registerStylesheets().then(
78
- function () {
79
- return less.refresh(less.env === 'development');
77
+ if (options.onReady) {
78
+ if (/!watch/.test(window.location.hash)) {
79
+ less.watch();
80
80
  }
81
- );
82
81
 
83
- },{"./add-default-options":1,"./index":7,"promise/polyfill.js":undefined}],3:[function(require,module,exports){
82
+ less.pageLoadFinished = less.registerStylesheets().then(
83
+ function () {
84
+ return less.refresh(less.env === 'development');
85
+ }
86
+ );
87
+ }
88
+ },{"./add-default-options":1,"./index":7,"promise/polyfill.js":"promise/polyfill.js"}],3:[function(require,module,exports){
84
89
  var utils = require("./utils");
85
90
  module.exports = {
86
91
  createCSS: function (document, styles, sheet) {
@@ -153,19 +158,19 @@ module.exports = function(window, options, logger) {
153
158
  var cache = null;
154
159
  if (options.env !== 'development') {
155
160
  try {
156
- cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
161
+ cache = (typeof window.localStorage === 'undefined') ? null : window.localStorage;
157
162
  } catch (_) {}
158
163
  }
159
164
  return {
160
165
  setCSS: function(path, lastModified, styles) {
161
166
  if (cache) {
162
- logger.info('saving ' + path+ ' to cache.');
167
+ logger.info('saving ' + path + ' to cache.');
163
168
  try {
164
169
  cache.setItem(path, styles);
165
170
  cache.setItem(path + ':timestamp', lastModified);
166
171
  } catch(e) {
167
172
  //TODO - could do with adding more robust error handling
168
- logger.error('failed to save');
173
+ logger.error('failed to save "' + path + '" to local storage for caching.');
169
174
  }
170
175
  }
171
176
  },
@@ -360,120 +365,120 @@ module.exports = function(window, less, options) {
360
365
 
361
366
  module.exports = function(options, logger) {
362
367
 
363
- var AbstractFileManager = require("../less/environment/abstract-file-manager.js");
368
+ var AbstractFileManager = require("../less/environment/abstract-file-manager.js");
364
369
 
365
- var fileCache = {};
370
+ var fileCache = {};
366
371
 
367
- //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
372
+ //TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
368
373
 
369
- function getXMLHttpRequest() {
370
- if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
371
- return new XMLHttpRequest();
372
- } else {
373
- try {
374
- /*global ActiveXObject */
375
- return new ActiveXObject("Microsoft.XMLHTTP");
376
- } catch (e) {
377
- logger.error("browser doesn't support AJAX.");
378
- return null;
374
+ function getXMLHttpRequest() {
375
+ if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
376
+ return new XMLHttpRequest();
377
+ } else {
378
+ try {
379
+ /*global ActiveXObject */
380
+ return new ActiveXObject("Microsoft.XMLHTTP");
381
+ } catch (e) {
382
+ logger.error("browser doesn't support AJAX.");
383
+ return null;
384
+ }
379
385
  }
380
386
  }
381
- }
382
387
 
383
- var FileManager = function() {
384
- };
388
+ var FileManager = function() {
389
+ };
385
390
 
386
- FileManager.prototype = new AbstractFileManager();
391
+ FileManager.prototype = new AbstractFileManager();
387
392
 
388
- FileManager.prototype.alwaysMakePathsAbsolute = function alwaysMakePathsAbsolute() {
389
- return true;
390
- };
391
- FileManager.prototype.join = function join(basePath, laterPath) {
392
- if (!basePath) {
393
- return laterPath;
394
- }
395
- return this.extractUrlParts(laterPath, basePath).path;
396
- };
397
- FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
393
+ FileManager.prototype.alwaysMakePathsAbsolute = function alwaysMakePathsAbsolute() {
394
+ return true;
395
+ };
396
+ FileManager.prototype.join = function join(basePath, laterPath) {
397
+ if (!basePath) {
398
+ return laterPath;
399
+ }
400
+ return this.extractUrlParts(laterPath, basePath).path;
401
+ };
402
+ FileManager.prototype.doXHR = function doXHR(url, type, callback, errback) {
398
403
 
399
- var xhr = getXMLHttpRequest();
400
- var async = options.isFileProtocol ? options.fileAsync : options.async;
404
+ var xhr = getXMLHttpRequest();
405
+ var async = options.isFileProtocol ? options.fileAsync : options.async;
401
406
 
402
- if (typeof(xhr.overrideMimeType) === 'function') {
403
- xhr.overrideMimeType('text/css');
404
- }
405
- logger.debug("XHR: Getting '" + url + "'");
406
- xhr.open('GET', url, async);
407
- xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
408
- xhr.send(null);
407
+ if (typeof xhr.overrideMimeType === 'function') {
408
+ xhr.overrideMimeType('text/css');
409
+ }
410
+ logger.debug("XHR: Getting '" + url + "'");
411
+ xhr.open('GET', url, async);
412
+ xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
413
+ xhr.send(null);
409
414
 
410
- function handleResponse(xhr, callback, errback) {
411
- if (xhr.status >= 200 && xhr.status < 300) {
412
- callback(xhr.responseText,
413
- xhr.getResponseHeader("Last-Modified"));
414
- } else if (typeof(errback) === 'function') {
415
- errback(xhr.status, url);
415
+ function handleResponse(xhr, callback, errback) {
416
+ if (xhr.status >= 200 && xhr.status < 300) {
417
+ callback(xhr.responseText,
418
+ xhr.getResponseHeader("Last-Modified"));
419
+ } else if (typeof errback === 'function') {
420
+ errback(xhr.status, url);
421
+ }
416
422
  }
417
- }
418
423
 
419
- if (options.isFileProtocol && !options.fileAsync) {
420
- if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
421
- callback(xhr.responseText);
424
+ if (options.isFileProtocol && !options.fileAsync) {
425
+ if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
426
+ callback(xhr.responseText);
427
+ } else {
428
+ errback(xhr.status, url);
429
+ }
430
+ } else if (async) {
431
+ xhr.onreadystatechange = function () {
432
+ if (xhr.readyState == 4) {
433
+ handleResponse(xhr, callback, errback);
434
+ }
435
+ };
422
436
  } else {
423
- errback(xhr.status, url);
437
+ handleResponse(xhr, callback, errback);
424
438
  }
425
- } else if (async) {
426
- xhr.onreadystatechange = function () {
427
- if (xhr.readyState == 4) {
428
- handleResponse(xhr, callback, errback);
429
- }
430
- };
431
- } else {
432
- handleResponse(xhr, callback, errback);
433
- }
434
- };
435
- FileManager.prototype.supports = function(filename, currentDirectory, options, environment) {
436
- return true;
437
- };
439
+ };
440
+ FileManager.prototype.supports = function(filename, currentDirectory, options, environment) {
441
+ return true;
442
+ };
438
443
 
439
- FileManager.prototype.clearFileCache = function() {
440
- fileCache = {};
441
- };
444
+ FileManager.prototype.clearFileCache = function() {
445
+ fileCache = {};
446
+ };
442
447
 
443
- FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
444
- if (currentDirectory && !this.isPathAbsolute(filename)) {
445
- filename = currentDirectory + filename;
446
- }
448
+ FileManager.prototype.loadFile = function loadFile(filename, currentDirectory, options, environment, callback) {
449
+ if (currentDirectory && !this.isPathAbsolute(filename)) {
450
+ filename = currentDirectory + filename;
451
+ }
447
452
 
448
- options = options || {};
453
+ options = options || {};
449
454
 
450
- // sheet may be set to the stylesheet for the initial load or a collection of properties including
451
- // some context variables for imports
452
- var hrefParts = this.extractUrlParts(filename, window.location.href);
453
- var href = hrefParts.url;
455
+ // sheet may be set to the stylesheet for the initial load or a collection of properties including
456
+ // some context variables for imports
457
+ var hrefParts = this.extractUrlParts(filename, window.location.href);
458
+ var href = hrefParts.url;
454
459
 
455
- if (options.useFileCache && fileCache[href]) {
456
- try {
457
- var lessText = fileCache[href];
458
- callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
459
- } catch (e) {
460
- callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
460
+ if (options.useFileCache && fileCache[href]) {
461
+ try {
462
+ var lessText = fileCache[href];
463
+ callback(null, { contents: lessText, filename: href, webInfo: { lastModified: new Date() }});
464
+ } catch (e) {
465
+ callback({filename: href, message: "Error loading file " + href + " error was " + e.message});
466
+ }
467
+ return;
461
468
  }
462
- return;
463
- }
464
469
 
465
- this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
466
- // per file cache
467
- fileCache[href] = data;
470
+ this.doXHR(href, options.mime, function doXHRCallback(data, lastModified) {
471
+ // per file cache
472
+ fileCache[href] = data;
468
473
 
469
- // Use remote copy (re-parse)
470
- callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
471
- }, function doXHRError(status, url) {
472
- callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
473
- });
474
- };
474
+ // Use remote copy (re-parse)
475
+ callback(null, { contents: data, filename: href, webInfo: { lastModified: lastModified }});
476
+ }, function doXHRError(status, url) {
477
+ callback({ type: 'File', message: "'" + url + "' wasn't found (" + status + ")", href: href });
478
+ });
479
+ };
475
480
 
476
- return FileManager;
481
+ return FileManager;
477
482
  };
478
483
 
479
484
  },{"../less/environment/abstract-file-manager.js":14}],7:[function(require,module,exports){
@@ -485,251 +490,252 @@ var addDataAttr = require("./utils").addDataAttr,
485
490
  browser = require("./browser");
486
491
 
487
492
  module.exports = function(window, options) {
488
- var document = window.document;
489
- var less = require('../less')();
490
- module.exports = less;
491
- less.options = options;
492
- var environment = less.environment,
493
- FileManager = require("./file-manager")(options, less.logger),
494
- fileManager = new FileManager();
495
- environment.addFileManager(fileManager);
496
- less.FileManager = FileManager;
497
-
498
- require("./log-listener")(less, options);
499
- var errors = require("./error-reporting")(window, less, options);
500
- var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
501
-
502
- //Setup user functions
503
- if (options.functions) {
504
- less.functions.functionRegistry.addMultiple(options.functions);
505
- }
493
+ var document = window.document;
494
+ var less = require('../less')();
495
+ //module.exports = less;
496
+ less.options = options;
497
+ var environment = less.environment,
498
+ FileManager = require("./file-manager")(options, less.logger),
499
+ fileManager = new FileManager();
500
+ environment.addFileManager(fileManager);
501
+ less.FileManager = FileManager;
506
502
 
507
- var typePattern = /^text\/(x-)?less$/;
503
+ require("./log-listener")(less, options);
504
+ var errors = require("./error-reporting")(window, less, options);
505
+ var cache = less.cache = options.cache || require("./cache")(window, options, less.logger);
508
506
 
509
- function postProcessCSS(styles) {
510
- if (options.postProcessor && typeof options.postProcessor === 'function') {
511
- styles = options.postProcessor.call(styles, styles) || styles;
507
+ //Setup user functions
508
+ if (options.functions) {
509
+ less.functions.functionRegistry.addMultiple(options.functions);
512
510
  }
513
- return styles;
514
- }
515
511
 
516
- function clone(obj) {
517
- var cloned = {};
518
- for(var prop in obj) {
519
- if (obj.hasOwnProperty(prop)) {
520
- cloned[prop] = obj[prop];
512
+ var typePattern = /^text\/(x-)?less$/;
513
+
514
+ function postProcessCSS(styles) {
515
+ if (options.postProcessor && typeof options.postProcessor === 'function') {
516
+ styles = options.postProcessor.call(styles, styles) || styles;
521
517
  }
518
+ return styles;
522
519
  }
523
- return cloned;
524
- }
525
-
526
- // only really needed for phantom
527
- function bind(func, thisArg) {
528
- var curryArgs = Array.prototype.slice.call(arguments, 2);
529
- return function() {
530
- var args = curryArgs.concat(Array.prototype.slice.call(arguments, 0));
531
- return func.apply(thisArg, args);
532
- };
533
- }
534
520
 
535
- function loadStyles(modifyVars) {
536
- var styles = document.getElementsByTagName('style'),
537
- style;
521
+ function clone(obj) {
522
+ var cloned = {};
523
+ for (var prop in obj) {
524
+ if (obj.hasOwnProperty(prop)) {
525
+ cloned[prop] = obj[prop];
526
+ }
527
+ }
528
+ return cloned;
529
+ }
538
530
 
539
- for (var i = 0; i < styles.length; i++) {
540
- style = styles[i];
541
- if (style.type.match(typePattern)) {
542
- var instanceOptions = clone(options);
543
- instanceOptions.modifyVars = modifyVars;
544
- var lessText = style.innerHTML || '';
545
- instanceOptions.filename = document.location.href.replace(/#.*$/, '');
531
+ // only really needed for phantom
532
+ function bind(func, thisArg) {
533
+ var curryArgs = Array.prototype.slice.call(arguments, 2);
534
+ return function() {
535
+ var args = curryArgs.concat(Array.prototype.slice.call(arguments, 0));
536
+ return func.apply(thisArg, args);
537
+ };
538
+ }
546
539
 
547
- /*jshint loopfunc:true */
548
- // use closure to store current style
549
- less.render(lessText, instanceOptions,
550
- bind(function(style, e, result) {
551
- if (e) {
552
- errors.add(e, "inline");
553
- } else {
554
- style.type = 'text/css';
555
- if (style.styleSheet) {
556
- style.styleSheet.cssText = result.css;
540
+ function loadStyles(modifyVars) {
541
+ var styles = document.getElementsByTagName('style'),
542
+ style;
543
+
544
+ for (var i = 0; i < styles.length; i++) {
545
+ style = styles[i];
546
+ if (style.type.match(typePattern)) {
547
+ var instanceOptions = clone(options);
548
+ instanceOptions.modifyVars = modifyVars;
549
+ var lessText = style.innerHTML || '';
550
+ instanceOptions.filename = document.location.href.replace(/#.*$/, '');
551
+
552
+ /*jshint loopfunc:true */
553
+ // use closure to store current style
554
+ less.render(lessText, instanceOptions,
555
+ bind(function(style, e, result) {
556
+ if (e) {
557
+ errors.add(e, "inline");
557
558
  } else {
558
- style.innerHTML = result.css;
559
+ style.type = 'text/css';
560
+ if (style.styleSheet) {
561
+ style.styleSheet.cssText = result.css;
562
+ } else {
563
+ style.innerHTML = result.css;
564
+ }
559
565
  }
560
- }
561
- }, null, style));
566
+ }, null, style));
567
+ }
562
568
  }
563
569
  }
564
- }
565
570
 
566
- function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
571
+ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
567
572
 
568
- var instanceOptions = clone(options);
569
- addDataAttr(instanceOptions, sheet);
570
- instanceOptions.mime = sheet.type;
573
+ var instanceOptions = clone(options);
574
+ addDataAttr(instanceOptions, sheet);
575
+ instanceOptions.mime = sheet.type;
571
576
 
572
- if (modifyVars) {
573
- instanceOptions.modifyVars = modifyVars;
574
- }
577
+ if (modifyVars) {
578
+ instanceOptions.modifyVars = modifyVars;
579
+ }
575
580
 
576
- function loadInitialFileCallback(loadedFile) {
581
+ function loadInitialFileCallback(loadedFile) {
577
582
 
578
- var data = loadedFile.contents,
579
- path = loadedFile.filename,
580
- webInfo = loadedFile.webInfo;
583
+ var data = loadedFile.contents,
584
+ path = loadedFile.filename,
585
+ webInfo = loadedFile.webInfo;
581
586
 
582
- var newFileInfo = {
583
- currentDirectory: fileManager.getPath(path),
584
- filename: path,
585
- rootFilename: path,
586
- relativeUrls: instanceOptions.relativeUrls};
587
+ var newFileInfo = {
588
+ currentDirectory: fileManager.getPath(path),
589
+ filename: path,
590
+ rootFilename: path,
591
+ relativeUrls: instanceOptions.relativeUrls};
587
592
 
588
- newFileInfo.entryPath = newFileInfo.currentDirectory;
589
- newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
593
+ newFileInfo.entryPath = newFileInfo.currentDirectory;
594
+ newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
590
595
 
591
- if (webInfo) {
592
- webInfo.remaining = remaining;
596
+ if (webInfo) {
597
+ webInfo.remaining = remaining;
593
598
 
594
- var css = cache.getCSS(path, webInfo);
595
- if (!reload && css) {
596
- browser.createCSS(window.document, css, sheet);
597
- webInfo.local = true;
598
- callback(null, null, data, sheet, webInfo, path);
599
- return;
599
+ if (!instanceOptions.modifyVars) {
600
+ var css = cache.getCSS(path, webInfo);
601
+ if (!reload && css) {
602
+ webInfo.local = true;
603
+ callback(null, css, data, sheet, webInfo, path);
604
+ return;
605
+ }
606
+ }
600
607
  }
601
- }
602
608
 
603
- //TODO add tests around how this behaves when reloading
604
- errors.remove(path);
609
+ //TODO add tests around how this behaves when reloading
610
+ errors.remove(path);
611
+
612
+ instanceOptions.rootFileInfo = newFileInfo;
613
+ less.render(data, instanceOptions, function(e, result) {
614
+ if (e) {
615
+ e.href = path;
616
+ callback(e);
617
+ } else {
618
+ result.css = postProcessCSS(result.css);
619
+ if (!instanceOptions.modifyVars) {
620
+ cache.setCSS(sheet.href, webInfo.lastModified, result.css);
621
+ }
622
+ callback(null, result.css, data, sheet, webInfo, path);
623
+ }
624
+ });
625
+ }
605
626
 
606
- instanceOptions.rootFileInfo = newFileInfo;
607
- less.render(data, instanceOptions, function(e, result) {
627
+ fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
608
628
  if (e) {
609
- e.href = path;
610
629
  callback(e);
611
- } else {
612
- callback(null, result.css, data, sheet, webInfo, path);
630
+ return;
613
631
  }
632
+ loadInitialFileCallback(loadedFile);
614
633
  });
615
634
  }
616
635
 
617
- fileManager.loadFile(sheet.href, null, instanceOptions, environment, function(e, loadedFile) {
618
- if (e) {
619
- callback(e);
620
- return;
636
+ function loadStyleSheets(callback, reload, modifyVars) {
637
+ for (var i = 0; i < less.sheets.length; i++) {
638
+ loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
621
639
  }
622
- loadInitialFileCallback(loadedFile);
623
- });
624
- }
625
-
626
- function loadStyleSheets(callback, reload, modifyVars) {
627
- for (var i = 0; i < less.sheets.length; i++) {
628
- loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1), modifyVars);
629
- }
630
- }
631
-
632
- function initRunningMode(){
633
- if (less.env === 'development') {
634
- less.watchTimer = setInterval(function () {
635
- if (less.watchMode) {
636
- fileManager.clearFileCache();
637
- loadStyleSheets(function (e, css, _, sheet, context) {
638
- if (e) {
639
- errors.add(e, e.href || sheet.href);
640
- } else if (css) {
641
- css = postProcessCSS(css);
642
- browser.createCSS(window.document, css, sheet);
643
- cache.setCSS(sheet.href, context.lastModified, css);
644
- }
645
- });
646
- }
647
- }, options.poll);
648
640
  }
649
- }
650
641
 
651
- //
652
- // Watch mode
653
- //
654
- less.watch = function () {
655
- if (!less.watchMode ){
656
- less.env = 'development';
657
- initRunningMode();
642
+ function initRunningMode() {
643
+ if (less.env === 'development') {
644
+ less.watchTimer = setInterval(function () {
645
+ if (less.watchMode) {
646
+ fileManager.clearFileCache();
647
+ loadStyleSheets(function (e, css, _, sheet, webInfo) {
648
+ if (e) {
649
+ errors.add(e, e.href || sheet.href);
650
+ } else if (css) {
651
+ browser.createCSS(window.document, css, sheet);
652
+ }
653
+ });
654
+ }
655
+ }, options.poll);
656
+ }
658
657
  }
659
- this.watchMode = true;
660
- return true;
661
- };
662
658
 
663
- less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
659
+ //
660
+ // Watch mode
661
+ //
662
+ less.watch = function () {
663
+ if (!less.watchMode ) {
664
+ less.env = 'development';
665
+ initRunningMode();
666
+ }
667
+ this.watchMode = true;
668
+ return true;
669
+ };
664
670
 
665
- //
666
- // Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
667
- //
668
- less.registerStylesheets = function() {
669
- return new Promise(function(resolve, reject) {
670
- var links = document.getElementsByTagName('link');
671
- less.sheets = [];
671
+ less.unwatch = function () {clearInterval(less.watchTimer); this.watchMode = false; return false; };
672
672
 
673
- for (var i = 0; i < links.length; i++) {
674
- if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
675
- (links[i].type.match(typePattern)))) {
676
- less.sheets.push(links[i]);
673
+ //
674
+ // Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
675
+ //
676
+ less.registerStylesheets = function() {
677
+ return new Promise(function(resolve, reject) {
678
+ var links = document.getElementsByTagName('link');
679
+ less.sheets = [];
680
+
681
+ for (var i = 0; i < links.length; i++) {
682
+ if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
683
+ (links[i].type.match(typePattern)))) {
684
+ less.sheets.push(links[i]);
685
+ }
677
686
  }
678
- }
679
687
 
680
- resolve();
681
- });
682
- };
688
+ resolve();
689
+ });
690
+ };
683
691
 
684
- //
685
- // With this function, it's possible to alter variables and re-render
686
- // CSS without reloading less-files
687
- //
688
- less.modifyVars = function(record) {
689
- return less.refresh(true, record, false);
690
- };
692
+ //
693
+ // With this function, it's possible to alter variables and re-render
694
+ // CSS without reloading less-files
695
+ //
696
+ less.modifyVars = function(record) {
697
+ return less.refresh(true, record, false);
698
+ };
691
699
 
692
- less.refresh = function (reload, modifyVars, clearFileCache) {
693
- if ((reload || clearFileCache) && clearFileCache !== false) {
694
- fileManager.clearFileCache();
695
- }
696
- return new Promise(function (resolve, reject) {
697
- var startTime, endTime, totalMilliseconds;
698
- startTime = endTime = new Date();
700
+ less.refresh = function (reload, modifyVars, clearFileCache) {
701
+ if ((reload || clearFileCache) && clearFileCache !== false) {
702
+ fileManager.clearFileCache();
703
+ }
704
+ return new Promise(function (resolve, reject) {
705
+ var startTime, endTime, totalMilliseconds;
706
+ startTime = endTime = new Date();
699
707
 
700
- loadStyleSheets(function (e, css, _, sheet, webInfo) {
701
- if (e) {
702
- errors.add(e, e.href || sheet.href);
703
- reject(e);
704
- return;
705
- }
706
- if (webInfo.local) {
707
- less.logger.info("loading " + sheet.href + " from cache.");
708
- } else {
709
- less.logger.info("rendered " + sheet.href + " successfully.");
710
- css = postProcessCSS(css);
708
+ loadStyleSheets(function (e, css, _, sheet, webInfo) {
709
+ if (e) {
710
+ errors.add(e, e.href || sheet.href);
711
+ reject(e);
712
+ return;
713
+ }
714
+ if (webInfo.local) {
715
+ less.logger.info("loading " + sheet.href + " from cache.");
716
+ } else {
717
+ less.logger.info("rendered " + sheet.href + " successfully.");
718
+ }
711
719
  browser.createCSS(window.document, css, sheet);
712
- cache.setCSS(sheet.href, webInfo.lastModified, css);
713
- }
714
- less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
715
- if (webInfo.remaining === 0) {
716
- totalMilliseconds = new Date() - startTime;
717
- less.logger.info("less has finished. css generated in " + totalMilliseconds + 'ms');
718
- resolve({
719
- startTime: startTime,
720
- endTime: endTime,
721
- totalMilliseconds: totalMilliseconds,
722
- sheets: less.sheets.length
723
- });
724
- }
725
- endTime = new Date();
726
- }, reload, modifyVars);
720
+ less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
721
+ if (webInfo.remaining === 0) {
722
+ totalMilliseconds = new Date() - startTime;
723
+ less.logger.info("less has finished. css generated in " + totalMilliseconds + 'ms');
724
+ resolve({
725
+ startTime: startTime,
726
+ endTime: endTime,
727
+ totalMilliseconds: totalMilliseconds,
728
+ sheets: less.sheets.length
729
+ });
730
+ }
731
+ endTime = new Date();
732
+ }, reload, modifyVars);
727
733
 
728
- loadStyles(modifyVars);
729
- });
730
- };
734
+ loadStyles(modifyVars);
735
+ });
736
+ };
731
737
 
732
- less.refreshStyles = loadStyles;
738
+ less.refreshStyles = loadStyles;
733
739
  return less;
734
740
  };
735
741
 
@@ -747,7 +753,7 @@ module.exports = function(less, options) {
747
753
  // 1 - Errors
748
754
  // 0 - None
749
755
  // Defaults to 2
750
- options.logLevel = typeof(options.logLevel) !== 'undefined' ? options.logLevel : (options.env === 'development' ? logLevel_info : logLevel_error);
756
+ options.logLevel = typeof options.logLevel !== 'undefined' ? options.logLevel : (options.env === 'development' ? logLevel_info : logLevel_error);
751
757
 
752
758
  if (!options.loggers) {
753
759
  options.loggers = [{
@@ -773,7 +779,7 @@ module.exports = function(less, options) {
773
779
  }
774
780
  }];
775
781
  }
776
- for(var i = 0; i < options.loggers.length; i++) {
782
+ for (var i = 0; i < options.loggers.length; i++) {
777
783
  less.logger.addListener(options.loggers[i]);
778
784
  }
779
785
  };
@@ -781,12 +787,12 @@ module.exports = function(less, options) {
781
787
  },{}],9:[function(require,module,exports){
782
788
  module.exports = {
783
789
  extractId: function(href) {
784
- return href.replace(/^[a-z-]+:\/+?[^\/]+/, '' ) // Remove protocol & domain
785
- .replace(/[\?\&]livereload=\w+/,'' ) // Remove LiveReload cachebuster
786
- .replace(/^\//, '' ) // Remove root /
787
- .replace(/\.[a-zA-Z]+$/, '' ) // Remove simple extension
788
- .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
789
- .replace(/\./g, ':'); // Replace dots with colons(for valid id)
790
+ return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
791
+ .replace(/[\?\&]livereload=\w+/, '') // Remove LiveReload cachebuster
792
+ .replace(/^\//, '') // Remove root /
793
+ .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
794
+ .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
795
+ .replace(/\./g, ':'); // Replace dots with colons(for valid id)
790
796
  },
791
797
  addDataAttr: function(options, tag) {
792
798
  for (var opt in tag.dataset) {
@@ -811,7 +817,7 @@ module.exports = contexts;
811
817
  var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
812
818
  if (!original) { return; }
813
819
 
814
- for(var i = 0; i < propertiesToCopy.length; i++) {
820
+ for (var i = 0; i < propertiesToCopy.length; i++) {
815
821
  if (original.hasOwnProperty(propertiesToCopy[i])) {
816
822
  destination[propertiesToCopy[i]] = original[propertiesToCopy[i]];
817
823
  }
@@ -848,6 +854,7 @@ contexts.Parse = function(options) {
848
854
  };
849
855
 
850
856
  var evalCopyProperties = [
857
+ 'paths', // additional include paths
851
858
  'compress', // whether to compress
852
859
  'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
853
860
  'strictMath', // whether math has to be within parenthesis
@@ -883,7 +890,7 @@ contexts.Eval.prototype.isMathOn = function () {
883
890
  };
884
891
 
885
892
  contexts.Eval.prototype.isPathRelative = function (path) {
886
- return !/^(?:[a-z-]+:|\/)/i.test(path);
893
+ return !/^(?:[a-z-]+:|\/|#)/i.test(path);
887
894
  };
888
895
 
889
896
  contexts.Eval.prototype.normalizePath = function( path ) {
@@ -915,7 +922,6 @@ contexts.Eval.prototype.normalizePath = function( path ) {
915
922
 
916
923
  //todo - do the same for the toCSS ?
917
924
 
918
-
919
925
  },{}],11:[function(require,module,exports){
920
926
  module.exports = {
921
927
  'aliceblue':'#f0f8ff',
@@ -1089,9 +1095,9 @@ module.exports = {
1089
1095
  'ms': 0.001
1090
1096
  },
1091
1097
  angle: {
1092
- 'rad': 1/(2*Math.PI),
1093
- 'deg': 1/360,
1094
- 'grad': 1/400,
1098
+ 'rad': 1 / (2 * Math.PI),
1099
+ 'deg': 1 / 360,
1100
+ 'grad': 1 / 400,
1095
1101
  'turn': 1
1096
1102
  }
1097
1103
  };
@@ -1127,7 +1133,7 @@ abstractFileManager.prototype.alwaysMakePathsAbsolute = function() {
1127
1133
  };
1128
1134
 
1129
1135
  abstractFileManager.prototype.isPathAbsolute = function(filename) {
1130
- return (/^(?:[a-z-]+:|\/|\\)/i).test(filename);
1136
+ return (/^(?:[a-z-]+:|\/|\\|#)/i).test(filename);
1131
1137
  };
1132
1138
 
1133
1139
  abstractFileManager.prototype.join = function(basePath, laterPath) {
@@ -1146,15 +1152,15 @@ abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {
1146
1152
  return "";
1147
1153
  }
1148
1154
  max = Math.max(baseUrlParts.directories.length, urlParts.directories.length);
1149
- for(i = 0; i < max; i++) {
1155
+ for (i = 0; i < max; i++) {
1150
1156
  if (baseUrlParts.directories[i] !== urlParts.directories[i]) { break; }
1151
1157
  }
1152
1158
  baseUrlDirectories = baseUrlParts.directories.slice(i);
1153
1159
  urlDirectories = urlParts.directories.slice(i);
1154
- for(i = 0; i < baseUrlDirectories.length-1; i++) {
1160
+ for (i = 0; i < baseUrlDirectories.length - 1; i++) {
1155
1161
  diff += "../";
1156
1162
  }
1157
- for(i = 0; i < urlDirectories.length-1; i++) {
1163
+ for (i = 0; i < urlDirectories.length - 1; i++) {
1158
1164
  diff += urlDirectories[i] + "/";
1159
1165
  }
1160
1166
  return diff;
@@ -1179,7 +1185,7 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1179
1185
  if (baseUrl && (!urlParts[1] || urlParts[2])) {
1180
1186
  baseUrlParts = baseUrl.match(urlPartsRegex);
1181
1187
  if (!baseUrlParts) {
1182
- throw new Error("Could not parse page url - '"+baseUrl+"'");
1188
+ throw new Error("Could not parse page url - '" + baseUrl + "'");
1183
1189
  }
1184
1190
  urlParts[1] = urlParts[1] || baseUrlParts[1] || "";
1185
1191
  if (!urlParts[2]) {
@@ -1191,16 +1197,16 @@ abstractFileManager.prototype.extractUrlParts = function extractUrlParts(url, ba
1191
1197
  directories = urlParts[3].replace(/\\/g, "/").split("/");
1192
1198
 
1193
1199
  // extract out . before .. so .. doesn't absorb a non-directory
1194
- for(i = 0; i < directories.length; i++) {
1200
+ for (i = 0; i < directories.length; i++) {
1195
1201
  if (directories[i] === ".") {
1196
1202
  directories.splice(i, 1);
1197
1203
  i -= 1;
1198
1204
  }
1199
1205
  }
1200
1206
 
1201
- for(i = 0; i < directories.length; i++) {
1207
+ for (i = 0; i < directories.length; i++) {
1202
1208
  if (directories[i] === ".." && i > 0) {
1203
- directories.splice(i-1, 2);
1209
+ directories.splice(i - 1, 2);
1204
1210
  i -= 2;
1205
1211
  }
1206
1212
  }
@@ -1226,7 +1232,7 @@ var environment = function(externalEnvironment, fileManagers) {
1226
1232
  requiredFunctions = [],
1227
1233
  functions = requiredFunctions.concat(optionalFunctions);
1228
1234
 
1229
- for(var i = 0; i < functions.length; i++) {
1235
+ for (var i = 0; i < functions.length; i++) {
1230
1236
  var propName = functions[i],
1231
1237
  environmentFunc = externalEnvironment[propName];
1232
1238
  if (environmentFunc) {
@@ -1250,7 +1256,7 @@ environment.prototype.getFileManager = function (filename, currentDirectory, opt
1250
1256
  if (options.pluginManager) {
1251
1257
  fileManagers = [].concat(fileManagers).concat(options.pluginManager.getFileManagers());
1252
1258
  }
1253
- for(var i = fileManagers.length - 1; i >= 0 ; i--) {
1259
+ for (var i = fileManagers.length - 1; i >= 0 ; i--) {
1254
1260
  var fileManager = fileManagers[i];
1255
1261
  if (fileManager[isSync ? "supportsSync" : "supports"](filename, currentDirectory, options, environment)) {
1256
1262
  return fileManager;
@@ -1305,9 +1311,9 @@ var colorBlendModeFunctions = {
1305
1311
  },
1306
1312
  overlay: function(cb, cs) {
1307
1313
  cb *= 2;
1308
- return (cb <= 1)
1309
- ? colorBlendModeFunctions.multiply(cb, cs)
1310
- : colorBlendModeFunctions.screen(cb - 1, cs);
1314
+ return (cb <= 1) ?
1315
+ colorBlendModeFunctions.multiply(cb, cs) :
1316
+ colorBlendModeFunctions.screen(cb - 1, cs);
1311
1317
  },
1312
1318
  softlight: function(cb, cs) {
1313
1319
  var d = 1, e = cb;
@@ -1345,7 +1351,7 @@ for (var f in colorBlendModeFunctions) {
1345
1351
 
1346
1352
  functionRegistry.addMultiple(colorBlend);
1347
1353
 
1348
- },{"../tree/color":46,"./function-registry":21}],17:[function(require,module,exports){
1354
+ },{"../tree/color":47,"./function-registry":21}],17:[function(require,module,exports){
1349
1355
  var Dimension = require("../tree/dimension"),
1350
1356
  Color = require("../tree/color"),
1351
1357
  Quoted = require("../tree/quoted"),
@@ -1362,7 +1368,7 @@ function hsla(color) {
1362
1368
  function number(n) {
1363
1369
  if (n instanceof Dimension) {
1364
1370
  return parseFloat(n.unit.is('%') ? n.value / 100 : n.value);
1365
- } else if (typeof(n) === 'number') {
1371
+ } else if (typeof n === 'number') {
1366
1372
  return n;
1367
1373
  } else {
1368
1374
  throw {
@@ -1393,10 +1399,18 @@ colorFunctions = {
1393
1399
  hsla: function (h, s, l, a) {
1394
1400
  function hue(h) {
1395
1401
  h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
1396
- if (h * 6 < 1) { return m1 + (m2 - m1) * h * 6; }
1397
- else if (h * 2 < 1) { return m2; }
1398
- else if (h * 3 < 2) { return m1 + (m2 - m1) * (2/3 - h) * 6; }
1399
- else { return m1; }
1402
+ if (h * 6 < 1) {
1403
+ return m1 + (m2 - m1) * h * 6;
1404
+ }
1405
+ else if (h * 2 < 1) {
1406
+ return m2;
1407
+ }
1408
+ else if (h * 3 < 2) {
1409
+ return m1 + (m2 - m1) * (2 / 3 - h) * 6;
1410
+ }
1411
+ else {
1412
+ return m1;
1413
+ }
1400
1414
  }
1401
1415
 
1402
1416
  h = (number(h) % 360) / 360;
@@ -1405,9 +1419,9 @@ colorFunctions = {
1405
1419
  var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
1406
1420
  var m1 = l * 2 - m2;
1407
1421
 
1408
- return colorFunctions.rgba(hue(h + 1/3) * 255,
1422
+ return colorFunctions.rgba(hue(h + 1 / 3) * 255,
1409
1423
  hue(h) * 255,
1410
- hue(h - 1/3) * 255,
1424
+ hue(h - 1 / 3) * 255,
1411
1425
  a);
1412
1426
  },
1413
1427
 
@@ -1475,9 +1489,9 @@ colorFunctions = {
1475
1489
  },
1476
1490
  luminance: function (color) {
1477
1491
  var luminance =
1478
- (0.2126 * color.rgb[0] / 255)
1479
- + (0.7152 * color.rgb[1] / 255)
1480
- + (0.0722 * color.rgb[2] / 255);
1492
+ (0.2126 * color.rgb[0] / 255) +
1493
+ (0.7152 * color.rgb[1] / 255) +
1494
+ (0.0722 * color.rgb[2] / 255);
1481
1495
 
1482
1496
  return new Dimension(luminance * color.alpha * 100, '%');
1483
1497
  },
@@ -1607,7 +1621,7 @@ colorFunctions = {
1607
1621
  return new Color(c.value.slice(1));
1608
1622
  }
1609
1623
  if ((c instanceof Color) || (c = Color.fromKeyword(c.value))) {
1610
- c.keyword = undefined;
1624
+ c.value = undefined;
1611
1625
  return c;
1612
1626
  }
1613
1627
  throw {
@@ -1616,7 +1630,7 @@ colorFunctions = {
1616
1630
  };
1617
1631
  },
1618
1632
  tint: function(color, amount) {
1619
- return colorFunctions.mix(colorFunctions.rgb(255,255,255), color, amount);
1633
+ return colorFunctions.mix(colorFunctions.rgb(255, 255, 255), color, amount);
1620
1634
  },
1621
1635
  shade: function(color, amount) {
1622
1636
  return colorFunctions.mix(colorFunctions.rgb(0, 0, 0), color, amount);
@@ -1624,9 +1638,9 @@ colorFunctions = {
1624
1638
  };
1625
1639
  functionRegistry.addMultiple(colorFunctions);
1626
1640
 
1627
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/quoted":69,"./function-registry":21}],18:[function(require,module,exports){
1641
+ },{"../tree/anonymous":43,"../tree/color":47,"../tree/dimension":53,"../tree/quoted":70,"./function-registry":21}],18:[function(require,module,exports){
1628
1642
  module.exports = function(environment) {
1629
- var Anonymous = require("../tree/anonymous"),
1643
+ var Quoted = require("../tree/quoted"),
1630
1644
  URL = require("../tree/url"),
1631
1645
  functionRegistry = require("./function-registry"),
1632
1646
  fallback = function(functionThis, node) {
@@ -1643,12 +1657,13 @@ module.exports = function(environment) {
1643
1657
 
1644
1658
  var mimetype = mimetypeNode && mimetypeNode.value;
1645
1659
  var filePath = filePathNode.value;
1646
- var currentDirectory = filePathNode.currentFileInfo.relativeUrls ?
1647
- filePathNode.currentFileInfo.currentDirectory : filePathNode.currentFileInfo.entryPath;
1660
+ var currentFileInfo = this.currentFileInfo;
1661
+ var currentDirectory = currentFileInfo.relativeUrls ?
1662
+ currentFileInfo.currentDirectory : currentFileInfo.entryPath;
1648
1663
 
1649
1664
  var fragmentStart = filePath.indexOf('#');
1650
1665
  var fragment = '';
1651
- if (fragmentStart!==-1) {
1666
+ if (fragmentStart !== -1) {
1652
1667
  fragment = filePath.slice(fragmentStart);
1653
1668
  filePath = filePath.slice(0, fragmentStart);
1654
1669
  }
@@ -1666,9 +1681,13 @@ module.exports = function(environment) {
1666
1681
 
1667
1682
  mimetype = environment.mimeLookup(filePath);
1668
1683
 
1669
- // use base 64 unless it's an ASCII or UTF-8 format
1670
- var charset = environment.charsetLookup(mimetype);
1671
- useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
1684
+ if (mimetype === "image/svg+xml") {
1685
+ useBase64 = false;
1686
+ } else {
1687
+ // use base 64 unless it's an ASCII or UTF-8 format
1688
+ var charset = environment.charsetLookup(mimetype);
1689
+ useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
1690
+ }
1672
1691
  if (useBase64) { mimetype += ';base64'; }
1673
1692
  }
1674
1693
  else {
@@ -1677,33 +1696,36 @@ module.exports = function(environment) {
1677
1696
 
1678
1697
  var fileSync = fileManager.loadFileSync(filePath, currentDirectory, this.context, environment);
1679
1698
  if (!fileSync.contents) {
1680
- logger.warn("Skipped data-uri embedding because file not found");
1699
+ logger.warn("Skipped data-uri embedding of " + filePath + " because file not found");
1681
1700
  return fallback(this, filePathNode || mimetypeNode);
1682
1701
  }
1683
1702
  var buf = fileSync.contents;
1703
+ if (useBase64 && !environment.encodeBase64) {
1704
+ return fallback(this, filePathNode);
1705
+ }
1706
+
1707
+ buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
1684
1708
 
1685
- // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
1709
+ var uri = "data:" + mimetype + ',' + buf + fragment;
1710
+
1711
+ // IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded
1686
1712
  // and the --ieCompat flag is enabled, return a normal url() instead.
1687
- var DATA_URI_MAX_KB = 32,
1688
- fileSizeInKB = parseInt((buf.length / 1024), 10);
1689
- if (fileSizeInKB >= DATA_URI_MAX_KB) {
1713
+ var DATA_URI_MAX = 32768;
1714
+ if (uri.length >= DATA_URI_MAX) {
1690
1715
 
1691
1716
  if (this.context.ieCompat !== false) {
1692
- logger.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
1717
+ logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length +
1718
+ " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
1693
1719
 
1694
1720
  return fallback(this, filePathNode || mimetypeNode);
1695
1721
  }
1696
1722
  }
1697
1723
 
1698
- buf = useBase64 ? buf.toString('base64')
1699
- : encodeURIComponent(buf);
1700
-
1701
- var uri = "\"data:" + mimetype + ',' + buf + fragment + "\"";
1702
- return new URL(new Anonymous(uri), this.index, this.currentFileInfo);
1724
+ return new URL(new Quoted('"' + uri + '"', uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
1703
1725
  });
1704
1726
  };
1705
1727
 
1706
- },{"../logger":31,"../tree/anonymous":42,"../tree/url":76,"./function-registry":21}],19:[function(require,module,exports){
1728
+ },{"../logger":31,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],19:[function(require,module,exports){
1707
1729
  var Keyword = require("../tree/keyword"),
1708
1730
  functionRegistry = require("./function-registry");
1709
1731
 
@@ -1732,7 +1754,7 @@ functionRegistry.add("default", defaultFunc.eval.bind(defaultFunc));
1732
1754
 
1733
1755
  module.exports = defaultFunc;
1734
1756
 
1735
- },{"../tree/keyword":61,"./function-registry":21}],20:[function(require,module,exports){
1757
+ },{"../tree/keyword":62,"./function-registry":21}],20:[function(require,module,exports){
1736
1758
  var functionRegistry = require("./function-registry");
1737
1759
 
1738
1760
  var functionCaller = function(name, context, index, currentFileInfo) {
@@ -1829,13 +1851,13 @@ for (var f in mathFunctions) {
1829
1851
  }
1830
1852
 
1831
1853
  mathFunctions.round = function (n, f) {
1832
- var fraction = typeof(f) === "undefined" ? 0 : f.value;
1854
+ var fraction = typeof f === "undefined" ? 0 : f.value;
1833
1855
  return _math(function(num) { return num.toFixed(fraction); }, null, n);
1834
1856
  };
1835
1857
 
1836
1858
  functionRegistry.addMultiple(mathFunctions);
1837
1859
 
1838
- },{"../tree/dimension":52,"./function-registry":21}],24:[function(require,module,exports){
1860
+ },{"../tree/dimension":53,"./function-registry":21}],24:[function(require,module,exports){
1839
1861
  var Dimension = require("../tree/dimension"),
1840
1862
  Anonymous = require("../tree/anonymous"),
1841
1863
  functionRegistry = require("./function-registry");
@@ -1852,7 +1874,7 @@ var minMax = function (isMin, args) {
1852
1874
  for (i = 0; i < args.length; i++) {
1853
1875
  current = args[i];
1854
1876
  if (!(current instanceof Dimension)) {
1855
- if(Array.isArray(args[i].value)) {
1877
+ if (Array.isArray(args[i].value)) {
1856
1878
  Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
1857
1879
  }
1858
1880
  continue;
@@ -1863,7 +1885,7 @@ var minMax = function (isMin, args) {
1863
1885
  unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone;
1864
1886
  j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
1865
1887
  if (j === undefined) {
1866
- if(unitStatic !== undefined && unit !== unitStatic) {
1888
+ if (unitStatic !== undefined && unit !== unitStatic) {
1867
1889
  throw{ type: "Argument", message: "incompatible types" };
1868
1890
  }
1869
1891
  values[unit] = order.length;
@@ -1913,7 +1935,7 @@ functionRegistry.addMultiple({
1913
1935
  }
1914
1936
  });
1915
1937
 
1916
- },{"../tree/anonymous":42,"../tree/dimension":52,"./function-registry":21}],25:[function(require,module,exports){
1938
+ },{"../tree/anonymous":43,"../tree/dimension":53,"./function-registry":21}],25:[function(require,module,exports){
1917
1939
  var Quoted = require("../tree/quoted"),
1918
1940
  Anonymous = require("../tree/anonymous"),
1919
1941
  JavaScript = require("../tree/javascript"),
@@ -1924,7 +1946,9 @@ functionRegistry.addMultiple({
1924
1946
  return new Anonymous(str instanceof JavaScript ? str.evaluated : str.value);
1925
1947
  },
1926
1948
  escape: function (str) {
1927
- return new Anonymous(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29"));
1949
+ return new Anonymous(
1950
+ encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B")
1951
+ .replace(/\(/g, "%28").replace(/\)/g, "%29"));
1928
1952
  },
1929
1953
  replace: function (string, pattern, replacement, flags) {
1930
1954
  var result = string.value;
@@ -1948,18 +1972,21 @@ functionRegistry.addMultiple({
1948
1972
  }
1949
1973
  });
1950
1974
 
1951
- },{"../tree/anonymous":42,"../tree/javascript":59,"../tree/quoted":69,"./function-registry":21}],26:[function(require,module,exports){
1975
+ },{"../tree/anonymous":43,"../tree/javascript":60,"../tree/quoted":70,"./function-registry":21}],26:[function(require,module,exports){
1952
1976
  module.exports = function(environment) {
1953
1977
  var Dimension = require("../tree/dimension"),
1954
1978
  Color = require("../tree/color"),
1955
- Anonymous = require("../tree/anonymous"),
1979
+ Expression = require("../tree/expression"),
1980
+ Quoted = require("../tree/quoted"),
1956
1981
  URL = require("../tree/url"),
1957
1982
  functionRegistry = require("./function-registry");
1958
1983
 
1959
1984
  functionRegistry.add("svg-gradient", function(direction) {
1960
1985
 
1961
1986
  function throwArgumentDescriptor() {
1962
- throw { type: "Argument", message: "svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]" };
1987
+ throw { type: "Argument",
1988
+ message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
1989
+ " end_color [end_position]" };
1963
1990
  }
1964
1991
 
1965
1992
  if (arguments.length < 3) {
@@ -1969,7 +1996,6 @@ module.exports = function(environment) {
1969
1996
  gradientDirectionSvg,
1970
1997
  gradientType = "linear",
1971
1998
  rectangleDimension = 'x="0" y="0" width="1" height="1"',
1972
- useBase64 = true,
1973
1999
  renderEnv = {compress: false},
1974
2000
  returner,
1975
2001
  directionValue = direction.toCSS(renderEnv),
@@ -1995,14 +2021,15 @@ module.exports = function(environment) {
1995
2021
  rectangleDimension = 'x="-50" y="-50" width="101" height="101"';
1996
2022
  break;
1997
2023
  default:
1998
- throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'" };
2024
+ throw { type: "Argument", message: "svg-gradient direction must be 'to bottom', 'to right'," +
2025
+ " 'to bottom right', 'to top right' or 'ellipse at center'" };
1999
2026
  }
2000
2027
  returner = '<?xml version="1.0" ?>' +
2001
2028
  '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' +
2002
2029
  '<' + gradientType + 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' + gradientDirectionSvg + '>';
2003
2030
 
2004
2031
  for (i = 0; i < stops.length; i+= 1) {
2005
- if (stops[i].value) {
2032
+ if (stops[i] instanceof Expression) {
2006
2033
  color = stops[i].value[0];
2007
2034
  position = stops[i].value[1];
2008
2035
  } else {
@@ -2010,7 +2037,7 @@ module.exports = function(environment) {
2010
2037
  position = undefined;
2011
2038
  }
2012
2039
 
2013
- if (!(color instanceof Color) || (!((i === 0 || i+1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
2040
+ if (!(color instanceof Color) || (!((i === 0 || i + 1 === stops.length) && position === undefined) && !(position instanceof Dimension))) {
2014
2041
  throwArgumentDescriptor();
2015
2042
  }
2016
2043
  positionValue = position ? position.toCSS(renderEnv) : i === 0 ? "0%" : "100%";
@@ -2020,21 +2047,16 @@ module.exports = function(environment) {
2020
2047
  returner += '</' + gradientType + 'Gradient>' +
2021
2048
  '<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
2022
2049
 
2023
- if (useBase64) {
2024
- try {
2025
- returner = environment.encodeBase64(returner);
2026
- } catch(e) {
2027
- useBase64 = false;
2028
- }
2029
- }
2050
+ returner = encodeURIComponent(returner);
2030
2051
 
2031
- returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'";
2032
- return new URL(new Anonymous(returner), this.index, this.currentFileInfo);
2052
+ returner = "data:image/svg+xml," + returner;
2053
+ return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
2033
2054
  });
2034
2055
  };
2035
2056
 
2036
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/url":76,"./function-registry":21}],27:[function(require,module,exports){
2057
+ },{"../tree/color":47,"../tree/dimension":53,"../tree/expression":56,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],27:[function(require,module,exports){
2037
2058
  var Keyword = require("../tree/keyword"),
2059
+ DetachedRuleset = require("../tree/detached-ruleset"),
2038
2060
  Dimension = require("../tree/dimension"),
2039
2061
  Color = require("../tree/color"),
2040
2062
  Quoted = require("../tree/quoted"),
@@ -2044,12 +2066,35 @@ var Keyword = require("../tree/keyword"),
2044
2066
  functionRegistry = require("./function-registry");
2045
2067
 
2046
2068
  var isa = function (n, Type) {
2047
- return (n instanceof Type) ? Keyword.True : Keyword.False;
2069
+ return (n instanceof Type) ? Keyword.True : Keyword.False;
2048
2070
  },
2049
2071
  isunit = function (n, unit) {
2050
- return (n instanceof Dimension) && n.unit.is(unit.value || unit) ? Keyword.True : Keyword.False;
2072
+ if (unit === undefined) {
2073
+ throw { type: "Argument", message: "missing the required second argument to isunit." };
2074
+ }
2075
+ unit = typeof unit.value === "string" ? unit.value : unit;
2076
+ if (typeof unit !== "string") {
2077
+ throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." };
2078
+ }
2079
+ return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
2080
+ },
2081
+ getItemsFromNode = function(node) {
2082
+ // handle non-array values as an array of length 1
2083
+ // return 'undefined' if index is invalid
2084
+ var items = Array.isArray(node.value) ?
2085
+ node.value : Array(node);
2086
+
2087
+ return items.filter(function(item) {
2088
+ if (item.type === "Comment") {
2089
+ return false;
2090
+ }
2091
+ return true;
2092
+ });
2051
2093
  };
2052
2094
  functionRegistry.addMultiple({
2095
+ isruleset: function (n) {
2096
+ return isa(n, DetachedRuleset);
2097
+ },
2053
2098
  iscolor: function (n) {
2054
2099
  return isa(n, Color);
2055
2100
  },
@@ -2076,8 +2121,10 @@ functionRegistry.addMultiple({
2076
2121
  },
2077
2122
  isunit: isunit,
2078
2123
  unit: function (val, unit) {
2079
- if(!(val instanceof Dimension)) {
2080
- throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
2124
+ if (!(val instanceof Dimension)) {
2125
+ throw { type: "Argument",
2126
+ message: "the first argument to unit must be a number" +
2127
+ (val instanceof Operation ? ". Have you forgotten parenthesis?" : "") };
2081
2128
  }
2082
2129
  if (unit) {
2083
2130
  if (unit instanceof Keyword) {
@@ -2095,18 +2142,15 @@ functionRegistry.addMultiple({
2095
2142
  },
2096
2143
  extract: function(values, index) {
2097
2144
  index = index.value - 1; // (1-based index)
2098
- // handle non-array values as an array of length 1
2099
- // return 'undefined' if index is invalid
2100
- return Array.isArray(values.value) ?
2101
- values.value[index] : Array(values)[index];
2145
+
2146
+ return getItemsFromNode(values)[index];
2102
2147
  },
2103
2148
  length: function(values) {
2104
- var n = Array.isArray(values.value) ? values.value.length : 1;
2105
- return new Dimension(n);
2149
+ return new Dimension(getItemsFromNode(values).length);
2106
2150
  }
2107
2151
  });
2108
2152
 
2109
- },{"../tree/anonymous":42,"../tree/color":46,"../tree/dimension":52,"../tree/keyword":61,"../tree/operation":67,"../tree/quoted":69,"../tree/url":76,"./function-registry":21}],28:[function(require,module,exports){
2153
+ },{"../tree/anonymous":43,"../tree/color":47,"../tree/detached-ruleset":52,"../tree/dimension":53,"../tree/keyword":62,"../tree/operation":68,"../tree/quoted":70,"../tree/url":77,"./function-registry":21}],28:[function(require,module,exports){
2110
2154
  var contexts = require("./contexts"),
2111
2155
  Parser = require('./parser/parser');
2112
2156
 
@@ -2149,12 +2193,14 @@ module.exports = function(environment) {
2149
2193
  importManager.queue.splice(importManager.queue.indexOf(path), 1); // Remove the path from the queue
2150
2194
 
2151
2195
  var importedEqualsRoot = fullPath === importManager.rootFilename;
2152
-
2153
- importManager.files[fullPath] = root;
2154
-
2155
- if (e && !importManager.error) { importManager.error = e; }
2156
-
2157
- callback(e, root, importedEqualsRoot, fullPath);
2196
+ if (importOptions.optional && e) {
2197
+ callback(null, {rules:[]}, false, null);
2198
+ }
2199
+ else {
2200
+ importManager.files[fullPath] = root;
2201
+ if (e && !importManager.error) { importManager.error = e; }
2202
+ callback(e, root, importedEqualsRoot, fullPath);
2203
+ }
2158
2204
  };
2159
2205
 
2160
2206
  var newFileInfo = {
@@ -2177,7 +2223,7 @@ module.exports = function(environment) {
2177
2223
 
2178
2224
  var loadFileCallback = function(loadedFile) {
2179
2225
  var resolvedFilename = loadedFile.filename,
2180
- contents = loadedFile.contents;
2226
+ contents = loadedFile.contents.replace(/^\uFEFF/, '');
2181
2227
 
2182
2228
  // Pass on an updated rootpath if path of imported file is relative and file
2183
2229
  // is in a (sub|sup) directory
@@ -2188,8 +2234,11 @@ module.exports = function(environment) {
2188
2234
  // - If path of imported file is '../mixins.less' and rootpath is 'less/',
2189
2235
  // then rootpath should become 'less/../'
2190
2236
  newFileInfo.currentDirectory = fileManager.getPath(resolvedFilename);
2191
- if(newFileInfo.relativeUrls) {
2192
- newFileInfo.rootpath = fileManager.join((importManager.context.rootpath || ""), fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
2237
+ if (newFileInfo.relativeUrls) {
2238
+ newFileInfo.rootpath = fileManager.join(
2239
+ (importManager.context.rootpath || ""),
2240
+ fileManager.pathDiff(newFileInfo.currentDirectory, newFileInfo.entryPath));
2241
+
2193
2242
  if (!fileManager.isPathAbsolute(newFileInfo.rootpath) && fileManager.alwaysMakePathsAbsolute()) {
2194
2243
  newFileInfo.rootpath = fileManager.join(newFileInfo.entryPath, newFileInfo.rootpath);
2195
2244
  }
@@ -2229,12 +2278,12 @@ module.exports = function(environment) {
2229
2278
  return ImportManager;
2230
2279
  };
2231
2280
 
2232
- },{"./contexts":10,"./parser/parser":35}],29:[function(require,module,exports){
2281
+ },{"./contexts":10,"./parser/parser":36}],29:[function(require,module,exports){
2233
2282
  module.exports = function(environment, fileManagers) {
2234
2283
  var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
2235
2284
 
2236
2285
  var less = {
2237
- version: [2, 1, 2],
2286
+ version: [2, 4, 0],
2238
2287
  data: require('./data'),
2239
2288
  tree: require('./tree'),
2240
2289
  Environment: (Environment = require("./environment/environment")),
@@ -2249,6 +2298,7 @@ module.exports = function(environment, fileManagers) {
2249
2298
  ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)),
2250
2299
  ImportManager: (ImportManager = require('./import-manager')(environment)),
2251
2300
  render: require("./render")(environment, ParseTree, ImportManager),
2301
+ parse: require("./parse")(environment, ParseTree, ImportManager),
2252
2302
  LessError: require('./less-error'),
2253
2303
  transformTree: require('./transform-tree'),
2254
2304
  utils: require('./utils'),
@@ -2259,7 +2309,7 @@ module.exports = function(environment, fileManagers) {
2259
2309
  return less;
2260
2310
  };
2261
2311
 
2262
- },{"./contexts":10,"./data":12,"./environment/abstract-file-manager":14,"./environment/environment":15,"./functions":22,"./import-manager":28,"./less-error":30,"./logger":31,"./parse-tree":32,"./parser/parser":35,"./plugin-manager":36,"./render":37,"./source-map-builder":38,"./source-map-output":39,"./transform-tree":40,"./tree":58,"./utils":79,"./visitors":83}],30:[function(require,module,exports){
2312
+ },{"./contexts":10,"./data":12,"./environment/abstract-file-manager":14,"./environment/environment":15,"./functions":22,"./import-manager":28,"./less-error":30,"./logger":31,"./parse":33,"./parse-tree":32,"./parser/parser":36,"./plugin-manager":37,"./render":38,"./source-map-builder":39,"./source-map-output":40,"./transform-tree":41,"./tree":59,"./utils":80,"./visitors":84}],30:[function(require,module,exports){
2263
2313
  var utils = require("./utils");
2264
2314
 
2265
2315
  var LessError = module.exports = function LessError(e, importManager, currentFilename) {
@@ -2279,7 +2329,7 @@ var LessError = module.exports = function LessError(e, importManager, currentFil
2279
2329
  this.type = e.type || 'Syntax';
2280
2330
  this.filename = filename;
2281
2331
  this.index = e.index;
2282
- this.line = typeof(line) === 'number' ? line + 1 : null;
2332
+ this.line = typeof line === 'number' ? line + 1 : null;
2283
2333
  this.callLine = callLine + 1;
2284
2334
  this.callExtract = lines[callLine];
2285
2335
  this.column = col;
@@ -2303,7 +2353,7 @@ if (typeof Object.create === 'undefined') {
2303
2353
 
2304
2354
  LessError.prototype.constructor = LessError;
2305
2355
 
2306
- },{"./utils":79}],31:[function(require,module,exports){
2356
+ },{"./utils":80}],31:[function(require,module,exports){
2307
2357
  module.exports = {
2308
2358
  error: function(msg) {
2309
2359
  this._fireEvent("error", msg);
@@ -2321,7 +2371,7 @@ module.exports = {
2321
2371
  this._listeners.push(listener);
2322
2372
  },
2323
2373
  removeListener: function(listener) {
2324
- for(var i = 0; i < this._listeners.length; i++) {
2374
+ for (var i = 0; i < this._listeners.length; i++) {
2325
2375
  if (this._listeners[i] === listener) {
2326
2376
  this._listeners.splice(i, 1);
2327
2377
  return;
@@ -2329,7 +2379,7 @@ module.exports = {
2329
2379
  }
2330
2380
  },
2331
2381
  _fireEvent: function(type, msg) {
2332
- for(var i = 0; i < this._listeners.length; i++) {
2382
+ for (var i = 0; i < this._listeners.length; i++) {
2333
2383
  var logFunction = this._listeners[i][type];
2334
2384
  if (logFunction) {
2335
2385
  logFunction(msg);
@@ -2341,82 +2391,158 @@ module.exports = {
2341
2391
 
2342
2392
  },{}],32:[function(require,module,exports){
2343
2393
  var LessError = require('./less-error'),
2344
- transformTree = require("./transform-tree");
2394
+ transformTree = require("./transform-tree"),
2395
+ logger = require("./logger");
2345
2396
 
2346
2397
  module.exports = function(SourceMapBuilder) {
2347
- var ParseTree = function(root, imports) {
2348
- this.root = root;
2349
- this.imports = imports;
2350
- };
2398
+ var ParseTree = function(root, imports) {
2399
+ this.root = root;
2400
+ this.imports = imports;
2401
+ };
2351
2402
 
2352
- ParseTree.prototype.toCSS = function(options) {
2353
- var evaldRoot, result = {}, sourceMapBuilder;
2354
- try {
2355
- evaldRoot = transformTree(this.root, options);
2356
- } catch (e) {
2357
- throw new LessError(e, this.imports);
2358
- }
2403
+ ParseTree.prototype.toCSS = function(options) {
2404
+ var evaldRoot, result = {}, sourceMapBuilder;
2405
+ try {
2406
+ evaldRoot = transformTree(this.root, options);
2407
+ } catch (e) {
2408
+ throw new LessError(e, this.imports);
2409
+ }
2359
2410
 
2360
- try {
2361
- var toCSSOptions = {
2362
- compress: Boolean(options.compress),
2363
- dumpLineNumbers: options.dumpLineNumbers,
2364
- strictUnits: Boolean(options.strictUnits),
2365
- numPrecision: 8};
2411
+ try {
2412
+ var compress = Boolean(options.compress);
2413
+ if (compress) {
2414
+ logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.");
2415
+ }
2366
2416
 
2367
- if (options.sourceMap) {
2368
- sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
2369
- result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
2370
- } else {
2371
- result.css = evaldRoot.toCSS(toCSSOptions);
2417
+ var toCSSOptions = {
2418
+ compress: compress,
2419
+ dumpLineNumbers: options.dumpLineNumbers,
2420
+ strictUnits: Boolean(options.strictUnits),
2421
+ numPrecision: 8};
2422
+
2423
+ if (options.sourceMap) {
2424
+ sourceMapBuilder = new SourceMapBuilder(options.sourceMap);
2425
+ result.css = sourceMapBuilder.toCSS(evaldRoot, toCSSOptions, this.imports);
2426
+ } else {
2427
+ result.css = evaldRoot.toCSS(toCSSOptions);
2428
+ }
2429
+ } catch (e) {
2430
+ throw new LessError(e, this.imports);
2372
2431
  }
2373
- } catch (e) {
2374
- throw new LessError(e, this.imports);
2375
- }
2376
2432
 
2377
- if (options.pluginManager) {
2378
- var postProcessors = options.pluginManager.getPostProcessors();
2379
- for(var i = 0; i < postProcessors.length; i++) {
2380
- result.css = postProcessors[i].process(result.css, { sourceMap: sourceMapBuilder, options: options, imports: this.imports });
2433
+ if (options.pluginManager) {
2434
+ var postProcessors = options.pluginManager.getPostProcessors();
2435
+ for (var i = 0; i < postProcessors.length; i++) {
2436
+ result.css = postProcessors[i].process(result.css, { sourceMap: sourceMapBuilder, options: options, imports: this.imports });
2437
+ }
2438
+ }
2439
+ if (options.sourceMap) {
2440
+ result.map = sourceMapBuilder.getExternalSourceMap();
2381
2441
  }
2382
- }
2383
- if (options.sourceMap) {
2384
- result.map = sourceMapBuilder.getExternalSourceMap();
2385
- }
2386
2442
 
2387
- result.imports = [];
2388
- for(var file in this.imports.files) {
2389
- if (this.imports.files.hasOwnProperty(file) && file !== this.imports.rootFilename) {
2390
- result.imports.push(file);
2443
+ result.imports = [];
2444
+ for (var file in this.imports.files) {
2445
+ if (this.imports.files.hasOwnProperty(file) && file !== this.imports.rootFilename) {
2446
+ result.imports.push(file);
2447
+ }
2391
2448
  }
2392
- }
2393
- return result;
2394
- };
2395
- return ParseTree;
2449
+ return result;
2450
+ };
2451
+ return ParseTree;
2396
2452
  };
2397
2453
 
2398
- },{"./less-error":30,"./transform-tree":40}],33:[function(require,module,exports){
2399
- // Split the input into chunks.
2400
- module.exports = function (input, fail) {
2401
- var len = input.length, level = 0, parenLevel = 0,
2402
- lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
2403
- chunks = [], emitFrom = 0,
2404
- chunkerCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
2454
+ },{"./less-error":30,"./logger":31,"./transform-tree":41}],33:[function(require,module,exports){
2455
+ var PromiseConstructor,
2456
+ contexts = require("./contexts"),
2457
+ Parser = require('./parser/parser'),
2458
+ PluginManager = require('./plugin-manager');
2405
2459
 
2406
- function emitChunk(force) {
2407
- var len = chunkerCurrentIndex - emitFrom;
2408
- if (((len < 512) && !force) || !len) {
2409
- return;
2410
- }
2411
- chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1));
2412
- emitFrom = chunkerCurrentIndex + 1;
2413
- }
2460
+ module.exports = function(environment, ParseTree, ImportManager) {
2461
+ var parse = function (input, options, callback) {
2462
+ options = options || {};
2414
2463
 
2415
- for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
2416
- cc = input.charCodeAt(chunkerCurrentIndex);
2417
- if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
2418
- // a-z or whitespace
2419
- continue;
2464
+ if (typeof options === 'function') {
2465
+ callback = options;
2466
+ options = {};
2467
+ }
2468
+
2469
+ if (!callback) {
2470
+ if (!PromiseConstructor) {
2471
+ PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
2472
+ }
2473
+ var self = this;
2474
+ return new PromiseConstructor(function (resolve, reject) {
2475
+ parse.call(self, input, options, function(err, output) {
2476
+ if (err) {
2477
+ reject(err);
2478
+ } else {
2479
+ resolve(output);
2480
+ }
2481
+ });
2482
+ });
2483
+ } else {
2484
+ var context,
2485
+ rootFileInfo,
2486
+ pluginManager = new PluginManager(this);
2487
+
2488
+ pluginManager.addPlugins(options.plugins);
2489
+ options.pluginManager = pluginManager;
2490
+
2491
+ context = new contexts.Parse(options);
2492
+
2493
+ if (options.rootFileInfo) {
2494
+ rootFileInfo = options.rootFileInfo;
2495
+ } else {
2496
+ var filename = options.filename || "input";
2497
+ var entryPath = filename.replace(/[^\/\\]*$/, "");
2498
+ rootFileInfo = {
2499
+ filename: filename,
2500
+ relativeUrls: context.relativeUrls,
2501
+ rootpath: context.rootpath || "",
2502
+ currentDirectory: entryPath,
2503
+ entryPath: entryPath,
2504
+ rootFilename: filename
2505
+ };
2506
+ // add in a missing trailing slash
2507
+ if (rootFileInfo.rootpath && rootFileInfo.rootpath.slice(-1) !== "/") {
2508
+ rootFileInfo.rootpath += "/";
2509
+ }
2510
+ }
2511
+
2512
+ var imports = new ImportManager(context, rootFileInfo);
2513
+
2514
+ new Parser(context, imports, rootFileInfo)
2515
+ .parse(input, function (e, root) {
2516
+ if (e) { return callback(e); }
2517
+ callback(null, root, imports, options);
2518
+ }, options);
2519
+ }
2520
+ };
2521
+ return parse;
2522
+ };
2523
+
2524
+ },{"./contexts":10,"./parser/parser":36,"./plugin-manager":37,"promise":undefined}],34:[function(require,module,exports){
2525
+ // Split the input into chunks.
2526
+ module.exports = function (input, fail) {
2527
+ var len = input.length, level = 0, parenLevel = 0,
2528
+ lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
2529
+ chunks = [], emitFrom = 0,
2530
+ chunkerCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
2531
+
2532
+ function emitChunk(force) {
2533
+ var len = chunkerCurrentIndex - emitFrom;
2534
+ if (((len < 512) && !force) || !len) {
2535
+ return;
2536
+ }
2537
+ chunks.push(input.slice(emitFrom, chunkerCurrentIndex + 1));
2538
+ emitFrom = chunkerCurrentIndex + 1;
2539
+ }
2540
+
2541
+ for (chunkerCurrentIndex = 0; chunkerCurrentIndex < len; chunkerCurrentIndex++) {
2542
+ cc = input.charCodeAt(chunkerCurrentIndex);
2543
+ if (((cc >= 97) && (cc <= 122)) || (cc < 34)) {
2544
+ // a-z or whitespace
2545
+ continue;
2420
2546
  }
2421
2547
 
2422
2548
  switch (cc) {
@@ -2509,7 +2635,7 @@ module.exports = function (input, fail) {
2509
2635
  return chunks;
2510
2636
  };
2511
2637
 
2512
- },{}],34:[function(require,module,exports){
2638
+ },{}],35:[function(require,module,exports){
2513
2639
  var chunker = require('./chunker');
2514
2640
 
2515
2641
  module.exports = function() {
@@ -2528,7 +2654,8 @@ module.exports = function() {
2528
2654
  saveStack.push( { current: current, i: parserInput.i, j: j });
2529
2655
  };
2530
2656
  parserInput.restore = function(possibleErrorMessage) {
2531
- if (parserInput.i > furthest) {
2657
+
2658
+ if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
2532
2659
  furthest = parserInput.i;
2533
2660
  furthestPossibleErrorMessage = possibleErrorMessage;
2534
2661
  }
@@ -2584,7 +2711,7 @@ module.exports = function() {
2584
2711
  //
2585
2712
  skipWhitespace(length);
2586
2713
 
2587
- if(typeof(match) === 'string') {
2714
+ if (typeof match === 'string') {
2588
2715
  return match;
2589
2716
  } else {
2590
2717
  return match.length === 1 ? match[0] : match;
@@ -2603,7 +2730,7 @@ module.exports = function() {
2603
2730
  }
2604
2731
 
2605
2732
  skipWhitespace(m[0].length);
2606
- if(typeof m === "string") {
2733
+ if (typeof m === "string") {
2607
2734
  return m;
2608
2735
  }
2609
2736
 
@@ -2696,7 +2823,7 @@ module.exports = function() {
2696
2823
  // Same as $(), but don't change the state of the parser,
2697
2824
  // just return the match.
2698
2825
  parserInput.peek = function(tok) {
2699
- if (typeof(tok) === 'string') {
2826
+ if (typeof tok === 'string') {
2700
2827
  return input.charAt(parserInput.i) === tok;
2701
2828
  } else {
2702
2829
  return tok.test(current);
@@ -2750,7 +2877,7 @@ module.exports = function() {
2750
2877
 
2751
2878
  parserInput.end = function() {
2752
2879
  var message,
2753
- isFinished = parserInput.i >= input.length - 1;
2880
+ isFinished = parserInput.i >= input.length;
2754
2881
 
2755
2882
  if (parserInput.i < furthest) {
2756
2883
  message = furthestPossibleErrorMessage;
@@ -2768,7 +2895,7 @@ module.exports = function() {
2768
2895
  return parserInput;
2769
2896
  };
2770
2897
 
2771
- },{"./chunker":33}],35:[function(require,module,exports){
2898
+ },{"./chunker":34}],36:[function(require,module,exports){
2772
2899
  var LessError = require('../less-error'),
2773
2900
  tree = require("../tree"),
2774
2901
  visitors = require("../visitors"),
@@ -2818,7 +2945,7 @@ var Parser = function Parser(context, imports, fileInfo) {
2818
2945
  if (result) {
2819
2946
  return result;
2820
2947
  }
2821
- error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'"
2948
+ error(msg || (typeof arg === 'string' ? "expected '" + arg + "' got '" + parserInput.currentChar() + "'"
2822
2949
  : "unexpected token"));
2823
2950
  }
2824
2951
 
@@ -2863,17 +2990,26 @@ var Parser = function Parser(context, imports, fileInfo) {
2863
2990
  // @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
2864
2991
  //
2865
2992
  parse: function (str, callback, additionalData) {
2866
- var root, error = null, globalVars, modifyVars, preText = "";
2993
+ var root, error = null, globalVars, modifyVars, ignored, preText = "";
2867
2994
 
2868
2995
  globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : '';
2869
2996
  modifyVars = (additionalData && additionalData.modifyVars) ? '\n' + Parser.serializeVars(additionalData.modifyVars) : '';
2870
2997
 
2998
+ if (context.pluginManager) {
2999
+ var preProcessors = context.pluginManager.getPreProcessors();
3000
+ for (var i = 0; i < preProcessors.length; i++) {
3001
+ str = preProcessors[i].process(str, { context: context, imports: imports, fileInfo: fileInfo });
3002
+ }
3003
+ }
3004
+
2871
3005
  if (globalVars || (additionalData && additionalData.banner)) {
2872
3006
  preText = ((additionalData && additionalData.banner) ? additionalData.banner : "") + globalVars;
2873
- imports.contentsIgnoredChars[fileInfo.filename] = preText.length;
3007
+ ignored = imports.contentsIgnoredChars;
3008
+ ignored[fileInfo.filename] = ignored[fileInfo.filename] || 0;
3009
+ ignored[fileInfo.filename] += preText.length;
2874
3010
  }
2875
3011
 
2876
- str = str.replace(/\r\n/g, '\n');
3012
+ str = str.replace(/\r\n?/g, '\n');
2877
3013
  // Remove potential UTF Byte Order Mark
2878
3014
  str = preText + str.replace(/^\uFEFF/, '') + modifyVars;
2879
3015
  imports.contents[fileInfo.filename] = str;
@@ -2975,7 +3111,7 @@ var Parser = function Parser(context, imports, fileInfo) {
2975
3111
  // Ruleset (Selector '.class', [
2976
3112
  // Rule ("color", Value ([Expression [Color #fff]]))
2977
3113
  // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]]))
2978
- // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]]))
3114
+ // Rule ("width", Value ([Expression [Operation " + " [Variable "@w"][Dimension 4px]]]))
2979
3115
  // Ruleset (Selector [Element '>', '.child'], [...])
2980
3116
  // ])
2981
3117
  //
@@ -3002,13 +3138,17 @@ var Parser = function Parser(context, imports, fileInfo) {
3002
3138
  primary: function () {
3003
3139
  var mixin = this.mixin, root = [], node;
3004
3140
 
3005
- while (!parserInput.finished)
3141
+ while (true)
3006
3142
  {
3007
- while(true) {
3143
+ while (true) {
3008
3144
  node = this.comment();
3009
3145
  if (!node) { break; }
3010
3146
  root.push(node);
3011
3147
  }
3148
+ // always process comments before deciding if finished
3149
+ if (parserInput.finished) {
3150
+ break;
3151
+ }
3012
3152
  if (parserInput.peek('}')) {
3013
3153
  break;
3014
3154
  }
@@ -3099,7 +3239,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3099
3239
 
3100
3240
  if (nameLC === 'alpha') {
3101
3241
  alpha = parsers.alpha();
3102
- if(alpha) {
3242
+ if (alpha) {
3103
3243
  return alpha;
3104
3244
  }
3105
3245
  }
@@ -3221,7 +3361,9 @@ var Parser = function Parser(context, imports, fileInfo) {
3221
3361
  var rgb;
3222
3362
 
3223
3363
  if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
3224
- var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string
3364
+ // strip colons, brackets, whitespaces and other characters that should not
3365
+ // definitely be part of color string
3366
+ var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
3225
3367
  colorCandidateString = colorCandidateString[1];
3226
3368
  if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
3227
3369
  error("Invalid HEX color code");
@@ -3312,17 +3454,27 @@ var Parser = function Parser(context, imports, fileInfo) {
3312
3454
  elements = null;
3313
3455
  while (! (option = parserInput.$re(/^(all)(?=\s*(\)|,))/))) {
3314
3456
  e = this.element();
3315
- if (!e) { break; }
3316
- if (elements) { elements.push(e); } else { elements = [ e ]; }
3457
+ if (!e) {
3458
+ break;
3459
+ }
3460
+ if (elements) {
3461
+ elements.push(e);
3462
+ } else {
3463
+ elements = [ e ];
3464
+ }
3317
3465
  }
3318
3466
 
3319
3467
  option = option && option[1];
3320
- if (!elements)
3468
+ if (!elements) {
3321
3469
  error("Missing target selector for :extend().");
3470
+ }
3322
3471
  extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
3323
- if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
3324
-
3325
- } while(parserInput.$char(","));
3472
+ if (extendList) {
3473
+ extendList.push(extend);
3474
+ } else {
3475
+ extendList = [ extend ];
3476
+ }
3477
+ } while (parserInput.$char(","));
3326
3478
 
3327
3479
  expect(/^\)/);
3328
3480
 
@@ -3370,7 +3522,11 @@ var Parser = function Parser(context, imports, fileInfo) {
3370
3522
  break;
3371
3523
  }
3372
3524
  elem = new(tree.Element)(c, e, elemIndex, fileInfo);
3373
- if (elements) { elements.push(elem); } else { elements = [ elem ]; }
3525
+ if (elements) {
3526
+ elements.push(elem);
3527
+ } else {
3528
+ elements = [ elem ];
3529
+ }
3374
3530
  c = parserInput.$char('>');
3375
3531
  }
3376
3532
 
@@ -3628,8 +3784,10 @@ var Parser = function Parser(context, imports, fileInfo) {
3628
3784
 
3629
3785
  c = this.combinator();
3630
3786
 
3631
- e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) || parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
3632
- parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^()@]+\)/) || parserInput.$re(/^[\.#](?=@)/) ||
3787
+ e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) ||
3788
+ parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
3789
+ parserInput.$char('*') || parserInput.$char('&') || this.attribute() ||
3790
+ parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
3633
3791
  this.entities.variableCurly();
3634
3792
 
3635
3793
  if (! e) {
@@ -3709,11 +3867,19 @@ var Parser = function Parser(context, imports, fileInfo) {
3709
3867
  } else if (condition) {
3710
3868
  error("CSS guard can only be used at the end of selector");
3711
3869
  } else if (extendList) {
3712
- if (allExtends) { allExtends = allExtends.concat(extendList); } else { allExtends = extendList; }
3870
+ if (allExtends) {
3871
+ allExtends = allExtends.concat(extendList);
3872
+ } else {
3873
+ allExtends = extendList;
3874
+ }
3713
3875
  } else {
3714
3876
  if (allExtends) { error("Extend can only be used at the end of selector"); }
3715
3877
  c = parserInput.currentChar();
3716
- if (elements) { elements.push(e); } else { elements = [ e ]; }
3878
+ if (elements) {
3879
+ elements.push(e);
3880
+ } else {
3881
+ elements = [ e ];
3882
+ }
3717
3883
  e = null;
3718
3884
  }
3719
3885
  if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') {
@@ -3788,7 +3954,11 @@ var Parser = function Parser(context, imports, fileInfo) {
3788
3954
  if (!s) {
3789
3955
  break;
3790
3956
  }
3791
- if (selectors) { selectors.push(s); } else { selectors = [ s ]; }
3957
+ if (selectors) {
3958
+ selectors.push(s);
3959
+ } else {
3960
+ selectors = [ s ];
3961
+ }
3792
3962
  parserInput.commentStore.length = 0;
3793
3963
  if (s.condition && selectors.length > 1) {
3794
3964
  error("Guards are only currently allowed on a single selector.");
@@ -3925,11 +4095,11 @@ var Parser = function Parser(context, imports, fileInfo) {
3925
4095
  case "css":
3926
4096
  optionName = "less";
3927
4097
  value = false;
3928
- break;
4098
+ break;
3929
4099
  case "once":
3930
4100
  optionName = "multiple";
3931
4101
  value = false;
3932
- break;
4102
+ break;
3933
4103
  }
3934
4104
  options[optionName] = value;
3935
4105
  if (! parserInput.$char(',')) { break; }
@@ -3940,7 +4110,7 @@ var Parser = function Parser(context, imports, fileInfo) {
3940
4110
  },
3941
4111
 
3942
4112
  importOption: function() {
3943
- var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference)/);
4113
+ var opt = parserInput.$re(/^(less|css|multiple|once|inline|reference|optional)/);
3944
4114
  if (opt) {
3945
4115
  return opt[1];
3946
4116
  }
@@ -4140,7 +4310,7 @@ var Parser = function Parser(context, imports, fileInfo) {
4140
4310
  expressions.push(e);
4141
4311
  if (! parserInput.$char(',')) { break; }
4142
4312
  }
4143
- } while(e);
4313
+ } while (e);
4144
4314
 
4145
4315
  if (expressions.length > 0) {
4146
4316
  return new(tree.Value)(expressions);
@@ -4154,15 +4324,19 @@ var Parser = function Parser(context, imports, fileInfo) {
4154
4324
  sub: function () {
4155
4325
  var a, e;
4156
4326
 
4327
+ parserInput.save();
4157
4328
  if (parserInput.$char('(')) {
4158
4329
  a = this.addition();
4159
- if (a) {
4330
+ if (a && parserInput.$char(')')) {
4331
+ parserInput.forget();
4160
4332
  e = new(tree.Expression)([a]);
4161
- expectChar(')');
4162
4333
  e.parens = true;
4163
4334
  return e;
4164
4335
  }
4336
+ parserInput.restore("Expected ')'");
4337
+ return;
4165
4338
  }
4339
+ parserInput.restore();
4166
4340
  },
4167
4341
  multiplication: function () {
4168
4342
  var m, a, op, operation, isSpaced;
@@ -4369,8 +4543,8 @@ Parser.serializeVars = function(vars) {
4369
4543
  for (var name in vars) {
4370
4544
  if (Object.hasOwnProperty.call(vars, name)) {
4371
4545
  var value = vars[name];
4372
- s += ((name[0] === '@') ? '' : '@') + name +': '+ value +
4373
- ((('' + value).slice(-1) === ';') ? '' : ';');
4546
+ s += ((name[0] === '@') ? '' : '@') + name + ': ' + value +
4547
+ ((String(value).slice(-1) === ';') ? '' : ';');
4374
4548
  }
4375
4549
  }
4376
4550
 
@@ -4379,13 +4553,14 @@ Parser.serializeVars = function(vars) {
4379
4553
 
4380
4554
  module.exports = Parser;
4381
4555
 
4382
- },{"../less-error":30,"../tree":58,"../utils":79,"../visitors":83,"./parser-input":34}],36:[function(require,module,exports){
4556
+ },{"../less-error":30,"../tree":59,"../utils":80,"../visitors":84,"./parser-input":35}],37:[function(require,module,exports){
4383
4557
  /**
4384
4558
  * Plugin Manager
4385
4559
  */
4386
4560
  var PluginManager = function(less) {
4387
4561
  this.less = less;
4388
4562
  this.visitors = [];
4563
+ this.preProcessors = [];
4389
4564
  this.postProcessors = [];
4390
4565
  this.installedPlugins = [];
4391
4566
  this.fileManagers = [];
@@ -4396,7 +4571,7 @@ var PluginManager = function(less) {
4396
4571
  */
4397
4572
  PluginManager.prototype.addPlugins = function(plugins) {
4398
4573
  if (plugins) {
4399
- for(var i = 0;i < plugins.length; i++) {
4574
+ for (var i = 0; i < plugins.length; i++) {
4400
4575
  this.addPlugin(plugins[i]);
4401
4576
  }
4402
4577
  }
@@ -4417,6 +4592,20 @@ PluginManager.prototype.addPlugin = function(plugin) {
4417
4592
  PluginManager.prototype.addVisitor = function(visitor) {
4418
4593
  this.visitors.push(visitor);
4419
4594
  };
4595
+ /**
4596
+ * Adds a pre processor object
4597
+ * @param {object} preProcessor
4598
+ * @param {number} priority - guidelines 1 = before import, 1000 = import, 2000 = after import
4599
+ */
4600
+ PluginManager.prototype.addPreProcessor = function(preProcessor, priority) {
4601
+ var indexToInsertAt;
4602
+ for (indexToInsertAt = 0; indexToInsertAt < this.preProcessors.length; indexToInsertAt++) {
4603
+ if (this.preProcessors[indexToInsertAt].priority >= priority) {
4604
+ break;
4605
+ }
4606
+ }
4607
+ this.preProcessors.splice(indexToInsertAt, 0, {preProcessor: preProcessor, priority: priority});
4608
+ };
4420
4609
  /**
4421
4610
  * Adds a post processor object
4422
4611
  * @param {object} postProcessor
@@ -4424,7 +4613,7 @@ PluginManager.prototype.addVisitor = function(visitor) {
4424
4613
  */
4425
4614
  PluginManager.prototype.addPostProcessor = function(postProcessor, priority) {
4426
4615
  var indexToInsertAt;
4427
- for(indexToInsertAt = 0; indexToInsertAt < this.postProcessors.length; indexToInsertAt++) {
4616
+ for (indexToInsertAt = 0; indexToInsertAt < this.postProcessors.length; indexToInsertAt++) {
4428
4617
  if (this.postProcessors[indexToInsertAt].priority >= priority) {
4429
4618
  break;
4430
4619
  }
@@ -4438,6 +4627,18 @@ PluginManager.prototype.addPostProcessor = function(postProcessor, priority) {
4438
4627
  PluginManager.prototype.addFileManager = function(manager) {
4439
4628
  this.fileManagers.push(manager);
4440
4629
  };
4630
+ /**
4631
+ *
4632
+ * @returns {Array}
4633
+ * @private
4634
+ */
4635
+ PluginManager.prototype.getPreProcessors = function() {
4636
+ var preProcessors = [];
4637
+ for (var i = 0; i < this.preProcessors.length; i++) {
4638
+ preProcessors.push(this.preProcessors[i].preProcessor);
4639
+ }
4640
+ return preProcessors;
4641
+ };
4441
4642
  /**
4442
4643
  *
4443
4644
  * @returns {Array}
@@ -4445,7 +4646,7 @@ PluginManager.prototype.addFileManager = function(manager) {
4445
4646
  */
4446
4647
  PluginManager.prototype.getPostProcessors = function() {
4447
4648
  var postProcessors = [];
4448
- for(var i = 0; i < this.postProcessors.length; i++) {
4649
+ for (var i = 0; i < this.postProcessors.length; i++) {
4449
4650
  postProcessors.push(this.postProcessors[i].postProcessor);
4450
4651
  }
4451
4652
  return postProcessors;
@@ -4468,22 +4669,20 @@ PluginManager.prototype.getFileManagers = function() {
4468
4669
  };
4469
4670
  module.exports = PluginManager;
4470
4671
 
4471
- },{}],37:[function(require,module,exports){
4472
- var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise,
4473
- contexts = require("./contexts"),
4474
- Parser = require('./parser/parser'),
4475
- PluginManager = require('./plugin-manager');
4672
+ },{}],38:[function(require,module,exports){
4673
+ var PromiseConstructor;
4476
4674
 
4477
4675
  module.exports = function(environment, ParseTree, ImportManager) {
4478
4676
  var render = function (input, options, callback) {
4479
- options = options || {};
4480
-
4481
- if (typeof(options) === 'function') {
4677
+ if (typeof options === 'function') {
4482
4678
  callback = options;
4483
4679
  options = {};
4484
4680
  }
4485
4681
 
4486
4682
  if (!callback) {
4683
+ if (!PromiseConstructor) {
4684
+ PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
4685
+ }
4487
4686
  var self = this;
4488
4687
  return new PromiseConstructor(function (resolve, reject) {
4489
4688
  render.call(self, input, options, function(err, output) {
@@ -4495,49 +4694,25 @@ module.exports = function(environment, ParseTree, ImportManager) {
4495
4694
  });
4496
4695
  });
4497
4696
  } else {
4498
- var context,
4499
- rootFileInfo,
4500
- pluginManager = new PluginManager(this);
4501
-
4502
- pluginManager.addPlugins(options.plugins);
4503
- options.pluginManager = pluginManager;
4504
-
4505
- context = new contexts.Parse(options);
4506
-
4507
- if (options.rootFileInfo) {
4508
- rootFileInfo = options.rootFileInfo;
4509
- } else {
4510
- var filename = options.filename || "input";
4511
- var entryPath = filename.replace(/[^\/\\]*$/, "");
4512
- rootFileInfo = {
4513
- filename: filename,
4514
- relativeUrls: context.relativeUrls,
4515
- rootpath: context.rootpath || "",
4516
- currentDirectory: entryPath,
4517
- entryPath: entryPath,
4518
- rootFilename: filename
4519
- };
4520
- }
4697
+ this.parse(input, options, function(err, root, imports, options) {
4698
+ if (err) { return callback(err); }
4521
4699
 
4522
- var imports = new ImportManager(context, rootFileInfo);
4523
-
4524
- new Parser(context, imports, rootFileInfo)
4525
- .parse(input, function (e, root) {
4526
- if (e) { return callback(e); }
4527
4700
  var result;
4528
4701
  try {
4529
4702
  var parseTree = new ParseTree(root, imports);
4530
4703
  result = parseTree.toCSS(options);
4531
4704
  }
4532
- catch (err) { return callback( err); }
4705
+ catch (err) { return callback(err); }
4706
+
4533
4707
  callback(null, result);
4534
- }, options);
4708
+ });
4535
4709
  }
4536
4710
  };
4711
+
4537
4712
  return render;
4538
4713
  };
4539
4714
 
4540
- },{"./contexts":10,"./parser/parser":35,"./plugin-manager":36,"promise":undefined}],38:[function(require,module,exports){
4715
+ },{"promise":undefined}],39:[function(require,module,exports){
4541
4716
  module.exports = function (SourceMapOutput, environment) {
4542
4717
 
4543
4718
  var SourceMapBuilder = function (options) {
@@ -4570,8 +4745,12 @@ module.exports = function (SourceMapOutput, environment) {
4570
4745
  };
4571
4746
 
4572
4747
  SourceMapBuilder.prototype.getCSSAppendage = function() {
4748
+
4573
4749
  var sourceMapURL = this.sourceMapURL;
4574
4750
  if (this.options.sourceMapFileInline) {
4751
+ if (this.sourceMap === undefined) {
4752
+ return "";
4753
+ }
4575
4754
  sourceMapURL = "data:application/json;base64," + environment.encodeBase64(this.sourceMap);
4576
4755
  }
4577
4756
 
@@ -4604,7 +4783,7 @@ module.exports = function (SourceMapOutput, environment) {
4604
4783
  return SourceMapBuilder;
4605
4784
  };
4606
4785
 
4607
- },{}],39:[function(require,module,exports){
4786
+ },{}],40:[function(require,module,exports){
4608
4787
  module.exports = function (environment) {
4609
4788
 
4610
4789
  var SourceMapOutput = function (options) {
@@ -4622,7 +4801,7 @@ module.exports = function (environment) {
4622
4801
  }
4623
4802
  if (options.sourceMapRootpath) {
4624
4803
  this._sourceMapRootpath = options.sourceMapRootpath.replace(/\\/g, '/');
4625
- if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length-1) !== '/') {
4804
+ if (this._sourceMapRootpath.charAt(this._sourceMapRootpath.length - 1) !== '/') {
4626
4805
  this._sourceMapRootpath += '/';
4627
4806
  }
4628
4807
  } else {
@@ -4641,7 +4820,7 @@ module.exports = function (environment) {
4641
4820
  if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
4642
4821
  filename = filename.substring(this._sourceMapBasepath.length);
4643
4822
  if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
4644
- filename = filename.substring(1);
4823
+ filename = filename.substring(1);
4645
4824
  }
4646
4825
  }
4647
4826
  return (this._sourceMapRootpath || "") + filename;
@@ -4673,11 +4852,11 @@ module.exports = function (environment) {
4673
4852
  }
4674
4853
  inputSource = inputSource.substring(0, index);
4675
4854
  sourceLines = inputSource.split("\n");
4676
- sourceColumns = sourceLines[sourceLines.length-1];
4855
+ sourceColumns = sourceLines[sourceLines.length - 1];
4677
4856
  }
4678
4857
 
4679
4858
  lines = chunk.split("\n");
4680
- columns = lines[lines.length-1];
4859
+ columns = lines[lines.length - 1];
4681
4860
 
4682
4861
  if (fileInfo) {
4683
4862
  if (!mapLines) {
@@ -4685,7 +4864,7 @@ module.exports = function (environment) {
4685
4864
  original: { line: sourceLines.length, column: sourceColumns.length},
4686
4865
  source: this.normalizeFilename(fileInfo.filename)});
4687
4866
  } else {
4688
- for(i = 0; i < lines.length; i++) {
4867
+ for (i = 0; i < lines.length; i++) {
4689
4868
  this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + i + 1, column: i === 0 ? this._column : 0},
4690
4869
  original: { line: sourceLines.length + i, column: i === 0 ? sourceColumns.length : 0},
4691
4870
  source: this.normalizeFilename(fileInfo.filename)});
@@ -4711,7 +4890,7 @@ module.exports = function (environment) {
4711
4890
  this._sourceMapGenerator = new this._sourceMapGeneratorConstructor({ file: this._outputFilename, sourceRoot: null });
4712
4891
 
4713
4892
  if (this._outputSourceFiles) {
4714
- for(var filename in this._contentsMap) {
4893
+ for (var filename in this._contentsMap) {
4715
4894
  if (this._contentsMap.hasOwnProperty(filename))
4716
4895
  {
4717
4896
  var source = this._contentsMap[filename];
@@ -4745,7 +4924,7 @@ module.exports = function (environment) {
4745
4924
  return SourceMapOutput;
4746
4925
  };
4747
4926
 
4748
- },{}],40:[function(require,module,exports){
4927
+ },{}],41:[function(require,module,exports){
4749
4928
  var contexts = require("./contexts"),
4750
4929
  visitor = require("./visitors"),
4751
4930
  tree = require("./tree");
@@ -4769,7 +4948,7 @@ module.exports = function(root, options) {
4769
4948
  // ])
4770
4949
  // )
4771
4950
  //
4772
- if (typeof(variables) === 'object' && !Array.isArray(variables)) {
4951
+ if (typeof variables === 'object' && !Array.isArray(variables)) {
4773
4952
  variables = Object.keys(variables).map(function (k) {
4774
4953
  var value = variables[k];
4775
4954
 
@@ -4793,7 +4972,7 @@ module.exports = function(root, options) {
4793
4972
 
4794
4973
  if (options.pluginManager) {
4795
4974
  var pluginVisitors = options.pluginManager.getVisitors();
4796
- for(i =0; i < pluginVisitors.length; i++) {
4975
+ for (i = 0; i < pluginVisitors.length; i++) {
4797
4976
  var pluginVisitor = pluginVisitors[i];
4798
4977
  if (pluginVisitor.isPreEvalVisitor) {
4799
4978
  preEvalVisitors.push(pluginVisitor);
@@ -4807,20 +4986,20 @@ module.exports = function(root, options) {
4807
4986
  }
4808
4987
  }
4809
4988
 
4810
- for(i = 0; i < preEvalVisitors.length; i++) {
4989
+ for (i = 0; i < preEvalVisitors.length; i++) {
4811
4990
  preEvalVisitors[i].run(root);
4812
4991
  }
4813
4992
 
4814
4993
  evaldRoot = root.eval(evalEnv);
4815
4994
 
4816
- for(i = 0; i < visitors.length; i++) {
4995
+ for (i = 0; i < visitors.length; i++) {
4817
4996
  visitors[i].run(evaldRoot);
4818
4997
  }
4819
4998
 
4820
4999
  return evaldRoot;
4821
5000
  };
4822
5001
 
4823
- },{"./contexts":10,"./tree":58,"./visitors":83}],41:[function(require,module,exports){
5002
+ },{"./contexts":10,"./tree":59,"./visitors":84}],42:[function(require,module,exports){
4824
5003
  var Node = require("./node");
4825
5004
 
4826
5005
  var Alpha = function (val) {
@@ -4850,7 +5029,7 @@ Alpha.prototype.genCSS = function (context, output) {
4850
5029
 
4851
5030
  module.exports = Alpha;
4852
5031
 
4853
- },{"./node":66}],42:[function(require,module,exports){
5032
+ },{"./node":67}],43:[function(require,module,exports){
4854
5033
  var Node = require("./node");
4855
5034
 
4856
5035
  var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) {
@@ -4858,7 +5037,7 @@ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike)
4858
5037
  this.index = index;
4859
5038
  this.mapLines = mapLines;
4860
5039
  this.currentFileInfo = currentFileInfo;
4861
- this.rulesetLike = (typeof rulesetLike === 'undefined')? false : rulesetLike;
5040
+ this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
4862
5041
  };
4863
5042
  Anonymous.prototype = new Node();
4864
5043
  Anonymous.prototype.type = "Anonymous";
@@ -4876,7 +5055,7 @@ Anonymous.prototype.genCSS = function (context, output) {
4876
5055
  };
4877
5056
  module.exports = Anonymous;
4878
5057
 
4879
- },{"./node":66}],43:[function(require,module,exports){
5058
+ },{"./node":67}],44:[function(require,module,exports){
4880
5059
  var Node = require("./node");
4881
5060
 
4882
5061
  var Assignment = function (key, val) {
@@ -4905,8 +5084,7 @@ Assignment.prototype.genCSS = function (context, output) {
4905
5084
  };
4906
5085
  module.exports = Assignment;
4907
5086
 
4908
-
4909
- },{"./node":66}],44:[function(require,module,exports){
5087
+ },{"./node":67}],45:[function(require,module,exports){
4910
5088
  var Node = require("./node");
4911
5089
 
4912
5090
  var Attribute = function (key, op, value) {
@@ -4935,7 +5113,7 @@ Attribute.prototype.toCSS = function (context) {
4935
5113
  };
4936
5114
  module.exports = Attribute;
4937
5115
 
4938
- },{"./node":66}],45:[function(require,module,exports){
5116
+ },{"./node":67}],46:[function(require,module,exports){
4939
5117
  var Node = require("./node"),
4940
5118
  FunctionCaller = require("../functions/function-caller");
4941
5119
  //
@@ -4988,7 +5166,7 @@ Call.prototype.eval = function (context) {
4988
5166
  Call.prototype.genCSS = function (context, output) {
4989
5167
  output.add(this.name + "(", this.currentFileInfo, this.index);
4990
5168
 
4991
- for(var i = 0; i < this.args.length; i++) {
5169
+ for (var i = 0; i < this.args.length; i++) {
4992
5170
  this.args[i].genCSS(context, output);
4993
5171
  if (i + 1 < this.args.length) {
4994
5172
  output.add(", ");
@@ -4999,7 +5177,7 @@ Call.prototype.genCSS = function (context, output) {
4999
5177
  };
5000
5178
  module.exports = Call;
5001
5179
 
5002
- },{"../functions/function-caller":20,"./node":66}],46:[function(require,module,exports){
5180
+ },{"../functions/function-caller":20,"./node":67}],47:[function(require,module,exports){
5003
5181
  var Node = require("./node"),
5004
5182
  colors = require("../data/colors");
5005
5183
 
@@ -5024,7 +5202,7 @@ var Color = function (rgb, a) {
5024
5202
  return parseInt(c + c, 16);
5025
5203
  });
5026
5204
  }
5027
- this.alpha = typeof(a) === 'number' ? a : 1;
5205
+ this.alpha = typeof a === 'number' ? a : 1;
5028
5206
  };
5029
5207
 
5030
5208
  Color.prototype = new Node();
@@ -5058,11 +5236,11 @@ Color.prototype.genCSS = function (context, output) {
5058
5236
  Color.prototype.toCSS = function (context, doNotCompress) {
5059
5237
  var compress = context && context.compress && !doNotCompress, color, alpha;
5060
5238
 
5061
- // `keyword` is set if this color was originally
5239
+ // `value` is set if this color was originally
5062
5240
  // converted from a named color string so we need
5063
5241
  // to respect this and try to output named color too.
5064
- if (this.keyword) {
5065
- return this.keyword;
5242
+ if (this.value) {
5243
+ return this.value;
5066
5244
  }
5067
5245
 
5068
5246
  // If we have some transparency, the only way to represent it
@@ -5151,7 +5329,7 @@ Color.prototype.toHSV = function () {
5151
5329
  if (max === min) {
5152
5330
  h = 0;
5153
5331
  } else {
5154
- switch(max){
5332
+ switch(max) {
5155
5333
  case r: h = (g - b) / d + (g < b ? 6 : 0); break;
5156
5334
  case g: h = (b - r) / d + 2; break;
5157
5335
  case b: h = (r - g) / d + 4; break;
@@ -5181,13 +5359,13 @@ Color.fromKeyword = function(keyword) {
5181
5359
  }
5182
5360
 
5183
5361
  if (c) {
5184
- c.keyword = keyword;
5362
+ c.value = keyword;
5185
5363
  return c;
5186
5364
  }
5187
5365
  };
5188
5366
  module.exports = Color;
5189
5367
 
5190
- },{"../data/colors":11,"./node":66}],47:[function(require,module,exports){
5368
+ },{"../data/colors":11,"./node":67}],48:[function(require,module,exports){
5191
5369
  var Node = require("./node");
5192
5370
 
5193
5371
  var Combinator = function (value) {
@@ -5212,7 +5390,7 @@ Combinator.prototype.genCSS = function (context, output) {
5212
5390
  };
5213
5391
  module.exports = Combinator;
5214
5392
 
5215
- },{"./node":66}],48:[function(require,module,exports){
5393
+ },{"./node":67}],49:[function(require,module,exports){
5216
5394
  var Node = require("./node"),
5217
5395
  getDebugInfo = require("./debug-info");
5218
5396
 
@@ -5242,7 +5420,7 @@ Comment.prototype.isRulesetLike = function(root) {
5242
5420
  };
5243
5421
  module.exports = Comment;
5244
5422
 
5245
- },{"./debug-info":50,"./node":66}],49:[function(require,module,exports){
5423
+ },{"./debug-info":51,"./node":67}],50:[function(require,module,exports){
5246
5424
  var Node = require("./node");
5247
5425
 
5248
5426
  var Condition = function (op, l, r, i, negate) {
@@ -5265,21 +5443,25 @@ Condition.prototype.eval = function (context) {
5265
5443
  case 'or': return a || b;
5266
5444
  default:
5267
5445
  switch (Node.compare(a, b)) {
5268
- case -1: return op === '<' || op === '=<' || op === '<=';
5269
- case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
5270
- case 1: return op === '>' || op === '>=';
5271
- default: return false;
5446
+ case -1:
5447
+ return op === '<' || op === '=<' || op === '<=';
5448
+ case 0:
5449
+ return op === '=' || op === '>=' || op === '=<' || op === '<=';
5450
+ case 1:
5451
+ return op === '>' || op === '>=';
5452
+ default:
5453
+ return false;
5272
5454
  }
5273
5455
  }
5274
- }) (this.op, this.lvalue.eval(context), this.rvalue.eval(context));
5456
+ })(this.op, this.lvalue.eval(context), this.rvalue.eval(context));
5275
5457
 
5276
5458
  return this.negate ? !result : result;
5277
5459
  };
5278
5460
  module.exports = Condition;
5279
5461
 
5280
- },{"./node":66}],50:[function(require,module,exports){
5462
+ },{"./node":67}],51:[function(require,module,exports){
5281
5463
  var debugInfo = function(context, ctx, lineSeparator) {
5282
- var result="";
5464
+ var result = "";
5283
5465
  if (context.dumpLineNumbers && !context.compress) {
5284
5466
  switch(context.dumpLineNumbers) {
5285
5467
  case 'comments':
@@ -5301,8 +5483,12 @@ debugInfo.asComment = function(ctx) {
5301
5483
  };
5302
5484
 
5303
5485
  debugInfo.asMediaQuery = function(ctx) {
5486
+ var filenameWithProtocol = ctx.debugInfo.fileName;
5487
+ if (!/^[a-z]+:\/\//i.test(filenameWithProtocol)) {
5488
+ filenameWithProtocol = 'file://' + filenameWithProtocol;
5489
+ }
5304
5490
  return '@media -sass-debug-info{filename{font-family:' +
5305
- ('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) {
5491
+ filenameWithProtocol.replace(/([.:\/\\])/g, function (a) {
5306
5492
  if (a == '\\') {
5307
5493
  a = '\/';
5308
5494
  }
@@ -5313,7 +5499,7 @@ debugInfo.asMediaQuery = function(ctx) {
5313
5499
 
5314
5500
  module.exports = debugInfo;
5315
5501
 
5316
- },{}],51:[function(require,module,exports){
5502
+ },{}],52:[function(require,module,exports){
5317
5503
  var Node = require("./node"),
5318
5504
  contexts = require("../contexts");
5319
5505
 
@@ -5336,7 +5522,7 @@ DetachedRuleset.prototype.callEval = function (context) {
5336
5522
  };
5337
5523
  module.exports = DetachedRuleset;
5338
5524
 
5339
- },{"../contexts":10,"./node":66}],52:[function(require,module,exports){
5525
+ },{"../contexts":10,"./node":67}],53:[function(require,module,exports){
5340
5526
  var Node = require("./node"),
5341
5527
  unitConversions = require("../data/unit-conversions"),
5342
5528
  Unit = require("./unit"),
@@ -5364,7 +5550,7 @@ Dimension.prototype.toColor = function () {
5364
5550
  };
5365
5551
  Dimension.prototype.genCSS = function (context, output) {
5366
5552
  if ((context && context.strictUnits) && !this.unit.isSingular()) {
5367
- throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
5553
+ throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: " + this.unit.toString());
5368
5554
  }
5369
5555
 
5370
5556
  var value = this.fround(context, this.value),
@@ -5409,9 +5595,9 @@ Dimension.prototype.operate = function (context, op, other) {
5409
5595
  } else {
5410
5596
  other = other.convertTo(this.unit.usedUnits());
5411
5597
 
5412
- if(context.strictUnits && other.unit.toString() !== unit.toString()) {
5413
- throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
5414
- "' and '" + other.unit.toString() + "'.");
5598
+ if (context.strictUnits && other.unit.toString() !== unit.toString()) {
5599
+ throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
5600
+ "' and '" + other.unit.toString() + "'.");
5415
5601
  }
5416
5602
 
5417
5603
  value = this._operate(context, op, this.value, other.value);
@@ -5455,7 +5641,7 @@ Dimension.prototype.convertTo = function (conversions) {
5455
5641
  i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
5456
5642
 
5457
5643
  if (typeof conversions === 'string') {
5458
- for(i in unitConversions) {
5644
+ for (i in unitConversions) {
5459
5645
  if (unitConversions[i].hasOwnProperty(conversions)) {
5460
5646
  derivedConversions = {};
5461
5647
  derivedConversions[i] = conversions;
@@ -5493,11 +5679,11 @@ Dimension.prototype.convertTo = function (conversions) {
5493
5679
  };
5494
5680
  module.exports = Dimension;
5495
5681
 
5496
- },{"../data/unit-conversions":13,"./color":46,"./node":66,"./unit":75}],53:[function(require,module,exports){
5682
+ },{"../data/unit-conversions":13,"./color":47,"./node":67,"./unit":76}],54:[function(require,module,exports){
5497
5683
  var Node = require("./node"),
5498
5684
  Ruleset = require("./ruleset");
5499
5685
 
5500
- var Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
5686
+ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isReferenced) {
5501
5687
  this.name = name;
5502
5688
  this.value = value;
5503
5689
  if (rules) {
@@ -5507,6 +5693,7 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo)
5507
5693
  this.index = index;
5508
5694
  this.currentFileInfo = currentFileInfo;
5509
5695
  this.debugInfo = debugInfo;
5696
+ this.isReferenced = isReferenced;
5510
5697
  };
5511
5698
 
5512
5699
  Directive.prototype = new Node();
@@ -5534,7 +5721,10 @@ Directive.prototype.genCSS = function (context, output) {
5534
5721
  value.genCSS(context, output);
5535
5722
  }
5536
5723
  if (rules) {
5537
- this.outputRuleset(context, output, [rules]);
5724
+ if (rules.type === "Ruleset") {
5725
+ rules = [rules];
5726
+ }
5727
+ this.outputRuleset(context, output, rules);
5538
5728
  } else {
5539
5729
  output.add(';');
5540
5730
  }
@@ -5549,11 +5739,23 @@ Directive.prototype.eval = function (context) {
5549
5739
  rules.root = true;
5550
5740
  }
5551
5741
  return new Directive(this.name, value, rules,
5552
- this.index, this.currentFileInfo, this.debugInfo);
5742
+ this.index, this.currentFileInfo, this.debugInfo, this.isReferenced);
5743
+ };
5744
+ Directive.prototype.variable = function (name) {
5745
+ if (this.rules) {
5746
+ return Ruleset.prototype.variable.call(this.rules, name);
5747
+ }
5748
+ };
5749
+ Directive.prototype.find = function () {
5750
+ if (this.rules) {
5751
+ return Ruleset.prototype.find.apply(this.rules, arguments);
5752
+ }
5753
+ };
5754
+ Directive.prototype.rulesets = function () {
5755
+ if (this.rules) {
5756
+ return Ruleset.prototype.rulesets.apply(this.rules);
5757
+ }
5553
5758
  };
5554
- Directive.prototype.variable = function (name) { if (this.rules) return Ruleset.prototype.variable.call(this.rules, name); };
5555
- Directive.prototype.find = function () { if (this.rules) return Ruleset.prototype.find.apply(this.rules, arguments); };
5556
- Directive.prototype.rulesets = function () { if (this.rules) return Ruleset.prototype.rulesets.apply(this.rules); };
5557
5759
  Directive.prototype.markReferenced = function () {
5558
5760
  var i, rules;
5559
5761
  this.isReferenced = true;
@@ -5566,6 +5768,9 @@ Directive.prototype.markReferenced = function () {
5566
5768
  }
5567
5769
  }
5568
5770
  };
5771
+ Directive.prototype.getIsReferenced = function () {
5772
+ return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
5773
+ };
5569
5774
  Directive.prototype.outputRuleset = function (context, output, rules) {
5570
5775
  var ruleCnt = rules.length, i;
5571
5776
  context.tabLevel = (context.tabLevel | 0) + 1;
@@ -5599,7 +5804,7 @@ Directive.prototype.outputRuleset = function (context, output, rules) {
5599
5804
  };
5600
5805
  module.exports = Directive;
5601
5806
 
5602
- },{"./node":66,"./ruleset":72}],54:[function(require,module,exports){
5807
+ },{"./node":67,"./ruleset":73}],55:[function(require,module,exports){
5603
5808
  var Node = require("./node"),
5604
5809
  Paren = require("./paren"),
5605
5810
  Combinator = require("./combinator");
@@ -5608,7 +5813,7 @@ var Element = function (combinator, value, index, currentFileInfo) {
5608
5813
  this.combinator = combinator instanceof Combinator ?
5609
5814
  combinator : new Combinator(combinator);
5610
5815
 
5611
- if (typeof(value) === 'string') {
5816
+ if (typeof value === 'string') {
5612
5817
  this.value = value.trim();
5613
5818
  } else if (value) {
5614
5819
  this.value = value;
@@ -5654,7 +5859,7 @@ Element.prototype.toCSS = function (context) {
5654
5859
  };
5655
5860
  module.exports = Element;
5656
5861
 
5657
- },{"./combinator":47,"./node":66,"./paren":68}],55:[function(require,module,exports){
5862
+ },{"./combinator":48,"./node":67,"./paren":69}],56:[function(require,module,exports){
5658
5863
  var Node = require("./node"),
5659
5864
  Paren = require("./paren"),
5660
5865
  Comment = require("./comment");
@@ -5662,7 +5867,7 @@ var Node = require("./node"),
5662
5867
  var Expression = function (value) {
5663
5868
  this.value = value;
5664
5869
  if (!value) {
5665
- throw new Error("Expression requires a array parameter");
5870
+ throw new Error("Expression requires an array parameter");
5666
5871
  }
5667
5872
  };
5668
5873
  Expression.prototype = new Node();
@@ -5698,7 +5903,7 @@ Expression.prototype.eval = function (context) {
5698
5903
  return returnValue;
5699
5904
  };
5700
5905
  Expression.prototype.genCSS = function (context, output) {
5701
- for(var i = 0; i < this.value.length; i++) {
5906
+ for (var i = 0; i < this.value.length; i++) {
5702
5907
  this.value[i].genCSS(context, output);
5703
5908
  if (i + 1 < this.value.length) {
5704
5909
  output.add(" ");
@@ -5712,7 +5917,7 @@ Expression.prototype.throwAwayComments = function () {
5712
5917
  };
5713
5918
  module.exports = Expression;
5714
5919
 
5715
- },{"./comment":48,"./node":66,"./paren":68}],56:[function(require,module,exports){
5920
+ },{"./comment":49,"./node":67,"./paren":69}],57:[function(require,module,exports){
5716
5921
  var Node = require("./node");
5717
5922
 
5718
5923
  var Extend = function Extend(selector, option, index) {
@@ -5726,11 +5931,11 @@ var Extend = function Extend(selector, option, index) {
5726
5931
  case "all":
5727
5932
  this.allowBefore = true;
5728
5933
  this.allowAfter = true;
5729
- break;
5934
+ break;
5730
5935
  default:
5731
5936
  this.allowBefore = false;
5732
5937
  this.allowAfter = false;
5733
- break;
5938
+ break;
5734
5939
  }
5735
5940
  };
5736
5941
  Extend.next_id = 0;
@@ -5751,7 +5956,7 @@ Extend.prototype.findSelfSelectors = function (selectors) {
5751
5956
  i,
5752
5957
  selectorElements;
5753
5958
 
5754
- for(i = 0; i < selectors.length; i++) {
5959
+ for (i = 0; i < selectors.length; i++) {
5755
5960
  selectorElements = selectors[i].elements;
5756
5961
  // duplicate the logic in genCSS function inside the selector node.
5757
5962
  // future TODO - move both logics into the selector joiner visitor
@@ -5765,7 +5970,7 @@ Extend.prototype.findSelfSelectors = function (selectors) {
5765
5970
  };
5766
5971
  module.exports = Extend;
5767
5972
 
5768
- },{"./node":66}],57:[function(require,module,exports){
5973
+ },{"./node":67}],58:[function(require,module,exports){
5769
5974
  var Node = require("./node"),
5770
5975
  Media = require("./media"),
5771
5976
  URL = require("./url"),
@@ -5796,7 +6001,7 @@ var Import = function (path, features, options, index, currentFileInfo) {
5796
6001
  this.css = !this.options.less || this.options.inline;
5797
6002
  } else {
5798
6003
  var pathValue = this.getPath();
5799
- if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
6004
+ if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
5800
6005
  this.css = true;
5801
6006
  }
5802
6007
  }
@@ -5868,7 +6073,7 @@ Import.prototype.evalPath = function (context) {
5868
6073
  var pathValue = path.value;
5869
6074
  // Add the base path if the import is relative
5870
6075
  if (pathValue && context.isPathRelative(pathValue)) {
5871
- path.value = rootpath +pathValue;
6076
+ path.value = rootpath + pathValue;
5872
6077
  }
5873
6078
  }
5874
6079
  path.value = context.normalizePath(path.value);
@@ -5907,9 +6112,10 @@ Import.prototype.eval = function (context) {
5907
6112
  };
5908
6113
  module.exports = Import;
5909
6114
 
5910
- },{"./anonymous":42,"./media":62,"./node":66,"./quoted":69,"./ruleset":72,"./url":76}],58:[function(require,module,exports){
6115
+ },{"./anonymous":43,"./media":63,"./node":67,"./quoted":70,"./ruleset":73,"./url":77}],59:[function(require,module,exports){
5911
6116
  var tree = {};
5912
6117
 
6118
+ tree.Node = require('./node');
5913
6119
  tree.Alpha = require('./alpha');
5914
6120
  tree.Color = require('./color');
5915
6121
  tree.Directive = require('./directive');
@@ -5949,7 +6155,7 @@ tree.RulesetCall = require('./ruleset-call');
5949
6155
 
5950
6156
  module.exports = tree;
5951
6157
 
5952
- },{"./alpha":41,"./anonymous":42,"./assignment":43,"./attribute":44,"./call":45,"./color":46,"./combinator":47,"./comment":48,"./condition":49,"./detached-ruleset":51,"./dimension":52,"./directive":53,"./element":54,"./expression":55,"./extend":56,"./import":57,"./javascript":59,"./keyword":61,"./media":62,"./mixin-call":63,"./mixin-definition":64,"./negative":65,"./operation":67,"./paren":68,"./quoted":69,"./rule":70,"./ruleset":72,"./ruleset-call":71,"./selector":73,"./unicode-descriptor":74,"./unit":75,"./url":76,"./value":77,"./variable":78}],59:[function(require,module,exports){
6158
+ },{"./alpha":42,"./anonymous":43,"./assignment":44,"./attribute":45,"./call":46,"./color":47,"./combinator":48,"./comment":49,"./condition":50,"./detached-ruleset":52,"./dimension":53,"./directive":54,"./element":55,"./expression":56,"./extend":57,"./import":58,"./javascript":60,"./keyword":62,"./media":63,"./mixin-call":64,"./mixin-definition":65,"./negative":66,"./node":67,"./operation":68,"./paren":69,"./quoted":70,"./rule":71,"./ruleset":73,"./ruleset-call":72,"./selector":74,"./unicode-descriptor":75,"./unit":76,"./url":77,"./value":78,"./variable":79}],60:[function(require,module,exports){
5953
6159
  var JsEvalNode = require("./js-eval-node"),
5954
6160
  Dimension = require("./dimension"),
5955
6161
  Quoted = require("./quoted"),
@@ -5966,9 +6172,9 @@ JavaScript.prototype.type = "JavaScript";
5966
6172
  JavaScript.prototype.eval = function(context) {
5967
6173
  var result = this.evaluateJavaScript(this.expression, context);
5968
6174
 
5969
- if (typeof(result) === 'number') {
6175
+ if (typeof result === 'number') {
5970
6176
  return new Dimension(result);
5971
- } else if (typeof(result) === 'string') {
6177
+ } else if (typeof result === 'string') {
5972
6178
  return new Quoted('"' + result + '"', result, this.escaped, this.index);
5973
6179
  } else if (Array.isArray(result)) {
5974
6180
  return new Anonymous(result.join(', '));
@@ -5979,7 +6185,7 @@ JavaScript.prototype.eval = function(context) {
5979
6185
 
5980
6186
  module.exports = JavaScript;
5981
6187
 
5982
- },{"./anonymous":42,"./dimension":52,"./js-eval-node":60,"./quoted":69}],60:[function(require,module,exports){
6188
+ },{"./anonymous":43,"./dimension":53,"./js-eval-node":61,"./quoted":70}],61:[function(require,module,exports){
5983
6189
  var Node = require("./node"),
5984
6190
  Variable = require("./variable");
5985
6191
 
@@ -6042,7 +6248,7 @@ JsEvalNode.prototype.jsify = function (obj) {
6042
6248
 
6043
6249
  module.exports = JsEvalNode;
6044
6250
 
6045
- },{"./node":66,"./variable":78}],61:[function(require,module,exports){
6251
+ },{"./node":67,"./variable":79}],62:[function(require,module,exports){
6046
6252
  var Node = require("./node");
6047
6253
 
6048
6254
  var Keyword = function (value) { this.value = value; };
@@ -6058,7 +6264,7 @@ Keyword.False = new Keyword('false');
6058
6264
 
6059
6265
  module.exports = Keyword;
6060
6266
 
6061
- },{"./node":66}],62:[function(require,module,exports){
6267
+ },{"./node":67}],63:[function(require,module,exports){
6062
6268
  var Ruleset = require("./ruleset"),
6063
6269
  Value = require("./value"),
6064
6270
  Element = require("./element"),
@@ -6100,7 +6306,7 @@ Media.prototype.eval = function (context) {
6100
6306
  }
6101
6307
 
6102
6308
  var media = new Media(null, [], this.index, this.currentFileInfo);
6103
- if(this.debugInfo) {
6309
+ if (this.debugInfo) {
6104
6310
  this.rules[0].debugInfo = this.debugInfo;
6105
6311
  media.debugInfo = this.debugInfo;
6106
6312
  }
@@ -6188,7 +6394,7 @@ Media.prototype.evalNested = function (context) {
6188
6394
  return fragment.toCSS ? fragment : new Anonymous(fragment);
6189
6395
  });
6190
6396
 
6191
- for(i = path.length - 1; i > 0; i--) {
6397
+ for (i = path.length - 1; i > 0; i--) {
6192
6398
  path.splice(i, 0, new Anonymous("and"));
6193
6399
  }
6194
6400
 
@@ -6199,29 +6405,30 @@ Media.prototype.evalNested = function (context) {
6199
6405
  return new Ruleset([], []);
6200
6406
  };
6201
6407
  Media.prototype.permute = function (arr) {
6202
- if (arr.length === 0) {
6203
- return [];
6204
- } else if (arr.length === 1) {
6205
- return arr[0];
6206
- } else {
6207
- var result = [];
6208
- var rest = this.permute(arr.slice(1));
6209
- for (var i = 0; i < rest.length; i++) {
6210
- for (var j = 0; j < arr[0].length; j++) {
6211
- result.push([arr[0][j]].concat(rest[i]));
6212
- }
6213
- }
6214
- return result;
6215
- }
6408
+ if (arr.length === 0) {
6409
+ return [];
6410
+ } else if (arr.length === 1) {
6411
+ return arr[0];
6412
+ } else {
6413
+ var result = [];
6414
+ var rest = this.permute(arr.slice(1));
6415
+ for (var i = 0; i < rest.length; i++) {
6416
+ for (var j = 0; j < arr[0].length; j++) {
6417
+ result.push([arr[0][j]].concat(rest[i]));
6418
+ }
6419
+ }
6420
+ return result;
6421
+ }
6216
6422
  };
6217
6423
  Media.prototype.bubbleSelectors = function (selectors) {
6218
- if (!selectors)
6219
- return;
6220
- this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
6424
+ if (!selectors) {
6425
+ return;
6426
+ }
6427
+ this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
6221
6428
  };
6222
6429
  module.exports = Media;
6223
6430
 
6224
- },{"./anonymous":42,"./directive":53,"./element":54,"./expression":55,"./ruleset":72,"./selector":73,"./value":77}],63:[function(require,module,exports){
6431
+ },{"./anonymous":43,"./directive":54,"./element":55,"./expression":56,"./ruleset":73,"./selector":74,"./value":78}],64:[function(require,module,exports){
6225
6432
  var Node = require("./node"),
6226
6433
  Selector = require("./selector"),
6227
6434
  MixinDefinition = require("./mixin-definition"),
@@ -6246,7 +6453,7 @@ MixinCall.prototype.accept = function (visitor) {
6246
6453
  };
6247
6454
  MixinCall.prototype.eval = function (context) {
6248
6455
  var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
6249
- candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase=-1,
6456
+ candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
6250
6457
  defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
6251
6458
 
6252
6459
  function calcDefGroup(mixin, mixinPath) {
@@ -6255,7 +6462,7 @@ MixinCall.prototype.eval = function (context) {
6255
6462
  for (f = 0; f < 2; f++) {
6256
6463
  conditionResult[f] = true;
6257
6464
  defaultFunc.value(f);
6258
- for(p = 0; p < mixinPath.length && conditionResult[f]; p++) {
6465
+ for (p = 0; p < mixinPath.length && conditionResult[f]; p++) {
6259
6466
  namespace = mixinPath[p];
6260
6467
  if (namespace.matchCondition) {
6261
6468
  conditionResult[f] = conditionResult[f] && namespace.matchCondition(null, context);
@@ -6295,7 +6502,7 @@ MixinCall.prototype.eval = function (context) {
6295
6502
  mixin = mixins[m].rule;
6296
6503
  mixinPath = mixins[m].path;
6297
6504
  isRecursive = false;
6298
- for(f = 0; f < context.frames.length; f++) {
6505
+ for (f = 0; f < context.frames.length; f++) {
6299
6506
  if ((!(mixin instanceof MixinDefinition)) && mixin === (context.frames[f].originalRuleset || context.frames[f])) {
6300
6507
  isRecursive = true;
6301
6508
  break;
@@ -6308,7 +6515,7 @@ MixinCall.prototype.eval = function (context) {
6308
6515
  if (mixin.matchArgs(args, context)) {
6309
6516
  candidate = {mixin: mixin, group: calcDefGroup(mixin, mixinPath)};
6310
6517
 
6311
- if (candidate.group!==defFalseEitherCase) {
6518
+ if (candidate.group !== defFalseEitherCase) {
6312
6519
  candidates.push(candidate);
6313
6520
  }
6314
6521
 
@@ -6329,8 +6536,7 @@ MixinCall.prototype.eval = function (context) {
6329
6536
  defaultResult = defTrue;
6330
6537
  if ((count[defTrue] + count[defFalse]) > 1) {
6331
6538
  throw { type: 'Runtime',
6332
- message: 'Ambiguous use of `default()` found when matching for `'
6333
- + this.format(args) + '`',
6539
+ message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
6334
6540
  index: this.index, filename: this.currentFileInfo.filename };
6335
6541
  }
6336
6542
  }
@@ -6393,7 +6599,7 @@ MixinCall.prototype.format = function (args) {
6393
6599
  };
6394
6600
  module.exports = MixinCall;
6395
6601
 
6396
- },{"../functions/default":19,"./mixin-definition":64,"./node":66,"./selector":73}],64:[function(require,module,exports){
6602
+ },{"../functions/default":19,"./mixin-definition":65,"./node":67,"./selector":74}],65:[function(require,module,exports){
6397
6603
  var Selector = require("./selector"),
6398
6604
  Element = require("./element"),
6399
6605
  Ruleset = require("./ruleset"),
@@ -6411,8 +6617,12 @@ var Definition = function (name, params, rules, condition, variadic, frames) {
6411
6617
  this.rules = rules;
6412
6618
  this._lookups = {};
6413
6619
  this.required = params.reduce(function (count, p) {
6414
- if (!p.name || (p.name && !p.value)) { return count + 1; }
6415
- else { return count; }
6620
+ if (!p.name || (p.name && !p.value)) {
6621
+ return count + 1;
6622
+ }
6623
+ else {
6624
+ return count;
6625
+ }
6416
6626
  }, 0);
6417
6627
  this.frames = frames;
6418
6628
  };
@@ -6441,11 +6651,11 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume
6441
6651
  args = args.slice(0);
6442
6652
  argsLength = args.length;
6443
6653
 
6444
- for(i = 0; i < argsLength; i++) {
6654
+ for (i = 0; i < argsLength; i++) {
6445
6655
  arg = args[i];
6446
6656
  if (name = (arg && arg.name)) {
6447
6657
  isNamedFound = false;
6448
- for(j = 0; j < params.length; j++) {
6658
+ for (j = 0; j < params.length; j++) {
6449
6659
  if (!evaldArguments[j] && name === params[j].name) {
6450
6660
  evaldArguments[j] = arg.value.eval(context);
6451
6661
  frame.prependRule(new Rule(name, arg.value.eval(context)));
@@ -6504,6 +6714,17 @@ Definition.prototype.evalParams = function (context, mixinEnv, args, evaldArgume
6504
6714
 
6505
6715
  return frame;
6506
6716
  };
6717
+ Definition.prototype.makeImportant = function() {
6718
+ var rules = !this.rules ? this.rules : this.rules.map(function (r) {
6719
+ if (r.makeImportant) {
6720
+ return r.makeImportant(true);
6721
+ } else {
6722
+ return r;
6723
+ }
6724
+ });
6725
+ var result = new Definition (this.name, this.params, rules, this.condition, this.variadic, this.frames);
6726
+ return result;
6727
+ };
6507
6728
  Definition.prototype.eval = function (context) {
6508
6729
  return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0));
6509
6730
  };
@@ -6521,16 +6742,17 @@ Definition.prototype.evalCall = function (context, args, important) {
6521
6742
  ruleset.originalRuleset = this;
6522
6743
  ruleset = ruleset.eval(new contexts.Eval(context, [this, frame].concat(mixinFrames)));
6523
6744
  if (important) {
6524
- ruleset = this.makeImportant.apply(ruleset);
6745
+ ruleset = ruleset.makeImportant();
6525
6746
  }
6526
6747
  return ruleset;
6527
6748
  };
6528
6749
  Definition.prototype.matchCondition = function (args, context) {
6529
6750
  if (this.condition && !this.condition.eval(
6530
6751
  new contexts.Eval(context,
6531
- [this.evalParams(context, new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])] // the parameter variables
6532
- .concat(this.frames) // the parent namespace/mixin frames
6533
- .concat(context.frames)))) { // the current environment frames
6752
+ [this.evalParams(context, /* the parameter variables*/
6753
+ new contexts.Eval(context, this.frames ? this.frames.concat(context.frames) : context.frames), args, [])]
6754
+ .concat(this.frames) // the parent namespace/mixin frames
6755
+ .concat(context.frames)))) { // the current environment frames
6534
6756
  return false;
6535
6757
  }
6536
6758
  return true;
@@ -6539,10 +6761,16 @@ Definition.prototype.matchArgs = function (args, context) {
6539
6761
  var argsLength = (args && args.length) || 0, len;
6540
6762
 
6541
6763
  if (! this.variadic) {
6542
- if (argsLength < this.required) { return false; }
6543
- if (argsLength > this.params.length) { return false; }
6764
+ if (argsLength < this.required) {
6765
+ return false;
6766
+ }
6767
+ if (argsLength > this.params.length) {
6768
+ return false;
6769
+ }
6544
6770
  } else {
6545
- if (argsLength < (this.required - 1)) { return false; }
6771
+ if (argsLength < (this.required - 1)) {
6772
+ return false;
6773
+ }
6546
6774
  }
6547
6775
 
6548
6776
  len = Math.min(argsLength, this.arity);
@@ -6558,7 +6786,7 @@ Definition.prototype.matchArgs = function (args, context) {
6558
6786
  };
6559
6787
  module.exports = Definition;
6560
6788
 
6561
- },{"../contexts":10,"./element":54,"./expression":55,"./rule":70,"./ruleset":72,"./selector":73}],65:[function(require,module,exports){
6789
+ },{"../contexts":10,"./element":55,"./expression":56,"./rule":71,"./ruleset":73,"./selector":74}],66:[function(require,module,exports){
6562
6790
  var Node = require("./node"),
6563
6791
  Operation = require("./operation"),
6564
6792
  Dimension = require("./dimension");
@@ -6580,7 +6808,7 @@ Negative.prototype.eval = function (context) {
6580
6808
  };
6581
6809
  module.exports = Negative;
6582
6810
 
6583
- },{"./dimension":52,"./node":66,"./operation":67}],66:[function(require,module,exports){
6811
+ },{"./dimension":53,"./node":67,"./operation":68}],67:[function(require,module,exports){
6584
6812
  var Node = function() {
6585
6813
  };
6586
6814
  Node.prototype.toCSS = function (context) {
@@ -6656,7 +6884,7 @@ Node.numericCompare = function (a, b) {
6656
6884
  };
6657
6885
  module.exports = Node;
6658
6886
 
6659
- },{}],67:[function(require,module,exports){
6887
+ },{}],68:[function(require,module,exports){
6660
6888
  var Node = require("./node"),
6661
6889
  Color = require("./color"),
6662
6890
  Dimension = require("./dimension");
@@ -6706,7 +6934,7 @@ Operation.prototype.genCSS = function (context, output) {
6706
6934
 
6707
6935
  module.exports = Operation;
6708
6936
 
6709
- },{"./color":46,"./dimension":52,"./node":66}],68:[function(require,module,exports){
6937
+ },{"./color":47,"./dimension":53,"./node":67}],69:[function(require,module,exports){
6710
6938
  var Node = require("./node");
6711
6939
 
6712
6940
  var Paren = function (node) {
@@ -6724,7 +6952,7 @@ Paren.prototype.eval = function (context) {
6724
6952
  };
6725
6953
  module.exports = Paren;
6726
6954
 
6727
- },{"./node":66}],69:[function(require,module,exports){
6955
+ },{"./node":67}],70:[function(require,module,exports){
6728
6956
  var Node = require("./node"),
6729
6957
  JsEvalNode = require("./js-eval-node"),
6730
6958
  Variable = require("./variable");
@@ -6762,9 +6990,9 @@ Quoted.prototype.eval = function (context) {
6762
6990
  function iterativeReplace(value, regexp, replacementFnc) {
6763
6991
  var evaluatedValue = value;
6764
6992
  do {
6765
- value = evaluatedValue;
6766
- evaluatedValue = value.replace(regexp, replacementFnc);
6767
- } while (value!==evaluatedValue);
6993
+ value = evaluatedValue;
6994
+ evaluatedValue = value.replace(regexp, replacementFnc);
6995
+ } while (value !== evaluatedValue);
6768
6996
  return evaluatedValue;
6769
6997
  }
6770
6998
  value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
@@ -6781,7 +7009,7 @@ Quoted.prototype.compare = function (other) {
6781
7009
  };
6782
7010
  module.exports = Quoted;
6783
7011
 
6784
- },{"./js-eval-node":60,"./node":66,"./variable":78}],70:[function(require,module,exports){
7012
+ },{"./js-eval-node":61,"./node":67,"./variable":79}],71:[function(require,module,exports){
6785
7013
  var Node = require("./node"),
6786
7014
  Value = require("./value"),
6787
7015
  Keyword = require("./keyword");
@@ -6826,10 +7054,9 @@ Rule.prototype.eval = function (context) {
6826
7054
  if (typeof name !== "string") {
6827
7055
  // expand 'primitive' name directly to get
6828
7056
  // things faster (~10% for benchmark.less):
6829
- name = (name.length === 1)
6830
- && (name[0] instanceof Keyword)
6831
- ? name[0].value : evalName(context, name);
6832
- variable = false; // never treat expanded interpolation as new variable name
7057
+ name = (name.length === 1) && (name[0] instanceof Keyword) ?
7058
+ name[0].value : evalName(context, name);
7059
+ variable = false; // never treat expanded interpolation as new variable name
6833
7060
  }
6834
7061
  if (name === "font" && !context.strictMath) {
6835
7062
  strictMathBypass = true;
@@ -6879,7 +7106,7 @@ Rule.prototype.makeImportant = function () {
6879
7106
 
6880
7107
  module.exports = Rule;
6881
7108
 
6882
- },{"./keyword":61,"./node":66,"./value":77}],71:[function(require,module,exports){
7109
+ },{"./keyword":62,"./node":67,"./value":78}],72:[function(require,module,exports){
6883
7110
  var Node = require("./node"),
6884
7111
  Variable = require("./variable");
6885
7112
 
@@ -6894,11 +7121,12 @@ RulesetCall.prototype.eval = function (context) {
6894
7121
  };
6895
7122
  module.exports = RulesetCall;
6896
7123
 
6897
- },{"./node":66,"./variable":78}],72:[function(require,module,exports){
7124
+ },{"./node":67,"./variable":79}],73:[function(require,module,exports){
6898
7125
  var Node = require("./node"),
6899
7126
  Rule = require("./rule"),
6900
7127
  Selector = require("./selector"),
6901
7128
  Element = require("./element"),
7129
+ Paren = require("./paren"),
6902
7130
  contexts = require("../contexts"),
6903
7131
  defaultFunc = require("../functions/default"),
6904
7132
  getDebugInfo = require("./debug-info");
@@ -6954,7 +7182,7 @@ Ruleset.prototype.eval = function (context) {
6954
7182
  ruleset.firstRoot = this.firstRoot;
6955
7183
  ruleset.allowImports = this.allowImports;
6956
7184
 
6957
- if(this.debugInfo) {
7185
+ if (this.debugInfo) {
6958
7186
  ruleset.debugInfo = this.debugInfo;
6959
7187
  }
6960
7188
 
@@ -7004,7 +7232,7 @@ Ruleset.prototype.eval = function (context) {
7004
7232
  });
7005
7233
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
7006
7234
  rsRuleCnt += rules.length - 1;
7007
- i += rules.length-1;
7235
+ i += rules.length - 1;
7008
7236
  ruleset.resetCache();
7009
7237
  } else if (rsRules[i].type === "RulesetCall") {
7010
7238
  /*jshint loopfunc:true */
@@ -7017,7 +7245,7 @@ Ruleset.prototype.eval = function (context) {
7017
7245
  });
7018
7246
  rsRules.splice.apply(rsRules, [i, 1].concat(rules));
7019
7247
  rsRuleCnt += rules.length - 1;
7020
- i += rules.length-1;
7248
+ i += rules.length - 1;
7021
7249
  ruleset.resetCache();
7022
7250
  }
7023
7251
  }
@@ -7039,7 +7267,7 @@ Ruleset.prototype.eval = function (context) {
7039
7267
  if (rule.selectors[0].isJustParentSelector()) {
7040
7268
  rsRules.splice(i--, 1);
7041
7269
 
7042
- for(var j = 0; j < rule.rules.length; j++) {
7270
+ for (var j = 0; j < rule.rules.length; j++) {
7043
7271
  subRule = rule.rules[j];
7044
7272
  if (!(subRule instanceof Rule) || !subRule.variable) {
7045
7273
  rsRules.splice(++i, 0, subRule);
@@ -7070,7 +7298,7 @@ Ruleset.prototype.evalImports = function(context) {
7070
7298
  importRules = rules[i].eval(context);
7071
7299
  if (importRules && importRules.length) {
7072
7300
  rules.splice.apply(rules, [i, 1].concat(importRules));
7073
- i+= importRules.length-1;
7301
+ i+= importRules.length - 1;
7074
7302
  } else {
7075
7303
  rules.splice(i, 1, importRules);
7076
7304
  }
@@ -7079,20 +7307,22 @@ Ruleset.prototype.evalImports = function(context) {
7079
7307
  }
7080
7308
  };
7081
7309
  Ruleset.prototype.makeImportant = function() {
7082
- return new Ruleset(this.selectors, this.rules.map(function (r) {
7083
- if (r.makeImportant) {
7084
- return r.makeImportant();
7085
- } else {
7086
- return r;
7087
- }
7088
- }), this.strictImports);
7310
+ var result = new Ruleset(this.selectors, this.rules.map(function (r) {
7311
+ if (r.makeImportant) {
7312
+ return r.makeImportant();
7313
+ } else {
7314
+ return r;
7315
+ }
7316
+ }), this.strictImports);
7317
+
7318
+ return result;
7089
7319
  };
7090
7320
  Ruleset.prototype.matchArgs = function (args) {
7091
7321
  return !args || args.length === 0;
7092
7322
  };
7093
7323
  // lets you call a css selector with a guard
7094
7324
  Ruleset.prototype.matchCondition = function (args, context) {
7095
- var lastSelector = this.selectors[this.selectors.length-1];
7325
+ var lastSelector = this.selectors[this.selectors.length - 1];
7096
7326
  if (!lastSelector.evaldCondition) {
7097
7327
  return false;
7098
7328
  }
@@ -7117,9 +7347,10 @@ Ruleset.prototype.variables = function () {
7117
7347
  }
7118
7348
  // when evaluating variables in an import statement, imports have not been eval'd
7119
7349
  // so we need to go inside import statements.
7120
- if (r.type === "Import" && r.root) {
7350
+ // guard against root being a string (in the case of inlined less)
7351
+ if (r.type === "Import" && r.root && r.root.variables) {
7121
7352
  var vars = r.root.variables();
7122
- for(var name in vars) {
7353
+ for (var name in vars) {
7123
7354
  if (vars.hasOwnProperty(name)) {
7124
7355
  hash[name] = vars[name];
7125
7356
  }
@@ -7150,7 +7381,11 @@ Ruleset.prototype.rulesets = function () {
7150
7381
  };
7151
7382
  Ruleset.prototype.prependRule = function (rule) {
7152
7383
  var rules = this.rules;
7153
- if (rules) { rules.unshift(rule); } else { this.rules = [ rule ]; }
7384
+ if (rules) {
7385
+ rules.unshift(rule);
7386
+ } else {
7387
+ this.rules = [ rule ];
7388
+ }
7154
7389
  };
7155
7390
  Ruleset.prototype.find = function (selector, self, filter) {
7156
7391
  self = self || this;
@@ -7165,13 +7400,13 @@ Ruleset.prototype.find = function (selector, self, filter) {
7165
7400
  match = selector.match(rule.selectors[j]);
7166
7401
  if (match) {
7167
7402
  if (selector.elements.length > match) {
7168
- if (!filter || filter(rule)) {
7169
- foundMixins = rule.find(new Selector(selector.elements.slice(match)), self, filter);
7170
- for (var i = 0; i < foundMixins.length; ++i) {
7171
- foundMixins[i].path.push(rule);
7403
+ if (!filter || filter(rule)) {
7404
+ foundMixins = rule.find(new Selector(selector.elements.slice(match)), self, filter);
7405
+ for (var i = 0; i < foundMixins.length; ++i) {
7406
+ foundMixins[i].path.push(rule);
7407
+ }
7408
+ Array.prototype.push.apply(rules, foundMixins);
7172
7409
  }
7173
- Array.prototype.push.apply(rules, foundMixins);
7174
- }
7175
7410
  } else {
7176
7411
  rules.push({ rule: rule, path: []});
7177
7412
  }
@@ -7204,19 +7439,17 @@ Ruleset.prototype.genCSS = function (context, output) {
7204
7439
  sep;
7205
7440
 
7206
7441
  function isRulesetLikeNode(rule, root) {
7207
- // if it has nested rules, then it should be treated like a ruleset
7208
- // medias and comments do not have nested rules, but should be treated like rulesets anyway
7209
- // some directives and anonymous nodes are ruleset like, others are not
7210
- if (typeof rule.isRulesetLike === "boolean")
7211
- {
7212
- return rule.isRulesetLike;
7213
- } else if (typeof rule.isRulesetLike === "function")
7214
- {
7215
- return rule.isRulesetLike(root);
7216
- }
7442
+ // if it has nested rules, then it should be treated like a ruleset
7443
+ // medias and comments do not have nested rules, but should be treated like rulesets anyway
7444
+ // some directives and anonymous nodes are ruleset like, others are not
7445
+ if (typeof rule.isRulesetLike === "boolean") {
7446
+ return rule.isRulesetLike;
7447
+ } else if (typeof rule.isRulesetLike === "function") {
7448
+ return rule.isRulesetLike(root);
7449
+ }
7217
7450
 
7218
- //anything else is assumed to be a rule
7219
- return false;
7451
+ //anything else is assumed to be a rule
7452
+ return false;
7220
7453
  }
7221
7454
 
7222
7455
  for (i = 0; i < this.rules.length; i++) {
@@ -7310,194 +7543,301 @@ Ruleset.prototype.genCSS = function (context, output) {
7310
7543
  }
7311
7544
  };
7312
7545
  Ruleset.prototype.markReferenced = function () {
7313
- if (!this.selectors) {
7314
- return;
7546
+ var s;
7547
+ if (this.selectors) {
7548
+ for (s = 0; s < this.selectors.length; s++) {
7549
+ this.selectors[s].markReferenced();
7550
+ }
7551
+ }
7552
+
7553
+ if (this.rules) {
7554
+ for (s = 0; s < this.rules.length; s++) {
7555
+ if (this.rules[s].markReferenced) {
7556
+ this.rules[s].markReferenced();
7557
+ }
7558
+ }
7559
+ }
7560
+ };
7561
+ Ruleset.prototype.getIsReferenced = function() {
7562
+ var i, j, path, selector;
7563
+
7564
+ if (this.paths) {
7565
+ for (i = 0; i < this.paths.length; i++) {
7566
+ path = this.paths[i];
7567
+ for (j = 0; j < path.length; j++) {
7568
+ if (path[j].getIsReferenced && path[j].getIsReferenced()) {
7569
+ return true;
7570
+ }
7571
+ }
7572
+ }
7315
7573
  }
7316
- for (var s = 0; s < this.selectors.length; s++) {
7317
- this.selectors[s].markReferenced();
7574
+
7575
+ if (this.selectors) {
7576
+ for (i = 0; i < this.selectors.length; i++) {
7577
+ selector = this.selectors[i];
7578
+ if (selector.getIsReferenced && selector.getIsReferenced()) {
7579
+ return true;
7580
+ }
7581
+ }
7318
7582
  }
7583
+ return false;
7319
7584
  };
7585
+
7320
7586
  Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
7321
7587
  for (var s = 0; s < selectors.length; s++) {
7322
7588
  this.joinSelector(paths, context, selectors[s]);
7323
7589
  }
7324
7590
  };
7325
- Ruleset.prototype.joinSelector = function (paths, context, selector) {
7326
7591
 
7327
- var i, j, k,
7328
- hasParentSelector, newSelectors, el, sel, parentSel,
7329
- newSelectorPath, afterParentJoin, newJoinedSelector,
7330
- newJoinedSelectorEmpty, lastSelector, currentElements,
7331
- selectorsMultiplied;
7592
+ Ruleset.prototype.joinSelector = function (paths, context, selector) {
7332
7593
 
7333
- for (i = 0; i < selector.elements.length; i++) {
7334
- el = selector.elements[i];
7335
- if (el.value === '&') {
7336
- hasParentSelector = true;
7337
- }
7338
- }
7594
+ function createParenthesis(elementsToPak, originalElement) {
7595
+ var replacementParen, j;
7596
+ if (elementsToPak.length === 0) {
7597
+ replacementParen = new Paren(elementsToPak[0]);
7598
+ } else {
7599
+ var insideParent = [];
7600
+ for (j = 0; j < elementsToPak.length; j++) {
7601
+ insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
7602
+ }
7603
+ replacementParen = new Paren(new Selector(insideParent));
7604
+ }
7605
+ return replacementParen;
7606
+ }
7607
+
7608
+ function createSelector(containedElement, originalElement) {
7609
+ var element, selector;
7610
+ element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
7611
+ selector = new Selector([element]);
7612
+ return selector;
7613
+ }
7614
+
7615
+ // replace all parent selectors inside `inSelector` by content of `context` array
7616
+ // resulting selectors are returned inside `paths` array
7617
+ // returns true if `inSelector` contained at least one parent selector
7618
+ function replaceParentSelector(paths, context, inSelector) {
7619
+ // The paths are [[Selector]]
7620
+ // The first list is a list of comma separated selectors
7621
+ // The inner list is a list of inheritance separated selectors
7622
+ // e.g.
7623
+ // .a, .b {
7624
+ // .c {
7625
+ // }
7626
+ // }
7627
+ // == [[.a] [.c]] [[.b] [.c]]
7628
+ //
7629
+ var i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false, length, lastSelector;
7630
+ function findNestedSelector(element) {
7631
+ var maybeSelector;
7632
+ if (element.value.type !== 'Paren') {
7633
+ return null;
7634
+ }
7339
7635
 
7340
- if (!hasParentSelector) {
7341
- if (context.length > 0) {
7342
- for (i = 0; i < context.length; i++) {
7343
- paths.push(context[i].concat(selector));
7636
+ maybeSelector = element.value.value;
7637
+ if (maybeSelector.type !== 'Selector') {
7638
+ return null;
7344
7639
  }
7640
+
7641
+ return maybeSelector;
7345
7642
  }
7346
- else {
7347
- paths.push([selector]);
7348
- }
7349
- return;
7350
- }
7351
7643
 
7352
- // The paths are [[Selector]]
7353
- // The first list is a list of comma separated selectors
7354
- // The inner list is a list of inheritance separated selectors
7355
- // e.g.
7356
- // .a, .b {
7357
- // .c {
7358
- // }
7359
- // }
7360
- // == [[.a] [.c]] [[.b] [.c]]
7361
- //
7644
+ // the elements from the current selector so far
7645
+ currentElements = [];
7646
+ // the current list of new selectors to add to the path.
7647
+ // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
7648
+ // by the parents
7649
+ newSelectors = [
7650
+ []
7651
+ ];
7362
7652
 
7363
- // the elements from the current selector so far
7364
- currentElements = [];
7365
- // the current list of new selectors to add to the path.
7366
- // We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
7367
- // by the parents
7368
- newSelectors = [[]];
7369
-
7370
- for (i = 0; i < selector.elements.length; i++) {
7371
- el = selector.elements[i];
7372
- // non parent reference elements just get added
7373
- if (el.value !== "&") {
7374
- currentElements.push(el);
7375
- } else {
7376
- // the new list of selectors to add
7377
- selectorsMultiplied = [];
7378
-
7379
- // merge the current list of non parent selector elements
7380
- // on to the current list of selectors to add
7381
- if (currentElements.length > 0) {
7382
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
7383
- }
7384
-
7385
- // loop through our current selectors
7386
- for (j = 0; j < newSelectors.length; j++) {
7387
- sel = newSelectors[j];
7388
- // if we don't have any parent paths, the & might be in a mixin so that it can be used
7389
- // whether there are parents or not
7390
- if (context.length === 0) {
7391
- // the combinator used on el should now be applied to the next element instead so that
7392
- // it is not lost
7393
- if (sel.length > 0) {
7394
- sel[0].elements = sel[0].elements.slice(0);
7395
- sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
7653
+ for (i = 0; i < inSelector.elements.length; i++) {
7654
+ el = inSelector.elements[i];
7655
+ // non parent reference elements just get added
7656
+ if (el.value !== "&") {
7657
+ var nestedSelector = findNestedSelector(el);
7658
+ if (nestedSelector != null) {
7659
+ // merge the current list of non parent selector elements
7660
+ // on to the current list of selectors to add
7661
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7662
+
7663
+ var nestedPaths = [], replaced, replacedNewSelectors = [];
7664
+ replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
7665
+ hadParentSelector = hadParentSelector || replaced;
7666
+ //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
7667
+ for (k = 0; k < nestedPaths.length; k++) {
7668
+ var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
7669
+ addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
7396
7670
  }
7397
- selectorsMultiplied.push(sel);
7671
+ newSelectors = replacedNewSelectors;
7672
+ currentElements = [];
7673
+
7674
+ } else {
7675
+ currentElements.push(el);
7398
7676
  }
7399
- else {
7400
- // and the parent selectors
7401
- for (k = 0; k < context.length; k++) {
7402
- parentSel = context[k];
7403
- // We need to put the current selectors
7404
- // then join the last selector's elements on to the parents selectors
7405
-
7406
- // our new selector path
7407
- newSelectorPath = [];
7408
- // selectors from the parent after the join
7409
- afterParentJoin = [];
7410
- newJoinedSelectorEmpty = true;
7411
-
7412
- //construct the joined selector - if & is the first thing this will be empty,
7413
- // if not newJoinedSelector will be the last set of elements in the selector
7677
+
7678
+ } else {
7679
+ hadParentSelector = true;
7680
+ // the new list of selectors to add
7681
+ selectorsMultiplied = [];
7682
+
7683
+ // merge the current list of non parent selector elements
7684
+ // on to the current list of selectors to add
7685
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7686
+
7687
+ // loop through our current selectors
7688
+ for (j = 0; j < newSelectors.length; j++) {
7689
+ sel = newSelectors[j];
7690
+ // if we don't have any parent paths, the & might be in a mixin so that it can be used
7691
+ // whether there are parents or not
7692
+ if (context.length === 0) {
7693
+ // the combinator used on el should now be applied to the next element instead so that
7694
+ // it is not lost
7414
7695
  if (sel.length > 0) {
7415
- newSelectorPath = sel.slice(0);
7416
- lastSelector = newSelectorPath.pop();
7417
- newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
7418
- newJoinedSelectorEmpty = false;
7696
+ sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
7419
7697
  }
7420
- else {
7421
- newJoinedSelector = selector.createDerived([]);
7698
+ selectorsMultiplied.push(sel);
7699
+ }
7700
+ else {
7701
+ // and the parent selectors
7702
+ for (k = 0; k < context.length; k++) {
7703
+ // We need to put the current selectors
7704
+ // then join the last selector's elements on to the parents selectors
7705
+ var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
7706
+ // add that to our new set of selectors
7707
+ selectorsMultiplied.push(newSelectorPath);
7422
7708
  }
7709
+ }
7710
+ }
7423
7711
 
7424
- //put together the parent selectors after the join
7425
- if (parentSel.length > 1) {
7426
- afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
7427
- }
7712
+ // our new selectors has been multiplied, so reset the state
7713
+ newSelectors = selectorsMultiplied;
7714
+ currentElements = [];
7715
+ }
7716
+ }
7428
7717
 
7429
- if (parentSel.length > 0) {
7430
- newJoinedSelectorEmpty = false;
7431
-
7432
- // /deep/ is a combinator that is valid without anything in front of it
7433
- // so if the & does not have a combinator that is "" or " " then
7434
- // and there is a combinator on the parent, then grab that.
7435
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
7436
- var combinator = el.combinator,
7437
- parentEl = parentSel[0].elements[0];
7438
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
7439
- combinator = parentEl.combinator;
7440
- }
7441
- // join the elements so far with the first part of the parent
7442
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, el.index, el.currentFileInfo));
7443
- newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
7444
- }
7718
+ // if we have any elements left over (e.g. .a& .b == .b)
7719
+ // add them on to all the current selectors
7720
+ mergeElementsOnToSelectors(currentElements, newSelectors);
7445
7721
 
7446
- if (!newJoinedSelectorEmpty) {
7447
- // now add the joined selector
7448
- newSelectorPath.push(newJoinedSelector);
7449
- }
7722
+ for (i = 0; i < newSelectors.length; i++) {
7723
+ length = newSelectors[i].length;
7724
+ if (length > 0) {
7725
+ paths.push(newSelectors[i]);
7726
+ lastSelector = newSelectors[i][length - 1];
7727
+ newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
7728
+ }
7729
+ }
7450
7730
 
7451
- // and the rest of the parent
7452
- newSelectorPath = newSelectorPath.concat(afterParentJoin);
7731
+ return hadParentSelector;
7732
+ }
7453
7733
 
7454
- // add that to our new set of selectors
7455
- selectorsMultiplied.push(newSelectorPath);
7456
- }
7457
- }
7734
+ // joins selector path from `beginningPath` with selector path in `addPath`
7735
+ // `replacedElement` contains element that is being replaced by `addPath`
7736
+ // returns concatenated path
7737
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
7738
+ var newSelectorPath, lastSelector, newJoinedSelector;
7739
+ // our new selector path
7740
+ newSelectorPath = [];
7741
+
7742
+ //construct the joined selector - if & is the first thing this will be empty,
7743
+ // if not newJoinedSelector will be the last set of elements in the selector
7744
+ if (beginningPath.length > 0) {
7745
+ newSelectorPath = beginningPath.slice(0);
7746
+ lastSelector = newSelectorPath.pop();
7747
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
7748
+ }
7749
+ else {
7750
+ newJoinedSelector = originalSelector.createDerived([]);
7751
+ }
7752
+
7753
+ if (addPath.length > 0) {
7754
+ // /deep/ is a combinator that is valid without anything in front of it
7755
+ // so if the & does not have a combinator that is "" or " " then
7756
+ // and there is a combinator on the parent, then grab that.
7757
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
7758
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
7759
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
7760
+ combinator = parentEl.combinator;
7458
7761
  }
7762
+ // join the elements so far with the first part of the parent
7763
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
7764
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
7765
+ }
7459
7766
 
7460
- // our new selectors has been multiplied, so reset the state
7461
- newSelectors = selectorsMultiplied;
7462
- currentElements = [];
7767
+ // now add the joined selector - but only if it is not empty
7768
+ if (newJoinedSelector.elements.length !== 0) {
7769
+ newSelectorPath.push(newJoinedSelector);
7463
7770
  }
7464
- }
7465
7771
 
7466
- // if we have any elements left over (e.g. .a& .b == .b)
7467
- // add them on to all the current selectors
7468
- if (currentElements.length > 0) {
7469
- this.mergeElementsOnToSelectors(currentElements, newSelectors);
7772
+ //put together the parent selectors after the join (e.g. the rest of the parent)
7773
+ if (addPath.length > 1) {
7774
+ newSelectorPath = newSelectorPath.concat(addPath.slice(1));
7775
+ }
7776
+ return newSelectorPath;
7470
7777
  }
7471
7778
 
7472
- for (i = 0; i < newSelectors.length; i++) {
7473
- if (newSelectors[i].length > 0) {
7474
- paths.push(newSelectors[i]);
7779
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
7780
+ // `replacedElement` contains element that is being replaced by `addPath`
7781
+ // returns array with all concatenated paths
7782
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
7783
+ var j;
7784
+ for (j = 0; j < beginningPath.length; j++) {
7785
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
7786
+ result.push(newSelectorPath);
7475
7787
  }
7788
+ return result;
7476
7789
  }
7477
- };
7478
- Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
7479
- var i, sel;
7480
7790
 
7481
- if (selectors.length === 0) {
7482
- selectors.push([ new Selector(elements) ]);
7483
- return;
7791
+ function mergeElementsOnToSelectors(elements, selectors) {
7792
+ var i, sel;
7793
+
7794
+ if (elements.length === 0) {
7795
+ return ;
7796
+ }
7797
+ if (selectors.length === 0) {
7798
+ selectors.push([ new Selector(elements) ]);
7799
+ return;
7800
+ }
7801
+
7802
+ for (i = 0; i < selectors.length; i++) {
7803
+ sel = selectors[i];
7804
+
7805
+ // if the previous thing in sel is a parent this needs to join on to it
7806
+ if (sel.length > 0) {
7807
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
7808
+ }
7809
+ else {
7810
+ sel.push(new Selector(elements));
7811
+ }
7812
+ }
7484
7813
  }
7485
7814
 
7486
- for (i = 0; i < selectors.length; i++) {
7487
- sel = selectors[i];
7815
+ // joinSelector code follows
7816
+ var i, newPaths, hadParentSelector;
7817
+
7818
+ newPaths = [];
7819
+ hadParentSelector = replaceParentSelector(newPaths, context, selector);
7488
7820
 
7489
- // if the previous thing in sel is a parent this needs to join on to it
7490
- if (sel.length > 0) {
7491
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
7821
+ if (!hadParentSelector) {
7822
+ if (context.length > 0) {
7823
+ newPaths = [];
7824
+ for (i = 0; i < context.length; i++) {
7825
+ newPaths.push(context[i].concat(selector));
7826
+ }
7492
7827
  }
7493
7828
  else {
7494
- sel.push(new Selector(elements));
7829
+ newPaths = [[selector]];
7495
7830
  }
7496
7831
  }
7832
+
7833
+ for (i = 0; i < newPaths.length; i++) {
7834
+ paths.push(newPaths[i]);
7835
+ }
7836
+
7497
7837
  };
7498
7838
  module.exports = Ruleset;
7499
7839
 
7500
- },{"../contexts":10,"../functions/default":19,"./debug-info":50,"./element":54,"./node":66,"./rule":70,"./selector":73}],73:[function(require,module,exports){
7840
+ },{"../contexts":10,"../functions/default":19,"./debug-info":51,"./element":55,"./node":67,"./paren":69,"./rule":71,"./selector":74}],74:[function(require,module,exports){
7501
7841
  var Node = require("./node");
7502
7842
 
7503
7843
  var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
@@ -7551,8 +7891,9 @@ Selector.prototype.match = function (other) {
7551
7891
  return olen; // return number of matched elements
7552
7892
  };
7553
7893
  Selector.prototype.CacheElements = function() {
7554
- if (this._elements)
7894
+ if (this._elements) {
7555
7895
  return;
7896
+ }
7556
7897
 
7557
7898
  var elements = this.elements.map( function(v) {
7558
7899
  return v.combinator.value + (v.value.value || v.value);
@@ -7590,7 +7931,7 @@ Selector.prototype.genCSS = function (context, output) {
7590
7931
  }
7591
7932
  if (!this._css) {
7592
7933
  //TODO caching? speed comparison?
7593
- for(i = 0; i < this.elements.length; i++) {
7934
+ for (i = 0; i < this.elements.length; i++) {
7594
7935
  element = this.elements[i];
7595
7936
  element.genCSS(context, output);
7596
7937
  }
@@ -7607,7 +7948,7 @@ Selector.prototype.getIsOutput = function() {
7607
7948
  };
7608
7949
  module.exports = Selector;
7609
7950
 
7610
- },{"./node":66}],74:[function(require,module,exports){
7951
+ },{"./node":67}],75:[function(require,module,exports){
7611
7952
  var Node = require("./node");
7612
7953
 
7613
7954
  var UnicodeDescriptor = function (value) {
@@ -7618,7 +7959,7 @@ UnicodeDescriptor.prototype.type = "UnicodeDescriptor";
7618
7959
 
7619
7960
  module.exports = UnicodeDescriptor;
7620
7961
 
7621
- },{"./node":66}],75:[function(require,module,exports){
7962
+ },{"./node":67}],76:[function(require,module,exports){
7622
7963
  var Node = require("./node"),
7623
7964
  unitConversions = require("../data/unit-conversions");
7624
7965
 
@@ -7644,6 +7985,8 @@ Unit.prototype.genCSS = function (context, output) {
7644
7985
  output.add(this.numerator[0]); // the ideal situation
7645
7986
  } else if (!strictUnits && this.backupUnit) {
7646
7987
  output.add(this.backupUnit);
7988
+ } else if (!strictUnits && this.denominator.length) {
7989
+ output.add(this.denominator[0]);
7647
7990
  }
7648
7991
  };
7649
7992
  Unit.prototype.toString = function () {
@@ -7738,7 +8081,7 @@ Unit.prototype.cancel = function () {
7738
8081
  };
7739
8082
  module.exports = Unit;
7740
8083
 
7741
- },{"../data/unit-conversions":13,"./node":66}],76:[function(require,module,exports){
8084
+ },{"../data/unit-conversions":13,"./node":67}],77:[function(require,module,exports){
7742
8085
  var Node = require("./node");
7743
8086
 
7744
8087
  var URL = function (val, index, currentFileInfo, isEvald) {
@@ -7764,9 +8107,12 @@ URL.prototype.eval = function (context) {
7764
8107
  if (!this.isEvald) {
7765
8108
  // Add the base path if the URL is relative
7766
8109
  rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
7767
- if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) {
8110
+ if (rootpath &&
8111
+ typeof val.value === "string" &&
8112
+ context.isPathRelative(val.value)) {
8113
+
7768
8114
  if (!val.quote) {
7769
- rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
8115
+ rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\" + match; });
7770
8116
  }
7771
8117
  val.value = rootpath + val.value;
7772
8118
  }
@@ -7791,7 +8137,7 @@ URL.prototype.eval = function (context) {
7791
8137
  };
7792
8138
  module.exports = URL;
7793
8139
 
7794
- },{"./node":66}],77:[function(require,module,exports){
8140
+ },{"./node":67}],78:[function(require,module,exports){
7795
8141
  var Node = require("./node");
7796
8142
 
7797
8143
  var Value = function (value) {
@@ -7818,16 +8164,16 @@ Value.prototype.eval = function (context) {
7818
8164
  };
7819
8165
  Value.prototype.genCSS = function (context, output) {
7820
8166
  var i;
7821
- for(i = 0; i < this.value.length; i++) {
8167
+ for (i = 0; i < this.value.length; i++) {
7822
8168
  this.value[i].genCSS(context, output);
7823
- if (i+1 < this.value.length) {
8169
+ if (i + 1 < this.value.length) {
7824
8170
  output.add((context && context.compress) ? ',' : ', ');
7825
8171
  }
7826
8172
  }
7827
8173
  };
7828
8174
  module.exports = Value;
7829
8175
 
7830
- },{"./node":66}],78:[function(require,module,exports){
8176
+ },{"./node":67}],79:[function(require,module,exports){
7831
8177
  var Node = require("./node");
7832
8178
 
7833
8179
  var Variable = function (name, index, currentFileInfo) {
@@ -7857,7 +8203,7 @@ Variable.prototype.eval = function (context) {
7857
8203
  var v = frame.variable(name);
7858
8204
  if (v) {
7859
8205
  if (v.important) {
7860
- var importantScope = context.importantScope[context.importantScope.length-1];
8206
+ var importantScope = context.importantScope[context.importantScope.length - 1];
7861
8207
  importantScope.important = v.important;
7862
8208
  }
7863
8209
  return v.value.eval(context);
@@ -7882,7 +8228,7 @@ Variable.prototype.find = function (obj, fun) {
7882
8228
  };
7883
8229
  module.exports = Variable;
7884
8230
 
7885
- },{"./node":66}],79:[function(require,module,exports){
8231
+ },{"./node":67}],80:[function(require,module,exports){
7886
8232
  module.exports = {
7887
8233
  getLocation: function(index, inputStream) {
7888
8234
  var n = index + 1,
@@ -7904,9 +8250,10 @@ module.exports = {
7904
8250
  }
7905
8251
  };
7906
8252
 
7907
- },{}],80:[function(require,module,exports){
8253
+ },{}],81:[function(require,module,exports){
7908
8254
  var tree = require("../tree"),
7909
- Visitor = require("./visitor");
8255
+ Visitor = require("./visitor"),
8256
+ logger = require("../logger");
7910
8257
 
7911
8258
  /*jshint loopfunc:true */
7912
8259
 
@@ -7937,7 +8284,7 @@ ExtendFinderVisitor.prototype = {
7937
8284
 
7938
8285
  // get &:extend(.a); rules which apply to all selectors in this ruleset
7939
8286
  var rules = rulesetNode.rules, ruleCnt = rules ? rules.length : 0;
7940
- for(i = 0; i < ruleCnt; i++) {
8287
+ for (i = 0; i < ruleCnt; i++) {
7941
8288
  if (rulesetNode.rules[i] instanceof tree.Extend) {
7942
8289
  allSelectorsExtendList.push(rules[i]);
7943
8290
  rulesetNode.extendOnEveryPath = true;
@@ -7947,7 +8294,7 @@ ExtendFinderVisitor.prototype = {
7947
8294
  // now find every selector and apply the extends that apply to all extends
7948
8295
  // and the ones which apply to an individual extend
7949
8296
  var paths = rulesetNode.paths;
7950
- for(i = 0; i < paths.length; i++) {
8297
+ for (i = 0; i < paths.length; i++) {
7951
8298
  var selectorPath = paths[i],
7952
8299
  selector = selectorPath[selectorPath.length - 1],
7953
8300
  selExtendList = selector.extendList;
@@ -7961,13 +8308,13 @@ ExtendFinderVisitor.prototype = {
7961
8308
  });
7962
8309
  }
7963
8310
 
7964
- for(j = 0; j < extendList.length; j++) {
8311
+ for (j = 0; j < extendList.length; j++) {
7965
8312
  this.foundExtends = true;
7966
8313
  extend = extendList[j];
7967
8314
  extend.findSelfSelectors(selectorPath);
7968
8315
  extend.ruleset = rulesetNode;
7969
8316
  if (j === 0) { extend.firstExtendOnThisSelectorPath = true; }
7970
- this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
8317
+ this.allExtendsStack[this.allExtendsStack.length - 1].push(extend);
7971
8318
  }
7972
8319
  }
7973
8320
 
@@ -8001,23 +8348,44 @@ var ProcessExtendsVisitor = function() {
8001
8348
  ProcessExtendsVisitor.prototype = {
8002
8349
  run: function(root) {
8003
8350
  var extendFinder = new ExtendFinderVisitor();
8351
+ this.extendIndicies = {};
8004
8352
  extendFinder.run(root);
8005
8353
  if (!extendFinder.foundExtends) { return root; }
8006
8354
  root.allExtends = root.allExtends.concat(this.doExtendChaining(root.allExtends, root.allExtends));
8007
8355
  this.allExtendsStack = [root.allExtends];
8008
- return this._visitor.visit(root);
8356
+ var newRoot = this._visitor.visit(root);
8357
+ this.checkExtendsForNonMatched(root.allExtends);
8358
+ return newRoot;
8359
+ },
8360
+ checkExtendsForNonMatched: function(extendList) {
8361
+ var indicies = this.extendIndicies;
8362
+ extendList.filter(function(extend) {
8363
+ return !extend.hasFoundMatches && extend.parent_ids.length == 1;
8364
+ }).forEach(function(extend) {
8365
+ var selector = "_unknown_";
8366
+ try {
8367
+ selector = extend.selector.toCSS({});
8368
+ }
8369
+ catch(_) {}
8370
+
8371
+ if (!indicies[extend.index + ' ' + selector]) {
8372
+ indicies[extend.index + ' ' + selector] = true;
8373
+ logger.warn("extend '" + selector + "' has no matches");
8374
+ }
8375
+ });
8009
8376
  },
8010
8377
  doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {
8011
8378
  //
8012
- // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering and pasting
8013
- // the selector we would do normally, but we are also adding an extend with the same target selector
8379
+ // chaining is different from normal extension.. if we extend an extend then we are not just copying, altering
8380
+ // and pasting the selector we would do normally, but we are also adding an extend with the same target selector
8014
8381
  // this means this new extend can then go and alter other extends
8015
8382
  //
8016
8383
  // this method deals with all the chaining work - without it, extend is flat and doesn't work on other extend selectors
8017
- // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already processed if
8018
- // we look at each selector at a time, as is done in visitRuleset
8384
+ // this is also the most expensive.. and a match on one selector can cause an extension of a selector we had already
8385
+ // processed if we look at each selector at a time, as is done in visitRuleset
8019
8386
 
8020
- var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath, extend, targetExtend, newExtend;
8387
+ var extendIndex, targetExtendIndex, matches, extendsToAdd = [], newSelector, extendVisitor = this, selectorPath,
8388
+ extend, targetExtend, newExtend;
8021
8389
 
8022
8390
  iterationCount = iterationCount || 0;
8023
8391
 
@@ -8027,14 +8395,14 @@ ProcessExtendsVisitor.prototype = {
8027
8395
  // and the second is the target.
8028
8396
  // the seperation into two lists allows us to process a subset of chains with a bigger set, as is the
8029
8397
  // case when processing media queries
8030
- for(extendIndex = 0; extendIndex < extendsList.length; extendIndex++){
8031
- for(targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++){
8398
+ for (extendIndex = 0; extendIndex < extendsList.length; extendIndex++) {
8399
+ for (targetExtendIndex = 0; targetExtendIndex < extendsListTarget.length; targetExtendIndex++) {
8032
8400
 
8033
8401
  extend = extendsList[extendIndex];
8034
8402
  targetExtend = extendsListTarget[targetExtendIndex];
8035
8403
 
8036
8404
  // look for circular references
8037
- if( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ){ continue; }
8405
+ if ( extend.parent_ids.indexOf( targetExtend.object_id ) >= 0 ) { continue; }
8038
8406
 
8039
8407
  // find a match in the target extends self selector (the bit before :extend)
8040
8408
  selectorPath = [targetExtend.selfSelectors[0]];
@@ -8042,6 +8410,8 @@ ProcessExtendsVisitor.prototype = {
8042
8410
 
8043
8411
  if (matches.length) {
8044
8412
 
8413
+ extend.hasFoundMatches = true;
8414
+
8045
8415
  // we found a match, so for each self selector..
8046
8416
  extend.selfSelectors.forEach(function(selfSelector) {
8047
8417
 
@@ -8053,7 +8423,7 @@ ProcessExtendsVisitor.prototype = {
8053
8423
  newExtend.selfSelectors = newSelector;
8054
8424
 
8055
8425
  // add the extend onto the list of extends for that selector
8056
- newSelector[newSelector.length-1].extendList = [newExtend];
8426
+ newSelector[newSelector.length - 1].extendList = [newExtend];
8057
8427
 
8058
8428
  // record that we need to add it.
8059
8429
  extendsToAdd.push(newExtend);
@@ -8087,11 +8457,13 @@ ProcessExtendsVisitor.prototype = {
8087
8457
  selectorTwo = extendsToAdd[0].selector.toCSS();
8088
8458
  }
8089
8459
  catch(e) {}
8090
- throw {message: "extend circular reference detected. One of the circular extends is currently:"+selectorOne+":extend(" + selectorTwo+")"};
8460
+ throw { message: "extend circular reference detected. One of the circular extends is currently:" +
8461
+ selectorOne + ":extend(" + selectorTwo + ")"};
8091
8462
  }
8092
8463
 
8093
- // now process the new extends on the existing rules so that we can handle a extending b extending c ectending d extending e...
8094
- return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount+1));
8464
+ // now process the new extends on the existing rules so that we can handle a extending b extending c extending
8465
+ // d extending e...
8466
+ return extendsToAdd.concat(extendVisitor.doExtendChaining(extendsToAdd, extendsListTarget, iterationCount + 1));
8095
8467
  } else {
8096
8468
  return extendsToAdd;
8097
8469
  }
@@ -8109,22 +8481,24 @@ ProcessExtendsVisitor.prototype = {
8109
8481
  if (rulesetNode.root) {
8110
8482
  return;
8111
8483
  }
8112
- var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [], extendVisitor = this, selectorPath;
8484
+ var matches, pathIndex, extendIndex, allExtends = this.allExtendsStack[this.allExtendsStack.length - 1],
8485
+ selectorsToAdd = [], extendVisitor = this, selectorPath;
8113
8486
 
8114
8487
  // look at each selector path in the ruleset, find any extend matches and then copy, find and replace
8115
8488
 
8116
- for(extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
8117
- for(pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
8489
+ for (extendIndex = 0; extendIndex < allExtends.length; extendIndex++) {
8490
+ for (pathIndex = 0; pathIndex < rulesetNode.paths.length; pathIndex++) {
8118
8491
  selectorPath = rulesetNode.paths[pathIndex];
8119
8492
 
8120
8493
  // extending extends happens initially, before the main pass
8121
8494
  if (rulesetNode.extendOnEveryPath) { continue; }
8122
- var extendList = selectorPath[selectorPath.length-1].extendList;
8495
+ var extendList = selectorPath[selectorPath.length - 1].extendList;
8123
8496
  if (extendList && extendList.length) { continue; }
8124
8497
 
8125
8498
  matches = this.findMatch(allExtends[extendIndex], selectorPath);
8126
8499
 
8127
8500
  if (matches.length) {
8501
+ allExtends[extendIndex].hasFoundMatches = true;
8128
8502
 
8129
8503
  allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
8130
8504
  selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
@@ -8146,24 +8520,25 @@ ProcessExtendsVisitor.prototype = {
8146
8520
  potentialMatches = [], potentialMatch, matches = [];
8147
8521
 
8148
8522
  // loop through the haystack elements
8149
- for(haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
8523
+ for (haystackSelectorIndex = 0; haystackSelectorIndex < haystackSelectorPath.length; haystackSelectorIndex++) {
8150
8524
  hackstackSelector = haystackSelectorPath[haystackSelectorIndex];
8151
8525
 
8152
- for(hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
8526
+ for (hackstackElementIndex = 0; hackstackElementIndex < hackstackSelector.elements.length; hackstackElementIndex++) {
8153
8527
 
8154
8528
  haystackElement = hackstackSelector.elements[hackstackElementIndex];
8155
8529
 
8156
8530
  // if we allow elements before our match we can add a potential match every time. otherwise only at the first element.
8157
8531
  if (extend.allowBefore || (haystackSelectorIndex === 0 && hackstackElementIndex === 0)) {
8158
- potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0, initialCombinator: haystackElement.combinator});
8532
+ potentialMatches.push({pathIndex: haystackSelectorIndex, index: hackstackElementIndex, matched: 0,
8533
+ initialCombinator: haystackElement.combinator});
8159
8534
  }
8160
8535
 
8161
- for(i = 0; i < potentialMatches.length; i++) {
8536
+ for (i = 0; i < potentialMatches.length; i++) {
8162
8537
  potentialMatch = potentialMatches[i];
8163
8538
 
8164
8539
  // selectors add " " onto the first element. When we use & it joins the selectors together, but if we don't
8165
- // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to work out
8166
- // what the resulting combinator will be
8540
+ // then each selector in haystackSelectorPath has a space before it added in the toCSS phase. so we need to
8541
+ // work out what the resulting combinator will be
8167
8542
  targetCombinator = haystackElement.combinator.value;
8168
8543
  if (targetCombinator === '' && hackstackElementIndex === 0) {
8169
8544
  targetCombinator = ' ';
@@ -8181,7 +8556,8 @@ ProcessExtendsVisitor.prototype = {
8181
8556
  if (potentialMatch) {
8182
8557
  potentialMatch.finished = potentialMatch.matched === needleElements.length;
8183
8558
  if (potentialMatch.finished &&
8184
- (!extend.allowAfter && (hackstackElementIndex+1 < hackstackSelector.elements.length || haystackSelectorIndex+1 < haystackSelectorPath.length))) {
8559
+ (!extend.allowAfter &&
8560
+ (hackstackElementIndex + 1 < hackstackSelector.elements.length || haystackSelectorIndex + 1 < haystackSelectorPath.length))) {
8185
8561
  potentialMatch = null;
8186
8562
  }
8187
8563
  }
@@ -8227,7 +8603,7 @@ ProcessExtendsVisitor.prototype = {
8227
8603
  if (!(elementValue2 instanceof tree.Selector) || elementValue1.elements.length !== elementValue2.elements.length) {
8228
8604
  return false;
8229
8605
  }
8230
- for(var i = 0; i <elementValue1.elements.length; i++) {
8606
+ for (var i = 0; i < elementValue1.elements.length; i++) {
8231
8607
  if (elementValue1.elements[i].combinator.value !== elementValue2.elements[i].combinator.value) {
8232
8608
  if (i !== 0 || (elementValue1.elements[i].combinator.value || ' ') !== (elementValue2.elements[i].combinator.value || ' ')) {
8233
8609
  return false;
@@ -8265,7 +8641,8 @@ ProcessExtendsVisitor.prototype = {
8265
8641
  );
8266
8642
 
8267
8643
  if (match.pathIndex > currentSelectorPathIndex && currentSelectorPathElementIndex > 0) {
8268
- path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8644
+ path[path.length - 1].elements = path[path.length - 1]
8645
+ .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8269
8646
  currentSelectorPathElementIndex = 0;
8270
8647
  currentSelectorPathIndex++;
8271
8648
  }
@@ -8294,7 +8671,8 @@ ProcessExtendsVisitor.prototype = {
8294
8671
  }
8295
8672
 
8296
8673
  if (currentSelectorPathIndex < selectorPath.length && currentSelectorPathElementIndex > 0) {
8297
- path[path.length - 1].elements = path[path.length - 1].elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8674
+ path[path.length - 1].elements = path[path.length - 1]
8675
+ .elements.concat(selectorPath[currentSelectorPathIndex].elements.slice(currentSelectorPathElementIndex));
8298
8676
  currentSelectorPathIndex++;
8299
8677
  }
8300
8678
 
@@ -8305,30 +8683,35 @@ ProcessExtendsVisitor.prototype = {
8305
8683
  visitRulesetOut: function (rulesetNode) {
8306
8684
  },
8307
8685
  visitMedia: function (mediaNode, visitArgs) {
8308
- var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
8686
+ var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
8309
8687
  newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
8310
8688
  this.allExtendsStack.push(newAllExtends);
8311
8689
  },
8312
8690
  visitMediaOut: function (mediaNode) {
8313
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
8691
+ var lastIndex = this.allExtendsStack.length - 1;
8692
+ this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
8693
+ this.allExtendsStack.length = lastIndex;
8314
8694
  },
8315
8695
  visitDirective: function (directiveNode, visitArgs) {
8316
- var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);
8696
+ var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
8317
8697
  newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
8318
8698
  this.allExtendsStack.push(newAllExtends);
8319
8699
  },
8320
8700
  visitDirectiveOut: function (directiveNode) {
8321
- this.allExtendsStack.length = this.allExtendsStack.length - 1;
8701
+ var lastIndex = this.allExtendsStack.length - 1;
8702
+ this.checkExtendsForNonMatched(this.allExtendsStack[lastIndex]);
8703
+ this.allExtendsStack.length = lastIndex;
8322
8704
  }
8323
8705
  };
8324
8706
 
8325
8707
  module.exports = ProcessExtendsVisitor;
8326
8708
 
8327
- },{"../tree":58,"./visitor":86}],81:[function(require,module,exports){
8709
+ },{"../logger":31,"../tree":59,"./visitor":87}],82:[function(require,module,exports){
8328
8710
  function ImportSequencer(onSequencerEmpty) {
8329
8711
  this.imports = [];
8330
8712
  this.variableImports = [];
8331
8713
  this._onSequencerEmpty = onSequencerEmpty;
8714
+ this._currentDepth = 0;
8332
8715
  }
8333
8716
 
8334
8717
  ImportSequencer.prototype.addImport = function(callback) {
@@ -8351,30 +8734,35 @@ ImportSequencer.prototype.addVariableImport = function(callback) {
8351
8734
  };
8352
8735
 
8353
8736
  ImportSequencer.prototype.tryRun = function() {
8354
- while(true) {
8355
- while(this.imports.length > 0) {
8356
- var importItem = this.imports[0];
8357
- if (!importItem.isReady) {
8358
- return;
8737
+ this._currentDepth++;
8738
+ try {
8739
+ while (true) {
8740
+ while (this.imports.length > 0) {
8741
+ var importItem = this.imports[0];
8742
+ if (!importItem.isReady) {
8743
+ return;
8744
+ }
8745
+ this.imports = this.imports.slice(1);
8746
+ importItem.callback.apply(null, importItem.args);
8359
8747
  }
8360
- this.imports = this.imports.slice(1);
8361
- importItem.callback.apply(null, importItem.args);
8362
- }
8363
- if (this.variableImports.length === 0) {
8364
- break;
8748
+ if (this.variableImports.length === 0) {
8749
+ break;
8750
+ }
8751
+ var variableImport = this.variableImports[0];
8752
+ this.variableImports = this.variableImports.slice(1);
8753
+ variableImport();
8365
8754
  }
8366
- var variableImport = this.variableImports[0];
8367
- this.variableImports = this.variableImports.slice(1);
8368
- variableImport();
8755
+ } finally {
8756
+ this._currentDepth--;
8369
8757
  }
8370
- if (this._onSequencerEmpty) {
8758
+ if (this._currentDepth === 0 && this._onSequencerEmpty) {
8371
8759
  this._onSequencerEmpty();
8372
8760
  }
8373
8761
  };
8374
8762
 
8375
8763
  module.exports = ImportSequencer;
8376
8764
 
8377
- },{}],82:[function(require,module,exports){
8765
+ },{}],83:[function(require,module,exports){
8378
8766
  var contexts = require("../contexts"),
8379
8767
  Visitor = require("./visitor"),
8380
8768
  ImportSequencer = require("./import-sequencer");
@@ -8388,26 +8776,28 @@ var ImportVisitor = function(importer, finish) {
8388
8776
  this.importCount = 0;
8389
8777
  this.onceFileDetectionMap = {};
8390
8778
  this.recursionDetector = {};
8391
- this._sequencer = new ImportSequencer();
8779
+ this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
8392
8780
  };
8393
8781
 
8394
8782
  ImportVisitor.prototype = {
8395
8783
  isReplacing: false,
8396
8784
  run: function (root) {
8397
- var error;
8398
8785
  try {
8399
8786
  // process the contents
8400
8787
  this._visitor.visit(root);
8401
8788
  }
8402
8789
  catch(e) {
8403
- error = e;
8790
+ this.error = e;
8404
8791
  }
8405
8792
 
8406
8793
  this.isFinished = true;
8407
8794
  this._sequencer.tryRun();
8408
- if (this.importCount === 0) {
8409
- this._finish(error || this.error);
8795
+ },
8796
+ _onSequencerEmpty: function() {
8797
+ if (!this.isFinished) {
8798
+ return;
8410
8799
  }
8800
+ this._finish(this.error);
8411
8801
  },
8412
8802
  visitImport: function (importNode, visitArgs) {
8413
8803
  var inlineCSS = importNode.options.inline;
@@ -8432,7 +8822,7 @@ ImportVisitor.prototype = {
8432
8822
 
8433
8823
  try {
8434
8824
  evaldImportNode = importNode.evalForImport(context);
8435
- } catch(e){
8825
+ } catch(e) {
8436
8826
  if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
8437
8827
  // attempt to eval properly and treat as css
8438
8828
  importNode.css = true;
@@ -8449,7 +8839,7 @@ ImportVisitor.prototype = {
8449
8839
  // try appending if we haven't determined if it is css or not
8450
8840
  var tryAppendLessExtension = evaldImportNode.css === undefined;
8451
8841
 
8452
- for(var i = 0; i < importParent.rules.length; i++) {
8842
+ for (var i = 0; i < importParent.rules.length; i++) {
8453
8843
  if (importParent.rules[i] === importNode) {
8454
8844
  importParent.rules[i] = evaldImportNode;
8455
8845
  break;
@@ -8459,9 +8849,13 @@ ImportVisitor.prototype = {
8459
8849
  var onImported = this.onImported.bind(this, evaldImportNode, context),
8460
8850
  sequencedOnImported = this._sequencer.addImport(onImported);
8461
8851
 
8462
- this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, evaldImportNode.options, sequencedOnImported);
8852
+ this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
8853
+ evaldImportNode.options, sequencedOnImported);
8463
8854
  } else {
8464
8855
  this.importCount--;
8856
+ if (this.isFinished) {
8857
+ this._sequencer.tryRun();
8858
+ }
8465
8859
  }
8466
8860
  },
8467
8861
  onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
@@ -8511,10 +8905,7 @@ ImportVisitor.prototype = {
8511
8905
  importVisitor.importCount--;
8512
8906
 
8513
8907
  if (importVisitor.isFinished) {
8514
- this._sequencer.tryRun();
8515
- if (importVisitor.importCount === 0) {
8516
- importVisitor._finish(importVisitor.error);
8517
- }
8908
+ importVisitor._sequencer.tryRun();
8518
8909
  }
8519
8910
  },
8520
8911
  visitRule: function (ruleNode, visitArgs) {
@@ -8547,7 +8938,7 @@ ImportVisitor.prototype = {
8547
8938
  };
8548
8939
  module.exports = ImportVisitor;
8549
8940
 
8550
- },{"../contexts":10,"./import-sequencer":81,"./visitor":86}],83:[function(require,module,exports){
8941
+ },{"../contexts":10,"./import-sequencer":82,"./visitor":87}],84:[function(require,module,exports){
8551
8942
  var visitors = {
8552
8943
  Visitor: require("./visitor"),
8553
8944
  ImportVisitor: require('./import-visitor'),
@@ -8558,7 +8949,7 @@ var visitors = {
8558
8949
 
8559
8950
  module.exports = visitors;
8560
8951
 
8561
- },{"./extend-visitor":80,"./import-visitor":82,"./join-selector-visitor":84,"./to-css-visitor":85,"./visitor":86}],84:[function(require,module,exports){
8952
+ },{"./extend-visitor":81,"./import-visitor":83,"./join-selector-visitor":85,"./to-css-visitor":86,"./visitor":87}],85:[function(require,module,exports){
8562
8953
  var Visitor = require("./visitor");
8563
8954
 
8564
8955
  var JoinSelectorVisitor = function() {
@@ -8605,7 +8996,7 @@ JoinSelectorVisitor.prototype = {
8605
8996
 
8606
8997
  module.exports = JoinSelectorVisitor;
8607
8998
 
8608
- },{"./visitor":86}],85:[function(require,module,exports){
8999
+ },{"./visitor":87}],86:[function(require,module,exports){
8609
9000
  var tree = require("../tree"),
8610
9001
  Visitor = require("./visitor");
8611
9002
 
@@ -8654,16 +9045,16 @@ ToCSSVisitor.prototype = {
8654
9045
  },
8655
9046
 
8656
9047
  visitDirective: function(directiveNode, visitArgs) {
8657
- if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
8658
- return;
8659
- }
8660
9048
  if (directiveNode.name === "@charset") {
9049
+ if (!directiveNode.getIsReferenced()) {
9050
+ return;
9051
+ }
8661
9052
  // Only output the debug info together with subsequent @charset definitions
8662
9053
  // a comment (or @media statement) before the actual @charset directive would
8663
9054
  // be considered illegal css as it has to be on the first line
8664
9055
  if (this.charset) {
8665
9056
  if (directiveNode.debugInfo) {
8666
- var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "")+" */\n");
9057
+ var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
8667
9058
  comment.debugInfo = directiveNode.debugInfo;
8668
9059
  return this._visitor.visit(comment);
8669
9060
  }
@@ -8673,13 +9064,45 @@ ToCSSVisitor.prototype = {
8673
9064
  }
8674
9065
  if (directiveNode.rules && directiveNode.rules.rules) {
8675
9066
  this._mergeRules(directiveNode.rules.rules);
9067
+ //process childs
9068
+ directiveNode.accept(this._visitor);
9069
+ visitArgs.visitDeeper = false;
9070
+
9071
+ // the directive was directly referenced and therefore needs to be shown in the output
9072
+ if (directiveNode.getIsReferenced()) {
9073
+ return directiveNode;
9074
+ }
9075
+
9076
+ if (!directiveNode.rules.rules) {
9077
+ return ;
9078
+ }
9079
+
9080
+ //the directive was not directly referenced
9081
+ for (var r = 0; r < directiveNode.rules.rules.length; r++) {
9082
+ var rule = directiveNode.rules.rules[r];
9083
+ if (rule.getIsReferenced && rule.getIsReferenced()) {
9084
+ //the directive contains something that was referenced (likely by extend)
9085
+ //therefore it needs to be shown in output too
9086
+
9087
+ //marking as referenced in case the directive is stored inside another directive
9088
+ directiveNode.markReferenced();
9089
+ return directiveNode;
9090
+ }
9091
+ }
9092
+ //The directive was not directly referenced and does not contain anything that
9093
+ //was referenced. Therefore it must not be shown in output.
9094
+ return ;
9095
+ } else {
9096
+ if (!directiveNode.getIsReferenced()) {
9097
+ return;
9098
+ }
8676
9099
  }
8677
9100
  return directiveNode;
8678
9101
  },
8679
9102
 
8680
9103
  checkPropertiesInRoot: function(rules) {
8681
9104
  var ruleNode;
8682
- for(var i = 0; i < rules.length; i++) {
9105
+ for (var i = 0; i < rules.length; i++) {
8683
9106
  ruleNode = rules[i];
8684
9107
  if (ruleNode instanceof tree.Rule && !ruleNode.variable) {
8685
9108
  throw { message: "properties must be inside selector blocks, they cannot be in the root.",
@@ -8701,7 +9124,7 @@ ToCSSVisitor.prototype = {
8701
9124
  if (p[0].elements[0].combinator.value === ' ') {
8702
9125
  p[0].elements[0].combinator = new(tree.Combinator)('');
8703
9126
  }
8704
- for(i = 0; i < p.length; i++) {
9127
+ for (i = 0; i < p.length; i++) {
8705
9128
  if (p[i].getIsReferenced() && p[i].getIsOutput()) {
8706
9129
  return true;
8707
9130
  }
@@ -8766,7 +9189,7 @@ ToCSSVisitor.prototype = {
8766
9189
  var ruleCache = {},
8767
9190
  ruleList, rule, i;
8768
9191
 
8769
- for(i = rules.length - 1; i >= 0 ; i--) {
9192
+ for (i = rules.length - 1; i >= 0 ; i--) {
8770
9193
  rule = rules[i];
8771
9194
  if (rule instanceof tree.Rule) {
8772
9195
  if (!ruleCache[rule.name]) {
@@ -8833,8 +9256,8 @@ ToCSSVisitor.prototype = {
8833
9256
  var spacedGroups = [];
8834
9257
  var lastSpacedGroup = [];
8835
9258
  parts.map(function (p) {
8836
- if (p.merge==="+") {
8837
- if (lastSpacedGroup.length > 0) {
9259
+ if (p.merge === "+") {
9260
+ if (lastSpacedGroup.length > 0) {
8838
9261
  spacedGroups.push(toExpression(lastSpacedGroup));
8839
9262
  }
8840
9263
  lastSpacedGroup = [];
@@ -8850,7 +9273,7 @@ ToCSSVisitor.prototype = {
8850
9273
 
8851
9274
  module.exports = ToCSSVisitor;
8852
9275
 
8853
- },{"../tree":58,"./visitor":86}],86:[function(require,module,exports){
9276
+ },{"../tree":59,"./visitor":87}],87:[function(require,module,exports){
8854
9277
  var tree = require("../tree");
8855
9278
 
8856
9279
  var _visitArgs = { visitDeeper: true },
@@ -9004,73 +9427,43 @@ Visitor.prototype = {
9004
9427
  };
9005
9428
  module.exports = Visitor;
9006
9429
 
9007
- },{"../tree":58}],87:[function(require,module,exports){
9430
+ },{"../tree":59}],88:[function(require,module,exports){
9008
9431
  // shim for using process in browser
9009
9432
 
9010
9433
  var process = module.exports = {};
9434
+ var queue = [];
9435
+ var draining = false;
9011
9436
 
9012
- process.nextTick = (function () {
9013
- var canSetImmediate = typeof window !== 'undefined'
9014
- && window.setImmediate;
9015
- var canMutationObserver = typeof window !== 'undefined'
9016
- && window.MutationObserver;
9017
- var canPost = typeof window !== 'undefined'
9018
- && window.postMessage && window.addEventListener
9019
- ;
9020
-
9021
- if (canSetImmediate) {
9022
- return function (f) { return window.setImmediate(f) };
9437
+ function drainQueue() {
9438
+ if (draining) {
9439
+ return;
9023
9440
  }
9024
-
9025
- var queue = [];
9026
-
9027
- if (canMutationObserver) {
9028
- var hiddenDiv = document.createElement("div");
9029
- var observer = new MutationObserver(function () {
9030
- var queueList = queue.slice();
9031
- queue.length = 0;
9032
- queueList.forEach(function (fn) {
9033
- fn();
9034
- });
9035
- });
9036
-
9037
- observer.observe(hiddenDiv, { attributes: true });
9038
-
9039
- return function nextTick(fn) {
9040
- if (!queue.length) {
9041
- hiddenDiv.setAttribute('yes', 'no');
9042
- }
9043
- queue.push(fn);
9044
- };
9441
+ draining = true;
9442
+ var currentQueue;
9443
+ var len = queue.length;
9444
+ while(len) {
9445
+ currentQueue = queue;
9446
+ queue = [];
9447
+ var i = -1;
9448
+ while (++i < len) {
9449
+ currentQueue[i]();
9450
+ }
9451
+ len = queue.length;
9045
9452
  }
9046
-
9047
- if (canPost) {
9048
- window.addEventListener('message', function (ev) {
9049
- var source = ev.source;
9050
- if ((source === window || source === null) && ev.data === 'process-tick') {
9051
- ev.stopPropagation();
9052
- if (queue.length > 0) {
9053
- var fn = queue.shift();
9054
- fn();
9055
- }
9056
- }
9057
- }, true);
9058
-
9059
- return function nextTick(fn) {
9060
- queue.push(fn);
9061
- window.postMessage('process-tick', '*');
9062
- };
9453
+ draining = false;
9454
+ }
9455
+ process.nextTick = function (fun) {
9456
+ queue.push(fun);
9457
+ if (!draining) {
9458
+ setTimeout(drainQueue, 0);
9063
9459
  }
9064
-
9065
- return function nextTick(fn) {
9066
- setTimeout(fn, 0);
9067
- };
9068
- })();
9460
+ };
9069
9461
 
9070
9462
  process.title = 'browser';
9071
9463
  process.browser = true;
9072
9464
  process.env = {};
9073
9465
  process.argv = [];
9466
+ process.version = ''; // empty string to avoid regexp issues
9074
9467
 
9075
9468
  function noop() {}
9076
9469
 
@@ -9091,225 +9484,226 @@ process.cwd = function () { return '/' };
9091
9484
  process.chdir = function (dir) {
9092
9485
  throw new Error('process.chdir is not supported');
9093
9486
  };
9487
+ process.umask = function() { return 0; };
9094
9488
 
9095
- },{}],88:[function(require,module,exports){
9096
- 'use strict';
9097
-
9098
- var asap = require('asap')
9099
-
9100
- module.exports = Promise;
9101
- function Promise(fn) {
9102
- if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
9103
- if (typeof fn !== 'function') throw new TypeError('not a function')
9104
- var state = null
9105
- var value = null
9106
- var deferreds = []
9107
- var self = this
9108
-
9109
- this.then = function(onFulfilled, onRejected) {
9110
- return new self.constructor(function(resolve, reject) {
9111
- handle(new Handler(onFulfilled, onRejected, resolve, reject))
9112
- })
9113
- }
9114
-
9115
- function handle(deferred) {
9116
- if (state === null) {
9117
- deferreds.push(deferred)
9118
- return
9119
- }
9120
- asap(function() {
9121
- var cb = state ? deferred.onFulfilled : deferred.onRejected
9122
- if (cb === null) {
9123
- (state ? deferred.resolve : deferred.reject)(value)
9124
- return
9125
- }
9126
- var ret
9127
- try {
9128
- ret = cb(value)
9129
- }
9130
- catch (e) {
9131
- deferred.reject(e)
9132
- return
9133
- }
9134
- deferred.resolve(ret)
9135
- })
9136
- }
9137
-
9138
- function resolve(newValue) {
9139
- try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
9140
- if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
9141
- if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
9142
- var then = newValue.then
9143
- if (typeof then === 'function') {
9144
- doResolve(then.bind(newValue), resolve, reject)
9145
- return
9146
- }
9147
- }
9148
- state = true
9149
- value = newValue
9150
- finale()
9151
- } catch (e) { reject(e) }
9152
- }
9153
-
9154
- function reject(newValue) {
9155
- state = false
9156
- value = newValue
9157
- finale()
9158
- }
9159
-
9160
- function finale() {
9161
- for (var i = 0, len = deferreds.length; i < len; i++)
9162
- handle(deferreds[i])
9163
- deferreds = null
9164
- }
9165
-
9166
- doResolve(fn, resolve, reject)
9167
- }
9168
-
9169
-
9170
- function Handler(onFulfilled, onRejected, resolve, reject){
9171
- this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
9172
- this.onRejected = typeof onRejected === 'function' ? onRejected : null
9173
- this.resolve = resolve
9174
- this.reject = reject
9175
- }
9176
-
9177
- /**
9178
- * Take a potentially misbehaving resolver function and make sure
9179
- * onFulfilled and onRejected are only called once.
9180
- *
9181
- * Makes no guarantees about asynchrony.
9182
- */
9183
- function doResolve(fn, onFulfilled, onRejected) {
9184
- var done = false;
9185
- try {
9186
- fn(function (value) {
9187
- if (done) return
9188
- done = true
9189
- onFulfilled(value)
9190
- }, function (reason) {
9191
- if (done) return
9192
- done = true
9193
- onRejected(reason)
9194
- })
9195
- } catch (ex) {
9196
- if (done) return
9197
- done = true
9198
- onRejected(ex)
9199
- }
9200
- }
9201
-
9202
- },{"asap":90}],89:[function(require,module,exports){
9203
- 'use strict';
9204
-
9205
- //This file contains the ES6 extensions to the core Promises/A+ API
9206
-
9207
- var Promise = require('./core.js')
9208
- var asap = require('asap')
9209
-
9210
- module.exports = Promise
9211
-
9212
- /* Static Functions */
9213
-
9214
- function ValuePromise(value) {
9215
- this.then = function (onFulfilled) {
9216
- if (typeof onFulfilled !== 'function') return this
9217
- return new Promise(function (resolve, reject) {
9218
- asap(function () {
9219
- try {
9220
- resolve(onFulfilled(value))
9221
- } catch (ex) {
9222
- reject(ex);
9223
- }
9224
- })
9225
- })
9226
- }
9227
- }
9228
- ValuePromise.prototype = Promise.prototype
9229
-
9230
- var TRUE = new ValuePromise(true)
9231
- var FALSE = new ValuePromise(false)
9232
- var NULL = new ValuePromise(null)
9233
- var UNDEFINED = new ValuePromise(undefined)
9234
- var ZERO = new ValuePromise(0)
9235
- var EMPTYSTRING = new ValuePromise('')
9236
-
9237
- Promise.resolve = function (value) {
9238
- if (value instanceof Promise) return value
9239
-
9240
- if (value === null) return NULL
9241
- if (value === undefined) return UNDEFINED
9242
- if (value === true) return TRUE
9243
- if (value === false) return FALSE
9244
- if (value === 0) return ZERO
9245
- if (value === '') return EMPTYSTRING
9246
-
9247
- if (typeof value === 'object' || typeof value === 'function') {
9248
- try {
9249
- var then = value.then
9250
- if (typeof then === 'function') {
9251
- return new Promise(then.bind(value))
9252
- }
9253
- } catch (ex) {
9254
- return new Promise(function (resolve, reject) {
9255
- reject(ex)
9256
- })
9257
- }
9258
- }
9259
-
9260
- return new ValuePromise(value)
9261
- }
9262
-
9263
- Promise.all = function (arr) {
9264
- var args = Array.prototype.slice.call(arr)
9265
-
9266
- return new Promise(function (resolve, reject) {
9267
- if (args.length === 0) return resolve([])
9268
- var remaining = args.length
9269
- function res(i, val) {
9270
- try {
9271
- if (val && (typeof val === 'object' || typeof val === 'function')) {
9272
- var then = val.then
9273
- if (typeof then === 'function') {
9274
- then.call(val, function (val) { res(i, val) }, reject)
9275
- return
9276
- }
9277
- }
9278
- args[i] = val
9279
- if (--remaining === 0) {
9280
- resolve(args);
9281
- }
9282
- } catch (ex) {
9283
- reject(ex)
9284
- }
9285
- }
9286
- for (var i = 0; i < args.length; i++) {
9287
- res(i, args[i])
9288
- }
9289
- })
9290
- }
9291
-
9292
- Promise.reject = function (value) {
9293
- return new Promise(function (resolve, reject) {
9294
- reject(value);
9295
- });
9296
- }
9297
-
9298
- Promise.race = function (values) {
9299
- return new Promise(function (resolve, reject) {
9300
- values.forEach(function(value){
9301
- Promise.resolve(value).then(resolve, reject);
9302
- })
9303
- });
9304
- }
9305
-
9306
- /* Prototype Methods */
9307
-
9308
- Promise.prototype['catch'] = function (onRejected) {
9309
- return this.then(null, onRejected);
9310
- }
9489
+ },{}],89:[function(require,module,exports){
9490
+ 'use strict';
9491
+
9492
+ var asap = require('asap')
9493
+
9494
+ module.exports = Promise;
9495
+ function Promise(fn) {
9496
+ if (typeof this !== 'object') throw new TypeError('Promises must be constructed via new')
9497
+ if (typeof fn !== 'function') throw new TypeError('not a function')
9498
+ var state = null
9499
+ var value = null
9500
+ var deferreds = []
9501
+ var self = this
9502
+
9503
+ this.then = function(onFulfilled, onRejected) {
9504
+ return new self.constructor(function(resolve, reject) {
9505
+ handle(new Handler(onFulfilled, onRejected, resolve, reject))
9506
+ })
9507
+ }
9508
+
9509
+ function handle(deferred) {
9510
+ if (state === null) {
9511
+ deferreds.push(deferred)
9512
+ return
9513
+ }
9514
+ asap(function() {
9515
+ var cb = state ? deferred.onFulfilled : deferred.onRejected
9516
+ if (cb === null) {
9517
+ (state ? deferred.resolve : deferred.reject)(value)
9518
+ return
9519
+ }
9520
+ var ret
9521
+ try {
9522
+ ret = cb(value)
9523
+ }
9524
+ catch (e) {
9525
+ deferred.reject(e)
9526
+ return
9527
+ }
9528
+ deferred.resolve(ret)
9529
+ })
9530
+ }
9311
9531
 
9312
- },{"./core.js":88,"asap":90}],90:[function(require,module,exports){
9532
+ function resolve(newValue) {
9533
+ try { //Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
9534
+ if (newValue === self) throw new TypeError('A promise cannot be resolved with itself.')
9535
+ if (newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
9536
+ var then = newValue.then
9537
+ if (typeof then === 'function') {
9538
+ doResolve(then.bind(newValue), resolve, reject)
9539
+ return
9540
+ }
9541
+ }
9542
+ state = true
9543
+ value = newValue
9544
+ finale()
9545
+ } catch (e) { reject(e) }
9546
+ }
9547
+
9548
+ function reject(newValue) {
9549
+ state = false
9550
+ value = newValue
9551
+ finale()
9552
+ }
9553
+
9554
+ function finale() {
9555
+ for (var i = 0, len = deferreds.length; i < len; i++)
9556
+ handle(deferreds[i])
9557
+ deferreds = null
9558
+ }
9559
+
9560
+ doResolve(fn, resolve, reject)
9561
+ }
9562
+
9563
+
9564
+ function Handler(onFulfilled, onRejected, resolve, reject){
9565
+ this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null
9566
+ this.onRejected = typeof onRejected === 'function' ? onRejected : null
9567
+ this.resolve = resolve
9568
+ this.reject = reject
9569
+ }
9570
+
9571
+ /**
9572
+ * Take a potentially misbehaving resolver function and make sure
9573
+ * onFulfilled and onRejected are only called once.
9574
+ *
9575
+ * Makes no guarantees about asynchrony.
9576
+ */
9577
+ function doResolve(fn, onFulfilled, onRejected) {
9578
+ var done = false;
9579
+ try {
9580
+ fn(function (value) {
9581
+ if (done) return
9582
+ done = true
9583
+ onFulfilled(value)
9584
+ }, function (reason) {
9585
+ if (done) return
9586
+ done = true
9587
+ onRejected(reason)
9588
+ })
9589
+ } catch (ex) {
9590
+ if (done) return
9591
+ done = true
9592
+ onRejected(ex)
9593
+ }
9594
+ }
9595
+
9596
+ },{"asap":91}],90:[function(require,module,exports){
9597
+ 'use strict';
9598
+
9599
+ //This file contains the ES6 extensions to the core Promises/A+ API
9600
+
9601
+ var Promise = require('./core.js')
9602
+ var asap = require('asap')
9603
+
9604
+ module.exports = Promise
9605
+
9606
+ /* Static Functions */
9607
+
9608
+ function ValuePromise(value) {
9609
+ this.then = function (onFulfilled) {
9610
+ if (typeof onFulfilled !== 'function') return this
9611
+ return new Promise(function (resolve, reject) {
9612
+ asap(function () {
9613
+ try {
9614
+ resolve(onFulfilled(value))
9615
+ } catch (ex) {
9616
+ reject(ex);
9617
+ }
9618
+ })
9619
+ })
9620
+ }
9621
+ }
9622
+ ValuePromise.prototype = Promise.prototype
9623
+
9624
+ var TRUE = new ValuePromise(true)
9625
+ var FALSE = new ValuePromise(false)
9626
+ var NULL = new ValuePromise(null)
9627
+ var UNDEFINED = new ValuePromise(undefined)
9628
+ var ZERO = new ValuePromise(0)
9629
+ var EMPTYSTRING = new ValuePromise('')
9630
+
9631
+ Promise.resolve = function (value) {
9632
+ if (value instanceof Promise) return value
9633
+
9634
+ if (value === null) return NULL
9635
+ if (value === undefined) return UNDEFINED
9636
+ if (value === true) return TRUE
9637
+ if (value === false) return FALSE
9638
+ if (value === 0) return ZERO
9639
+ if (value === '') return EMPTYSTRING
9640
+
9641
+ if (typeof value === 'object' || typeof value === 'function') {
9642
+ try {
9643
+ var then = value.then
9644
+ if (typeof then === 'function') {
9645
+ return new Promise(then.bind(value))
9646
+ }
9647
+ } catch (ex) {
9648
+ return new Promise(function (resolve, reject) {
9649
+ reject(ex)
9650
+ })
9651
+ }
9652
+ }
9653
+
9654
+ return new ValuePromise(value)
9655
+ }
9656
+
9657
+ Promise.all = function (arr) {
9658
+ var args = Array.prototype.slice.call(arr)
9659
+
9660
+ return new Promise(function (resolve, reject) {
9661
+ if (args.length === 0) return resolve([])
9662
+ var remaining = args.length
9663
+ function res(i, val) {
9664
+ try {
9665
+ if (val && (typeof val === 'object' || typeof val === 'function')) {
9666
+ var then = val.then
9667
+ if (typeof then === 'function') {
9668
+ then.call(val, function (val) { res(i, val) }, reject)
9669
+ return
9670
+ }
9671
+ }
9672
+ args[i] = val
9673
+ if (--remaining === 0) {
9674
+ resolve(args);
9675
+ }
9676
+ } catch (ex) {
9677
+ reject(ex)
9678
+ }
9679
+ }
9680
+ for (var i = 0; i < args.length; i++) {
9681
+ res(i, args[i])
9682
+ }
9683
+ })
9684
+ }
9685
+
9686
+ Promise.reject = function (value) {
9687
+ return new Promise(function (resolve, reject) {
9688
+ reject(value);
9689
+ });
9690
+ }
9691
+
9692
+ Promise.race = function (values) {
9693
+ return new Promise(function (resolve, reject) {
9694
+ values.forEach(function(value){
9695
+ Promise.resolve(value).then(resolve, reject);
9696
+ })
9697
+ });
9698
+ }
9699
+
9700
+ /* Prototype Methods */
9701
+
9702
+ Promise.prototype['catch'] = function (onRejected) {
9703
+ return this.then(null, onRejected);
9704
+ }
9705
+
9706
+ },{"./core.js":89,"asap":91}],91:[function(require,module,exports){
9313
9707
  (function (process){
9314
9708
 
9315
9709
  // Use the fastest possible means to execute a task in a future turn
@@ -9426,30 +9820,30 @@ module.exports = asap;
9426
9820
 
9427
9821
 
9428
9822
  }).call(this,require('_process'))
9429
- },{"_process":87}],91:[function(require,module,exports){
9430
- // should work in any browser without browserify
9431
-
9432
- if (typeof Promise.prototype.done !== 'function') {
9433
- Promise.prototype.done = function (onFulfilled, onRejected) {
9434
- var self = arguments.length ? this.then.apply(this, arguments) : this
9435
- self.then(null, function (err) {
9436
- setTimeout(function () {
9437
- throw err
9438
- }, 0)
9439
- })
9440
- }
9823
+ },{"_process":88}],92:[function(require,module,exports){
9824
+ // should work in any browser without browserify
9825
+
9826
+ if (typeof Promise.prototype.done !== 'function') {
9827
+ Promise.prototype.done = function (onFulfilled, onRejected) {
9828
+ var self = arguments.length ? this.then.apply(this, arguments) : this
9829
+ self.then(null, function (err) {
9830
+ setTimeout(function () {
9831
+ throw err
9832
+ }, 0)
9833
+ })
9834
+ }
9441
9835
  }
9442
9836
  },{}],"promise/polyfill.js":[function(require,module,exports){
9443
- // not "use strict" so we can declare global "Promise"
9444
-
9445
- var asap = require('asap');
9446
-
9447
- if (typeof Promise === 'undefined') {
9448
- Promise = require('./lib/core.js')
9449
- require('./lib/es6-extensions.js')
9450
- }
9451
-
9452
- require('./polyfill-done.js');
9837
+ // not "use strict" so we can declare global "Promise"
9838
+
9839
+ var asap = require('asap');
9840
+
9841
+ if (typeof Promise === 'undefined') {
9842
+ Promise = require('./lib/core.js')
9843
+ require('./lib/es6-extensions.js')
9844
+ }
9845
+
9846
+ require('./polyfill-done.js');
9453
9847
 
9454
- },{"./lib/core.js":88,"./lib/es6-extensions.js":89,"./polyfill-done.js":91,"asap":90}]},{},[2])(2)
9848
+ },{"./lib/core.js":89,"./lib/es6-extensions.js":90,"./polyfill-done.js":92,"asap":91}]},{},[2])(2)
9455
9849
  });