less 1.2.21 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +4 -3
- data/.gitmodules +6 -0
- data/Gemfile +3 -0
- data/README.md +39 -46
- data/Rakefile +5 -50
- data/bin/lessc +1 -100
- data/less.gemspec +21 -125
- data/lib/less.rb +11 -30
- data/{LICENSE → lib/less/js/LICENSE} +1 -1
- data/lib/less/js/Makefile +56 -0
- data/lib/less/js/README.md +20 -0
- data/lib/less/js/benchmark/benchmark.less +3979 -0
- data/lib/less/js/benchmark/less-benchmark.js +49 -0
- data/lib/less/js/bin/lessc +105 -0
- data/lib/less/js/build/ecma-5.js +120 -0
- data/lib/less/js/build/header.js +7 -0
- data/lib/less/js/build/require.js +7 -0
- data/lib/less/js/dist/less-1.0.44.js +2655 -0
- data/lib/less/js/dist/less-1.1.0.js +2695 -0
- data/lib/less/js/dist/less-1.1.0.min.js +16 -0
- data/lib/less/js/dist/less-1.1.1.js +2710 -0
- data/lib/less/js/dist/less-1.1.1.min.js +16 -0
- data/lib/less/js/dist/less-1.1.2.js +2712 -0
- data/lib/less/js/dist/less-1.1.2.min.js +16 -0
- data/lib/less/js/dist/less-1.1.3.js +2721 -0
- data/lib/less/js/dist/less-1.1.3.min.js +16 -0
- data/lib/less/js/lib/less/browser.js +369 -0
- data/lib/less/js/lib/less/functions.js +174 -0
- data/lib/less/js/lib/less/index.js +137 -0
- data/lib/less/js/lib/less/parser.js +1098 -0
- data/lib/less/js/lib/less/tree.js +13 -0
- data/lib/less/js/lib/less/tree/alpha.js +17 -0
- data/lib/less/js/lib/less/tree/anonymous.js +13 -0
- data/lib/less/js/lib/less/tree/call.js +45 -0
- data/lib/less/js/lib/less/tree/color.js +98 -0
- data/lib/less/js/lib/less/tree/comment.js +14 -0
- data/lib/less/js/lib/less/tree/dimension.js +34 -0
- data/lib/less/js/lib/less/tree/directive.js +33 -0
- data/lib/less/js/lib/less/tree/element.js +32 -0
- data/lib/less/js/lib/less/tree/expression.js +23 -0
- data/lib/less/js/lib/less/tree/import.js +77 -0
- data/lib/less/js/lib/less/tree/javascript.js +51 -0
- data/lib/less/js/lib/less/tree/keyword.js +9 -0
- data/lib/less/js/lib/less/tree/mixin.js +106 -0
- data/lib/less/js/lib/less/tree/operation.js +32 -0
- data/lib/less/js/lib/less/tree/quoted.js +29 -0
- data/lib/less/js/lib/less/tree/rule.js +38 -0
- data/lib/less/js/lib/less/tree/ruleset.js +179 -0
- data/lib/less/js/lib/less/tree/selector.js +28 -0
- data/lib/less/js/lib/less/tree/url.js +25 -0
- data/lib/less/js/lib/less/tree/value.js +24 -0
- data/lib/less/js/lib/less/tree/variable.js +24 -0
- data/lib/less/js/package.json +13 -0
- data/lib/less/js/test/css/colors.css +42 -0
- data/lib/less/js/test/css/comments.css +52 -0
- data/lib/less/js/test/css/css-3.css +42 -0
- data/lib/less/js/test/css/css-escapes.css +20 -0
- data/lib/less/js/test/css/css.css +82 -0
- data/lib/less/js/test/css/functions.css +30 -0
- data/{spec → lib/less/js/test}/css/import.css +4 -2
- data/lib/less/js/test/css/javascript.css +22 -0
- data/lib/less/js/test/css/lazy-eval.css +3 -0
- data/lib/less/js/test/css/media.css +21 -0
- data/lib/less/js/test/css/mixins-args.css +61 -0
- data/lib/less/js/test/css/mixins-closure.css +9 -0
- data/lib/less/js/test/css/mixins-nested.css +14 -0
- data/lib/less/js/test/css/mixins-pattern.css +49 -0
- data/lib/less/js/test/css/mixins.css +50 -0
- data/{spec → lib/less/js/test}/css/operations.css +20 -2
- data/{spec → lib/less/js/test}/css/parens.css +0 -0
- data/lib/less/js/test/css/rulesets.css +29 -0
- data/{spec → lib/less/js/test}/css/scope.css +6 -2
- data/lib/less/js/test/css/selectors.css +32 -0
- data/lib/less/js/test/css/strings.css +38 -0
- data/lib/less/js/test/css/variables.css +24 -0
- data/lib/less/js/test/css/whitespace.css +36 -0
- data/lib/less/js/test/less-test.js +75 -0
- data/{spec → lib/less/js/test}/less/colors.less +13 -2
- data/{spec → lib/less/js/test}/less/comments.less +19 -2
- data/{spec → lib/less/js/test}/less/css-3.less +4 -1
- data/lib/less/js/test/less/css-escapes.less +28 -0
- data/{spec → lib/less/js/test}/less/css.less +10 -18
- data/lib/less/js/test/less/functions.less +35 -0
- data/{spec → lib/less/js/test}/less/import.less +1 -1
- data/{spec → lib/less/js/test}/less/import/import-test-a.less +0 -0
- data/{spec → lib/less/js/test}/less/import/import-test-b.less +0 -0
- data/{spec → lib/less/js/test}/less/import/import-test-c.less +0 -0
- data/{spec → lib/less/js/test}/less/import/import-test-d.css +0 -0
- data/lib/less/js/test/less/javascript.less +27 -0
- data/{spec → lib/less/js/test}/less/lazy-eval.less +0 -0
- data/lib/less/js/test/less/media.less +25 -0
- data/lib/less/js/test/less/mixins-args.less +118 -0
- data/lib/less/js/test/less/mixins-closure.less +26 -0
- data/lib/less/js/test/less/mixins-nested.less +22 -0
- data/lib/less/js/test/less/mixins-pattern.less +96 -0
- data/{spec → lib/less/js/test}/less/mixins.less +8 -4
- data/{spec → lib/less/js/test}/less/operations.less +19 -0
- data/{spec → lib/less/js/test}/less/parens.less +0 -0
- data/{spec → lib/less/js/test}/less/rulesets.less +2 -2
- data/{spec → lib/less/js/test}/less/scope.less +1 -1
- data/{spec → lib/less/js/test}/less/selectors.less +1 -1
- data/lib/less/js/test/less/strings.less +49 -0
- data/lib/less/js/test/less/variables.less +50 -0
- data/{spec → lib/less/js/test}/less/whitespace.less +3 -0
- data/lib/less/loader.rb +67 -0
- data/lib/less/parser.rb +46 -0
- data/lib/less/version.rb +3 -0
- data/spec/less/one/one.less +1 -0
- data/spec/less/parser_spec.rb +30 -0
- data/spec/less/two/two.less +1 -0
- data/spec/spec_helper.rb +2 -7
- metadata +156 -106
- data/CHANGELOG +0 -62
- data/VERSION +0 -1
- data/lib/less/command.rb +0 -110
- data/lib/less/engine.rb +0 -52
- data/lib/less/engine/grammar/common.tt +0 -29
- data/lib/less/engine/grammar/entity.tt +0 -144
- data/lib/less/engine/grammar/less.tt +0 -341
- data/lib/less/engine/nodes.rb +0 -9
- data/lib/less/engine/nodes/element.rb +0 -281
- data/lib/less/engine/nodes/entity.rb +0 -79
- data/lib/less/engine/nodes/function.rb +0 -93
- data/lib/less/engine/nodes/literal.rb +0 -171
- data/lib/less/engine/nodes/property.rb +0 -232
- data/lib/less/engine/nodes/ruleset.rb +0 -12
- data/lib/less/engine/nodes/selector.rb +0 -44
- data/lib/less/ext.rb +0 -60
- data/spec/command_spec.rb +0 -102
- data/spec/css/accessors.css +0 -18
- data/spec/css/big.css +0 -3768
- data/spec/css/colors.css +0 -14
- data/spec/css/comments.css +0 -9
- data/spec/css/css-3.css +0 -21
- data/spec/css/css.css +0 -50
- data/spec/css/dash-prefix.css +0 -12
- data/spec/css/functions.css +0 -6
- data/spec/css/import-with-extra-paths.css +0 -8
- data/spec/css/import-with-partial-in-extra-path.css +0 -6
- data/spec/css/lazy-eval.css +0 -1
- data/spec/css/mixins-args.css +0 -32
- data/spec/css/mixins.css +0 -28
- data/spec/css/rulesets.css +0 -17
- data/spec/css/selectors.css +0 -13
- data/spec/css/strings.css +0 -12
- data/spec/css/variables.css +0 -8
- data/spec/css/whitespace.css +0 -7
- data/spec/engine_spec.rb +0 -127
- data/spec/less/accessors.less +0 -20
- data/spec/less/big.less +0 -1264
- data/spec/less/dash-prefix.less +0 -21
- data/spec/less/exceptions/mixed-units-error.less +0 -3
- data/spec/less/exceptions/name-error-1.0.less +0 -3
- data/spec/less/exceptions/syntax-error-1.0.less +0 -3
- data/spec/less/extra_import_path/extra.less +0 -1
- data/spec/less/extra_import_path/import/import-test-a.css +0 -1
- data/spec/less/extra_import_path/import/import-test-a.less +0 -4
- data/spec/less/functions.less +0 -6
- data/spec/less/hidden.less +0 -25
- data/spec/less/import-with-extra-paths.less +0 -4
- data/spec/less/literal-css.less +0 -11
- data/spec/less/mixins-args.less +0 -59
- data/spec/less/strings.less +0 -14
- data/spec/less/variables.less +0 -29
- data/spec/spec.css +0 -50
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require('less/tree').find = function (obj, fun) {
|
|
2
|
+
for (var i = 0, r; i < obj.length; i++) {
|
|
3
|
+
if (r = fun.call(obj, obj[i])) { return r }
|
|
4
|
+
}
|
|
5
|
+
return null;
|
|
6
|
+
};
|
|
7
|
+
require('less/tree').jsify = function (obj) {
|
|
8
|
+
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
|
|
9
|
+
return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']';
|
|
10
|
+
} else {
|
|
11
|
+
return obj.toCSS(false);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Alpha = function (val) {
|
|
4
|
+
this.value = val;
|
|
5
|
+
};
|
|
6
|
+
tree.Alpha.prototype = {
|
|
7
|
+
toCSS: function () {
|
|
8
|
+
return "alpha(opacity=" +
|
|
9
|
+
(this.value.toCSS ? this.value.toCSS() : this.value) + ")";
|
|
10
|
+
},
|
|
11
|
+
eval: function (env) {
|
|
12
|
+
if (this.value.eval) { this.value = this.value.eval(env) }
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Anonymous = function (string) {
|
|
4
|
+
this.value = string.value || string;
|
|
5
|
+
};
|
|
6
|
+
tree.Anonymous.prototype = {
|
|
7
|
+
toCSS: function () {
|
|
8
|
+
return this.value;
|
|
9
|
+
},
|
|
10
|
+
eval: function () { return this }
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
// A function call node.
|
|
5
|
+
//
|
|
6
|
+
tree.Call = function (name, args, index) {
|
|
7
|
+
this.name = name;
|
|
8
|
+
this.args = args;
|
|
9
|
+
this.index = index;
|
|
10
|
+
};
|
|
11
|
+
tree.Call.prototype = {
|
|
12
|
+
//
|
|
13
|
+
// When evaluating a function call,
|
|
14
|
+
// we either find the function in `tree.functions` [1],
|
|
15
|
+
// in which case we call it, passing the evaluated arguments,
|
|
16
|
+
// or we simply print it out as it appeared originally [2].
|
|
17
|
+
//
|
|
18
|
+
// The *functions.js* file contains the built-in functions.
|
|
19
|
+
//
|
|
20
|
+
// The reason why we evaluate the arguments, is in the case where
|
|
21
|
+
// we try to pass a variable to a function, like: `saturate(@color)`.
|
|
22
|
+
// The function should receive the value, not the variable.
|
|
23
|
+
//
|
|
24
|
+
eval: function (env) {
|
|
25
|
+
var args = this.args.map(function (a) { return a.eval(env) });
|
|
26
|
+
|
|
27
|
+
if (this.name in tree.functions) { // 1.
|
|
28
|
+
try {
|
|
29
|
+
return tree.functions[this.name].apply(tree.functions, args);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
throw { message: "error evaluating function `" + this.name + "`",
|
|
32
|
+
index: this.index };
|
|
33
|
+
}
|
|
34
|
+
} else { // 2.
|
|
35
|
+
return new(tree.Anonymous)(this.name +
|
|
36
|
+
"(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")");
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
|
|
40
|
+
toCSS: function (env) {
|
|
41
|
+
return this.eval(env).toCSS();
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
//
|
|
3
|
+
// RGB Colors - #ff0014, #eee
|
|
4
|
+
//
|
|
5
|
+
tree.Color = function (rgb, a) {
|
|
6
|
+
//
|
|
7
|
+
// The end goal here, is to parse the arguments
|
|
8
|
+
// into an integer triplet, such as `128, 255, 0`
|
|
9
|
+
//
|
|
10
|
+
// This facilitates operations and conversions.
|
|
11
|
+
//
|
|
12
|
+
if (Array.isArray(rgb)) {
|
|
13
|
+
this.rgb = rgb;
|
|
14
|
+
} else if (rgb.length == 6) {
|
|
15
|
+
this.rgb = rgb.match(/.{2}/g).map(function (c) {
|
|
16
|
+
return parseInt(c, 16);
|
|
17
|
+
});
|
|
18
|
+
} else if (rgb.length == 8) {
|
|
19
|
+
this.alpha = parseInt(rgb.substring(0,2), 16) / 255.0;
|
|
20
|
+
this.rgb = rgb.substr(2).match(/.{2}/g).map(function (c) {
|
|
21
|
+
return parseInt(c, 16);
|
|
22
|
+
});
|
|
23
|
+
} else {
|
|
24
|
+
this.rgb = rgb.split('').map(function (c) {
|
|
25
|
+
return parseInt(c + c, 16);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
this.alpha = typeof(a) === 'number' ? a : 1;
|
|
29
|
+
};
|
|
30
|
+
tree.Color.prototype = {
|
|
31
|
+
eval: function () { return this },
|
|
32
|
+
|
|
33
|
+
//
|
|
34
|
+
// If we have some transparency, the only way to represent it
|
|
35
|
+
// is via `rgba`. Otherwise, we use the hex representation,
|
|
36
|
+
// which has better compatibility with older browsers.
|
|
37
|
+
// Values are capped between `0` and `255`, rounded and zero-padded.
|
|
38
|
+
//
|
|
39
|
+
toCSS: function () {
|
|
40
|
+
if (this.alpha < 1.0) {
|
|
41
|
+
return "rgba(" + this.rgb.map(function (c) {
|
|
42
|
+
return Math.round(c);
|
|
43
|
+
}).concat(this.alpha).join(', ') + ")";
|
|
44
|
+
} else {
|
|
45
|
+
return '#' + this.rgb.map(function (i) {
|
|
46
|
+
i = Math.round(i);
|
|
47
|
+
i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
|
|
48
|
+
return i.length === 1 ? '0' + i : i;
|
|
49
|
+
}).join('');
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
//
|
|
54
|
+
// Operations have to be done per-channel, if not,
|
|
55
|
+
// channels will spill onto each other. Once we have
|
|
56
|
+
// our result, in the form of an integer triplet,
|
|
57
|
+
// we create a new Color node to hold the result.
|
|
58
|
+
//
|
|
59
|
+
operate: function (op, other) {
|
|
60
|
+
var result = [];
|
|
61
|
+
|
|
62
|
+
if (! (other instanceof tree.Color)) {
|
|
63
|
+
other = other.toColor();
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (var c = 0; c < 3; c++) {
|
|
67
|
+
result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
|
|
68
|
+
}
|
|
69
|
+
return new(tree.Color)(result, this.alpha + other.alpha);
|
|
70
|
+
},
|
|
71
|
+
|
|
72
|
+
toHSL: function () {
|
|
73
|
+
var r = this.rgb[0] / 255,
|
|
74
|
+
g = this.rgb[1] / 255,
|
|
75
|
+
b = this.rgb[2] / 255,
|
|
76
|
+
a = this.alpha;
|
|
77
|
+
|
|
78
|
+
var max = Math.max(r, g, b), min = Math.min(r, g, b);
|
|
79
|
+
var h, s, l = (max + min) / 2, d = max - min;
|
|
80
|
+
|
|
81
|
+
if (max === min) {
|
|
82
|
+
h = s = 0;
|
|
83
|
+
} else {
|
|
84
|
+
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
85
|
+
|
|
86
|
+
switch (max) {
|
|
87
|
+
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
|
|
88
|
+
case g: h = (b - r) / d + 2; break;
|
|
89
|
+
case b: h = (r - g) / d + 4; break;
|
|
90
|
+
}
|
|
91
|
+
h /= 6;
|
|
92
|
+
}
|
|
93
|
+
return { h: h * 360, s: s, l: l, a: a };
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Comment = function (value, silent) {
|
|
4
|
+
this.value = value;
|
|
5
|
+
this.silent = !!silent;
|
|
6
|
+
};
|
|
7
|
+
tree.Comment.prototype = {
|
|
8
|
+
toCSS: function (env) {
|
|
9
|
+
return env.compress ? '' : this.value;
|
|
10
|
+
},
|
|
11
|
+
eval: function () { return this }
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
//
|
|
4
|
+
// A number with a unit
|
|
5
|
+
//
|
|
6
|
+
tree.Dimension = function (value, unit) {
|
|
7
|
+
this.value = parseFloat(value);
|
|
8
|
+
this.unit = unit || null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
tree.Dimension.prototype = {
|
|
12
|
+
eval: function () { return this },
|
|
13
|
+
toColor: function () {
|
|
14
|
+
return new(tree.Color)([this.value, this.value, this.value]);
|
|
15
|
+
},
|
|
16
|
+
toCSS: function () {
|
|
17
|
+
var css = this.value + this.unit;
|
|
18
|
+
return css;
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
// In an operation between two Dimensions,
|
|
22
|
+
// we default to the first Dimension's unit,
|
|
23
|
+
// so `1px + 2em` will yield `3px`.
|
|
24
|
+
// In the future, we could implement some unit
|
|
25
|
+
// conversions such that `100cm + 10mm` would yield
|
|
26
|
+
// `101cm`.
|
|
27
|
+
operate: function (op, other) {
|
|
28
|
+
return new(tree.Dimension)
|
|
29
|
+
(tree.operate(op, this.value, other.value),
|
|
30
|
+
this.unit || other.unit);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Directive = function (name, value) {
|
|
4
|
+
this.name = name;
|
|
5
|
+
if (Array.isArray(value)) {
|
|
6
|
+
this.ruleset = new(tree.Ruleset)([], value);
|
|
7
|
+
} else {
|
|
8
|
+
this.value = value;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
tree.Directive.prototype = {
|
|
12
|
+
toCSS: function (ctx, env) {
|
|
13
|
+
if (this.ruleset) {
|
|
14
|
+
this.ruleset.root = true;
|
|
15
|
+
return this.name + (env.compress ? '{' : ' {\n ') +
|
|
16
|
+
this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') +
|
|
17
|
+
(env.compress ? '}': '\n}\n');
|
|
18
|
+
} else {
|
|
19
|
+
return this.name + ' ' + this.value.toCSS() + ';\n';
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
eval: function (env) {
|
|
23
|
+
env.frames.unshift(this);
|
|
24
|
+
this.ruleset = this.ruleset && this.ruleset.eval(env);
|
|
25
|
+
env.frames.shift();
|
|
26
|
+
return this;
|
|
27
|
+
},
|
|
28
|
+
variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) },
|
|
29
|
+
find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) },
|
|
30
|
+
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Element = function (combinator, value) {
|
|
4
|
+
this.combinator = combinator instanceof tree.Combinator ?
|
|
5
|
+
combinator : new(tree.Combinator)(combinator);
|
|
6
|
+
this.value = value.trim();
|
|
7
|
+
};
|
|
8
|
+
tree.Element.prototype.toCSS = function (env) {
|
|
9
|
+
return this.combinator.toCSS(env || {}) + this.value;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
tree.Combinator = function (value) {
|
|
13
|
+
if (value === ' ') {
|
|
14
|
+
this.value = ' ';
|
|
15
|
+
} else {
|
|
16
|
+
this.value = value ? value.trim() : "";
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
tree.Combinator.prototype.toCSS = function (env) {
|
|
20
|
+
return {
|
|
21
|
+
'' : '',
|
|
22
|
+
' ' : ' ',
|
|
23
|
+
'&' : '',
|
|
24
|
+
':' : ' :',
|
|
25
|
+
'::': '::',
|
|
26
|
+
'+' : env.compress ? '+' : ' + ',
|
|
27
|
+
'~' : env.compress ? '~' : ' ~ ',
|
|
28
|
+
'>' : env.compress ? '>' : ' > '
|
|
29
|
+
}[this.value];
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.Expression = function (value) { this.value = value };
|
|
4
|
+
tree.Expression.prototype = {
|
|
5
|
+
eval: function (env) {
|
|
6
|
+
if (this.value.length > 1) {
|
|
7
|
+
return new(tree.Expression)(this.value.map(function (e) {
|
|
8
|
+
return e.eval(env);
|
|
9
|
+
}));
|
|
10
|
+
} else if (this.value.length === 1) {
|
|
11
|
+
return this.value[0].eval(env);
|
|
12
|
+
} else {
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
toCSS: function (env) {
|
|
17
|
+
return this.value.map(function (e) {
|
|
18
|
+
return e.toCSS(env);
|
|
19
|
+
}).join(' ');
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
//
|
|
3
|
+
// CSS @import node
|
|
4
|
+
//
|
|
5
|
+
// The general strategy here is that we don't want to wait
|
|
6
|
+
// for the parsing to be completed, before we start importing
|
|
7
|
+
// the file. That's because in the context of a browser,
|
|
8
|
+
// most of the time will be spent waiting for the server to respond.
|
|
9
|
+
//
|
|
10
|
+
// On creation, we push the import path to our import queue, though
|
|
11
|
+
// `import,push`, we also pass it a callback, which it'll call once
|
|
12
|
+
// the file has been fetched, and parsed.
|
|
13
|
+
//
|
|
14
|
+
tree.Import = function (path, imports) {
|
|
15
|
+
var that = this;
|
|
16
|
+
|
|
17
|
+
this._path = path;
|
|
18
|
+
|
|
19
|
+
// The '.less' extension is optional
|
|
20
|
+
if (path instanceof tree.Quoted) {
|
|
21
|
+
this.path = /\.(le?|c)ss$/.test(path.value) ? path.value : path.value + '.less';
|
|
22
|
+
} else {
|
|
23
|
+
this.path = path.value.value || path.value;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
this.css = /css$/.test(this.path);
|
|
27
|
+
|
|
28
|
+
// Only pre-compile .less files
|
|
29
|
+
if (! this.css) {
|
|
30
|
+
imports.push(this.path, function (root) {
|
|
31
|
+
if (! root) {
|
|
32
|
+
throw new(Error)("Error parsing " + that.path);
|
|
33
|
+
}
|
|
34
|
+
that.root = root;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
//
|
|
40
|
+
// The actual import node doesn't return anything, when converted to CSS.
|
|
41
|
+
// The reason is that it's used at the evaluation stage, so that the rules
|
|
42
|
+
// it imports can be treated like any other rules.
|
|
43
|
+
//
|
|
44
|
+
// In `eval`, we make sure all Import nodes get evaluated, recursively, so
|
|
45
|
+
// we end up with a flat structure, which can easily be imported in the parent
|
|
46
|
+
// ruleset.
|
|
47
|
+
//
|
|
48
|
+
tree.Import.prototype = {
|
|
49
|
+
toCSS: function () {
|
|
50
|
+
if (this.css) {
|
|
51
|
+
return "@import " + this._path.toCSS() + ';\n';
|
|
52
|
+
} else {
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
eval: function (env) {
|
|
57
|
+
var ruleset;
|
|
58
|
+
|
|
59
|
+
if (this.css) {
|
|
60
|
+
return this;
|
|
61
|
+
} else {
|
|
62
|
+
ruleset = new(tree.Ruleset)(null, this.root.rules.slice(0));
|
|
63
|
+
|
|
64
|
+
for (var i = 0; i < ruleset.rules.length; i++) {
|
|
65
|
+
if (ruleset.rules[i] instanceof tree.Import) {
|
|
66
|
+
Array.prototype
|
|
67
|
+
.splice
|
|
68
|
+
.apply(ruleset.rules,
|
|
69
|
+
[i, 1].concat(ruleset.rules[i].eval(env)));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return ruleset.rules;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
})(require('less/tree'));
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
(function (tree) {
|
|
2
|
+
|
|
3
|
+
tree.JavaScript = function (string, index, escaped) {
|
|
4
|
+
this.escaped = escaped;
|
|
5
|
+
this.expression = string;
|
|
6
|
+
this.index = index;
|
|
7
|
+
};
|
|
8
|
+
tree.JavaScript.prototype = {
|
|
9
|
+
eval: function (env) {
|
|
10
|
+
var result,
|
|
11
|
+
that = this,
|
|
12
|
+
context = {};
|
|
13
|
+
|
|
14
|
+
var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
|
|
15
|
+
return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env));
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
expression = new(Function)('return (' + expression + ')');
|
|
20
|
+
} catch (e) {
|
|
21
|
+
throw { message: "JavaScript evaluation error: `" + expression + "`" ,
|
|
22
|
+
index: this.index };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (var k in env.frames[0].variables()) {
|
|
26
|
+
context[k.slice(1)] = {
|
|
27
|
+
value: env.frames[0].variables()[k].value,
|
|
28
|
+
toJS: function () {
|
|
29
|
+
return this.value.eval(env).toCSS();
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
result = expression.call(context);
|
|
36
|
+
} catch (e) {
|
|
37
|
+
throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" ,
|
|
38
|
+
index: this.index };
|
|
39
|
+
}
|
|
40
|
+
if (typeof(result) === 'string') {
|
|
41
|
+
return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index);
|
|
42
|
+
} else if (Array.isArray(result)) {
|
|
43
|
+
return new(tree.Anonymous)(result.join(', '));
|
|
44
|
+
} else {
|
|
45
|
+
return new(tree.Anonymous)(result);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
})(require('less/tree'));
|
|
51
|
+
|