less 3.6.0 → 3.8.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.
- package/CHANGELOG.md +13 -0
- package/Gruntfile.js +43 -6
- package/bin/lessc +32 -3
- package/dist/less.js +2810 -326
- package/dist/less.min.js +7 -7
- package/lib/less/constants.js +13 -0
- package/lib/less/contexts.js +45 -10
- package/lib/less/default-options.js +12 -4
- package/lib/less/functions/color.js +84 -41
- package/lib/less/functions/data-uri.js +1 -1
- package/lib/less/functions/index.js +1 -0
- package/lib/less/functions/list.js +101 -0
- package/lib/less/functions/types.js +1 -19
- package/lib/less/import-manager.js +3 -3
- package/lib/less/index.js +1 -1
- package/lib/less/parse.js +3 -3
- package/lib/less/parser/parser.js +31 -13
- package/lib/less/render.js +2 -2
- package/lib/less/source-map-output.js +2 -2
- package/lib/less/tree/color.js +58 -18
- package/lib/less/tree/declaration.js +11 -7
- package/lib/less/tree/expression.js +7 -3
- package/lib/less/tree/import.js +9 -8
- package/lib/less/tree/mixin-definition.js +1 -1
- package/lib/less/tree/operation.js +10 -4
- package/lib/less/tree/url.js +12 -8
- package/lib/less/utils.js +54 -19
- package/lib/less-browser/add-default-options.js +3 -3
- package/lib/less-browser/index.js +9 -2
- package/lib/less-node/image-size.js +1 -1
- package/lib/less-node/lessc-helper.js +12 -4
- package/package.json +5 -2
- package/test/browser/css/rewrite-urls/urls.css +36 -0
- package/test/browser/css/rootpath-rewrite-urls/urls.css +35 -0
- package/test/browser/less/rewrite-urls/urls.less +34 -0
- package/test/browser/less/rootpath-rewrite-urls/urls.less +33 -0
- package/test/browser/less.js +2810 -326
- package/test/browser/runner-browser-options.js +1 -1
- package/test/browser/runner-errors-options.js +1 -1
- package/test/browser/runner-legacy-options.js +1 -1
- package/test/browser/runner-rewrite-urls-options.js +3 -0
- package/test/browser/runner-rewrite-urls-spec.js +3 -0
- package/test/browser/runner-rootpath-relative-spec.js +1 -1
- package/test/browser/runner-rootpath-rewrite-urls-options.js +4 -0
- package/test/browser/runner-rootpath-rewrite-urls-spec.js +3 -0
- package/test/css/calc.css +2 -2
- package/test/css/colors.css +20 -3
- package/test/css/css-3.css +0 -8
- package/test/css/css-escapes.css +3 -0
- package/test/css/functions-each.css +48 -0
- package/test/css/functions.css +6 -4
- package/test/css/math/parens-division/media-math.css +10 -0
- package/test/css/math/parens-division/mixins-args.css +169 -0
- package/test/css/math/parens-division/new-division.css +16 -0
- package/test/css/math/parens-division/parens.css +37 -0
- package/test/css/math/strict/css.css +95 -0
- package/test/css/math/strict/media-math.css +10 -0
- package/test/css/math/strict/mixins-args.css +169 -0
- package/test/css/math/strict/parens.css +37 -0
- package/test/css/{strict-math → math/strict-legacy}/css.css +0 -0
- package/test/css/math/strict-legacy/media-math.css +10 -0
- package/test/css/{strict-math → math/strict-legacy}/mixins-args.css +0 -0
- package/test/css/{strict-math → math/strict-legacy}/parens.css +5 -1
- package/test/css/no-strict-math/no-sm-operations.css +3 -0
- package/test/css/rewrite-urls-all/rewrite-urls-all.css +17 -0
- package/test/css/rewrite-urls-local/rewrite-urls-local.css +17 -0
- package/test/css/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.css +17 -0
- package/test/css/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.css +17 -0
- package/test/css/static-urls/urls.css +2 -2
- package/test/css/urls.css +2 -2
- package/test/index.js +28 -15
- package/test/less/colors.less +18 -0
- package/test/less/css-3.less +0 -9
- package/test/less/css-escapes.less +4 -0
- package/test/less/errors/color-func-invalid-color.txt +1 -1
- package/test/less/errors/mixin-not-defined-2.less +7 -0
- package/test/less/errors/mixin-not-defined-2.txt +4 -0
- package/test/less/functions-each.less +81 -0
- package/test/less/functions.less +14 -2
- package/test/less/math/parens-division/media-math.less +9 -0
- package/test/less/math/parens-division/mixins-args.less +264 -0
- package/test/less/math/parens-division/new-division.less +17 -0
- package/test/less/{strict-math → math/parens-division}/parens.less +2 -1
- package/test/less/math/strict/css.less +108 -0
- package/test/less/math/strict/media-math.less +9 -0
- package/test/less/math/strict/mixins-args.less +264 -0
- package/test/less/math/strict/parens.less +46 -0
- package/test/less/{strict-math → math/strict-legacy}/css.less +0 -0
- package/test/less/math/strict-legacy/media-math.less +9 -0
- package/test/less/{strict-math → math/strict-legacy}/mixins-args.less +0 -0
- package/test/less/math/strict-legacy/parens.less +50 -0
- package/test/less/no-strict-math/no-sm-operations.less +3 -0
- package/test/less/rewrite-urls-all/folder/file.less +8 -0
- package/test/less/rewrite-urls-all/rewrite-urls-all.less +11 -0
- package/test/less/rewrite-urls-local/folder/file.less +8 -0
- package/test/less/rewrite-urls-local/rewrite-urls-local.less +11 -0
- package/test/less/rootpath-rewrite-urls-all/folder/file.less +8 -0
- package/test/less/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.less +11 -0
- package/test/less/rootpath-rewrite-urls-local/folder/file.less +8 -0
- package/test/less/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.less +11 -0
- package/test/less/sourcemaps/custom-props.less +8 -0
- package/test/less-bom/colors.less +18 -0
- package/test/less-bom/css-3.less +0 -9
- package/test/less-bom/css-escapes.less +4 -0
- package/test/less-bom/errors/color-func-invalid-color.txt +1 -1
- package/test/less-bom/errors/mixin-not-defined-2.less +7 -0
- package/test/less-bom/errors/mixin-not-defined-2.txt +4 -0
- package/test/less-bom/functions-each.less +81 -0
- package/test/less-bom/functions.less +14 -2
- package/test/less-bom/math/parens-division/media-math.less +9 -0
- package/test/less-bom/math/parens-division/mixins-args.less +264 -0
- package/test/less-bom/math/parens-division/new-division.less +17 -0
- package/test/less-bom/{strict-math → math/parens-division}/parens.less +2 -1
- package/test/less-bom/math/strict/css.less +108 -0
- package/test/less-bom/math/strict/media-math.less +9 -0
- package/test/less-bom/math/strict/mixins-args.less +264 -0
- package/test/less-bom/math/strict/parens.less +46 -0
- package/test/less-bom/{strict-math → math/strict-legacy}/css.less +0 -0
- package/test/less-bom/math/strict-legacy/media-math.less +9 -0
- package/test/less-bom/{strict-math → math/strict-legacy}/mixins-args.less +0 -0
- package/test/less-bom/math/strict-legacy/parens.less +50 -0
- package/test/less-bom/no-strict-math/no-sm-operations.less +3 -0
- package/test/less-bom/rewrite-urls-all/folder/file.less +8 -0
- package/test/less-bom/rewrite-urls-all/rewrite-urls-all.less +11 -0
- package/test/less-bom/rewrite-urls-local/folder/file.less +8 -0
- package/test/less-bom/rewrite-urls-local/rewrite-urls-local.less +11 -0
- package/test/less-bom/rootpath-rewrite-urls-all/folder/file.less +8 -0
- package/test/less-bom/rootpath-rewrite-urls-all/rootpath-rewrite-urls-all.less +11 -0
- package/test/less-bom/rootpath-rewrite-urls-local/folder/file.less +8 -0
- package/test/less-bom/rootpath-rewrite-urls-local/rootpath-rewrite-urls-local.less +11 -0
- package/test/less-bom/sourcemaps/custom-props.less +8 -0
- package/test/less-test.js +26 -12
- package/test/sourcemaps/custom-props.json +1 -0
- package/.npmignore +0 -8
- package/test/less/errors/color-invalid-hex-code.less +0 -4
- package/test/less/errors/color-invalid-hex-code.txt +0 -4
- package/test/less/errors/color-invalid-hex-code2.less +0 -4
- package/test/less/errors/color-invalid-hex-code2.txt +0 -4
- package/test/less-bom/errors/color-invalid-hex-code.less +0 -4
- package/test/less-bom/errors/color-invalid-hex-code.txt +0 -4
- package/test/less-bom/errors/color-invalid-hex-code2.less +0 -4
- package/test/less-bom/errors/color-invalid-hex-code2.txt +0 -4
|
@@ -636,15 +636,8 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
636
636
|
color: function () {
|
|
637
637
|
var rgb;
|
|
638
638
|
|
|
639
|
-
if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
|
|
640
|
-
|
|
641
|
-
// definitely be part of color string
|
|
642
|
-
var colorCandidateString = rgb.input.match(/^#([\w]+).*/);
|
|
643
|
-
colorCandidateString = colorCandidateString[1];
|
|
644
|
-
if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
|
|
645
|
-
error('Invalid HEX color code');
|
|
646
|
-
}
|
|
647
|
-
return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
|
|
639
|
+
if (parserInput.currentChar() === '#' && (rgb = parserInput.$re(/^#([A-Fa-f0-9]{8}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{3,4})/))) {
|
|
640
|
+
return new(tree.Color)(rgb[1], undefined, rgb[0]);
|
|
648
641
|
}
|
|
649
642
|
},
|
|
650
643
|
|
|
@@ -931,7 +924,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
931
924
|
returner = { args:null, variadic: false },
|
|
932
925
|
expressions = [], argsSemiColon = [], argsComma = [],
|
|
933
926
|
isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
|
|
934
|
-
value, arg, expand;
|
|
927
|
+
value, arg, expand, hasSep = true;
|
|
935
928
|
|
|
936
929
|
parserInput.save();
|
|
937
930
|
|
|
@@ -952,7 +945,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
952
945
|
arg = entities.variable() || entities.property() || entities.literal() || entities.keyword() || this.call(true);
|
|
953
946
|
}
|
|
954
947
|
|
|
955
|
-
if (!arg) {
|
|
948
|
+
if (!arg || !hasSep) {
|
|
956
949
|
break;
|
|
957
950
|
}
|
|
958
951
|
|
|
@@ -1018,10 +1011,12 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1018
1011
|
argsComma.push({ name:nameLoop, value:value, expand:expand });
|
|
1019
1012
|
|
|
1020
1013
|
if (parserInput.$char(',')) {
|
|
1014
|
+
hasSep = true;
|
|
1021
1015
|
continue;
|
|
1022
1016
|
}
|
|
1017
|
+
hasSep = parserInput.$char(';') === ';';
|
|
1023
1018
|
|
|
1024
|
-
if (
|
|
1019
|
+
if (hasSep || isSemiColonSeparated) {
|
|
1025
1020
|
|
|
1026
1021
|
if (expressionContainsNamed) {
|
|
1027
1022
|
error('Cannot mix ; and , as delimiter types');
|
|
@@ -1377,10 +1372,33 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1377
1372
|
},
|
|
1378
1373
|
|
|
1379
1374
|
detachedRuleset: function() {
|
|
1375
|
+
var argInfo, params, variadic;
|
|
1376
|
+
|
|
1377
|
+
parserInput.save();
|
|
1378
|
+
if (parserInput.$re(/^[.#]\(/)) {
|
|
1379
|
+
/**
|
|
1380
|
+
* DR args currently only implemented for each() function, and not
|
|
1381
|
+
* yet settable as `@dr: #(@arg) {}`
|
|
1382
|
+
* This should be done when DRs are merged with mixins.
|
|
1383
|
+
* See: https://github.com/less/less-meta/issues/16
|
|
1384
|
+
*/
|
|
1385
|
+
argInfo = this.mixin.args(false);
|
|
1386
|
+
params = argInfo.args;
|
|
1387
|
+
variadic = argInfo.variadic;
|
|
1388
|
+
if (!parserInput.$char(')')) {
|
|
1389
|
+
parserInput.restore();
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1380
1393
|
var blockRuleset = this.blockRuleset();
|
|
1381
1394
|
if (blockRuleset) {
|
|
1395
|
+
parserInput.forget();
|
|
1396
|
+
if (params) {
|
|
1397
|
+
return new tree.mixin.Definition(null, params, blockRuleset, null, variadic);
|
|
1398
|
+
}
|
|
1382
1399
|
return new tree.DetachedRuleset(blockRuleset);
|
|
1383
1400
|
}
|
|
1401
|
+
parserInput.restore();
|
|
1384
1402
|
},
|
|
1385
1403
|
|
|
1386
1404
|
//
|
|
@@ -1922,7 +1940,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1922
1940
|
|
|
1923
1941
|
parserInput.save();
|
|
1924
1942
|
|
|
1925
|
-
op = parserInput.$char('/') || parserInput.$char('*');
|
|
1943
|
+
op = parserInput.$char('/') || parserInput.$char('*') || parserInput.$str('./');
|
|
1926
1944
|
|
|
1927
1945
|
if (!op) { parserInput.forget(); break; }
|
|
1928
1946
|
|
package/lib/less/render.js
CHANGED
|
@@ -5,10 +5,10 @@ module.exports = function(environment, ParseTree, ImportManager) {
|
|
|
5
5
|
var render = function (input, options, callback) {
|
|
6
6
|
if (typeof options === 'function') {
|
|
7
7
|
callback = options;
|
|
8
|
-
options = utils.
|
|
8
|
+
options = utils.copyOptions(this.options, {});
|
|
9
9
|
}
|
|
10
10
|
else {
|
|
11
|
-
options = utils.
|
|
11
|
+
options = utils.copyOptions(this.options, options || {});
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
if (!callback) {
|
|
@@ -58,7 +58,7 @@ module.exports = function (environment) {
|
|
|
58
58
|
sourceColumns,
|
|
59
59
|
i;
|
|
60
60
|
|
|
61
|
-
if (fileInfo) {
|
|
61
|
+
if (fileInfo && fileInfo.filename) {
|
|
62
62
|
var inputSource = this._contentsMap[fileInfo.filename];
|
|
63
63
|
|
|
64
64
|
// remove vars/banner added to the top of the file
|
|
@@ -77,7 +77,7 @@ module.exports = function (environment) {
|
|
|
77
77
|
lines = chunk.split('\n');
|
|
78
78
|
columns = lines[lines.length - 1];
|
|
79
79
|
|
|
80
|
-
if (fileInfo) {
|
|
80
|
+
if (fileInfo && fileInfo.filename) {
|
|
81
81
|
if (!mapLines) {
|
|
82
82
|
this._sourceMapGenerator.addMapping({ generated: { line: this._lineNumber + 1, column: this._column},
|
|
83
83
|
original: { line: sourceLines.length, column: sourceColumns.length},
|
package/lib/less/tree/color.js
CHANGED
|
@@ -5,6 +5,7 @@ var Node = require('./node'),
|
|
|
5
5
|
// RGB Colors - #ff0014, #eee
|
|
6
6
|
//
|
|
7
7
|
var Color = function (rgb, a, originalForm) {
|
|
8
|
+
var self = this;
|
|
8
9
|
//
|
|
9
10
|
// The end goal here, is to parse the arguments
|
|
10
11
|
// into an integer triplet, such as `128, 255, 0`
|
|
@@ -13,16 +14,26 @@ var Color = function (rgb, a, originalForm) {
|
|
|
13
14
|
//
|
|
14
15
|
if (Array.isArray(rgb)) {
|
|
15
16
|
this.rgb = rgb;
|
|
16
|
-
} else if (rgb.length
|
|
17
|
-
this.rgb =
|
|
18
|
-
|
|
17
|
+
} else if (rgb.length >= 6) {
|
|
18
|
+
this.rgb = [];
|
|
19
|
+
rgb.match(/.{2}/g).map(function (c, i) {
|
|
20
|
+
if (i < 3) {
|
|
21
|
+
self.rgb.push(parseInt(c, 16));
|
|
22
|
+
} else {
|
|
23
|
+
self.alpha = (parseInt(c, 16)) / 255;
|
|
24
|
+
}
|
|
19
25
|
});
|
|
20
26
|
} else {
|
|
21
|
-
this.rgb =
|
|
22
|
-
|
|
27
|
+
this.rgb = [];
|
|
28
|
+
rgb.split('').map(function (c, i) {
|
|
29
|
+
if (i < 3) {
|
|
30
|
+
self.rgb.push(parseInt(c + c, 16));
|
|
31
|
+
} else {
|
|
32
|
+
self.alpha = (parseInt(c + c, 16)) / 255;
|
|
33
|
+
}
|
|
23
34
|
});
|
|
24
35
|
}
|
|
25
|
-
this.alpha = typeof a === 'number' ? a : 1;
|
|
36
|
+
this.alpha = this.alpha || (typeof a === 'number' ? a : 1);
|
|
26
37
|
if (typeof originalForm !== 'undefined') {
|
|
27
38
|
this.value = originalForm;
|
|
28
39
|
}
|
|
@@ -57,25 +68,54 @@ Color.prototype.genCSS = function (context, output) {
|
|
|
57
68
|
output.add(this.toCSS(context));
|
|
58
69
|
};
|
|
59
70
|
Color.prototype.toCSS = function (context, doNotCompress) {
|
|
60
|
-
var compress = context && context.compress && !doNotCompress, color, alpha
|
|
71
|
+
var compress = context && context.compress && !doNotCompress, color, alpha,
|
|
72
|
+
colorFunction, args = [];
|
|
61
73
|
|
|
62
74
|
// `value` is set if this color was originally
|
|
63
75
|
// converted from a named color string so we need
|
|
64
76
|
// to respect this and try to output named color too.
|
|
77
|
+
alpha = this.fround(context, this.alpha);
|
|
78
|
+
|
|
65
79
|
if (this.value) {
|
|
66
|
-
|
|
80
|
+
if (this.value.indexOf('rgb') === 0) {
|
|
81
|
+
if (alpha < 1) {
|
|
82
|
+
colorFunction = 'rgba';
|
|
83
|
+
}
|
|
84
|
+
} else if (this.value.indexOf('hsl') === 0) {
|
|
85
|
+
if (alpha < 1) {
|
|
86
|
+
colorFunction = 'hsla';
|
|
87
|
+
} else {
|
|
88
|
+
colorFunction = 'hsl';
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
return this.value;
|
|
92
|
+
}
|
|
93
|
+
} else {
|
|
94
|
+
if (alpha < 1) {
|
|
95
|
+
colorFunction = 'rgba';
|
|
96
|
+
}
|
|
67
97
|
}
|
|
68
98
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
switch (colorFunction) {
|
|
100
|
+
case 'rgba':
|
|
101
|
+
args = this.rgb.map(function (c) {
|
|
102
|
+
return clamp(Math.round(c), 255);
|
|
103
|
+
}).concat(clamp(alpha, 1));
|
|
104
|
+
break;
|
|
105
|
+
case 'hsla':
|
|
106
|
+
args.push(clamp(alpha, 1));
|
|
107
|
+
case 'hsl':
|
|
108
|
+
color = this.toHSL();
|
|
109
|
+
args = [
|
|
110
|
+
this.fround(context, color.h),
|
|
111
|
+
this.fround(context, color.s * 100) + '%',
|
|
112
|
+
this.fround(context, color.l * 100) + '%'
|
|
113
|
+
].concat(args);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (colorFunction) {
|
|
117
|
+
// Values are capped between `0` and `255`, rounded and zero-padded.
|
|
118
|
+
return colorFunction + '(' + args.join(',' + (compress ? '' : ' ')) + ')';
|
|
79
119
|
}
|
|
80
120
|
|
|
81
121
|
color = this.toRGB();
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
var Node = require('./node'),
|
|
2
2
|
Value = require('./value'),
|
|
3
3
|
Keyword = require('./keyword'),
|
|
4
|
-
Anonymous = require('./anonymous')
|
|
4
|
+
Anonymous = require('./anonymous'),
|
|
5
|
+
MATH = require('../constants').Math;
|
|
5
6
|
|
|
6
7
|
var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
|
|
7
8
|
this.name = name;
|
|
@@ -41,7 +42,7 @@ Declaration.prototype.genCSS = function (context, output) {
|
|
|
41
42
|
output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? '' : ';'), this._fileInfo, this._index);
|
|
42
43
|
};
|
|
43
44
|
Declaration.prototype.eval = function (context) {
|
|
44
|
-
var
|
|
45
|
+
var mathBypass = false, prevMath, name = this.name, evaldValue, variable = this.variable;
|
|
45
46
|
if (typeof name !== 'string') {
|
|
46
47
|
// expand 'primitive' name directly to get
|
|
47
48
|
// things faster (~10% for benchmark.less):
|
|
@@ -49,9 +50,12 @@ Declaration.prototype.eval = function (context) {
|
|
|
49
50
|
name[0].value : evalName(context, name);
|
|
50
51
|
variable = false; // never treat expanded interpolation as new variable name
|
|
51
52
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
53
|
+
|
|
54
|
+
// @todo remove when parens-division is default
|
|
55
|
+
if (name === 'font' && context.math === MATH.ALWAYS) {
|
|
56
|
+
mathBypass = true;
|
|
57
|
+
prevMath = context.math;
|
|
58
|
+
context.math = MATH.PARENS_DIVISION;
|
|
55
59
|
}
|
|
56
60
|
try {
|
|
57
61
|
context.importantScope.push({});
|
|
@@ -82,8 +86,8 @@ Declaration.prototype.eval = function (context) {
|
|
|
82
86
|
throw e;
|
|
83
87
|
}
|
|
84
88
|
finally {
|
|
85
|
-
if (
|
|
86
|
-
context.
|
|
89
|
+
if (mathBypass) {
|
|
90
|
+
context.math = prevMath;
|
|
87
91
|
}
|
|
88
92
|
}
|
|
89
93
|
};
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
var Node = require('./node'),
|
|
2
2
|
Paren = require('./paren'),
|
|
3
|
-
Comment = require('./comment')
|
|
3
|
+
Comment = require('./comment'),
|
|
4
|
+
Dimension = require('./dimension'),
|
|
5
|
+
MATH = require('../constants').Math;
|
|
4
6
|
|
|
5
7
|
var Expression = function (value, noSpacing) {
|
|
6
8
|
this.value = value;
|
|
@@ -17,7 +19,8 @@ Expression.prototype.accept = function (visitor) {
|
|
|
17
19
|
Expression.prototype.eval = function (context) {
|
|
18
20
|
var returnValue,
|
|
19
21
|
mathOn = context.isMathOn(),
|
|
20
|
-
inParenthesis = this.parens &&
|
|
22
|
+
inParenthesis = this.parens &&
|
|
23
|
+
(context.math !== MATH.STRICT_LEGACY || !this.parensInOp),
|
|
21
24
|
doubleParen = false;
|
|
22
25
|
if (inParenthesis) {
|
|
23
26
|
context.inParenthesis();
|
|
@@ -40,7 +43,8 @@ Expression.prototype.eval = function (context) {
|
|
|
40
43
|
if (inParenthesis) {
|
|
41
44
|
context.outOfParenthesis();
|
|
42
45
|
}
|
|
43
|
-
if (this.parens && this.parensInOp && !mathOn && !doubleParen
|
|
46
|
+
if (this.parens && this.parensInOp && !mathOn && !doubleParen
|
|
47
|
+
&& (!(returnValue instanceof Dimension))) {
|
|
44
48
|
returnValue = new Paren(returnValue);
|
|
45
49
|
}
|
|
46
50
|
return returnValue;
|
package/lib/less/tree/import.js
CHANGED
|
@@ -97,17 +97,18 @@ Import.prototype.evalForImport = function (context) {
|
|
|
97
97
|
};
|
|
98
98
|
Import.prototype.evalPath = function (context) {
|
|
99
99
|
var path = this.path.eval(context);
|
|
100
|
-
var
|
|
100
|
+
var fileInfo = this._fileInfo;
|
|
101
101
|
|
|
102
102
|
if (!(path instanceof URL)) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
// Add the rootpath if the URL requires a rewrite
|
|
104
|
+
var pathValue = path.value;
|
|
105
|
+
if (fileInfo &&
|
|
106
|
+
pathValue &&
|
|
107
|
+
context.pathRequiresRewrite(pathValue)) {
|
|
108
|
+
path.value = context.rewritePath(pathValue, fileInfo.rootpath);
|
|
109
|
+
} else {
|
|
110
|
+
path.value = context.normalizePath(path.value);
|
|
109
111
|
}
|
|
110
|
-
path.value = context.normalizePath(path.value);
|
|
111
112
|
}
|
|
112
113
|
|
|
113
114
|
return path;
|
|
@@ -8,7 +8,7 @@ var Selector = require('./selector'),
|
|
|
8
8
|
utils = require('../utils');
|
|
9
9
|
|
|
10
10
|
var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) {
|
|
11
|
-
this.name = name;
|
|
11
|
+
this.name = name || 'anonymous mixin';
|
|
12
12
|
this.selectors = [new Selector([new Element(null, name, false, this._index, this._fileInfo)])];
|
|
13
13
|
this.params = params;
|
|
14
14
|
this.condition = condition;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var Node = require('./node'),
|
|
2
2
|
Color = require('./color'),
|
|
3
|
-
Dimension = require('./dimension')
|
|
3
|
+
Dimension = require('./dimension'),
|
|
4
|
+
MATH = require('../constants').Math;
|
|
4
5
|
|
|
5
6
|
var Operation = function (op, operands, isSpaced) {
|
|
6
7
|
this.op = op.trim();
|
|
@@ -14,9 +15,11 @@ Operation.prototype.accept = function (visitor) {
|
|
|
14
15
|
};
|
|
15
16
|
Operation.prototype.eval = function (context) {
|
|
16
17
|
var a = this.operands[0].eval(context),
|
|
17
|
-
b = this.operands[1].eval(context)
|
|
18
|
+
b = this.operands[1].eval(context),
|
|
19
|
+
op;
|
|
18
20
|
|
|
19
|
-
if (context.isMathOn()) {
|
|
21
|
+
if (context.isMathOn(this.op)) {
|
|
22
|
+
op = this.op === './' ? '/' : this.op;
|
|
20
23
|
if (a instanceof Dimension && b instanceof Color) {
|
|
21
24
|
a = a.toColor();
|
|
22
25
|
}
|
|
@@ -24,11 +27,14 @@ Operation.prototype.eval = function (context) {
|
|
|
24
27
|
b = b.toColor();
|
|
25
28
|
}
|
|
26
29
|
if (!a.operate) {
|
|
30
|
+
if (a instanceof Operation && a.op === '/' && context.math === MATH.PARENS_DIVISION) {
|
|
31
|
+
return new Operation(this.op, [a, b], this.isSpaced);
|
|
32
|
+
}
|
|
27
33
|
throw { type: 'Operation',
|
|
28
34
|
message: 'Operation on an invalid type' };
|
|
29
35
|
}
|
|
30
36
|
|
|
31
|
-
return a.operate(context,
|
|
37
|
+
return a.operate(context, op, b);
|
|
32
38
|
} else {
|
|
33
39
|
return new Operation(this.op, [a, b], this.isSpaced);
|
|
34
40
|
}
|
package/lib/less/tree/url.js
CHANGED
|
@@ -21,20 +21,19 @@ URL.prototype.eval = function (context) {
|
|
|
21
21
|
rootpath;
|
|
22
22
|
|
|
23
23
|
if (!this.isEvald) {
|
|
24
|
-
// Add the
|
|
24
|
+
// Add the rootpath if the URL requires a rewrite
|
|
25
25
|
rootpath = this.fileInfo() && this.fileInfo().rootpath;
|
|
26
|
-
if (rootpath &&
|
|
26
|
+
if (typeof rootpath === 'string' &&
|
|
27
27
|
typeof val.value === 'string' &&
|
|
28
|
-
context.
|
|
29
|
-
|
|
28
|
+
context.pathRequiresRewrite(val.value)) {
|
|
30
29
|
if (!val.quote) {
|
|
31
|
-
rootpath = rootpath
|
|
30
|
+
rootpath = escapePath(rootpath);
|
|
32
31
|
}
|
|
33
|
-
val.value =
|
|
32
|
+
val.value = context.rewritePath(val.value, rootpath);
|
|
33
|
+
} else {
|
|
34
|
+
val.value = context.normalizePath(val.value);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
val.value = context.normalizePath(val.value);
|
|
37
|
-
|
|
38
37
|
// Add url args if enabled
|
|
39
38
|
if (context.urlArgs) {
|
|
40
39
|
if (!val.value.match(/^\s*data:/)) {
|
|
@@ -51,4 +50,9 @@ URL.prototype.eval = function (context) {
|
|
|
51
50
|
|
|
52
51
|
return new URL(val, this.getIndex(), this.fileInfo(), true);
|
|
53
52
|
};
|
|
53
|
+
|
|
54
|
+
function escapePath(path) {
|
|
55
|
+
return path.replace(/[\(\)'"\s]/g, function(match) { return '\\' + match; });
|
|
56
|
+
}
|
|
57
|
+
|
|
54
58
|
module.exports = URL;
|
package/lib/less/utils.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
/* jshint proto: true */
|
|
2
|
+
var Constants = require('./constants');
|
|
3
|
+
var clone = require('clone');
|
|
4
|
+
|
|
2
5
|
var utils = {
|
|
3
6
|
getLocation: function(index, inputStream) {
|
|
4
7
|
var n = index + 1,
|
|
@@ -36,27 +39,59 @@ var utils = {
|
|
|
36
39
|
}
|
|
37
40
|
return cloned;
|
|
38
41
|
},
|
|
39
|
-
|
|
40
|
-
if (
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
42
|
+
copyOptions: function(obj1, obj2) {
|
|
43
|
+
if (obj2 && obj2._defaults) {
|
|
44
|
+
return obj2;
|
|
45
|
+
}
|
|
46
|
+
var opts = utils.defaults(obj1, obj2);
|
|
47
|
+
if (opts.strictMath) {
|
|
48
|
+
opts.math = Constants.Math.STRICT_LEGACY;
|
|
49
|
+
}
|
|
50
|
+
// Back compat with changed relativeUrls option
|
|
51
|
+
if (opts.relativeUrls) {
|
|
52
|
+
opts.rewriteUrls = Constants.RewriteUrls.ALL;
|
|
53
|
+
}
|
|
54
|
+
if (typeof opts.math === 'string') {
|
|
55
|
+
switch (opts.math.toLowerCase()) {
|
|
56
|
+
case 'always':
|
|
57
|
+
opts.math = Constants.Math.ALWAYS;
|
|
58
|
+
break;
|
|
59
|
+
case 'parens-division':
|
|
60
|
+
opts.math = Constants.Math.PARENS_DIVISION;
|
|
61
|
+
break;
|
|
62
|
+
case 'strict':
|
|
63
|
+
case 'parens':
|
|
64
|
+
opts.math = Constants.Math.PARENS;
|
|
65
|
+
break;
|
|
66
|
+
case 'strict-legacy':
|
|
67
|
+
opts.math = Constants.Math.STRICT_LEGACY;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (typeof opts.rewriteUrls === 'string') {
|
|
71
|
+
switch (opts.rewriteUrls.toLowerCase()) {
|
|
72
|
+
case 'off':
|
|
73
|
+
opts.rewriteUrls = Constants.RewriteUrls.OFF;
|
|
74
|
+
break;
|
|
75
|
+
case 'local':
|
|
76
|
+
opts.rewriteUrls = Constants.RewriteUrls.LOCAL;
|
|
77
|
+
break;
|
|
78
|
+
case 'all':
|
|
79
|
+
opts.rewriteUrls = Constants.RewriteUrls.ALL;
|
|
80
|
+
break;
|
|
56
81
|
}
|
|
57
82
|
}
|
|
58
|
-
|
|
59
|
-
|
|
83
|
+
return opts;
|
|
84
|
+
},
|
|
85
|
+
defaults: function(obj1, obj2) {
|
|
86
|
+
var newObj = obj2 || {};
|
|
87
|
+
if (!obj2._defaults) {
|
|
88
|
+
newObj = {};
|
|
89
|
+
var defaults = clone(obj1);
|
|
90
|
+
newObj._defaults = defaults;
|
|
91
|
+
var cloned = obj2 ? clone(obj2) : {};
|
|
92
|
+
Object.assign(newObj, defaults, cloned);
|
|
93
|
+
}
|
|
94
|
+
return newObj;
|
|
60
95
|
},
|
|
61
96
|
merge: function(obj1, obj2) {
|
|
62
97
|
for (var prop in obj2) {
|
|
@@ -43,7 +43,7 @@ module.exports = function(window, options) {
|
|
|
43
43
|
options.onReady = true;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
if (options.relativeUrls) {
|
|
47
|
+
options.rewriteUrls = 'all';
|
|
48
|
+
}
|
|
49
49
|
};
|
|
@@ -30,7 +30,13 @@ module.exports = function(window, options) {
|
|
|
30
30
|
var typePattern = /^text\/(x-)?less$/;
|
|
31
31
|
|
|
32
32
|
function clone(obj) {
|
|
33
|
-
|
|
33
|
+
var cloned = {};
|
|
34
|
+
for (var prop in obj) {
|
|
35
|
+
if (obj.hasOwnProperty(prop)) {
|
|
36
|
+
cloned[prop] = obj[prop];
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return cloned;
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
// only really needed for phantom
|
|
@@ -93,7 +99,8 @@ module.exports = function(window, options) {
|
|
|
93
99
|
currentDirectory: fileManager.getPath(path),
|
|
94
100
|
filename: path,
|
|
95
101
|
rootFilename: path,
|
|
96
|
-
|
|
102
|
+
rewriteUrls: instanceOptions.rewriteUrls
|
|
103
|
+
};
|
|
97
104
|
|
|
98
105
|
newFileInfo.entryPath = newFileInfo.currentDirectory;
|
|
99
106
|
newFileInfo.rootpath = instanceOptions.rootpath || newFileInfo.currentDirectory;
|
|
@@ -6,7 +6,7 @@ module.exports = function(environment) {
|
|
|
6
6
|
function imageSize(functionContext, filePathNode) {
|
|
7
7
|
var filePath = filePathNode.value;
|
|
8
8
|
var currentFileInfo = functionContext.currentFileInfo;
|
|
9
|
-
var currentDirectory = currentFileInfo.
|
|
9
|
+
var currentDirectory = currentFileInfo.rewriteUrls ?
|
|
10
10
|
currentFileInfo.currentDirectory : currentFileInfo.entryPath;
|
|
11
11
|
|
|
12
12
|
var fragmentStart = filePath.indexOf('#');
|
|
@@ -47,10 +47,15 @@ var lessc_helper = {
|
|
|
47
47
|
console.log(' in generated CSS file.');
|
|
48
48
|
console.log(' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls');
|
|
49
49
|
console.log(' Works with or without the relative-urls option.');
|
|
50
|
-
console.log(' -ru
|
|
51
|
-
console.log('
|
|
52
|
-
console.log('
|
|
53
|
-
console.log('
|
|
50
|
+
console.log(' -ru=, --rewrite-urls= Rewrites URLs to make them relative to the base less file.');
|
|
51
|
+
console.log(' all|local|off \'all\' rewrites all URLs, \'local\' just those starting with a \'.\'');
|
|
52
|
+
console.log('');
|
|
53
|
+
console.log(' -m=, --math=');
|
|
54
|
+
console.log(' always Less will eagerly perform math operations always.');
|
|
55
|
+
console.log(' parens-division Math performed except for division (/) operator');
|
|
56
|
+
console.log(' parens | strict Math only performed inside parentheses');
|
|
57
|
+
console.log(' strict-legacy Parens required in very strict terms (legacy --strict-math)');
|
|
58
|
+
console.log('');
|
|
54
59
|
console.log(' -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units');
|
|
55
60
|
console.log(' --strict-units=on|off that cannot be represented.');
|
|
56
61
|
console.log(' --global-var=\'VAR=VALUE\' Defines a variable that can be referenced by the file.');
|
|
@@ -64,6 +69,9 @@ var lessc_helper = {
|
|
|
64
69
|
console.log(' or --clean-css="advanced"');
|
|
65
70
|
console.log('');
|
|
66
71
|
console.log('-------------------------- Deprecated ----------------');
|
|
72
|
+
console.log(' -sm=on|off Legacy parens-only math. Use --math');
|
|
73
|
+
console.log(' --strict-math=on|off ');
|
|
74
|
+
console.log('');
|
|
67
75
|
console.log(' --line-numbers=TYPE Outputs filename and line numbers.');
|
|
68
76
|
console.log(' TYPE can be either \'comments\', which will output');
|
|
69
77
|
console.log(' the debug info within comments, \'mediaquery\'');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "less",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.1",
|
|
4
4
|
"description": "Leaner CSS",
|
|
5
5
|
"homepage": "http://lesscss.org",
|
|
6
6
|
"author": {
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"less-plugin-autoprefix": "^1.5.1",
|
|
72
72
|
"less-plugin-clean-css": "^1.5.1",
|
|
73
73
|
"performance-now": "^0.2.0",
|
|
74
|
+
"phantomjs-polyfill-object-assign": "0.0.2",
|
|
74
75
|
"phantomjs-prebuilt": "^2.1.16",
|
|
75
76
|
"phin": "^2.2.3",
|
|
76
77
|
"promise": "^7.1.1",
|
|
@@ -104,5 +105,7 @@
|
|
|
104
105
|
],
|
|
105
106
|
"rawcurrent": "https://raw.github.com/less/less.js/v",
|
|
106
107
|
"sourcearchive": "https://github.com/less/less.js/archive/v",
|
|
107
|
-
"dependencies": {
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"clone": "^2.1.2"
|
|
110
|
+
}
|
|
108
111
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
@import "http://localhost:8081/test/browser/less/imports/modify-this.css";
|
|
2
|
+
@import "http://localhost:8081/test/browser/less/imports/modify-again.css";
|
|
3
|
+
.modify {
|
|
4
|
+
my-url: url("http://localhost:8081/test/browser/less/imports/a.png");
|
|
5
|
+
}
|
|
6
|
+
.modify {
|
|
7
|
+
my-url: url("http://localhost:8081/test/browser/less/imports/b.png");
|
|
8
|
+
}
|
|
9
|
+
@font-face {
|
|
10
|
+
src: url("/fonts/garamond-pro.ttf");
|
|
11
|
+
src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/rewrite-urls/fonts.svg#MyGeometricModern) format("svg");
|
|
12
|
+
}
|
|
13
|
+
#shorthands {
|
|
14
|
+
background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
|
|
15
|
+
}
|
|
16
|
+
#misc {
|
|
17
|
+
background-image: url(http://localhost:8081/test/browser/less/rewrite-urls/images/image.jpg);
|
|
18
|
+
background: url("#inline-svg");
|
|
19
|
+
}
|
|
20
|
+
#data-uri {
|
|
21
|
+
background: url(data:image/png;charset=utf-8;base64,
|
|
22
|
+
kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
|
|
23
|
+
k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
|
|
24
|
+
kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
|
|
25
|
+
background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
|
|
26
|
+
background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700);
|
|
27
|
+
}
|
|
28
|
+
#svg-data-uri {
|
|
29
|
+
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
|
|
30
|
+
}
|
|
31
|
+
.comma-delimited {
|
|
32
|
+
background: url(http://localhost:8081/test/browser/less/rewrite-urls/bg.jpg) no-repeat, url(http://localhost:8081/test/browser/less/rewrite-urls/bg.png) repeat-x top left, url(http://localhost:8081/test/browser/less/rewrite-urls/bg);
|
|
33
|
+
}
|
|
34
|
+
.values {
|
|
35
|
+
url: url('http://localhost:8081/test/browser/less/rewrite-urls/Trebuchet');
|
|
36
|
+
}
|