less 2.0.8 → 2.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/less/js/Makefile +8 -2
- data/lib/less/js/benchmark/less-benchmark.js +1 -1
- data/lib/less/js/bin/lessc +17 -11
- data/lib/less/js/build/amd.js +6 -0
- data/lib/less/js/dist/less-1.1.5.min.js +1 -8
- data/lib/less/js/dist/less-1.1.6.js +3004 -0
- data/lib/less/js/dist/less-1.1.6.min.js +9 -0
- data/lib/less/js/dist/less-1.2.0.js +3293 -0
- data/lib/less/js/dist/less-1.2.0.min.js +9 -0
- data/lib/less/js/dist/less-1.2.1.js +3318 -0
- data/lib/less/js/dist/less-1.2.1.min.js +9 -0
- data/lib/less/js/lib/less/browser.js +33 -28
- data/lib/less/js/lib/less/colors.js +151 -0
- data/lib/less/js/lib/less/cssmin.js +355 -0
- data/lib/less/js/lib/less/functions.js +49 -6
- data/lib/less/js/lib/less/index.js +21 -18
- data/lib/less/js/lib/less/parser.js +230 -92
- data/lib/less/js/lib/less/rhino.js +3 -1
- data/lib/less/js/lib/less/tree.js +6 -2
- data/lib/less/js/lib/less/tree/call.js +6 -3
- data/lib/less/js/lib/less/tree/condition.js +42 -0
- data/lib/less/js/lib/less/tree/dimension.js +15 -0
- data/lib/less/js/lib/less/tree/directive.js +8 -2
- data/lib/less/js/lib/less/tree/element.js +14 -2
- data/lib/less/js/lib/less/tree/expression.js +1 -1
- data/lib/less/js/lib/less/tree/import.js +13 -11
- data/lib/less/js/lib/less/tree/keyword.js +11 -1
- data/lib/less/js/lib/less/tree/mixin.js +31 -13
- data/lib/less/js/lib/less/tree/paren.js +16 -0
- data/lib/less/js/lib/less/tree/quoted.js +1 -1
- data/lib/less/js/lib/less/tree/rule.js +7 -3
- data/lib/less/js/lib/less/tree/ruleset.js +7 -4
- data/lib/less/js/lib/less/tree/selector.js +5 -0
- data/lib/less/js/lib/less/tree/variable.js +4 -2
- data/lib/less/js/package.json +1 -1
- data/lib/less/js/test/css/colors.css +10 -0
- data/lib/less/js/test/css/comments.css +9 -5
- data/lib/less/js/test/css/css-3.css +4 -2
- data/lib/less/js/test/css/css-escapes.css +1 -1
- data/lib/less/js/test/css/css.css +8 -4
- data/lib/less/js/test/css/functions.css +13 -0
- data/lib/less/js/test/css/import.css +10 -3
- data/lib/less/js/test/css/media.css +8 -2
- data/lib/less/js/test/css/mixins-args.css +5 -2
- data/lib/less/js/test/css/mixins-guards.css +58 -0
- data/lib/less/js/test/css/mixins-important.css +17 -0
- data/lib/less/js/test/css/mixins.css +2 -1
- data/lib/less/js/test/css/operations.css +3 -0
- data/lib/less/js/test/css/parens.css +1 -1
- data/lib/less/js/test/css/rulesets.css +6 -2
- data/lib/less/js/test/css/scope.css +6 -6
- data/lib/less/js/test/css/selectors.css +8 -4
- data/lib/less/js/test/css/strings.css +6 -4
- data/lib/less/js/test/css/variables.css +3 -0
- data/lib/less/js/test/css/whitespace.css +5 -3
- data/lib/less/js/test/less-test.js +1 -1
- data/lib/less/js/test/less/colors.less +13 -0
- data/lib/less/js/test/less/comments.less +8 -6
- data/lib/less/js/test/less/functions.less +15 -1
- data/lib/less/js/test/less/import.less +3 -1
- data/lib/less/js/test/less/import/import-test-e.less +2 -0
- data/lib/less/js/test/less/media.less +6 -0
- data/lib/less/js/test/less/mixins-args.less +6 -0
- data/lib/less/js/test/less/mixins-guards.less +94 -0
- data/lib/less/js/test/less/mixins-important.less +18 -0
- data/lib/less/js/test/less/operations.less +4 -0
- data/lib/less/js/test/less/strings.less +2 -0
- data/lib/less/js/test/less/variables.less +4 -0
- data/lib/less/version.rb +1 -1
- metadata +28 -12
@@ -3,7 +3,9 @@ var name;
|
|
3
3
|
function loadStyleSheet(sheet, callback, reload, remaining) {
|
4
4
|
var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href;
|
5
5
|
var input = readFile(sheetName);
|
6
|
-
var parser = new less.Parser(
|
6
|
+
var parser = new less.Parser({
|
7
|
+
paths: [sheet.href.replace(/[\w\.-]+$/, '')]
|
8
|
+
});
|
7
9
|
parser.parse(input, function (e, root) {
|
8
10
|
if (e) {
|
9
11
|
print("Error: " + e);
|
@@ -1,13 +1,17 @@
|
|
1
|
-
|
1
|
+
(function (tree) {
|
2
|
+
|
3
|
+
tree.find = function (obj, fun) {
|
2
4
|
for (var i = 0, r; i < obj.length; i++) {
|
3
5
|
if (r = fun.call(obj, obj[i])) { return r }
|
4
6
|
}
|
5
7
|
return null;
|
6
8
|
};
|
7
|
-
|
9
|
+
tree.jsify = function (obj) {
|
8
10
|
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
|
9
11
|
return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']';
|
10
12
|
} else {
|
11
13
|
return obj.toCSS(false);
|
12
14
|
}
|
13
15
|
};
|
16
|
+
|
17
|
+
})(require('./tree'));
|
@@ -3,10 +3,11 @@
|
|
3
3
|
//
|
4
4
|
// A function call node.
|
5
5
|
//
|
6
|
-
tree.Call = function (name, args, index) {
|
6
|
+
tree.Call = function (name, args, index, filename) {
|
7
7
|
this.name = name;
|
8
8
|
this.args = args;
|
9
9
|
this.index = index;
|
10
|
+
this.filename = filename;
|
10
11
|
};
|
11
12
|
tree.Call.prototype = {
|
12
13
|
//
|
@@ -28,8 +29,10 @@ tree.Call.prototype = {
|
|
28
29
|
try {
|
29
30
|
return tree.functions[this.name].apply(tree.functions, args);
|
30
31
|
} catch (e) {
|
31
|
-
throw {
|
32
|
-
|
32
|
+
throw { type: e.type || "Runtime",
|
33
|
+
message: "error evaluating function `" + this.name + "`" +
|
34
|
+
(e.message ? ': ' + e.message : ''),
|
35
|
+
index: this.index, filename: this.filename };
|
33
36
|
}
|
34
37
|
} else { // 2.
|
35
38
|
return new(tree.Anonymous)(this.name +
|
@@ -0,0 +1,42 @@
|
|
1
|
+
(function (tree) {
|
2
|
+
|
3
|
+
tree.Condition = function (op, l, r, i, negate) {
|
4
|
+
this.op = op.trim();
|
5
|
+
this.lvalue = l;
|
6
|
+
this.rvalue = r;
|
7
|
+
this.index = i;
|
8
|
+
this.negate = negate;
|
9
|
+
};
|
10
|
+
tree.Condition.prototype.eval = function (env) {
|
11
|
+
var a = this.lvalue.eval(env),
|
12
|
+
b = this.rvalue.eval(env);
|
13
|
+
|
14
|
+
var i = this.index, result;
|
15
|
+
|
16
|
+
var result = (function (op) {
|
17
|
+
switch (op) {
|
18
|
+
case 'and':
|
19
|
+
return a && b;
|
20
|
+
case 'or':
|
21
|
+
return a || b;
|
22
|
+
default:
|
23
|
+
if (a.compare) {
|
24
|
+
result = a.compare(b);
|
25
|
+
} else if (b.compare) {
|
26
|
+
result = b.compare(a);
|
27
|
+
} else {
|
28
|
+
throw { type: "Type",
|
29
|
+
message: "Unable to perform comparison",
|
30
|
+
index: i };
|
31
|
+
}
|
32
|
+
switch (result) {
|
33
|
+
case -1: return op === '<' || op === '=<';
|
34
|
+
case 0: return op === '=' || op === '>=' || op === '=<';
|
35
|
+
case 1: return op === '>' || op === '>=';
|
36
|
+
}
|
37
|
+
}
|
38
|
+
})(this.op);
|
39
|
+
return this.negate ? !result : result;
|
40
|
+
};
|
41
|
+
|
42
|
+
})(require('../tree'));
|
@@ -28,6 +28,21 @@ tree.Dimension.prototype = {
|
|
28
28
|
return new(tree.Dimension)
|
29
29
|
(tree.operate(op, this.value, other.value),
|
30
30
|
this.unit || other.unit);
|
31
|
+
},
|
32
|
+
|
33
|
+
// TODO: Perform unit conversion before comparing
|
34
|
+
compare: function (other) {
|
35
|
+
if (other instanceof tree.Dimension) {
|
36
|
+
if (other.value > this.value) {
|
37
|
+
return -1;
|
38
|
+
} else if (other.value < this.value) {
|
39
|
+
return 1;
|
40
|
+
} else {
|
41
|
+
return 0;
|
42
|
+
}
|
43
|
+
} else {
|
44
|
+
return -1;
|
45
|
+
}
|
31
46
|
}
|
32
47
|
};
|
33
48
|
|
@@ -1,18 +1,23 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Directive = function (name, value) {
|
3
|
+
tree.Directive = function (name, value, features) {
|
4
4
|
this.name = name;
|
5
|
+
this.features = features && new(tree.Value)(features);
|
6
|
+
|
5
7
|
if (Array.isArray(value)) {
|
6
8
|
this.ruleset = new(tree.Ruleset)([], value);
|
9
|
+
this.ruleset.allowImports = true;
|
7
10
|
} else {
|
8
11
|
this.value = value;
|
9
12
|
}
|
10
13
|
};
|
11
14
|
tree.Directive.prototype = {
|
12
15
|
toCSS: function (ctx, env) {
|
16
|
+
var features = this.features ? ' ' + this.features.toCSS(env) : '';
|
17
|
+
|
13
18
|
if (this.ruleset) {
|
14
19
|
this.ruleset.root = true;
|
15
|
-
return this.name + (env.compress ? '{' : ' {\n ') +
|
20
|
+
return this.name + features + (env.compress ? '{' : ' {\n ') +
|
16
21
|
this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') +
|
17
22
|
(env.compress ? '}': '\n}\n');
|
18
23
|
} else {
|
@@ -20,6 +25,7 @@ tree.Directive.prototype = {
|
|
20
25
|
}
|
21
26
|
},
|
22
27
|
eval: function (env) {
|
28
|
+
this.features = this.features && this.features.eval(env);
|
23
29
|
env.frames.unshift(this);
|
24
30
|
this.ruleset = this.ruleset && this.ruleset.eval(env);
|
25
31
|
env.frames.shift();
|
@@ -3,11 +3,23 @@
|
|
3
3
|
tree.Element = function (combinator, value, index) {
|
4
4
|
this.combinator = combinator instanceof tree.Combinator ?
|
5
5
|
combinator : new(tree.Combinator)(combinator);
|
6
|
-
|
6
|
+
|
7
|
+
if (typeof(value) === 'string') {
|
8
|
+
this.value = value.trim();
|
9
|
+
} else if (value) {
|
10
|
+
this.value = value;
|
11
|
+
} else {
|
12
|
+
this.value = "";
|
13
|
+
}
|
7
14
|
this.index = index;
|
8
15
|
};
|
16
|
+
tree.Element.prototype.eval = function (env) {
|
17
|
+
return new(tree.Element)(this.combinator,
|
18
|
+
this.value.eval ? this.value.eval(env) : this.value,
|
19
|
+
this.index);
|
20
|
+
};
|
9
21
|
tree.Element.prototype.toCSS = function (env) {
|
10
|
-
return this.combinator.toCSS(env || {}) + this.value;
|
22
|
+
return this.combinator.toCSS(env || {}) + (this.value.toCSS ? this.value.toCSS(env) : this.value);
|
11
23
|
};
|
12
24
|
|
13
25
|
tree.Combinator = function (value) {
|
@@ -11,10 +11,12 @@
|
|
11
11
|
// `import,push`, we also pass it a callback, which it'll call once
|
12
12
|
// the file has been fetched, and parsed.
|
13
13
|
//
|
14
|
-
tree.Import = function (path, imports) {
|
14
|
+
tree.Import = function (path, imports, features, index) {
|
15
15
|
var that = this;
|
16
16
|
|
17
|
+
this.index = index;
|
17
18
|
this._path = path;
|
19
|
+
this.features = features && new(tree.Value)(features);
|
18
20
|
|
19
21
|
// The '.less' extension is optional
|
20
22
|
if (path instanceof tree.Quoted) {
|
@@ -27,11 +29,9 @@ tree.Import = function (path, imports) {
|
|
27
29
|
|
28
30
|
// Only pre-compile .less files
|
29
31
|
if (! this.css) {
|
30
|
-
imports.push(this.path, function (root) {
|
31
|
-
if (
|
32
|
-
|
33
|
-
}
|
34
|
-
that.root = root;
|
32
|
+
imports.push(this.path, function (e, root) {
|
33
|
+
if (e) { e.index = index }
|
34
|
+
that.root = root || new(tree.Ruleset)([], []);
|
35
35
|
});
|
36
36
|
}
|
37
37
|
};
|
@@ -46,20 +46,22 @@ tree.Import = function (path, imports) {
|
|
46
46
|
// ruleset.
|
47
47
|
//
|
48
48
|
tree.Import.prototype = {
|
49
|
-
toCSS: function () {
|
49
|
+
toCSS: function (env) {
|
50
|
+
var features = this.features ? ' ' + this.features.toCSS(env) : '';
|
51
|
+
|
50
52
|
if (this.css) {
|
51
|
-
return "@import " + this._path.toCSS() + ';\n';
|
53
|
+
return "@import " + this._path.toCSS() + features + ';\n';
|
52
54
|
} else {
|
53
55
|
return "";
|
54
56
|
}
|
55
57
|
},
|
56
58
|
eval: function (env) {
|
57
|
-
var ruleset;
|
59
|
+
var ruleset, features = this.features && this.features.eval(env);
|
58
60
|
|
59
61
|
if (this.css) {
|
60
62
|
return this;
|
61
63
|
} else {
|
62
|
-
ruleset = new(tree.Ruleset)(
|
64
|
+
ruleset = new(tree.Ruleset)([], this.root.rules.slice(0));
|
63
65
|
|
64
66
|
for (var i = 0; i < ruleset.rules.length; i++) {
|
65
67
|
if (ruleset.rules[i] instanceof tree.Import) {
|
@@ -69,7 +71,7 @@ tree.Import.prototype = {
|
|
69
71
|
[i, 1].concat(ruleset.rules[i].eval(env)));
|
70
72
|
}
|
71
73
|
}
|
72
|
-
return ruleset.rules;
|
74
|
+
return this.features ? new(tree.Directive)('@media', ruleset.rules, this.features.value) : ruleset.rules;
|
73
75
|
}
|
74
76
|
}
|
75
77
|
};
|
@@ -3,7 +3,17 @@
|
|
3
3
|
tree.Keyword = function (value) { this.value = value };
|
4
4
|
tree.Keyword.prototype = {
|
5
5
|
eval: function () { return this },
|
6
|
-
toCSS: function () { return this.value }
|
6
|
+
toCSS: function () { return this.value },
|
7
|
+
compare: function (other) {
|
8
|
+
if (other instanceof tree.Keyword) {
|
9
|
+
return other.value === this.value ? 0 : 1;
|
10
|
+
} else {
|
11
|
+
return -1;
|
12
|
+
}
|
13
|
+
}
|
7
14
|
};
|
8
15
|
|
16
|
+
tree.True = new(tree.Keyword)('true');
|
17
|
+
tree.False = new(tree.Keyword)('false');
|
18
|
+
|
9
19
|
})(require('../tree'));
|
@@ -1,10 +1,12 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
3
|
tree.mixin = {};
|
4
|
-
tree.mixin.Call = function (elements, args, index) {
|
4
|
+
tree.mixin.Call = function (elements, args, index, filename, important) {
|
5
5
|
this.selector = new(tree.Selector)(elements);
|
6
6
|
this.arguments = args;
|
7
7
|
this.index = index;
|
8
|
+
this.filename = filename;
|
9
|
+
this.important = important;
|
8
10
|
};
|
9
11
|
tree.mixin.Call.prototype = {
|
10
12
|
eval: function (env) {
|
@@ -17,34 +19,37 @@ tree.mixin.Call.prototype = {
|
|
17
19
|
if (mixins[m].match(args, env)) {
|
18
20
|
try {
|
19
21
|
Array.prototype.push.apply(
|
20
|
-
rules, mixins[m].eval(env, this.arguments).rules);
|
22
|
+
rules, mixins[m].eval(env, this.arguments, this.important).rules);
|
21
23
|
match = true;
|
22
24
|
} catch (e) {
|
23
|
-
throw { message: e.message, index: e.index, stack: e.stack, call: this.index };
|
25
|
+
throw { message: e.message, index: e.index, filename: this.filename, stack: e.stack, call: this.index };
|
24
26
|
}
|
25
27
|
}
|
26
28
|
}
|
27
29
|
if (match) {
|
28
30
|
return rules;
|
29
31
|
} else {
|
30
|
-
throw {
|
32
|
+
throw { type: 'Runtime',
|
33
|
+
message: 'No matching definition was found for `' +
|
31
34
|
this.selector.toCSS().trim() + '(' +
|
32
35
|
this.arguments.map(function (a) {
|
33
36
|
return a.toCSS();
|
34
37
|
}).join(', ') + ")`",
|
35
|
-
index: this.index };
|
38
|
+
index: this.index, filename: this.filename };
|
36
39
|
}
|
37
40
|
}
|
38
41
|
}
|
39
|
-
throw {
|
40
|
-
|
42
|
+
throw { type: 'Name',
|
43
|
+
message: this.selector.toCSS().trim() + " is undefined",
|
44
|
+
index: this.index, filename: this.filename };
|
41
45
|
}
|
42
46
|
};
|
43
47
|
|
44
|
-
tree.mixin.Definition = function (name, params, rules) {
|
48
|
+
tree.mixin.Definition = function (name, params, rules, condition) {
|
45
49
|
this.name = name;
|
46
50
|
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])];
|
47
51
|
this.params = params;
|
52
|
+
this.condition = condition;
|
48
53
|
this.arity = params.length;
|
49
54
|
this.rules = rules;
|
50
55
|
this._lookups = {};
|
@@ -62,33 +67,46 @@ tree.mixin.Definition.prototype = {
|
|
62
67
|
find: function () { return this.parent.find.apply(this, arguments) },
|
63
68
|
rulesets: function () { return this.parent.rulesets.apply(this) },
|
64
69
|
|
65
|
-
|
66
|
-
var frame = new(tree.Ruleset)(null, [])
|
70
|
+
evalParams: function (env, args) {
|
71
|
+
var frame = new(tree.Ruleset)(null, []);
|
67
72
|
|
68
73
|
for (var i = 0, val; i < this.params.length; i++) {
|
69
74
|
if (this.params[i].name) {
|
70
75
|
if (val = (args && args[i]) || this.params[i].value) {
|
71
76
|
frame.rules.unshift(new(tree.Rule)(this.params[i].name, val.eval(env)));
|
72
77
|
} else {
|
73
|
-
throw { message: "wrong number of arguments for " + this.name +
|
78
|
+
throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
|
74
79
|
' (' + args.length + ' for ' + this.arity + ')' };
|
75
80
|
}
|
76
81
|
}
|
77
82
|
}
|
83
|
+
return frame;
|
84
|
+
},
|
85
|
+
eval: function (env, args, important) {
|
86
|
+
var frame = this.evalParams(env, args), context, _arguments = [], rules;
|
87
|
+
|
78
88
|
for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) {
|
79
89
|
_arguments.push(args[i] || this.params[i].value);
|
80
90
|
}
|
81
91
|
frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
|
82
92
|
|
83
|
-
|
93
|
+
rules = important ?
|
94
|
+
this.rules.map(function (r) {
|
95
|
+
return new(tree.Rule)(r.name, r.value, '!important', r.index);
|
96
|
+
}) : this.rules.slice(0);
|
97
|
+
|
98
|
+
return new(tree.Ruleset)(null, rules).eval({
|
84
99
|
frames: [this, frame].concat(this.frames, env.frames)
|
85
100
|
});
|
86
101
|
},
|
87
102
|
match: function (args, env) {
|
88
|
-
var argsLength = (args && args.length) || 0, len;
|
103
|
+
var argsLength = (args && args.length) || 0, len, frame;
|
89
104
|
|
90
105
|
if (argsLength < this.required) { return false }
|
91
106
|
if ((this.required > 0) && (argsLength > this.params.length)) { return false }
|
107
|
+
if (this.condition && !this.condition.eval({
|
108
|
+
frames: [this.evalParams(env, args)].concat(env.frames)
|
109
|
+
})) { return false }
|
92
110
|
|
93
111
|
len = Math.min(argsLength, this.arity);
|
94
112
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
(function (tree) {
|
3
|
+
|
4
|
+
tree.Paren = function (node) {
|
5
|
+
this.value = node;
|
6
|
+
};
|
7
|
+
tree.Paren.prototype = {
|
8
|
+
toCSS: function (env) {
|
9
|
+
return '(' + this.value.toCSS(env) + ')';
|
10
|
+
},
|
11
|
+
eval: function (env) {
|
12
|
+
return new(tree.Paren)(this.value.eval(env));
|
13
|
+
}
|
14
|
+
};
|
15
|
+
|
16
|
+
})(require('../tree'));
|
@@ -20,7 +20,7 @@ tree.Quoted.prototype = {
|
|
20
20
|
return new(tree.JavaScript)(exp, that.index, true).eval(env).value;
|
21
21
|
}).replace(/@\{([\w-]+)\}/g, function (_, name) {
|
22
22
|
var v = new(tree.Variable)('@' + name, that.index).eval(env);
|
23
|
-
return v.value
|
23
|
+
return ('value' in v) ? v.value : v.toCSS();
|
24
24
|
});
|
25
25
|
return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index);
|
26
26
|
}
|
@@ -1,10 +1,11 @@
|
|
1
1
|
(function (tree) {
|
2
2
|
|
3
|
-
tree.Rule = function (name, value, important, index) {
|
3
|
+
tree.Rule = function (name, value, important, index, 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.inline = inline || false;
|
8
9
|
|
9
10
|
if (name.charAt(0) === '@') {
|
10
11
|
this.variable = true;
|
@@ -15,12 +16,15 @@ tree.Rule.prototype.toCSS = function (env) {
|
|
15
16
|
else {
|
16
17
|
return this.name + (env.compress ? ':' : ': ') +
|
17
18
|
this.value.toCSS(env) +
|
18
|
-
this.important + ";";
|
19
|
+
this.important + (this.inline ? "" : ";");
|
19
20
|
}
|
20
21
|
};
|
21
22
|
|
22
23
|
tree.Rule.prototype.eval = function (context) {
|
23
|
-
return new(tree.Rule)(this.name,
|
24
|
+
return new(tree.Rule)(this.name,
|
25
|
+
this.value.eval(context),
|
26
|
+
this.important,
|
27
|
+
this.index, this.inline);
|
24
28
|
};
|
25
29
|
|
26
30
|
tree.Shorthand = function (a, b) {
|