less 2.3.3 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Changelog.md +5 -0
- data/less.gemspec +1 -1
- data/lib/less/js/.gitattributes +9 -0
- data/lib/less/js/.gitignore +1 -0
- data/lib/less/js/.npmignore +1 -1
- data/lib/less/js/CHANGELOG.md +68 -0
- data/lib/less/js/CONTRIBUTING.md +33 -34
- data/lib/less/js/Makefile +24 -9
- data/lib/less/js/README.md +2 -2
- data/lib/less/js/bin/lessc +102 -25
- data/lib/less/js/build/amd.js +1 -1
- data/lib/less/js/build/header.js +9 -7
- data/lib/less/js/dist/less-1.3.3.js +2 -2
- data/lib/less/js/dist/less-1.3.3.min.js +2 -2
- data/lib/less/js/dist/less-1.4.0-beta.js +5830 -0
- data/lib/less/js/dist/less-1.4.0-beta.min.js +11 -0
- data/lib/less/js/dist/less-1.4.0.js +5830 -0
- data/lib/less/js/dist/less-1.4.0.min.js +11 -0
- data/lib/less/js/dist/less-1.4.1.js +5837 -0
- data/lib/less/js/dist/less-1.4.1.min.js +11 -0
- data/lib/less/js/dist/less-1.4.2.js +5837 -0
- data/lib/less/js/dist/less-1.4.2.min.js +11 -0
- data/lib/less/js/dist/less-rhino-1.4.0.js +4273 -0
- data/lib/less/js/lib/less/browser.js +131 -101
- data/lib/less/js/lib/less/env.js +105 -0
- data/lib/less/js/lib/less/extend-visitor.js +391 -0
- data/lib/less/js/lib/less/functions.js +174 -19
- data/lib/less/js/lib/less/import-visitor.js +107 -0
- data/lib/less/js/lib/less/index.js +70 -63
- data/lib/less/js/lib/less/join-selector-visitor.js +37 -0
- data/lib/less/js/lib/less/lessc_helper.js +13 -4
- data/lib/less/js/lib/less/parser.js +353 -264
- data/lib/less/js/lib/less/rhino.js +5 -2
- data/lib/less/js/lib/less/tree.js +1 -1
- data/lib/less/js/lib/less/tree/alpha.js +7 -3
- data/lib/less/js/lib/less/tree/anonymous.js +1 -0
- data/lib/less/js/lib/less/tree/assignment.js +4 -0
- data/lib/less/js/lib/less/tree/call.js +14 -8
- data/lib/less/js/lib/less/tree/color.js +50 -5
- data/lib/less/js/lib/less/tree/comment.js +1 -0
- data/lib/less/js/lib/less/tree/condition.js +35 -28
- data/lib/less/js/lib/less/tree/dimension.js +270 -16
- data/lib/less/js/lib/less/tree/directive.js +7 -2
- data/lib/less/js/lib/less/tree/element.js +57 -21
- data/lib/less/js/lib/less/tree/expression.js +29 -4
- data/lib/less/js/lib/less/tree/extend.js +43 -0
- data/lib/less/js/lib/less/tree/import.js +49 -28
- data/lib/less/js/lib/less/tree/javascript.js +1 -0
- data/lib/less/js/lib/less/tree/keyword.js +3 -2
- data/lib/less/js/lib/less/tree/media.js +20 -4
- data/lib/less/js/lib/less/tree/mixin.js +38 -18
- data/lib/less/js/lib/less/tree/negative.js +22 -0
- data/lib/less/js/lib/less/tree/operation.js +32 -17
- data/lib/less/js/lib/less/tree/paren.js +5 -1
- data/lib/less/js/lib/less/tree/quoted.js +5 -3
- data/lib/less/js/lib/less/tree/rule.js +44 -31
- data/lib/less/js/lib/less/tree/ruleset.js +50 -23
- data/lib/less/js/lib/less/tree/selector.js +49 -39
- data/lib/less/js/lib/less/tree/unicode-descriptor.js +1 -0
- data/lib/less/js/lib/less/tree/url.js +9 -5
- data/lib/less/js/lib/less/tree/value.js +4 -1
- data/lib/less/js/lib/less/tree/variable.js +4 -3
- data/lib/less/js/lib/less/visitor.js +54 -0
- data/lib/less/js/package.json +69 -19
- data/lib/less/js/test/browser-test-prepare.js +23 -6
- data/lib/less/js/test/browser/common.js +55 -3
- data/lib/less/js/test/browser/css/urls.css +13 -0
- data/lib/less/js/test/browser/less/relative-urls/urls.less +1 -1
- data/lib/less/js/test/browser/less/urls.less +16 -0
- data/lib/less/js/test/browser/phantom-runner.js +7 -5
- data/lib/less/js/test/browser/runner-browser.js +5 -1
- data/lib/less/js/test/browser/runner-errors.js +5 -0
- data/lib/less/js/test/browser/runner-legacy.js +6 -0
- data/lib/less/js/test/browser/runner-production.js +7 -0
- data/lib/less/js/test/browser/template.htm +6 -6
- data/lib/less/js/test/css/comments.css +1 -0
- data/lib/less/js/test/css/compression/compression.css +2 -0
- data/lib/less/js/test/css/css-3.css +4 -0
- data/lib/less/js/test/css/css.css +9 -3
- data/lib/less/js/test/css/extend-chaining.css +72 -0
- data/lib/less/js/test/css/extend-clearfix.css +19 -0
- data/lib/less/js/test/css/extend-exact.css +37 -0
- data/lib/less/js/test/css/extend-media.css +24 -0
- data/lib/less/js/test/css/extend-nest.css +57 -0
- data/lib/less/js/test/css/extend-selector.css +72 -0
- data/lib/less/js/test/css/extend.css +76 -0
- data/lib/less/js/test/css/functions.css +28 -0
- data/lib/less/js/test/css/import-interpolation.css +6 -0
- data/lib/less/js/test/css/import.css +18 -1
- data/lib/less/js/test/css/legacy/legacy.css +7 -0
- data/lib/less/js/test/css/media.css +9 -1
- data/lib/less/js/test/css/mixins-args.css +18 -0
- data/lib/less/js/test/css/mixins-guards.css +5 -0
- data/lib/less/js/test/css/parens.css +18 -5
- data/lib/less/js/test/css/selectors.css +14 -6
- data/lib/less/js/test/css/urls.css +17 -0
- data/lib/less/js/test/css/variables.css +22 -3
- data/lib/less/js/test/data/data-uri-fail.png +0 -0
- data/lib/less/js/test/data/image.jpg +0 -0
- data/lib/less/js/test/data/page.html +1 -0
- data/lib/less/js/test/less-test.js +41 -9
- data/lib/less/js/test/less/colors.less +4 -4
- data/lib/less/js/test/less/comments.less +2 -2
- data/lib/less/js/test/less/compression/compression.less +16 -0
- data/lib/less/js/test/less/css-3.less +5 -1
- data/lib/less/js/test/less/css.less +9 -3
- data/lib/less/js/test/less/errors/add-mixed-units.less +3 -0
- data/lib/less/js/test/less/errors/add-mixed-units.txt +2 -0
- data/lib/less/js/test/less/errors/add-mixed-units2.less +3 -0
- data/lib/less/js/test/less/errors/add-mixed-units2.txt +2 -0
- data/lib/less/js/test/less/errors/bad-variable-declaration1.txt +1 -1
- data/lib/less/js/test/less/errors/color-operation-error.less +3 -0
- data/lib/less/js/test/less/errors/color-operation-error.txt +2 -0
- data/lib/less/js/test/less/errors/comment-in-selector.txt +1 -1
- data/lib/less/js/test/less/errors/divide-mixed-units.less +3 -0
- data/lib/less/js/test/less/errors/divide-mixed-units.txt +4 -0
- data/lib/less/js/test/less/errors/extend-no-selector.less +3 -0
- data/lib/less/js/test/less/errors/extend-no-selector.txt +3 -0
- data/lib/less/js/test/less/errors/extend-not-at-end.less +3 -0
- data/lib/less/js/test/less/errors/extend-not-at-end.txt +3 -0
- data/lib/less/js/test/less/errors/import-missing.less +5 -0
- data/lib/less/js/test/less/errors/import-missing.txt +3 -3
- data/lib/less/js/test/less/errors/import-no-semi.txt +1 -1
- data/lib/less/js/test/less/errors/import-subfolder1.txt +1 -1
- data/lib/less/js/test/less/errors/import-subfolder2.txt +1 -1
- data/lib/less/js/test/less/errors/javascript-error.txt +1 -1
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.txt +1 -1
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.txt +1 -1
- data/lib/less/js/test/less/errors/mixin-not-defined.txt +1 -1
- data/lib/less/js/test/less/errors/mixin-not-matched.txt +1 -1
- data/lib/less/js/test/less/errors/mixin-not-matched2.txt +1 -1
- data/lib/less/js/test/less/errors/multiply-mixed-units.less +7 -0
- data/lib/less/js/test/less/errors/multiply-mixed-units.txt +4 -0
- data/lib/less/js/test/less/errors/parens-error-1.less +3 -0
- data/lib/less/js/test/less/errors/parens-error-1.txt +4 -0
- data/lib/less/js/test/less/errors/parens-error-2.less +3 -0
- data/lib/less/js/test/less/errors/parens-error-2.txt +4 -0
- data/lib/less/js/test/less/errors/parens-error-3.less +3 -0
- data/lib/less/js/test/less/errors/parens-error-3.txt +4 -0
- data/lib/less/js/test/less/errors/parse-error-curly-bracket.txt +1 -1
- data/lib/less/js/test/less/errors/parse-error-missing-bracket.txt +2 -1
- data/lib/less/js/test/less/errors/parse-error-with-import.txt +1 -1
- data/lib/less/js/test/less/errors/property-ie5-hack.txt +1 -1
- data/lib/less/js/test/less/errors/property-in-root.less +4 -0
- data/lib/less/js/test/less/errors/property-in-root.txt +4 -0
- data/lib/less/js/test/less/errors/property-in-root2.less +1 -0
- data/lib/less/js/test/less/errors/property-in-root2.txt +4 -0
- data/lib/less/js/test/less/errors/property-in-root3.less +4 -0
- data/lib/less/js/test/less/errors/property-in-root3.txt +3 -0
- data/lib/less/js/test/less/errors/recursive-variable.txt +1 -1
- data/lib/less/js/test/less/extend-chaining.less +79 -0
- data/lib/less/js/test/less/extend-clearfix.less +19 -0
- data/lib/less/js/test/less/extend-exact.less +46 -0
- data/lib/less/js/test/less/extend-media.less +24 -0
- data/lib/less/js/test/less/extend-nest.less +65 -0
- data/lib/less/js/test/less/extend-selector.less +84 -0
- data/lib/less/js/test/less/extend.less +81 -0
- data/lib/less/js/test/less/functions.less +37 -6
- data/lib/less/js/test/less/import-interpolation.less +8 -0
- data/lib/less/js/test/less/import-once.less +4 -4
- data/lib/less/js/test/less/import.less +11 -2
- data/lib/less/js/test/less/import/deeper/import-once-test-a.less +1 -1
- data/lib/less/js/test/less/import/import-interpolation.less +1 -0
- data/lib/less/js/test/less/import/import-interpolation2.less +5 -0
- data/lib/less/js/test/less/javascript.less +1 -1
- data/lib/less/js/test/less/legacy/legacy.less +7 -0
- data/lib/less/js/test/less/media.less +14 -3
- data/lib/less/js/test/less/mixins-args.less +43 -5
- data/lib/less/js/test/less/mixins-guards.less +13 -0
- data/lib/less/js/test/less/mixins-named-args.less +5 -5
- data/lib/less/js/test/less/mixins-nested.less +2 -2
- data/lib/less/js/test/less/mixins-pattern.less +1 -1
- data/lib/less/js/test/less/mixins.less +1 -1
- data/lib/less/js/test/less/operations.less +27 -27
- data/lib/less/js/test/less/parens.less +20 -5
- data/lib/less/js/test/less/selectors.less +14 -7
- data/lib/less/js/test/less/urls.less +24 -0
- data/lib/less/js/test/less/variables.less +42 -12
- data/lib/less/loader.rb +33 -0
- data/lib/less/version.rb +1 -1
- data/spec/less/parser_spec.rb +5 -5
- metadata +76 -6
- data/lib/less/js/build/ecma-5.js +0 -120
- data/lib/less/js/lib/less/tree/ratio.js +0 -13
@@ -0,0 +1,22 @@
|
|
1
|
+
(function (tree) {
|
2
|
+
|
3
|
+
tree.Negative = function (node) {
|
4
|
+
this.value = node;
|
5
|
+
};
|
6
|
+
tree.Negative.prototype = {
|
7
|
+
type: "Negative",
|
8
|
+
accept: function (visitor) {
|
9
|
+
this.value = visitor.visit(this.value);
|
10
|
+
},
|
11
|
+
toCSS: function (env) {
|
12
|
+
return '-' + this.value.toCSS(env);
|
13
|
+
},
|
14
|
+
eval: function (env) {
|
15
|
+
if (env.isMathOn()) {
|
16
|
+
return (new(tree.Operation)('*', [new(tree.Dimension)(-1), this.value])).eval(env);
|
17
|
+
}
|
18
|
+
return new(tree.Negative)(this.value.eval(env));
|
19
|
+
}
|
20
|
+
};
|
21
|
+
|
22
|
+
})(require('../tree'));
|
@@ -1,31 +1,46 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Operation = function (op, operands) {
|
3
|
+
tree.Operation = function (op, operands, isSpaced) {
|
4
4
|
this.op = op.trim();
|
5
5
|
this.operands = operands;
|
6
|
+
this.isSpaced = isSpaced;
|
6
7
|
};
|
7
|
-
tree.Operation.prototype
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
tree.Operation.prototype = {
|
9
|
+
type: "Operation",
|
10
|
+
accept: function (visitor) {
|
11
|
+
this.operands = visitor.visit(this.operands);
|
12
|
+
},
|
13
|
+
eval: function (env) {
|
14
|
+
var a = this.operands[0].eval(env),
|
15
|
+
b = this.operands[1].eval(env),
|
16
|
+
temp;
|
11
17
|
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
if (env.isMathOn()) {
|
19
|
+
if (a instanceof tree.Dimension && b instanceof tree.Color) {
|
20
|
+
if (this.op === '*' || this.op === '+') {
|
21
|
+
temp = b, b = a, a = temp;
|
22
|
+
} else {
|
23
|
+
throw { type: "Operation",
|
24
|
+
message: "Can't substract or divide a color from a number" };
|
25
|
+
}
|
26
|
+
}
|
27
|
+
if (!a.operate) {
|
28
|
+
throw { type: "Operation",
|
29
|
+
message: "Operation on an invalid type" };
|
30
|
+
}
|
31
|
+
|
32
|
+
return a.operate(env, this.op, b);
|
15
33
|
} else {
|
16
|
-
|
17
|
-
message: "Can't substract or divide a color from a number" };
|
34
|
+
return new(tree.Operation)(this.op, [a, b], this.isSpaced);
|
18
35
|
}
|
36
|
+
},
|
37
|
+
toCSS: function (env) {
|
38
|
+
var separator = this.isSpaced ? " " : "";
|
39
|
+
return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS();
|
19
40
|
}
|
20
|
-
if (!a.operate) {
|
21
|
-
throw { name: "OperationError",
|
22
|
-
message: "Operation on an invalid type" };
|
23
|
-
}
|
24
|
-
|
25
|
-
return a.operate(this.op, b);
|
26
41
|
};
|
27
42
|
|
28
|
-
tree.operate = function (op, a, b) {
|
43
|
+
tree.operate = function (env, op, a, b) {
|
29
44
|
switch (op) {
|
30
45
|
case '+': return a + b;
|
31
46
|
case '-': return a - b;
|
@@ -5,8 +5,12 @@ tree.Paren = function (node) {
|
|
5
5
|
this.value = node;
|
6
6
|
};
|
7
7
|
tree.Paren.prototype = {
|
8
|
+
type: "Paren",
|
9
|
+
accept: function (visitor) {
|
10
|
+
this.value = visitor.visit(this.value);
|
11
|
+
},
|
8
12
|
toCSS: function (env) {
|
9
|
-
return '(' + this.value.toCSS(env) + ')';
|
13
|
+
return '(' + this.value.toCSS(env).trim() + ')';
|
10
14
|
},
|
11
15
|
eval: function (env) {
|
12
16
|
return new(tree.Paren)(this.value.eval(env));
|
@@ -1,12 +1,14 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Quoted = function (str, content, escaped,
|
3
|
+
tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
|
4
4
|
this.escaped = escaped;
|
5
5
|
this.value = content || '';
|
6
6
|
this.quote = str.charAt(0);
|
7
|
-
this.index =
|
7
|
+
this.index = index;
|
8
|
+
this.currentFileInfo = currentFileInfo;
|
8
9
|
};
|
9
10
|
tree.Quoted.prototype = {
|
11
|
+
type: "Quoted",
|
10
12
|
toCSS: function () {
|
11
13
|
if (this.escaped) {
|
12
14
|
return this.value;
|
@@ -19,7 +21,7 @@ tree.Quoted.prototype = {
|
|
19
21
|
var value = this.value.replace(/`([^`]+)`/g, function (_, exp) {
|
20
22
|
return new(tree.JavaScript)(exp, that.index, true).eval(env).value;
|
21
23
|
}).replace(/@\{([\w-]+)\}/g, function (_, name) {
|
22
|
-
var v = new(tree.Variable)('@' + name, that.index).eval(env);
|
24
|
+
var v = new(tree.Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true);
|
23
25
|
return (v instanceof tree.Quoted) ? v.value : v.toCSS();
|
24
26
|
});
|
25
27
|
return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index);
|
@@ -1,49 +1,62 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Rule = function (name, value, important, index, inline) {
|
3
|
+
tree.Rule = function (name, value, important, index, currentFileInfo, inline) {
|
4
4
|
this.name = name;
|
5
5
|
this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
|
6
6
|
this.important = important ? ' ' + important.trim() : '';
|
7
7
|
this.index = index;
|
8
|
+
this.currentFileInfo = currentFileInfo;
|
8
9
|
this.inline = inline || false;
|
9
10
|
|
10
11
|
if (name.charAt(0) === '@') {
|
11
12
|
this.variable = true;
|
12
13
|
} else { this.variable = false }
|
13
14
|
};
|
14
|
-
tree.Rule.prototype.toCSS = function (env) {
|
15
|
-
if (this.variable) { return "" }
|
16
|
-
else {
|
17
|
-
return this.name + (env.compress ? ':' : ': ') +
|
18
|
-
this.value.toCSS(env) +
|
19
|
-
this.important + (this.inline ? "" : ";");
|
20
|
-
}
|
21
|
-
};
|
22
|
-
|
23
|
-
tree.Rule.prototype.eval = function (context) {
|
24
|
-
return new(tree.Rule)(this.name,
|
25
|
-
this.value.eval(context),
|
26
|
-
this.important,
|
27
|
-
this.index, this.inline);
|
28
|
-
};
|
29
|
-
|
30
|
-
tree.Rule.prototype.makeImportant = function () {
|
31
|
-
return new(tree.Rule)(this.name,
|
32
|
-
this.value,
|
33
|
-
"!important",
|
34
|
-
this.index, this.inline);
|
35
|
-
};
|
36
15
|
|
37
|
-
tree.
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
tree.Shorthand.prototype = {
|
16
|
+
tree.Rule.prototype = {
|
17
|
+
type: "Rule",
|
18
|
+
accept: function (visitor) {
|
19
|
+
this.value = visitor.visit(this.value);
|
20
|
+
},
|
43
21
|
toCSS: function (env) {
|
44
|
-
|
22
|
+
if (this.variable) { return "" }
|
23
|
+
else {
|
24
|
+
try {
|
25
|
+
return this.name + (env.compress ? ':' : ': ') +
|
26
|
+
this.value.toCSS(env) +
|
27
|
+
this.important + (this.inline ? "" : ";");
|
28
|
+
}
|
29
|
+
catch(e) {
|
30
|
+
e.index = this.index;
|
31
|
+
e.filename = this.currentFileInfo.filename;
|
32
|
+
throw e;
|
33
|
+
}
|
34
|
+
}
|
45
35
|
},
|
46
|
-
eval: function () {
|
36
|
+
eval: function (env) {
|
37
|
+
var strictMathBypass = false;
|
38
|
+
if (this.name === "font" && !env.strictMath) {
|
39
|
+
strictMathBypass = true;
|
40
|
+
env.strictMath = true;
|
41
|
+
}
|
42
|
+
try {
|
43
|
+
return new(tree.Rule)(this.name,
|
44
|
+
this.value.eval(env),
|
45
|
+
this.important,
|
46
|
+
this.index, this.currentFileInfo, this.inline);
|
47
|
+
}
|
48
|
+
finally {
|
49
|
+
if (strictMathBypass) {
|
50
|
+
env.strictMath = false;
|
51
|
+
}
|
52
|
+
}
|
53
|
+
},
|
54
|
+
makeImportant: function () {
|
55
|
+
return new(tree.Rule)(this.name,
|
56
|
+
this.value,
|
57
|
+
"!important",
|
58
|
+
this.index, this.currentFileInfo, this.inline);
|
59
|
+
}
|
47
60
|
};
|
48
61
|
|
49
62
|
})(require('../tree'));
|
@@ -7,6 +7,11 @@ tree.Ruleset = function (selectors, rules, strictImports) {
|
|
7
7
|
this.strictImports = strictImports;
|
8
8
|
};
|
9
9
|
tree.Ruleset.prototype = {
|
10
|
+
type: "Ruleset",
|
11
|
+
accept: function (visitor) {
|
12
|
+
this.selectors = visitor.visit(this.selectors);
|
13
|
+
this.rules = visitor.visit(this.rules);
|
14
|
+
},
|
10
15
|
eval: function (env) {
|
11
16
|
var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) });
|
12
17
|
var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports);
|
@@ -14,6 +19,7 @@ tree.Ruleset.prototype = {
|
|
14
19
|
|
15
20
|
ruleset.originalRuleset = this;
|
16
21
|
ruleset.root = this.root;
|
22
|
+
ruleset.firstRoot = this.firstRoot;
|
17
23
|
ruleset.allowImports = this.allowImports;
|
18
24
|
|
19
25
|
if(this.debugInfo) {
|
@@ -23,6 +29,12 @@ tree.Ruleset.prototype = {
|
|
23
29
|
// push the current ruleset to the frames stack
|
24
30
|
env.frames.unshift(ruleset);
|
25
31
|
|
32
|
+
// currrent selectors
|
33
|
+
if (!env.selectors) {
|
34
|
+
env.selectors = [];
|
35
|
+
}
|
36
|
+
env.selectors.unshift(this.selectors);
|
37
|
+
|
26
38
|
// Evaluate imports
|
27
39
|
if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
|
28
40
|
ruleset.evalImports(env);
|
@@ -41,13 +53,21 @@ tree.Ruleset.prototype = {
|
|
41
53
|
// Evaluate mixin calls.
|
42
54
|
for (var i = 0; i < ruleset.rules.length; i++) {
|
43
55
|
if (ruleset.rules[i] instanceof tree.mixin.Call) {
|
44
|
-
rules = ruleset.rules[i].eval(env)
|
56
|
+
rules = ruleset.rules[i].eval(env).filter(function(r) {
|
57
|
+
if ((r instanceof tree.Rule) && r.variable) {
|
58
|
+
// do not pollute the scope if the variable is
|
59
|
+
// already there. consider returning false here
|
60
|
+
// but we need a way to "return" variable from mixins
|
61
|
+
return !(ruleset.variable(r.name));
|
62
|
+
}
|
63
|
+
return true;
|
64
|
+
});
|
45
65
|
ruleset.rules.splice.apply(ruleset.rules, [i, 1].concat(rules));
|
46
66
|
i += rules.length-1;
|
47
67
|
ruleset.resetCache();
|
48
68
|
}
|
49
69
|
}
|
50
|
-
|
70
|
+
|
51
71
|
// Evaluate everything else
|
52
72
|
for (var i = 0, rule; i < ruleset.rules.length; i++) {
|
53
73
|
rule = ruleset.rules[i];
|
@@ -59,6 +79,7 @@ tree.Ruleset.prototype = {
|
|
59
79
|
|
60
80
|
// Pop the stack
|
61
81
|
env.frames.shift();
|
82
|
+
env.selectors.shift();
|
62
83
|
|
63
84
|
if (env.mediaBlocks) {
|
64
85
|
for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) {
|
@@ -115,12 +136,9 @@ tree.Ruleset.prototype = {
|
|
115
136
|
return this.variables()[name];
|
116
137
|
},
|
117
138
|
rulesets: function () {
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition);
|
122
|
-
});
|
123
|
-
}
|
139
|
+
return this.rules.filter(function (r) {
|
140
|
+
return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition);
|
141
|
+
});
|
124
142
|
},
|
125
143
|
find: function (selector, self) {
|
126
144
|
self = self || this;
|
@@ -151,28 +169,23 @@ tree.Ruleset.prototype = {
|
|
151
169
|
//
|
152
170
|
// `context` holds an array of arrays.
|
153
171
|
//
|
154
|
-
toCSS: function (
|
172
|
+
toCSS: function (env) {
|
155
173
|
var css = [], // The CSS output
|
156
174
|
rules = [], // node.Rule instances
|
157
175
|
_rules = [], //
|
158
176
|
rulesets = [], // node.Ruleset instances
|
159
|
-
paths = [], // Current selectors
|
160
177
|
selector, // The fully rendered selector
|
161
178
|
debugInfo, // Line number debugging
|
162
179
|
rule;
|
163
180
|
|
164
|
-
if (! this.root) {
|
165
|
-
this.joinSelectors(paths, context, this.selectors);
|
166
|
-
}
|
167
|
-
|
168
181
|
// Compile rules and rulesets
|
169
182
|
for (var i = 0; i < this.rules.length; i++) {
|
170
183
|
rule = this.rules[i];
|
171
184
|
|
172
185
|
if (rule.rules || (rule instanceof tree.Media)) {
|
173
|
-
rulesets.push(rule.toCSS(
|
186
|
+
rulesets.push(rule.toCSS(env));
|
174
187
|
} else if (rule instanceof tree.Directive) {
|
175
|
-
var cssValue = rule.toCSS(
|
188
|
+
var cssValue = rule.toCSS(env);
|
176
189
|
// Output only the first @charset definition as such - convert the others
|
177
190
|
// to comments in case debug is enabled
|
178
191
|
if (rule.name === "@charset") {
|
@@ -199,6 +212,10 @@ tree.Ruleset.prototype = {
|
|
199
212
|
}
|
200
213
|
} else {
|
201
214
|
if (rule.toCSS && !rule.variable) {
|
215
|
+
if (this.firstRoot && rule instanceof tree.Rule) {
|
216
|
+
throw { message: "properties must be inside selector blocks, they cannot be in the root.",
|
217
|
+
index: rule.index, filename: rule.currentFileInfo ? rule.currentFileInfo.filename : null};
|
218
|
+
}
|
202
219
|
rules.push(rule.toCSS(env));
|
203
220
|
} else if (rule.value && !rule.variable) {
|
204
221
|
rules.push(rule.value.toString());
|
@@ -206,6 +223,14 @@ tree.Ruleset.prototype = {
|
|
206
223
|
}
|
207
224
|
}
|
208
225
|
|
226
|
+
// Remove last semicolon
|
227
|
+
if (env.compress && rules.length) {
|
228
|
+
rule = rules[rules.length - 1];
|
229
|
+
if (rule.charAt(rule.length - 1) === ';') {
|
230
|
+
rules[rules.length - 1] = rule.substring(0, rule.length - 1);
|
231
|
+
}
|
232
|
+
}
|
233
|
+
|
209
234
|
rulesets = rulesets.join('');
|
210
235
|
|
211
236
|
// If this is the root node, we don't render
|
@@ -216,7 +241,7 @@ tree.Ruleset.prototype = {
|
|
216
241
|
} else {
|
217
242
|
if (rules.length > 0) {
|
218
243
|
debugInfo = tree.debugInfo(env, this);
|
219
|
-
selector = paths.map(function (p) {
|
244
|
+
selector = this.paths.map(function (p) {
|
220
245
|
return p.map(function (s) {
|
221
246
|
return s.toCSS(env);
|
222
247
|
}).join('').trim();
|
@@ -224,7 +249,7 @@ tree.Ruleset.prototype = {
|
|
224
249
|
|
225
250
|
// Remove duplicates
|
226
251
|
for (var i = rules.length - 1; i >= 0; i--) {
|
227
|
-
if (_rules.indexOf(rules[i]) === -1) {
|
252
|
+
if (rules[i].slice(0, 2) === "/*" || _rules.indexOf(rules[i]) === -1) {
|
228
253
|
_rules.unshift(rules[i]);
|
229
254
|
}
|
230
255
|
}
|
@@ -339,11 +364,11 @@ tree.Ruleset.prototype = {
|
|
339
364
|
if (sel.length > 0) {
|
340
365
|
newSelectorPath = sel.slice(0);
|
341
366
|
lastSelector = newSelectorPath.pop();
|
342
|
-
newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0));
|
367
|
+
newJoinedSelector = new(tree.Selector)(lastSelector.elements.slice(0), selector.extendList);
|
343
368
|
newJoinedSelectorEmpty = false;
|
344
369
|
}
|
345
370
|
else {
|
346
|
-
newJoinedSelector = new(tree.Selector)([]);
|
371
|
+
newJoinedSelector = new(tree.Selector)([], selector.extendList);
|
347
372
|
}
|
348
373
|
|
349
374
|
//put together the parent selectors after the join
|
@@ -386,12 +411,14 @@ tree.Ruleset.prototype = {
|
|
386
411
|
}
|
387
412
|
|
388
413
|
for(i = 0; i < newSelectors.length; i++) {
|
389
|
-
|
414
|
+
if (newSelectors[i].length > 0) {
|
415
|
+
paths.push(newSelectors[i]);
|
416
|
+
}
|
390
417
|
}
|
391
418
|
},
|
392
419
|
|
393
420
|
mergeElementsOnToSelectors: function(elements, selectors) {
|
394
|
-
var i, sel;
|
421
|
+
var i, sel, extendList;
|
395
422
|
|
396
423
|
if (selectors.length == 0) {
|
397
424
|
selectors.push([ new(tree.Selector)(elements) ]);
|
@@ -403,7 +430,7 @@ tree.Ruleset.prototype = {
|
|
403
430
|
|
404
431
|
// if the previous thing in sel is a parent this needs to join on to it
|
405
432
|
if (sel.length > 0) {
|
406
|
-
sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements));
|
433
|
+
sel[sel.length - 1] = new(tree.Selector)(sel[sel.length - 1].elements.concat(elements), sel[sel.length - 1].extendList);
|
407
434
|
}
|
408
435
|
else {
|
409
436
|
sel.push(new(tree.Selector)(elements));
|
@@ -1,52 +1,62 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Selector = function (elements) {
|
3
|
+
tree.Selector = function (elements, extendList) {
|
4
4
|
this.elements = elements;
|
5
|
+
this.extendList = extendList || [];
|
5
6
|
};
|
6
|
-
tree.Selector.prototype
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
tree.Selector.prototype = {
|
8
|
+
type: "Selector",
|
9
|
+
accept: function (visitor) {
|
10
|
+
this.elements = visitor.visit(this.elements);
|
11
|
+
this.extendList = visitor.visit(this.extendList)
|
12
|
+
},
|
13
|
+
match: function (other) {
|
14
|
+
var elements = this.elements,
|
15
|
+
len = elements.length,
|
16
|
+
oelements, olen, max, i;
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
oelements = other.elements.slice(
|
19
|
+
(other.elements.length && other.elements[0].value === "&") ? 1 : 0);
|
20
|
+
olen = oelements.length;
|
21
|
+
max = Math.min(len, olen);
|
15
22
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
23
|
+
if (olen === 0 || len < olen) {
|
24
|
+
return false;
|
25
|
+
} else {
|
26
|
+
for (i = 0; i < max; i++) {
|
27
|
+
if (elements[i].value !== oelements[i].value) {
|
28
|
+
return false;
|
29
|
+
}
|
22
30
|
}
|
23
31
|
}
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
tree.Selector.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
};
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
this.
|
37
|
-
|
38
|
-
this._css = '';
|
39
|
-
}
|
40
|
-
|
41
|
-
this._css += this.elements.map(function (e) {
|
42
|
-
if (typeof(e) === 'string') {
|
43
|
-
return ' ' + e.trim();
|
32
|
+
return true;
|
33
|
+
},
|
34
|
+
eval: function (env) {
|
35
|
+
return new(tree.Selector)(this.elements.map(function (e) {
|
36
|
+
return e.eval(env);
|
37
|
+
}), this.extendList.map(function(extend) {
|
38
|
+
return extend.eval(env);
|
39
|
+
}));
|
40
|
+
},
|
41
|
+
toCSS: function (env) {
|
42
|
+
if (this._css) { return this._css }
|
43
|
+
|
44
|
+
if (this.elements[0].combinator.value === "") {
|
45
|
+
this._css = ' ';
|
44
46
|
} else {
|
45
|
-
|
47
|
+
this._css = '';
|
46
48
|
}
|
47
|
-
|
48
|
-
|
49
|
-
|
49
|
+
|
50
|
+
this._css += this.elements.map(function (e) {
|
51
|
+
if (typeof(e) === 'string') {
|
52
|
+
return ' ' + e.trim();
|
53
|
+
} else {
|
54
|
+
return e.toCSS(env);
|
55
|
+
}
|
56
|
+
}).join('');
|
57
|
+
|
58
|
+
return this._css;
|
59
|
+
}
|
50
60
|
};
|
51
61
|
|
52
62
|
})(require('../tree'));
|