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
@@ -1,16 +1,18 @@
1
1
  var Node = require("./node");
2
2
 
3
- var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike) {
3
+ var Anonymous = function (value, index, currentFileInfo, mapLines, rulesetLike, visibilityInfo) {
4
4
  this.value = value;
5
5
  this.index = index;
6
6
  this.mapLines = mapLines;
7
7
  this.currentFileInfo = currentFileInfo;
8
8
  this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;
9
+
10
+ this.copyVisibilityInfo(visibilityInfo);
9
11
  };
10
12
  Anonymous.prototype = new Node();
11
13
  Anonymous.prototype.type = "Anonymous";
12
14
  Anonymous.prototype.eval = function () {
13
- return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike);
15
+ return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
14
16
  };
15
17
  Anonymous.prototype.compare = function (other) {
16
18
  return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
@@ -4,7 +4,7 @@ var Node = require("./node"),
4
4
  //
5
5
  // RGB Colors - #ff0014, #eee
6
6
  //
7
- var Color = function (rgb, a) {
7
+ var Color = function (rgb, a, originalForm) {
8
8
  //
9
9
  // The end goal here, is to parse the arguments
10
10
  // into an integer triplet, such as `128, 255, 0`
@@ -23,6 +23,9 @@ var Color = function (rgb, a) {
23
23
  });
24
24
  }
25
25
  this.alpha = typeof a === 'number' ? a : 1;
26
+ if (typeof originalForm !== 'undefined') {
27
+ this.value = originalForm;
28
+ }
26
29
  };
27
30
 
28
31
  Color.prototype = new Node();
@@ -15,11 +15,7 @@ Comment.prototype.genCSS = function (context, output) {
15
15
  output.add(this.value);
16
16
  };
17
17
  Comment.prototype.isSilent = function(context) {
18
- var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
19
- isCompressed = context.compress && this.value[2] !== "!";
20
- return this.isLineComment || isReference || isCompressed;
21
- };
22
- Comment.prototype.markReferenced = function () {
23
- this.isReferenced = true;
18
+ var isCompressed = context.compress && this.value[2] !== "!";
19
+ return this.isLineComment || isCompressed;
24
20
  };
25
21
  module.exports = Comment;
@@ -2,7 +2,7 @@ var Node = require("./node"),
2
2
  Selector = require("./selector"),
3
3
  Ruleset = require("./ruleset");
4
4
 
5
- var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isReferenced, isRooted) {
5
+ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
6
6
  var i;
7
7
 
8
8
  this.name = name;
@@ -21,8 +21,8 @@ var Directive = function (name, value, rules, index, currentFileInfo, debugInfo,
21
21
  this.index = index;
22
22
  this.currentFileInfo = currentFileInfo;
23
23
  this.debugInfo = debugInfo;
24
- this.isReferenced = isReferenced;
25
24
  this.isRooted = isRooted || false;
25
+ this.copyVisibilityInfo(visibilityInfo);
26
26
  };
27
27
 
28
28
  Directive.prototype = new Node();
@@ -79,7 +79,7 @@ Directive.prototype.eval = function (context) {
79
79
  context.mediaBlocks = mediaBlocksBackup;
80
80
 
81
81
  return new Directive(this.name, value, rules,
82
- this.index, this.currentFileInfo, this.debugInfo, this.isReferenced, this.isRooted);
82
+ this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo());
83
83
  };
84
84
  Directive.prototype.variable = function (name) {
85
85
  if (this.rules) {
@@ -99,21 +99,6 @@ Directive.prototype.rulesets = function () {
99
99
  return Ruleset.prototype.rulesets.apply(this.rules[0]);
100
100
  }
101
101
  };
102
- Directive.prototype.markReferenced = function () {
103
- var i, rules;
104
- this.isReferenced = true;
105
- if (this.rules) {
106
- rules = this.rules;
107
- for (i = 0; i < rules.length; i++) {
108
- if (rules[i].markReferenced) {
109
- rules[i].markReferenced();
110
- }
111
- }
112
- }
113
- };
114
- Directive.prototype.getIsReferenced = function () {
115
- return !this.currentFileInfo || !this.currentFileInfo.reference || this.isReferenced;
116
- };
117
102
  Directive.prototype.outputRuleset = function (context, output, rules) {
118
103
  var ruleCnt = rules.length, i;
119
104
  context.tabLevel = (context.tabLevel | 0) + 1;
@@ -2,7 +2,7 @@ var Node = require("./node"),
2
2
  Paren = require("./paren"),
3
3
  Combinator = require("./combinator");
4
4
 
5
- var Element = function (combinator, value, index, currentFileInfo) {
5
+ var Element = function (combinator, value, index, currentFileInfo, info) {
6
6
  this.combinator = combinator instanceof Combinator ?
7
7
  combinator : new Combinator(combinator);
8
8
 
@@ -15,6 +15,7 @@ var Element = function (combinator, value, index, currentFileInfo) {
15
15
  }
16
16
  this.index = index;
17
17
  this.currentFileInfo = currentFileInfo;
18
+ this.copyVisibilityInfo(info);
18
19
  };
19
20
  Element.prototype = new Node();
20
21
  Element.prototype.type = "Element";
@@ -29,7 +30,13 @@ Element.prototype.eval = function (context) {
29
30
  return new Element(this.combinator,
30
31
  this.value.eval ? this.value.eval(context) : this.value,
31
32
  this.index,
32
- this.currentFileInfo);
33
+ this.currentFileInfo, this.visibilityInfo());
34
+ };
35
+ Element.prototype.clone = function () {
36
+ return new Element(this.combinator,
37
+ this.value,
38
+ this.index,
39
+ this.currentFileInfo, this.visibilityInfo());
33
40
  };
34
41
  Element.prototype.genCSS = function (context, output) {
35
42
  output.add(this.toCSS(context), this.currentFileInfo, this.index);
@@ -1,11 +1,14 @@
1
- var Node = require("./node");
1
+ var Node = require("./node"),
2
+ Selector = require("./selector");
2
3
 
3
- var Extend = function Extend(selector, option, index) {
4
+ var Extend = function Extend(selector, option, index, currentFileInfo, visibilityInfo) {
4
5
  this.selector = selector;
5
6
  this.option = option;
6
7
  this.index = index;
7
8
  this.object_id = Extend.next_id++;
8
9
  this.parent_ids = [this.object_id];
10
+ this.currentFileInfo = currentFileInfo || {};
11
+ this.copyVisibilityInfo(visibilityInfo);
9
12
 
10
13
  switch(option) {
11
14
  case "all":
@@ -26,11 +29,12 @@ Extend.prototype.accept = function (visitor) {
26
29
  this.selector = visitor.visit(this.selector);
27
30
  };
28
31
  Extend.prototype.eval = function (context) {
29
- return new Extend(this.selector.eval(context), this.option, this.index);
32
+ return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo());
30
33
  };
31
34
  Extend.prototype.clone = function (context) {
32
- return new Extend(this.selector, this.option, this.index);
35
+ return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo());
33
36
  };
37
+ //it concatenates (joins) all selectors in selector array
34
38
  Extend.prototype.findSelfSelectors = function (selectors) {
35
39
  var selfElements = [],
36
40
  i,
@@ -46,6 +50,7 @@ Extend.prototype.findSelfSelectors = function (selectors) {
46
50
  selfElements = selfElements.concat(selectors[i].elements);
47
51
  }
48
52
 
49
- this.selfSelectors = [{ elements: selfElements }];
53
+ this.selfSelectors = [new Selector(selfElements)];
54
+ this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo());
50
55
  };
51
56
  module.exports = Extend;
@@ -17,7 +17,7 @@ var Node = require("./node"),
17
17
  // `import,push`, we also pass it a callback, which it'll call once
18
18
  // the file has been fetched, and parsed.
19
19
  //
20
- var Import = function (path, features, options, index, currentFileInfo) {
20
+ var Import = function (path, features, options, index, currentFileInfo, visibilityInfo) {
21
21
  this.options = options;
22
22
  this.index = index;
23
23
  this.path = path;
@@ -32,6 +32,7 @@ var Import = function (path, features, options, index, currentFileInfo) {
32
32
  this.css = true;
33
33
  }
34
34
  }
35
+ this.copyVisibilityInfo(visibilityInfo);
35
36
  };
36
37
 
37
38
  //
@@ -87,7 +88,7 @@ Import.prototype.evalForImport = function (context) {
87
88
  path = path.value;
88
89
  }
89
90
 
90
- return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo);
91
+ return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo());
91
92
  };
92
93
  Import.prototype.evalPath = function (context) {
93
94
  var path = this.path.eval(context);
@@ -107,6 +108,20 @@ Import.prototype.evalPath = function (context) {
107
108
  return path;
108
109
  };
109
110
  Import.prototype.eval = function (context) {
111
+ var result = this.doEval(context);
112
+ if (this.options.reference || this.blocksVisibility()) {
113
+ if (result.length || result.length === 0) {
114
+ result.forEach(function (node) {
115
+ node.addVisibilityBlock();
116
+ }
117
+ );
118
+ } else {
119
+ result.addVisibilityBlock();
120
+ }
121
+ }
122
+ return result;
123
+ };
124
+ Import.prototype.doEval = function (context) {
110
125
  var ruleset, registry,
111
126
  features = this.features && this.features.eval(context);
112
127
 
@@ -126,9 +141,13 @@ Import.prototype.eval = function (context) {
126
141
  return [];
127
142
  }
128
143
  }
129
-
130
144
  if (this.options.inline) {
131
- var contents = new Anonymous(this.root, 0, {filename: this.importedFilename}, true, true);
145
+ var contents = new Anonymous(this.root, 0,
146
+ {
147
+ filename: this.importedFilename,
148
+ reference: this.path.currentFileInfo && this.path.currentFileInfo.reference
149
+ }, true, true);
150
+
132
151
  return this.features ? new Media([contents], this.features.value) : [contents];
133
152
  } else if (this.css) {
134
153
  var newImport = new Import(this.evalPath(context), features, this.options, this.index);
@@ -138,7 +157,6 @@ Import.prototype.eval = function (context) {
138
157
  return newImport;
139
158
  } else {
140
159
  ruleset = new Ruleset(null, this.root.rules.slice(0));
141
-
142
160
  ruleset.evalImports(context);
143
161
 
144
162
  return this.features ? new Media(ruleset.rules, this.features.value) : ruleset.rules;
@@ -5,7 +5,7 @@ var Ruleset = require("./ruleset"),
5
5
  Expression = require("./expression"),
6
6
  Directive = require("./directive");
7
7
 
8
- var Media = function (value, features, index, currentFileInfo) {
8
+ var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
9
9
  this.index = index;
10
10
  this.currentFileInfo = currentFileInfo;
11
11
 
@@ -14,6 +14,7 @@ var Media = function (value, features, index, currentFileInfo) {
14
14
  this.features = new Value(features);
15
15
  this.rules = [new Ruleset(selectors, value)];
16
16
  this.rules[0].allowImports = true;
17
+ this.copyVisibilityInfo(visibilityInfo);
17
18
  };
18
19
  Media.prototype = new Directive();
19
20
  Media.prototype.type = "Media";
@@ -37,7 +38,7 @@ Media.prototype.eval = function (context) {
37
38
  context.mediaPath = [];
38
39
  }
39
40
 
40
- var media = new Media(null, [], this.index, this.currentFileInfo);
41
+ var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo());
41
42
  if (this.debugInfo) {
42
43
  this.rules[0].debugInfo = this.debugInfo;
43
44
  media.debugInfo = this.debugInfo;
@@ -77,6 +78,7 @@ Media.prototype.evalTop = function (context) {
77
78
  var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
78
79
  result = new Ruleset(selectors, context.mediaBlocks);
79
80
  result.multiMedia = true;
81
+ result.copyVisibilityInfo(this.visibilityInfo());
80
82
  }
81
83
 
82
84
  delete context.mediaBlocks;
@@ -5,7 +5,7 @@ var Node = require("./node"),
5
5
 
6
6
  var MixinCall = function (elements, args, index, currentFileInfo, important) {
7
7
  this.selector = new Selector(elements);
8
- this.arguments = (args && args.length) ? args : null;
8
+ this.arguments = args || [];
9
9
  this.index = index;
10
10
  this.currentFileInfo = currentFileInfo;
11
11
  this.important = important;
@@ -16,17 +16,18 @@ MixinCall.prototype.accept = function (visitor) {
16
16
  if (this.selector) {
17
17
  this.selector = visitor.visit(this.selector);
18
18
  }
19
- if (this.arguments) {
19
+ if (this.arguments.length) {
20
20
  this.arguments = visitor.visitArray(this.arguments);
21
21
  }
22
22
  };
23
23
  MixinCall.prototype.eval = function (context) {
24
- var mixins, mixin, mixinPath, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
24
+ var mixins, mixin, mixinPath, args = [], arg, argValue,
25
+ rules = [], match = false, i, m, f, isRecursive, isOneFound,
25
26
  candidates = [], candidate, conditionResult = [], defaultResult, defFalseEitherCase = -1,
26
27
  defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset, noArgumentsFilter;
27
28
 
28
29
  function calcDefGroup(mixin, mixinPath) {
29
- var p, namespace;
30
+ var f, p, namespace;
30
31
 
31
32
  for (f = 0; f < 2; f++) {
32
33
  conditionResult[f] = true;
@@ -52,9 +53,18 @@ MixinCall.prototype.eval = function (context) {
52
53
  return defFalseEitherCase;
53
54
  }
54
55
 
55
- args = this.arguments && this.arguments.map(function (a) {
56
- return { name: a.name, value: a.value.eval(context) };
57
- });
56
+ for (i = 0; i < this.arguments.length; i++) {
57
+ arg = this.arguments[i];
58
+ argValue = arg.value.eval(context);
59
+ if (arg.expand && Array.isArray(argValue.value)) {
60
+ argValue = argValue.value;
61
+ for (m = 0; m < argValue.length; m++) {
62
+ args.push({value: argValue[m]});
63
+ }
64
+ } else {
65
+ args.push({name: arg.name, value: argValue});
66
+ }
67
+ }
58
68
 
59
69
  noArgumentsFilter = function(rule) {return rule.matchArgs(null, context);};
60
70
 
@@ -117,11 +127,12 @@ MixinCall.prototype.eval = function (context) {
117
127
  mixin = candidates[m].mixin;
118
128
  if (!(mixin instanceof MixinDefinition)) {
119
129
  originalRuleset = mixin.originalRuleset || mixin;
120
- mixin = new MixinDefinition("", [], mixin.rules, null, false);
130
+ mixin = new MixinDefinition("", [], mixin.rules, null, false, null, originalRuleset.visibilityInfo());
121
131
  mixin.originalRuleset = originalRuleset;
122
132
  }
123
- Array.prototype.push.apply(
124
- rules, mixin.evalCall(context, args, this.important).rules);
133
+ var newRules = mixin.evalCall(context, args, this.important).rules;
134
+ this._setVisibilityToReplacement(newRules);
135
+ Array.prototype.push.apply(rules, newRules);
125
136
  } catch (e) {
126
137
  throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
127
138
  }
@@ -129,14 +140,6 @@ MixinCall.prototype.eval = function (context) {
129
140
  }
130
141
 
131
142
  if (match) {
132
- if (!this.currentFileInfo || !this.currentFileInfo.reference) {
133
- for (i = 0; i < rules.length; i++) {
134
- rule = rules[i];
135
- if (rule.markReferenced) {
136
- rule.markReferenced();
137
- }
138
- }
139
- }
140
143
  return rules;
141
144
  }
142
145
  }
@@ -151,6 +154,16 @@ MixinCall.prototype.eval = function (context) {
151
154
  index: this.index, filename: this.currentFileInfo.filename };
152
155
  }
153
156
  };
157
+
158
+ MixinCall.prototype._setVisibilityToReplacement = function (replacement) {
159
+ var i, rule;
160
+ if (this.blocksVisibility()) {
161
+ for (i = 0; i < replacement.length; i++) {
162
+ rule = replacement[i];
163
+ rule.addVisibilityBlock();
164
+ }
165
+ }
166
+ };
154
167
  MixinCall.prototype.format = function (args) {
155
168
  return this.selector.toCSS().trim() + '(' +
156
169
  (args ? args.map(function (a) {
@@ -5,7 +5,7 @@ var Selector = require("./selector"),
5
5
  Expression = require("./expression"),
6
6
  contexts = require("../contexts");
7
7
 
8
- var Definition = function (name, params, rules, condition, variadic, frames) {
8
+ var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) {
9
9
  this.name = name;
10
10
  this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])];
11
11
  this.params = params;
@@ -14,15 +14,19 @@ var Definition = function (name, params, rules, condition, variadic, frames) {
14
14
  this.arity = params.length;
15
15
  this.rules = rules;
16
16
  this._lookups = {};
17
+ var optionalParameters = [];
17
18
  this.required = params.reduce(function (count, p) {
18
19
  if (!p.name || (p.name && !p.value)) {
19
20
  return count + 1;
20
21
  }
21
22
  else {
23
+ optionalParameters.push(p.name);
22
24
  return count;
23
25
  }
24
26
  }, 0);
27
+ this.optionalParameters = optionalParameters;
25
28
  this.frames = frames;
29
+ this.copyVisibilityInfo(visibilityInfo);
26
30
  };
27
31
  Definition.prototype = new Ruleset();
28
32
  Definition.prototype.type = "MixinDefinition";
@@ -123,7 +127,7 @@ Definition.prototype.makeImportant = function() {
123
127
  return r;
124
128
  }
125
129
  });
126
- var result = new Definition (this.name, this.params, rules, this.condition, this.variadic, this.frames);
130
+ var result = new Definition(this.name, this.params, rules, this.condition, this.variadic, this.frames);
127
131
  return result;
128
132
  };
129
133
  Definition.prototype.eval = function (context) {
@@ -159,22 +163,30 @@ Definition.prototype.matchCondition = function (args, context) {
159
163
  return true;
160
164
  };
161
165
  Definition.prototype.matchArgs = function (args, context) {
162
- var argsLength = (args && args.length) || 0, len;
166
+ var allArgsCnt = (args && args.length) || 0, len, optionalParameters = this.optionalParameters;
167
+ var requiredArgsCnt = !args ? 0 : args.reduce(function (count, p) {
168
+ if (optionalParameters.indexOf(p.name) < 0) {
169
+ return count + 1;
170
+ } else {
171
+ return count;
172
+ }
173
+ }, 0);
163
174
 
164
175
  if (! this.variadic) {
165
- if (argsLength < this.required) {
176
+ if (requiredArgsCnt < this.required) {
166
177
  return false;
167
178
  }
168
- if (argsLength > this.params.length) {
179
+ if (allArgsCnt > this.params.length) {
169
180
  return false;
170
181
  }
171
182
  } else {
172
- if (argsLength < (this.required - 1)) {
183
+ if (requiredArgsCnt < (this.required - 1)) {
173
184
  return false;
174
185
  }
175
186
  }
176
187
 
177
- len = Math.min(argsLength, this.arity);
188
+ // check patterns
189
+ len = Math.min(requiredArgsCnt, this.arity);
178
190
 
179
191
  for (var i = 0; i < len; i++) {
180
192
  if (!this.params[i].name && !this.params[i].variadic) {
@@ -71,4 +71,53 @@ Node.numericCompare = function (a, b) {
71
71
  : a === b ? 0
72
72
  : a > b ? 1 : undefined;
73
73
  };
74
+ // Returns true if this node represents root of ast imported by reference
75
+ Node.prototype.blocksVisibility = function () {
76
+ if (this.visibilityBlocks == null) {
77
+ this.visibilityBlocks = 0;
78
+ }
79
+ return this.visibilityBlocks !== 0;
80
+ };
81
+ Node.prototype.addVisibilityBlock = function () {
82
+ if (this.visibilityBlocks == null) {
83
+ this.visibilityBlocks = 0;
84
+ }
85
+ this.visibilityBlocks = this.visibilityBlocks + 1;
86
+ };
87
+ Node.prototype.removeVisibilityBlock = function () {
88
+ if (this.visibilityBlocks == null) {
89
+ this.visibilityBlocks = 0;
90
+ }
91
+ this.visibilityBlocks = this.visibilityBlocks - 1;
92
+ };
93
+ //Turns on node visibility - if called node will be shown in output regardless
94
+ //of whether it comes from import by reference or not
95
+ Node.prototype.ensureVisibility = function () {
96
+ this.nodeVisible = true;
97
+ };
98
+ //Turns off node visibility - if called node will NOT be shown in output regardless
99
+ //of whether it comes from import by reference or not
100
+ Node.prototype.ensureInvisibility = function () {
101
+ this.nodeVisible = false;
102
+ };
103
+ // return values:
104
+ // false - the node must not be visible
105
+ // true - the node must be visible
106
+ // undefined or null - the node has the same visibility as its parent
107
+ Node.prototype.isVisible = function () {
108
+ return this.nodeVisible;
109
+ };
110
+ Node.prototype.visibilityInfo = function() {
111
+ return {
112
+ visibilityBlocks: this.visibilityBlocks,
113
+ nodeVisible: this.nodeVisible
114
+ };
115
+ };
116
+ Node.prototype.copyVisibilityInfo = function(info) {
117
+ if (!info) {
118
+ return;
119
+ }
120
+ this.visibilityBlocks = info.visibilityBlocks;
121
+ this.nodeVisible = info.nodeVisible;
122
+ };
74
123
  module.exports = Node;
@@ -92,4 +92,4 @@ Rule.prototype.makeImportant = function () {
92
92
  this.index, this.currentFileInfo, this.inline);
93
93
  };
94
94
 
95
- module.exports = Rule;
95
+ module.exports = Rule;