less 2.5.1 → 2.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/.travis.yml +3 -2
  2. package/CHANGELOG.md +41 -0
  3. package/Gruntfile.js +5 -10
  4. package/README.md +3 -3
  5. package/appveyor.yml +2 -2
  6. package/bin/lessc +1 -0
  7. package/bower.json +1 -2
  8. package/dist/less.js +969 -605
  9. package/dist/less.min.js +13 -9
  10. package/gradlew +0 -0
  11. package/lib/less/contexts.js +0 -1
  12. package/lib/less/functions/color.js +5 -2
  13. package/lib/less/functions/math-helper.js +16 -0
  14. package/lib/less/functions/math.js +4 -16
  15. package/lib/less/functions/number.js +7 -2
  16. package/lib/less/index.js +1 -1
  17. package/lib/less/parser/parser-input.js +68 -68
  18. package/lib/less/parser/parser.js +159 -75
  19. package/lib/less/transform-tree.js +1 -0
  20. package/lib/less/tree/anonymous.js +4 -2
  21. package/lib/less/tree/color.js +4 -1
  22. package/lib/less/tree/comment.js +2 -6
  23. package/lib/less/tree/directive.js +3 -18
  24. package/lib/less/tree/element.js +9 -2
  25. package/lib/less/tree/extend.js +10 -5
  26. package/lib/less/tree/import.js +23 -5
  27. package/lib/less/tree/media.js +4 -2
  28. package/lib/less/tree/mixin-call.js +31 -18
  29. package/lib/less/tree/mixin-definition.js +19 -7
  30. package/lib/less/tree/node.js +49 -0
  31. package/lib/less/tree/rule.js +1 -1
  32. package/lib/less/tree/ruleset.js +107 -125
  33. package/lib/less/tree/selector.js +4 -9
  34. package/lib/less/tree/unit.js +2 -2
  35. package/lib/less/visitors/extend-visitor.js +17 -8
  36. package/lib/less/visitors/import-visitor.js +5 -0
  37. package/lib/less/visitors/index.js +1 -0
  38. package/lib/less/visitors/set-tree-visibility-visitor.js +38 -0
  39. package/lib/less/visitors/to-css-visitor.js +181 -98
  40. package/lib/less-browser/bootstrap.js +28 -2
  41. package/lib/less-browser/cache.js +11 -4
  42. package/lib/less-browser/error-reporting.js +10 -10
  43. package/lib/less-browser/file-manager.js +1 -1
  44. package/lib/less-browser/image-size.js +28 -0
  45. package/lib/less-browser/index.js +9 -10
  46. package/package.json +14 -14
  47. package/test/browser/less/errors/image-height-error.less +3 -0
  48. package/test/browser/less/errors/image-height-error.txt +4 -0
  49. package/test/browser/less/errors/image-size-error.less +3 -0
  50. package/test/browser/less/errors/image-size-error.txt +4 -0
  51. package/test/browser/less/errors/image-width-error.less +3 -0
  52. package/test/browser/less/errors/image-width-error.txt +4 -0
  53. package/test/browser/less.js +23 -19
  54. package/test/css/comments2.css +7 -1
  55. package/test/css/compression/compression.css +1 -1
  56. package/test/css/css-3.css +6 -0
  57. package/test/css/extend-selector.css +7 -0
  58. package/test/css/extract-and-length.css +1 -1
  59. package/test/css/functions.css +3 -3
  60. package/test/css/import-reference-issues.css +24 -0
  61. package/test/css/import-reference.css +5 -1
  62. package/test/css/include-path/include-path.css +1 -1
  63. package/test/css/include-path-string/include-path-string.css +1 -1
  64. package/test/css/mixins-args.css +51 -1
  65. package/test/css/mixins-guards.css +36 -0
  66. package/test/css/no-strict-math/mixins-guards.css +12 -0
  67. package/test/css/no-strict-math/no-sm-operations.css +12 -0
  68. package/test/css/operations.css +1 -0
  69. package/test/css/scope.css +1 -1
  70. package/test/css/strings.css +1 -1
  71. package/test/css/url-args/urls.css +5 -5
  72. package/test/css/urls.css +8 -8
  73. package/test/css/variables.css +5 -5
  74. package/test/data/image.jpg +0 -0
  75. package/test/data/image.svg +2 -1
  76. package/test/data/page.html +1 -1
  77. package/test/index.js +1 -0
  78. package/test/less/comments2.less +11 -0
  79. package/test/less/css-3.less +10 -2
  80. package/test/less/errors/at-rules-undefined-var.txt +4 -4
  81. package/test/less/errors/css-guard-default-func.txt +4 -4
  82. package/test/less/errors/javascript-undefined-var.txt +4 -4
  83. package/test/less/errors/mixins-guards-default-func-1.txt +4 -4
  84. package/test/less/errors/mixins-guards-default-func-2.txt +4 -4
  85. package/test/less/errors/mixins-guards-default-func-3.txt +4 -4
  86. package/test/less/errors/parse-error-media-no-block-1.txt +1 -1
  87. package/test/less/errors/parse-error-media-no-block-2.txt +1 -1
  88. package/test/less/errors/parse-error-media-no-block-3.txt +1 -1
  89. package/test/less/errors/percentage-non-number-argument.less +3 -0
  90. package/test/less/errors/percentage-non-number-argument.txt +4 -0
  91. package/test/less/errors/property-interp-not-defined.txt +2 -2
  92. package/test/less/extend-selector.less +12 -1
  93. package/test/less/import/import-inline-invalid-css.less +1 -0
  94. package/test/less/import/import-reference.less +10 -1
  95. package/test/less/import-reference-issues/appender-reference-1968.less +6 -0
  96. package/test/less/import-reference-issues/global-scope-import.less +13 -0
  97. package/test/less/import-reference-issues/global-scope-nested.less +3 -0
  98. package/test/less/import-reference-issues/mixin-1968.less +8 -0
  99. package/test/less/import-reference-issues/multiple-import-nested.less +12 -0
  100. package/test/less/import-reference-issues/multiple-import.less +10 -0
  101. package/test/less/import-reference-issues/simple-mixin.css +3 -0
  102. package/test/less/import-reference-issues/simple-ruleset-2162.less +3 -0
  103. package/test/less/import-reference-issues.less +50 -0
  104. package/test/less/import-reference.less +2 -0
  105. package/test/less/mixins-args.less +48 -0
  106. package/test/less/mixins-guards.less +78 -0
  107. package/test/less/no-strict-math/mixins-guards.less +25 -0
  108. package/test/less/no-strict-math/no-sm-operations.less +10 -0
  109. package/test/less/operations.less +1 -0
  110. package/test/less-bom/comments2.less +11 -0
  111. package/test/less-bom/css-3.less +10 -2
  112. package/test/less-bom/errors/at-rules-undefined-var.txt +4 -4
  113. package/test/less-bom/errors/css-guard-default-func.txt +4 -4
  114. package/test/less-bom/errors/javascript-undefined-var.txt +4 -4
  115. package/test/less-bom/errors/mixins-guards-default-func-1.txt +4 -4
  116. package/test/less-bom/errors/mixins-guards-default-func-2.txt +4 -4
  117. package/test/less-bom/errors/mixins-guards-default-func-3.txt +4 -4
  118. package/test/less-bom/errors/parse-error-media-no-block-1.txt +1 -1
  119. package/test/less-bom/errors/parse-error-media-no-block-2.txt +1 -1
  120. package/test/less-bom/errors/parse-error-media-no-block-3.txt +1 -1
  121. package/test/less-bom/errors/percentage-non-number-argument.less +3 -0
  122. package/test/less-bom/errors/percentage-non-number-argument.txt +4 -0
  123. package/test/less-bom/errors/property-interp-not-defined.txt +2 -2
  124. package/test/less-bom/extend-selector.less +12 -1
  125. package/test/less-bom/import/import-inline-invalid-css.less +1 -0
  126. package/test/less-bom/import/import-reference.less +10 -1
  127. package/test/less-bom/import-reference-issues/appender-reference-1968.less +6 -0
  128. package/test/less-bom/import-reference-issues/global-scope-import.less +13 -0
  129. package/test/less-bom/import-reference-issues/global-scope-nested.less +3 -0
  130. package/test/less-bom/import-reference-issues/mixin-1968.less +8 -0
  131. package/test/less-bom/import-reference-issues/multiple-import-nested.less +12 -0
  132. package/test/less-bom/import-reference-issues/multiple-import.less +10 -0
  133. package/test/less-bom/import-reference-issues/simple-mixin.css +3 -0
  134. package/test/less-bom/import-reference-issues/simple-ruleset-2162.less +3 -0
  135. package/test/less-bom/import-reference-issues.less +50 -0
  136. package/test/less-bom/import-reference.less +2 -0
  137. package/test/less-bom/mixins-args.less +48 -0
  138. package/test/less-bom/mixins-guards.less +78 -0
  139. package/test/less-bom/no-strict-math/mixins-guards.less +25 -0
  140. package/test/less-bom/no-strict-math/no-sm-operations.less +10 -0
  141. package/test/less-bom/operations.less +1 -0
  142. package/test/less-test.js +6 -1
  143. package/.idea/.name +0 -1
  144. package/.idea/jsLibraryMappings.xml +0 -6
  145. package/.idea/less.js.iml +0 -9
  146. package/.idea/libraries/less_js_node_modules.xml +0 -14
  147. package/.idea/misc.xml +0 -14
  148. package/.idea/modules.xml +0 -8
  149. package/.idea/vcs.xml +0 -6
  150. package/.idea/workspace.xml +0 -281
@@ -8,11 +8,12 @@ var Node = require("./node"),
8
8
  defaultFunc = require("../functions/default"),
9
9
  getDebugInfo = require("./debug-info");
10
10
 
11
- var Ruleset = function (selectors, rules, strictImports) {
11
+ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {
12
12
  this.selectors = selectors;
13
13
  this.rules = rules;
14
14
  this._lookups = {};
15
15
  this.strictImports = strictImports;
16
+ this.copyVisibilityInfo(visibilityInfo);
16
17
  };
17
18
  Ruleset.prototype = new Node();
18
19
  Ruleset.prototype.type = "Ruleset";
@@ -20,7 +21,7 @@ Ruleset.prototype.isRuleset = true;
20
21
  Ruleset.prototype.isRulesetLike = true;
21
22
  Ruleset.prototype.accept = function (visitor) {
22
23
  if (this.paths) {
23
- visitor.visitArray(this.paths, true);
24
+ this.paths = visitor.visitArray(this.paths, true);
24
25
  } else if (this.selectors) {
25
26
  this.selectors = visitor.visitArray(this.selectors);
26
27
  }
@@ -51,7 +52,7 @@ Ruleset.prototype.eval = function (context) {
51
52
  }
52
53
 
53
54
  var rules = this.rules ? this.rules.slice(0) : null,
54
- ruleset = new Ruleset(selectors, rules, this.strictImports),
55
+ ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()),
55
56
  rule, subRule;
56
57
 
57
58
  ruleset.originalRuleset = this;
@@ -159,6 +160,7 @@ Ruleset.prototype.eval = function (context) {
159
160
 
160
161
  for (var j = 0; j < rule.rules.length; j++) {
161
162
  subRule = rule.rules[j];
163
+ subRule.copyVisibilityInfo(rule.visibilityInfo());
162
164
  if (!(subRule instanceof Rule) || !subRule.variable) {
163
165
  rsRules.splice(++i, 0, subRule);
164
166
  }
@@ -186,7 +188,7 @@ Ruleset.prototype.evalImports = function(context) {
186
188
  for (i = 0; i < rules.length; i++) {
187
189
  if (rules[i].type === "Import") {
188
190
  importRules = rules[i].eval(context);
189
- if (importRules && importRules.length) {
191
+ if (importRules && (importRules.length || importRules.length === 0)) {
190
192
  rules.splice.apply(rules, [i, 1].concat(importRules));
191
193
  i+= importRules.length - 1;
192
194
  } else {
@@ -203,7 +205,7 @@ Ruleset.prototype.makeImportant = function() {
203
205
  } else {
204
206
  return r;
205
207
  }
206
- }), this.strictImports);
208
+ }), this.strictImports, this.visibilityInfo());
207
209
 
208
210
  return result;
209
211
  };
@@ -431,46 +433,6 @@ Ruleset.prototype.genCSS = function (context, output) {
431
433
  output.add('\n');
432
434
  }
433
435
  };
434
- Ruleset.prototype.markReferenced = function () {
435
- var s;
436
- if (this.selectors) {
437
- for (s = 0; s < this.selectors.length; s++) {
438
- this.selectors[s].markReferenced();
439
- }
440
- }
441
-
442
- if (this.rules) {
443
- for (s = 0; s < this.rules.length; s++) {
444
- if (this.rules[s].markReferenced) {
445
- this.rules[s].markReferenced();
446
- }
447
- }
448
- }
449
- };
450
- Ruleset.prototype.getIsReferenced = function() {
451
- var i, j, path, selector;
452
-
453
- if (this.paths) {
454
- for (i = 0; i < this.paths.length; i++) {
455
- path = this.paths[i];
456
- for (j = 0; j < path.length; j++) {
457
- if (path[j].getIsReferenced && path[j].getIsReferenced()) {
458
- return true;
459
- }
460
- }
461
- }
462
- }
463
-
464
- if (this.selectors) {
465
- for (i = 0; i < this.selectors.length; i++) {
466
- selector = this.selectors[i];
467
- if (selector.getIsReferenced && selector.getIsReferenced()) {
468
- return true;
469
- }
470
- }
471
- }
472
- return false;
473
- };
474
436
 
475
437
  Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
476
438
  for (var s = 0; s < selectors.length; s++) {
@@ -501,6 +463,91 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
501
463
  return selector;
502
464
  }
503
465
 
466
+ // joins selector path from `beginningPath` with selector path in `addPath`
467
+ // `replacedElement` contains element that is being replaced by `addPath`
468
+ // returns concatenated path
469
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
470
+ var newSelectorPath, lastSelector, newJoinedSelector;
471
+ // our new selector path
472
+ newSelectorPath = [];
473
+
474
+ //construct the joined selector - if & is the first thing this will be empty,
475
+ // if not newJoinedSelector will be the last set of elements in the selector
476
+ if (beginningPath.length > 0) {
477
+ newSelectorPath = beginningPath.slice(0);
478
+ lastSelector = newSelectorPath.pop();
479
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
480
+ }
481
+ else {
482
+ newJoinedSelector = originalSelector.createDerived([]);
483
+ }
484
+
485
+ if (addPath.length > 0) {
486
+ // /deep/ is a combinator that is valid without anything in front of it
487
+ // so if the & does not have a combinator that is "" or " " then
488
+ // and there is a combinator on the parent, then grab that.
489
+ // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
490
+ var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
491
+ if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
492
+ combinator = parentEl.combinator;
493
+ }
494
+ // join the elements so far with the first part of the parent
495
+ newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
496
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
497
+ }
498
+
499
+ // now add the joined selector - but only if it is not empty
500
+ if (newJoinedSelector.elements.length !== 0) {
501
+ newSelectorPath.push(newJoinedSelector);
502
+ }
503
+
504
+ //put together the parent selectors after the join (e.g. the rest of the parent)
505
+ if (addPath.length > 1) {
506
+ var restOfPath = addPath.slice(1);
507
+ restOfPath = restOfPath.map(function (selector) {
508
+ return selector.createDerived(selector.elements, []);
509
+ });
510
+ newSelectorPath = newSelectorPath.concat(restOfPath);
511
+ }
512
+ return newSelectorPath;
513
+ }
514
+
515
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
516
+ // `replacedElement` contains element that is being replaced by `addPath`
517
+ // returns array with all concatenated paths
518
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
519
+ var j;
520
+ for (j = 0; j < beginningPath.length; j++) {
521
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
522
+ result.push(newSelectorPath);
523
+ }
524
+ return result;
525
+ }
526
+
527
+ function mergeElementsOnToSelectors(elements, selectors) {
528
+ var i, sel;
529
+
530
+ if (elements.length === 0) {
531
+ return ;
532
+ }
533
+ if (selectors.length === 0) {
534
+ selectors.push([ new Selector(elements) ]);
535
+ return;
536
+ }
537
+
538
+ for (i = 0; i < selectors.length; i++) {
539
+ sel = selectors[i];
540
+
541
+ // if the previous thing in sel is a parent this needs to join on to it
542
+ if (sel.length > 0) {
543
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
544
+ }
545
+ else {
546
+ sel.push(new Selector(elements));
547
+ }
548
+ }
549
+ }
550
+
504
551
  // replace all parent selectors inside `inSelector` by content of `context` array
505
552
  // resulting selectors are returned inside `paths` array
506
553
  // returns true if `inSelector` contained at least one parent selector
@@ -614,91 +661,17 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
614
661
  paths.push(newSelectors[i]);
615
662
  lastSelector = newSelectors[i][length - 1];
616
663
  newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
664
+ //newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo());
617
665
  }
618
666
  }
619
667
 
620
668
  return hadParentSelector;
621
669
  }
622
670
 
623
- // joins selector path from `beginningPath` with selector path in `addPath`
624
- // `replacedElement` contains element that is being replaced by `addPath`
625
- // returns concatenated path
626
- function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
627
- var newSelectorPath, lastSelector, newJoinedSelector;
628
- // our new selector path
629
- newSelectorPath = [];
630
-
631
- //construct the joined selector - if & is the first thing this will be empty,
632
- // if not newJoinedSelector will be the last set of elements in the selector
633
- if (beginningPath.length > 0) {
634
- newSelectorPath = beginningPath.slice(0);
635
- lastSelector = newSelectorPath.pop();
636
- newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
637
- }
638
- else {
639
- newJoinedSelector = originalSelector.createDerived([]);
640
- }
641
-
642
- if (addPath.length > 0) {
643
- // /deep/ is a combinator that is valid without anything in front of it
644
- // so if the & does not have a combinator that is "" or " " then
645
- // and there is a combinator on the parent, then grab that.
646
- // this also allows + a { & .b { .a & { ... though not sure why you would want to do that
647
- var combinator = replacedElement.combinator, parentEl = addPath[0].elements[0];
648
- if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
649
- combinator = parentEl.combinator;
650
- }
651
- // join the elements so far with the first part of the parent
652
- newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
653
- newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
654
- }
655
-
656
- // now add the joined selector - but only if it is not empty
657
- if (newJoinedSelector.elements.length !== 0) {
658
- newSelectorPath.push(newJoinedSelector);
659
- }
660
-
661
- //put together the parent selectors after the join (e.g. the rest of the parent)
662
- if (addPath.length > 1) {
663
- newSelectorPath = newSelectorPath.concat(addPath.slice(1));
664
- }
665
- return newSelectorPath;
666
- }
667
-
668
- // joins selector path from `beginningPath` with every selector path in `addPaths` array
669
- // `replacedElement` contains element that is being replaced by `addPath`
670
- // returns array with all concatenated paths
671
- function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
672
- var j;
673
- for (j = 0; j < beginningPath.length; j++) {
674
- var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
675
- result.push(newSelectorPath);
676
- }
677
- return result;
678
- }
679
-
680
- function mergeElementsOnToSelectors(elements, selectors) {
681
- var i, sel;
682
-
683
- if (elements.length === 0) {
684
- return ;
685
- }
686
- if (selectors.length === 0) {
687
- selectors.push([ new Selector(elements) ]);
688
- return;
689
- }
690
-
691
- for (i = 0; i < selectors.length; i++) {
692
- sel = selectors[i];
693
-
694
- // if the previous thing in sel is a parent this needs to join on to it
695
- if (sel.length > 0) {
696
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
697
- }
698
- else {
699
- sel.push(new Selector(elements));
700
- }
701
- }
671
+ function deriveSelector(visibilityInfo, deriveFrom) {
672
+ var newSelector = deriveFrom.createDerived(deriveFrom.elements, deriveFrom.extendList, deriveFrom.evaldCondition);
673
+ newSelector.copyVisibilityInfo(visibilityInfo);
674
+ return newSelector;
702
675
  }
703
676
 
704
677
  // joinSelector code follows
@@ -711,7 +684,16 @@ Ruleset.prototype.joinSelector = function (paths, context, selector) {
711
684
  if (context.length > 0) {
712
685
  newPaths = [];
713
686
  for (i = 0; i < context.length; i++) {
714
- newPaths.push(context[i].concat(selector));
687
+ //var concatenated = [];
688
+ //context[i].forEach(function(entry) {
689
+ // var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition);
690
+ // newEntry.copyVisibilityInfo(selector.visibilityInfo());
691
+ // concatenated.push(newEntry);
692
+ //}, this);
693
+ var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo()));
694
+
695
+ concatenated.push(selector);
696
+ newPaths.push(concatenated);
715
697
  }
716
698
  }
717
699
  else {
@@ -1,15 +1,15 @@
1
1
  var Node = require("./node"),
2
2
  Element = require("./element");
3
3
 
4
- var Selector = function (elements, extendList, condition, index, currentFileInfo, isReferenced) {
4
+ var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) {
5
5
  this.elements = elements;
6
6
  this.extendList = extendList;
7
7
  this.condition = condition;
8
8
  this.currentFileInfo = currentFileInfo || {};
9
- this.isReferenced = isReferenced;
10
9
  if (!condition) {
11
10
  this.evaldCondition = true;
12
11
  }
12
+ this.copyVisibilityInfo(visibilityInfo);
13
13
  };
14
14
  Selector.prototype = new Node();
15
15
  Selector.prototype.type = "Selector";
@@ -25,8 +25,9 @@ Selector.prototype.accept = function (visitor) {
25
25
  }
26
26
  };
27
27
  Selector.prototype.createDerived = function(elements, extendList, evaldCondition) {
28
+ var info = this.visibilityInfo();
28
29
  evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
29
- var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
30
+ var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info);
30
31
  newSelector.evaldCondition = evaldCondition;
31
32
  newSelector.mediaEmpty = this.mediaEmpty;
32
33
  return newSelector;
@@ -104,12 +105,6 @@ Selector.prototype.genCSS = function (context, output) {
104
105
  }
105
106
  }
106
107
  };
107
- Selector.prototype.markReferenced = function () {
108
- this.isReferenced = true;
109
- };
110
- Selector.prototype.getIsReferenced = function() {
111
- return !this.currentFileInfo.reference || this.isReferenced;
112
- };
113
108
  Selector.prototype.getIsOutput = function() {
114
109
  return this.evaldCondition;
115
110
  };
@@ -61,7 +61,7 @@ Unit.prototype.map = function(callback) {
61
61
  }
62
62
  };
63
63
  Unit.prototype.usedUnits = function() {
64
- var group, result = {}, mapUnit;
64
+ var group, result = {}, mapUnit, groupName;
65
65
 
66
66
  mapUnit = function (atomicUnit) {
67
67
  /*jshint loopfunc:true */
@@ -72,7 +72,7 @@ Unit.prototype.usedUnits = function() {
72
72
  return atomicUnit;
73
73
  };
74
74
 
75
- for (var groupName in unitConversions) {
75
+ for (groupName in unitConversions) {
76
76
  if (unitConversions.hasOwnProperty(groupName)) {
77
77
  group = unitConversions[groupName];
78
78
 
@@ -156,17 +156,17 @@ ProcessExtendsVisitor.prototype = {
156
156
  matches = extendVisitor.findMatch(extend, selectorPath);
157
157
 
158
158
  if (matches.length) {
159
-
160
159
  extend.hasFoundMatches = true;
161
160
 
162
161
  // we found a match, so for each self selector..
163
162
  extend.selfSelectors.forEach(function(selfSelector) {
163
+ var info = targetExtend.visibilityInfo();
164
164
 
165
165
  // process the extend as usual
166
- newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector);
166
+ newSelector = extendVisitor.extendSelector(matches, selectorPath, selfSelector, extend.isVisible());
167
167
 
168
168
  // but now we create a new extend from it
169
- newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0);
169
+ newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info);
170
170
  newExtend.selfSelectors = newSelector;
171
171
 
172
172
  // add the extend onto the list of extends for that selector
@@ -247,7 +247,9 @@ ProcessExtendsVisitor.prototype = {
247
247
  allExtends[extendIndex].hasFoundMatches = true;
248
248
 
249
249
  allExtends[extendIndex].selfSelectors.forEach(function(selfSelector) {
250
- selectorsToAdd.push(extendVisitor.extendSelector(matches, selectorPath, selfSelector));
250
+ var extendedSelectors;
251
+ extendedSelectors = extendVisitor.extendSelector(matches, selectorPath, selfSelector, allExtends[extendIndex].isVisible());
252
+ selectorsToAdd.push(extendedSelectors);
251
253
  });
252
254
  }
253
255
  }
@@ -363,7 +365,7 @@ ProcessExtendsVisitor.prototype = {
363
365
  }
364
366
  return false;
365
367
  },
366
- extendSelector:function (matches, selectorPath, replacementSelector) {
368
+ extendSelector:function (matches, selectorPath, replacementSelector, isVisible) {
367
369
 
368
370
  //for a set of matches, replace each match with the replacement selector
369
371
 
@@ -423,11 +425,18 @@ ProcessExtendsVisitor.prototype = {
423
425
  }
424
426
 
425
427
  path = path.concat(selectorPath.slice(currentSelectorPathIndex, selectorPath.length));
426
-
428
+ path = path.map(function (currentValue) {
429
+ // we can re-use elements here, because the visibility property matters only for selectors
430
+ var derived = currentValue.createDerived(currentValue.elements);
431
+ if (isVisible) {
432
+ derived.ensureVisibility();
433
+ } else {
434
+ derived.ensureInvisibility();
435
+ }
436
+ return derived;
437
+ });
427
438
  return path;
428
439
  },
429
- visitRulesetOut: function (rulesetNode) {
430
- },
431
440
  visitMedia: function (mediaNode, visitArgs) {
432
441
  var newAllExtends = mediaNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
433
442
  newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, mediaNode.allExtends));
@@ -104,6 +104,7 @@ ImportVisitor.prototype = {
104
104
  var importVisitor = this,
105
105
  inlineCSS = importNode.options.inline,
106
106
  isPlugin = importNode.options.plugin,
107
+ isOptional = importNode.options.optional,
107
108
  duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
108
109
 
109
110
  if (!context.importMultiple) {
@@ -120,6 +121,10 @@ ImportVisitor.prototype = {
120
121
  }
121
122
  }
122
123
 
124
+ if (!fullPath && isOptional) {
125
+ importNode.skip = true;
126
+ }
127
+
123
128
  if (root) {
124
129
  importNode.root = root;
125
130
  importNode.importedFilename = fullPath;
@@ -1,6 +1,7 @@
1
1
  var visitors = {
2
2
  Visitor: require("./visitor"),
3
3
  ImportVisitor: require('./import-visitor'),
4
+ MarkVisibleSelectorsVisitor: require("./set-tree-visibility-visitor"),
4
5
  ExtendVisitor: require('./extend-visitor'),
5
6
  JoinSelectorVisitor: require('./join-selector-visitor'),
6
7
  ToCSSVisitor: require('./to-css-visitor')
@@ -0,0 +1,38 @@
1
+ var SetTreeVisibilityVisitor = function(visible) {
2
+ this.visible = visible;
3
+ };
4
+ SetTreeVisibilityVisitor.prototype.run = function(root) {
5
+ this.visit(root);
6
+ };
7
+ SetTreeVisibilityVisitor.prototype.visitArray = function(nodes) {
8
+ if (!nodes) {
9
+ return nodes;
10
+ }
11
+
12
+ var cnt = nodes.length, i;
13
+ for (i = 0; i < cnt; i++) {
14
+ this.visit(nodes[i]);
15
+ }
16
+ return nodes;
17
+ };
18
+ SetTreeVisibilityVisitor.prototype.visit = function(node) {
19
+ if (!node) {
20
+ return node;
21
+ }
22
+ if (node.constructor === Array) {
23
+ return this.visitArray(node);
24
+ }
25
+
26
+ if (!node.blocksVisibility || node.blocksVisibility()) {
27
+ return node;
28
+ }
29
+ if (this.visible) {
30
+ node.ensureVisibility();
31
+ } else {
32
+ node.ensureInvisibility();
33
+ }
34
+
35
+ node.accept(this);
36
+ return node;
37
+ };
38
+ module.exports = SetTreeVisibilityVisitor;