less 2.5.1 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.travis.yml +3 -2
- package/CHANGELOG.md +41 -0
- package/Gruntfile.js +5 -10
- package/README.md +3 -3
- package/appveyor.yml +2 -2
- package/bin/lessc +1 -0
- package/bower.json +1 -2
- package/dist/less.js +969 -605
- package/dist/less.min.js +13 -9
- package/gradlew +0 -0
- package/lib/less/contexts.js +0 -1
- package/lib/less/functions/color.js +5 -2
- package/lib/less/functions/math-helper.js +16 -0
- package/lib/less/functions/math.js +4 -16
- package/lib/less/functions/number.js +7 -2
- package/lib/less/index.js +1 -1
- package/lib/less/parser/parser-input.js +68 -68
- package/lib/less/parser/parser.js +159 -75
- package/lib/less/transform-tree.js +1 -0
- package/lib/less/tree/anonymous.js +4 -2
- package/lib/less/tree/color.js +4 -1
- package/lib/less/tree/comment.js +2 -6
- package/lib/less/tree/directive.js +3 -18
- package/lib/less/tree/element.js +9 -2
- package/lib/less/tree/extend.js +10 -5
- package/lib/less/tree/import.js +23 -5
- package/lib/less/tree/media.js +4 -2
- package/lib/less/tree/mixin-call.js +31 -18
- package/lib/less/tree/mixin-definition.js +19 -7
- package/lib/less/tree/node.js +49 -0
- package/lib/less/tree/rule.js +1 -1
- package/lib/less/tree/ruleset.js +107 -125
- package/lib/less/tree/selector.js +4 -9
- package/lib/less/tree/unit.js +2 -2
- package/lib/less/visitors/extend-visitor.js +17 -8
- package/lib/less/visitors/import-visitor.js +5 -0
- package/lib/less/visitors/index.js +1 -0
- package/lib/less/visitors/set-tree-visibility-visitor.js +38 -0
- package/lib/less/visitors/to-css-visitor.js +181 -98
- package/lib/less-browser/bootstrap.js +28 -2
- package/lib/less-browser/cache.js +11 -4
- package/lib/less-browser/error-reporting.js +10 -10
- package/lib/less-browser/file-manager.js +1 -1
- package/lib/less-browser/image-size.js +28 -0
- package/lib/less-browser/index.js +9 -10
- package/package.json +14 -14
- package/test/browser/less/errors/image-height-error.less +3 -0
- package/test/browser/less/errors/image-height-error.txt +4 -0
- package/test/browser/less/errors/image-size-error.less +3 -0
- package/test/browser/less/errors/image-size-error.txt +4 -0
- package/test/browser/less/errors/image-width-error.less +3 -0
- package/test/browser/less/errors/image-width-error.txt +4 -0
- package/test/browser/less.js +23 -19
- package/test/css/comments2.css +7 -1
- package/test/css/compression/compression.css +1 -1
- package/test/css/css-3.css +6 -0
- package/test/css/extend-selector.css +7 -0
- package/test/css/extract-and-length.css +1 -1
- package/test/css/functions.css +3 -3
- package/test/css/import-reference-issues.css +24 -0
- package/test/css/import-reference.css +5 -1
- package/test/css/include-path/include-path.css +1 -1
- package/test/css/include-path-string/include-path-string.css +1 -1
- package/test/css/mixins-args.css +51 -1
- package/test/css/mixins-guards.css +36 -0
- package/test/css/no-strict-math/mixins-guards.css +12 -0
- package/test/css/no-strict-math/no-sm-operations.css +12 -0
- package/test/css/operations.css +1 -0
- package/test/css/scope.css +1 -1
- package/test/css/strings.css +1 -1
- package/test/css/url-args/urls.css +5 -5
- package/test/css/urls.css +8 -8
- package/test/css/variables.css +5 -5
- package/test/data/image.jpg +0 -0
- package/test/data/image.svg +2 -1
- package/test/data/page.html +1 -1
- package/test/index.js +1 -0
- package/test/less/comments2.less +11 -0
- package/test/less/css-3.less +10 -2
- package/test/less/errors/at-rules-undefined-var.txt +4 -4
- package/test/less/errors/css-guard-default-func.txt +4 -4
- package/test/less/errors/javascript-undefined-var.txt +4 -4
- package/test/less/errors/mixins-guards-default-func-1.txt +4 -4
- package/test/less/errors/mixins-guards-default-func-2.txt +4 -4
- package/test/less/errors/mixins-guards-default-func-3.txt +4 -4
- package/test/less/errors/parse-error-media-no-block-1.txt +1 -1
- package/test/less/errors/parse-error-media-no-block-2.txt +1 -1
- package/test/less/errors/parse-error-media-no-block-3.txt +1 -1
- package/test/less/errors/percentage-non-number-argument.less +3 -0
- package/test/less/errors/percentage-non-number-argument.txt +4 -0
- package/test/less/errors/property-interp-not-defined.txt +2 -2
- package/test/less/extend-selector.less +12 -1
- package/test/less/import/import-inline-invalid-css.less +1 -0
- package/test/less/import/import-reference.less +10 -1
- package/test/less/import-reference-issues/appender-reference-1968.less +6 -0
- package/test/less/import-reference-issues/global-scope-import.less +13 -0
- package/test/less/import-reference-issues/global-scope-nested.less +3 -0
- package/test/less/import-reference-issues/mixin-1968.less +8 -0
- package/test/less/import-reference-issues/multiple-import-nested.less +12 -0
- package/test/less/import-reference-issues/multiple-import.less +10 -0
- package/test/less/import-reference-issues/simple-mixin.css +3 -0
- package/test/less/import-reference-issues/simple-ruleset-2162.less +3 -0
- package/test/less/import-reference-issues.less +50 -0
- package/test/less/import-reference.less +2 -0
- package/test/less/mixins-args.less +48 -0
- package/test/less/mixins-guards.less +78 -0
- package/test/less/no-strict-math/mixins-guards.less +25 -0
- package/test/less/no-strict-math/no-sm-operations.less +10 -0
- package/test/less/operations.less +1 -0
- package/test/less-bom/comments2.less +11 -0
- package/test/less-bom/css-3.less +10 -2
- package/test/less-bom/errors/at-rules-undefined-var.txt +4 -4
- package/test/less-bom/errors/css-guard-default-func.txt +4 -4
- package/test/less-bom/errors/javascript-undefined-var.txt +4 -4
- package/test/less-bom/errors/mixins-guards-default-func-1.txt +4 -4
- package/test/less-bom/errors/mixins-guards-default-func-2.txt +4 -4
- package/test/less-bom/errors/mixins-guards-default-func-3.txt +4 -4
- package/test/less-bom/errors/parse-error-media-no-block-1.txt +1 -1
- package/test/less-bom/errors/parse-error-media-no-block-2.txt +1 -1
- package/test/less-bom/errors/parse-error-media-no-block-3.txt +1 -1
- package/test/less-bom/errors/percentage-non-number-argument.less +3 -0
- package/test/less-bom/errors/percentage-non-number-argument.txt +4 -0
- package/test/less-bom/errors/property-interp-not-defined.txt +2 -2
- package/test/less-bom/extend-selector.less +12 -1
- package/test/less-bom/import/import-inline-invalid-css.less +1 -0
- package/test/less-bom/import/import-reference.less +10 -1
- package/test/less-bom/import-reference-issues/appender-reference-1968.less +6 -0
- package/test/less-bom/import-reference-issues/global-scope-import.less +13 -0
- package/test/less-bom/import-reference-issues/global-scope-nested.less +3 -0
- package/test/less-bom/import-reference-issues/mixin-1968.less +8 -0
- package/test/less-bom/import-reference-issues/multiple-import-nested.less +12 -0
- package/test/less-bom/import-reference-issues/multiple-import.less +10 -0
- package/test/less-bom/import-reference-issues/simple-mixin.css +3 -0
- package/test/less-bom/import-reference-issues/simple-ruleset-2162.less +3 -0
- package/test/less-bom/import-reference-issues.less +50 -0
- package/test/less-bom/import-reference.less +2 -0
- package/test/less-bom/mixins-args.less +48 -0
- package/test/less-bom/mixins-guards.less +78 -0
- package/test/less-bom/no-strict-math/mixins-guards.less +25 -0
- package/test/less-bom/no-strict-math/no-sm-operations.less +10 -0
- package/test/less-bom/operations.less +1 -0
- package/test/less-test.js +6 -1
- package/.idea/.name +0 -1
- package/.idea/jsLibraryMappings.xml +0 -6
- package/.idea/less.js.iml +0 -9
- package/.idea/libraries/less_js_node_modules.xml +0 -14
- package/.idea/misc.xml +0 -14
- package/.idea/modules.xml +0 -8
- package/.idea/vcs.xml +0 -6
- package/.idea/workspace.xml +0 -281
package/gradlew
CHANGED
|
File without changes
|
package/lib/less/contexts.js
CHANGED
|
@@ -30,7 +30,6 @@ var parseCopyProperties = [
|
|
|
30
30
|
// context
|
|
31
31
|
'processImports', // option & context - whether to process imports. if false then imports will not be imported.
|
|
32
32
|
// Used by the import manager to stop multiple import visitors being created.
|
|
33
|
-
'reference', // Used to indicate that the contents are imported by reference
|
|
34
33
|
'pluginManager' // Used as the plugin manager for the session
|
|
35
34
|
];
|
|
36
35
|
|
|
@@ -43,6 +43,9 @@ colorFunctions = {
|
|
|
43
43
|
return colorFunctions.hsla(h, s, l, 1.0);
|
|
44
44
|
},
|
|
45
45
|
hsla: function (h, s, l, a) {
|
|
46
|
+
|
|
47
|
+
var m1, m2;
|
|
48
|
+
|
|
46
49
|
function hue(h) {
|
|
47
50
|
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
|
|
48
51
|
if (h * 6 < 1) {
|
|
@@ -62,8 +65,8 @@ colorFunctions = {
|
|
|
62
65
|
h = (number(h) % 360) / 360;
|
|
63
66
|
s = clamp(number(s)); l = clamp(number(l)); a = clamp(number(a));
|
|
64
67
|
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
|
|
69
|
+
m1 = l * 2 - m2;
|
|
67
70
|
|
|
68
71
|
return colorFunctions.rgba(hue(h + 1 / 3) * 255,
|
|
69
72
|
hue(h) * 255,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
var Dimension = require("../tree/dimension");
|
|
2
|
+
|
|
3
|
+
var MathHelper = function() {
|
|
4
|
+
};
|
|
5
|
+
MathHelper._math = function (fn, unit, n) {
|
|
6
|
+
if (!(n instanceof Dimension)) {
|
|
7
|
+
throw { type: "Argument", message: "argument must be a number" };
|
|
8
|
+
}
|
|
9
|
+
if (unit == null) {
|
|
10
|
+
unit = n.unit;
|
|
11
|
+
} else {
|
|
12
|
+
n = n.unify();
|
|
13
|
+
}
|
|
14
|
+
return new Dimension(fn(parseFloat(n.value)), unit);
|
|
15
|
+
};
|
|
16
|
+
module.exports = MathHelper;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
1
|
+
var functionRegistry = require("./function-registry"),
|
|
2
|
+
mathHelper = require("./math-helper.js");
|
|
3
3
|
|
|
4
4
|
var mathFunctions = {
|
|
5
5
|
// name, unit
|
|
@@ -15,27 +15,15 @@ var mathFunctions = {
|
|
|
15
15
|
acos: "rad"
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
function _math(fn, unit, n) {
|
|
19
|
-
if (!(n instanceof Dimension)) {
|
|
20
|
-
throw { type: "Argument", message: "argument must be a number" };
|
|
21
|
-
}
|
|
22
|
-
if (unit == null) {
|
|
23
|
-
unit = n.unit;
|
|
24
|
-
} else {
|
|
25
|
-
n = n.unify();
|
|
26
|
-
}
|
|
27
|
-
return new Dimension(fn(parseFloat(n.value)), unit);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
18
|
for (var f in mathFunctions) {
|
|
31
19
|
if (mathFunctions.hasOwnProperty(f)) {
|
|
32
|
-
mathFunctions[f] = _math.bind(null, Math[f], mathFunctions[f]);
|
|
20
|
+
mathFunctions[f] = mathHelper._math.bind(null, Math[f], mathFunctions[f]);
|
|
33
21
|
}
|
|
34
22
|
}
|
|
35
23
|
|
|
36
24
|
mathFunctions.round = function (n, f) {
|
|
37
25
|
var fraction = typeof f === "undefined" ? 0 : f.value;
|
|
38
|
-
return _math(function(num) { return num.toFixed(fraction); }, null, n);
|
|
26
|
+
return mathHelper._math(function(num) { return num.toFixed(fraction); }, null, n);
|
|
39
27
|
};
|
|
40
28
|
|
|
41
29
|
functionRegistry.addMultiple(mathFunctions);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
var Dimension = require("../tree/dimension"),
|
|
2
2
|
Anonymous = require("../tree/anonymous"),
|
|
3
|
-
functionRegistry = require("./function-registry")
|
|
3
|
+
functionRegistry = require("./function-registry"),
|
|
4
|
+
mathHelper = require("./math-helper.js");
|
|
4
5
|
|
|
5
6
|
var minMax = function (isMin, args) {
|
|
6
7
|
args = Array.prototype.slice.call(args);
|
|
@@ -71,6 +72,10 @@ functionRegistry.addMultiple({
|
|
|
71
72
|
return new Dimension(Math.pow(x.value, y.value), x.unit);
|
|
72
73
|
},
|
|
73
74
|
percentage: function (n) {
|
|
74
|
-
|
|
75
|
+
var result = mathHelper._math(function(num) {
|
|
76
|
+
return num * 100;
|
|
77
|
+
}, '%', n);
|
|
78
|
+
|
|
79
|
+
return result;
|
|
75
80
|
}
|
|
76
81
|
});
|
package/lib/less/index.js
CHANGED
|
@@ -2,7 +2,7 @@ module.exports = function(environment, fileManagers) {
|
|
|
2
2
|
var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
|
|
3
3
|
|
|
4
4
|
var less = {
|
|
5
|
-
version: [2,
|
|
5
|
+
version: [2, 6, 1],
|
|
6
6
|
data: require('./data'),
|
|
7
7
|
tree: require('./tree'),
|
|
8
8
|
Environment: (Environment = require("./environment/environment")),
|
|
@@ -11,6 +11,74 @@ module.exports = function() {
|
|
|
11
11
|
currentPos, // index of current chunk, in `input`
|
|
12
12
|
parserInput = {};
|
|
13
13
|
|
|
14
|
+
var CHARCODE_SPACE = 32,
|
|
15
|
+
CHARCODE_TAB = 9,
|
|
16
|
+
CHARCODE_LF = 10,
|
|
17
|
+
CHARCODE_CR = 13,
|
|
18
|
+
CHARCODE_PLUS = 43,
|
|
19
|
+
CHARCODE_COMMA = 44,
|
|
20
|
+
CHARCODE_FORWARD_SLASH = 47,
|
|
21
|
+
CHARCODE_9 = 57;
|
|
22
|
+
|
|
23
|
+
function skipWhitespace(length) {
|
|
24
|
+
var oldi = parserInput.i, oldj = j,
|
|
25
|
+
curr = parserInput.i - currentPos,
|
|
26
|
+
endIndex = parserInput.i + current.length - curr,
|
|
27
|
+
mem = (parserInput.i += length),
|
|
28
|
+
inp = input,
|
|
29
|
+
c, nextChar, comment;
|
|
30
|
+
|
|
31
|
+
for (; parserInput.i < endIndex; parserInput.i++) {
|
|
32
|
+
c = inp.charCodeAt(parserInput.i);
|
|
33
|
+
|
|
34
|
+
if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
|
|
35
|
+
nextChar = inp.charAt(parserInput.i + 1);
|
|
36
|
+
if (nextChar === '/') {
|
|
37
|
+
comment = {index: parserInput.i, isLineComment: true};
|
|
38
|
+
var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
|
|
39
|
+
if (nextNewLine < 0) {
|
|
40
|
+
nextNewLine = endIndex;
|
|
41
|
+
}
|
|
42
|
+
parserInput.i = nextNewLine;
|
|
43
|
+
comment.text = inp.substr(comment.i, parserInput.i - comment.i);
|
|
44
|
+
parserInput.commentStore.push(comment);
|
|
45
|
+
continue;
|
|
46
|
+
} else if (nextChar === '*') {
|
|
47
|
+
var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
|
|
48
|
+
if (nextStarSlash >= 0) {
|
|
49
|
+
comment = {
|
|
50
|
+
index: parserInput.i,
|
|
51
|
+
text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
|
|
52
|
+
isLineComment: false
|
|
53
|
+
};
|
|
54
|
+
parserInput.i += comment.text.length - 1;
|
|
55
|
+
parserInput.commentStore.push(comment);
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
current = current.slice(length + parserInput.i - mem + curr);
|
|
68
|
+
currentPos = parserInput.i;
|
|
69
|
+
|
|
70
|
+
if (!current.length) {
|
|
71
|
+
if (j < chunks.length - 1) {
|
|
72
|
+
current = chunks[++j];
|
|
73
|
+
skipWhitespace(0); // skip space at the beginning of a chunk
|
|
74
|
+
return true; // things changed
|
|
75
|
+
}
|
|
76
|
+
parserInput.finished = true;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return oldi !== parserInput.i || oldj !== j;
|
|
80
|
+
}
|
|
81
|
+
|
|
14
82
|
parserInput.save = function() {
|
|
15
83
|
currentPos = parserInput.i;
|
|
16
84
|
saveStack.push( { current: current, i: parserInput.i, j: j });
|
|
@@ -105,78 +173,10 @@ module.exports = function() {
|
|
|
105
173
|
return null;
|
|
106
174
|
};
|
|
107
175
|
|
|
108
|
-
var CHARCODE_SPACE = 32,
|
|
109
|
-
CHARCODE_TAB = 9,
|
|
110
|
-
CHARCODE_LF = 10,
|
|
111
|
-
CHARCODE_CR = 13,
|
|
112
|
-
CHARCODE_PLUS = 43,
|
|
113
|
-
CHARCODE_COMMA = 44,
|
|
114
|
-
CHARCODE_FORWARD_SLASH = 47,
|
|
115
|
-
CHARCODE_9 = 57;
|
|
116
|
-
|
|
117
176
|
parserInput.autoCommentAbsorb = true;
|
|
118
177
|
parserInput.commentStore = [];
|
|
119
178
|
parserInput.finished = false;
|
|
120
179
|
|
|
121
|
-
var skipWhitespace = function(length) {
|
|
122
|
-
var oldi = parserInput.i, oldj = j,
|
|
123
|
-
curr = parserInput.i - currentPos,
|
|
124
|
-
endIndex = parserInput.i + current.length - curr,
|
|
125
|
-
mem = (parserInput.i += length),
|
|
126
|
-
inp = input,
|
|
127
|
-
c, nextChar, comment;
|
|
128
|
-
|
|
129
|
-
for (; parserInput.i < endIndex; parserInput.i++) {
|
|
130
|
-
c = inp.charCodeAt(parserInput.i);
|
|
131
|
-
|
|
132
|
-
if (parserInput.autoCommentAbsorb && c === CHARCODE_FORWARD_SLASH) {
|
|
133
|
-
nextChar = inp.charAt(parserInput.i + 1);
|
|
134
|
-
if (nextChar === '/') {
|
|
135
|
-
comment = {index: parserInput.i, isLineComment: true};
|
|
136
|
-
var nextNewLine = inp.indexOf("\n", parserInput.i + 2);
|
|
137
|
-
if (nextNewLine < 0) {
|
|
138
|
-
nextNewLine = endIndex;
|
|
139
|
-
}
|
|
140
|
-
parserInput.i = nextNewLine;
|
|
141
|
-
comment.text = inp.substr(comment.i, parserInput.i - comment.i);
|
|
142
|
-
parserInput.commentStore.push(comment);
|
|
143
|
-
continue;
|
|
144
|
-
} else if (nextChar === '*') {
|
|
145
|
-
var nextStarSlash = inp.indexOf("*/", parserInput.i + 2);
|
|
146
|
-
if (nextStarSlash >= 0) {
|
|
147
|
-
comment = {
|
|
148
|
-
index: parserInput.i,
|
|
149
|
-
text: inp.substr(parserInput.i, nextStarSlash + 2 - parserInput.i),
|
|
150
|
-
isLineComment: false
|
|
151
|
-
};
|
|
152
|
-
parserInput.i += comment.text.length - 1;
|
|
153
|
-
parserInput.commentStore.push(comment);
|
|
154
|
-
continue;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
if ((c !== CHARCODE_SPACE) && (c !== CHARCODE_LF) && (c !== CHARCODE_TAB) && (c !== CHARCODE_CR)) {
|
|
161
|
-
break;
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
current = current.slice(length + parserInput.i - mem + curr);
|
|
166
|
-
currentPos = parserInput.i;
|
|
167
|
-
|
|
168
|
-
if (!current.length) {
|
|
169
|
-
if (j < chunks.length - 1) {
|
|
170
|
-
current = chunks[++j];
|
|
171
|
-
skipWhitespace(0); // skip space at the beginning of a chunk
|
|
172
|
-
return true; // things changed
|
|
173
|
-
}
|
|
174
|
-
parserInput.finished = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return oldi !== parserInput.i || oldj !== j;
|
|
178
|
-
};
|
|
179
|
-
|
|
180
180
|
// Same as $(), but don't change the state of the parser,
|
|
181
181
|
// just return the match.
|
|
182
182
|
parserInput.peek = function(tok) {
|
|
@@ -35,15 +35,27 @@ var LessError = require('../less-error'),
|
|
|
35
35
|
// Token matching is done with the `$` function, which either takes
|
|
36
36
|
// a terminal string or regexp, or a non-terminal function to call.
|
|
37
37
|
// It also takes care of moving all the indices forwards.
|
|
38
|
-
|
|
38
|
+
//`
|
|
39
39
|
//
|
|
40
40
|
var Parser = function Parser(context, imports, fileInfo) {
|
|
41
41
|
var parsers,
|
|
42
42
|
parserInput = getParserInput();
|
|
43
43
|
|
|
44
|
+
function error(msg, type) {
|
|
45
|
+
throw new LessError(
|
|
46
|
+
{
|
|
47
|
+
index: parserInput.i,
|
|
48
|
+
filename: fileInfo.filename,
|
|
49
|
+
type: type || 'Syntax',
|
|
50
|
+
message: msg
|
|
51
|
+
},
|
|
52
|
+
imports
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
function expect(arg, msg, index) {
|
|
45
57
|
// some older browsers return typeof 'function' for RegExp
|
|
46
|
-
var result = (
|
|
58
|
+
var result = (arg instanceof Function) ? arg.call(parsers) : parserInput.$re(arg);
|
|
47
59
|
if (result) {
|
|
48
60
|
return result;
|
|
49
61
|
}
|
|
@@ -59,18 +71,6 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
59
71
|
error(msg || "expected '" + arg + "' got '" + parserInput.currentChar() + "'");
|
|
60
72
|
}
|
|
61
73
|
|
|
62
|
-
function error(msg, type) {
|
|
63
|
-
throw new LessError(
|
|
64
|
-
{
|
|
65
|
-
index: parserInput.i,
|
|
66
|
-
filename: fileInfo.filename,
|
|
67
|
-
type: type || 'Syntax',
|
|
68
|
-
message: msg
|
|
69
|
-
},
|
|
70
|
-
imports
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
74
|
function getDebugInfo(index) {
|
|
75
75
|
var filename = fileInfo.filename;
|
|
76
76
|
|
|
@@ -489,7 +489,25 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
489
489
|
if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
|
|
490
490
|
error("Invalid HEX color code");
|
|
491
491
|
}
|
|
492
|
-
return new(tree.Color)(rgb[1]);
|
|
492
|
+
return new(tree.Color)(rgb[1], undefined, '#' + colorCandidateString);
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
colorKeyword: function () {
|
|
497
|
+
parserInput.save();
|
|
498
|
+
var autoCommentAbsorb = parserInput.autoCommentAbsorb;
|
|
499
|
+
parserInput.autoCommentAbsorb = false;
|
|
500
|
+
var k = parserInput.$re(/^[A-Za-z]+/);
|
|
501
|
+
parserInput.autoCommentAbsorb = autoCommentAbsorb;
|
|
502
|
+
if (!k) {
|
|
503
|
+
parserInput.forget();
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
parserInput.restore();
|
|
507
|
+
var color = tree.Color.fromKeyword(k);
|
|
508
|
+
if (color) {
|
|
509
|
+
parserInput.$str(k);
|
|
510
|
+
return color;
|
|
493
511
|
}
|
|
494
512
|
},
|
|
495
513
|
|
|
@@ -503,7 +521,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
503
521
|
return;
|
|
504
522
|
}
|
|
505
523
|
|
|
506
|
-
var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-
|
|
524
|
+
var value = parserInput.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);
|
|
507
525
|
if (value) {
|
|
508
526
|
return new(tree.Dimension)(value[1], value[2]);
|
|
509
527
|
}
|
|
@@ -569,7 +587,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
569
587
|
rulesetCall: function () {
|
|
570
588
|
var name;
|
|
571
589
|
|
|
572
|
-
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\
|
|
590
|
+
if (parserInput.currentChar() === '@' && (name = parserInput.$re(/^(@[\w-]+)\(\s*\)\s*;/))) {
|
|
573
591
|
return new tree.RulesetCall(name[1]);
|
|
574
592
|
}
|
|
575
593
|
},
|
|
@@ -603,7 +621,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
603
621
|
if (!elements) {
|
|
604
622
|
error("Missing target selector for :extend().");
|
|
605
623
|
}
|
|
606
|
-
extend = new(tree.Extend)(new(tree.Selector)(elements), option, index);
|
|
624
|
+
extend = new(tree.Extend)(new(tree.Selector)(elements), option, index, fileInfo);
|
|
607
625
|
if (extendList) {
|
|
608
626
|
extendList.push(extend);
|
|
609
627
|
} else {
|
|
@@ -687,7 +705,8 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
687
705
|
var entities = parsers.entities,
|
|
688
706
|
returner = { args:null, variadic: false },
|
|
689
707
|
expressions = [], argsSemiColon = [], argsComma = [],
|
|
690
|
-
isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
|
|
708
|
+
isSemiColonSeparated, expressionContainsNamed, name, nameLoop,
|
|
709
|
+
value, arg, expand;
|
|
691
710
|
|
|
692
711
|
parserInput.save();
|
|
693
712
|
|
|
@@ -749,14 +768,18 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
749
768
|
}
|
|
750
769
|
}
|
|
751
770
|
nameLoop = (name = val.name);
|
|
752
|
-
} else if (
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
isSemiColonSeparated
|
|
771
|
+
} else if (parserInput.$str("...")) {
|
|
772
|
+
if (!isCall) {
|
|
773
|
+
returner.variadic = true;
|
|
774
|
+
if (parserInput.$char(";") && !isSemiColonSeparated) {
|
|
775
|
+
isSemiColonSeparated = true;
|
|
776
|
+
}
|
|
777
|
+
(isSemiColonSeparated ? argsSemiColon : argsComma)
|
|
778
|
+
.push({ name: arg.name, variadic: true });
|
|
779
|
+
break;
|
|
780
|
+
} else {
|
|
781
|
+
expand = true;
|
|
756
782
|
}
|
|
757
|
-
(isSemiColonSeparated ? argsSemiColon : argsComma)
|
|
758
|
-
.push({ name: arg.name, variadic: true });
|
|
759
|
-
break;
|
|
760
783
|
} else if (!isCall) {
|
|
761
784
|
name = nameLoop = val.name;
|
|
762
785
|
value = null;
|
|
@@ -767,7 +790,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
767
790
|
expressions.push(value);
|
|
768
791
|
}
|
|
769
792
|
|
|
770
|
-
argsComma.push({ name:nameLoop, value:value });
|
|
793
|
+
argsComma.push({ name:nameLoop, value:value, expand:expand });
|
|
771
794
|
|
|
772
795
|
if (parserInput.$char(',')) {
|
|
773
796
|
continue;
|
|
@@ -784,7 +807,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
784
807
|
if (expressions.length > 1) {
|
|
785
808
|
value = new(tree.Value)(expressions);
|
|
786
809
|
}
|
|
787
|
-
argsSemiColon.push({ name:name, value:value });
|
|
810
|
+
argsSemiColon.push({ name:name, value:value, expand:expand });
|
|
788
811
|
|
|
789
812
|
name = null;
|
|
790
813
|
expressions = [];
|
|
@@ -1264,12 +1287,10 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1264
1287
|
} else if (e) {
|
|
1265
1288
|
nodes.push(new(tree.Paren)(e));
|
|
1266
1289
|
} else {
|
|
1267
|
-
|
|
1268
|
-
return null;
|
|
1290
|
+
error("badly formed media feature definition");
|
|
1269
1291
|
}
|
|
1270
1292
|
} else {
|
|
1271
|
-
|
|
1272
|
-
return null;
|
|
1293
|
+
error("Missing closing ')'", "Parse");
|
|
1273
1294
|
}
|
|
1274
1295
|
}
|
|
1275
1296
|
} while (e);
|
|
@@ -1314,8 +1335,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1314
1335
|
rules = this.block();
|
|
1315
1336
|
|
|
1316
1337
|
if (!rules) {
|
|
1317
|
-
|
|
1318
|
-
return;
|
|
1338
|
+
error("media definitions require block statements after any features");
|
|
1319
1339
|
}
|
|
1320
1340
|
|
|
1321
1341
|
parserInput.forget();
|
|
@@ -1393,33 +1413,6 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1393
1413
|
}
|
|
1394
1414
|
|
|
1395
1415
|
switch(nonVendorSpecificName) {
|
|
1396
|
-
/*
|
|
1397
|
-
case "@font-face":
|
|
1398
|
-
case "@viewport":
|
|
1399
|
-
case "@top-left":
|
|
1400
|
-
case "@top-left-corner":
|
|
1401
|
-
case "@top-center":
|
|
1402
|
-
case "@top-right":
|
|
1403
|
-
case "@top-right-corner":
|
|
1404
|
-
case "@bottom-left":
|
|
1405
|
-
case "@bottom-left-corner":
|
|
1406
|
-
case "@bottom-center":
|
|
1407
|
-
case "@bottom-right":
|
|
1408
|
-
case "@bottom-right-corner":
|
|
1409
|
-
case "@left-top":
|
|
1410
|
-
case "@left-middle":
|
|
1411
|
-
case "@left-bottom":
|
|
1412
|
-
case "@right-top":
|
|
1413
|
-
case "@right-middle":
|
|
1414
|
-
case "@right-bottom":
|
|
1415
|
-
hasBlock = true;
|
|
1416
|
-
isRooted = true;
|
|
1417
|
-
break;
|
|
1418
|
-
*/
|
|
1419
|
-
case "@counter-style":
|
|
1420
|
-
hasIdentifier = true;
|
|
1421
|
-
hasBlock = true;
|
|
1422
|
-
break;
|
|
1423
1416
|
case "@charset":
|
|
1424
1417
|
hasIdentifier = true;
|
|
1425
1418
|
hasBlock = false;
|
|
@@ -1429,17 +1422,17 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1429
1422
|
hasBlock = false;
|
|
1430
1423
|
break;
|
|
1431
1424
|
case "@keyframes":
|
|
1425
|
+
case "@counter-style":
|
|
1432
1426
|
hasIdentifier = true;
|
|
1433
1427
|
break;
|
|
1434
|
-
case "@host":
|
|
1435
|
-
case "@page":
|
|
1436
|
-
hasUnknown = true;
|
|
1437
|
-
break;
|
|
1438
1428
|
case "@document":
|
|
1439
1429
|
case "@supports":
|
|
1440
1430
|
hasUnknown = true;
|
|
1441
1431
|
isRooted = false;
|
|
1442
1432
|
break;
|
|
1433
|
+
default:
|
|
1434
|
+
hasUnknown = true;
|
|
1435
|
+
break;
|
|
1443
1436
|
}
|
|
1444
1437
|
|
|
1445
1438
|
parserInput.commentStore.length = 0;
|
|
@@ -1456,6 +1449,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1456
1449
|
}
|
|
1457
1450
|
} else if (hasUnknown) {
|
|
1458
1451
|
value = (parserInput.$re(/^[^{;]+/) || '').trim();
|
|
1452
|
+
hasBlock = (parserInput.currentChar() == '{');
|
|
1459
1453
|
if (value) {
|
|
1460
1454
|
value = new(tree.Anonymous)(value);
|
|
1461
1455
|
}
|
|
@@ -1469,7 +1463,6 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1469
1463
|
parserInput.forget();
|
|
1470
1464
|
return new (tree.Directive)(name, value, rules, index, fileInfo,
|
|
1471
1465
|
context.dumpLineNumbers ? getDebugInfo(index) : null,
|
|
1472
|
-
false,
|
|
1473
1466
|
isRooted
|
|
1474
1467
|
);
|
|
1475
1468
|
}
|
|
@@ -1593,11 +1586,103 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1593
1586
|
}
|
|
1594
1587
|
},
|
|
1595
1588
|
condition: function () {
|
|
1596
|
-
var
|
|
1597
|
-
|
|
1589
|
+
var result, logical, next;
|
|
1590
|
+
function or() {
|
|
1591
|
+
return parserInput.$str("or");
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
result = this.conditionAnd(this);
|
|
1595
|
+
if (!result) {
|
|
1596
|
+
return ;
|
|
1597
|
+
}
|
|
1598
|
+
logical = or();
|
|
1599
|
+
if (logical) {
|
|
1600
|
+
next = this.condition();
|
|
1601
|
+
if (next) {
|
|
1602
|
+
result = new(tree.Condition)(logical, result, next);
|
|
1603
|
+
} else {
|
|
1604
|
+
return ;
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return result;
|
|
1608
|
+
},
|
|
1609
|
+
conditionAnd: function () {
|
|
1610
|
+
var result, logical, next;
|
|
1611
|
+
function insideCondition(me) {
|
|
1612
|
+
return me.negatedCondition() || me.parenthesisCondition();
|
|
1613
|
+
}
|
|
1614
|
+
function and() {
|
|
1615
|
+
return parserInput.$str("and");
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
result = insideCondition(this);
|
|
1619
|
+
if (!result) {
|
|
1620
|
+
return ;
|
|
1621
|
+
}
|
|
1622
|
+
logical = and();
|
|
1623
|
+
if (logical) {
|
|
1624
|
+
next = this.conditionAnd();
|
|
1625
|
+
if (next) {
|
|
1626
|
+
result = new(tree.Condition)(logical, result, next);
|
|
1627
|
+
} else {
|
|
1628
|
+
return ;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
return result;
|
|
1632
|
+
},
|
|
1633
|
+
negatedCondition: function () {
|
|
1634
|
+
if (parserInput.$str("not")) {
|
|
1635
|
+
var result = this.parenthesisCondition();
|
|
1636
|
+
if (result) {
|
|
1637
|
+
result.negate = !result.negate;
|
|
1638
|
+
}
|
|
1639
|
+
return result;
|
|
1640
|
+
}
|
|
1641
|
+
},
|
|
1642
|
+
parenthesisCondition: function () {
|
|
1643
|
+
function tryConditionFollowedByParenthesis(me) {
|
|
1644
|
+
var body;
|
|
1645
|
+
parserInput.save();
|
|
1646
|
+
body = me.condition();
|
|
1647
|
+
if (!body) {
|
|
1648
|
+
parserInput.restore();
|
|
1649
|
+
return ;
|
|
1650
|
+
}
|
|
1651
|
+
if (!parserInput.$char(')')) {
|
|
1652
|
+
parserInput.restore();
|
|
1653
|
+
return ;
|
|
1654
|
+
}
|
|
1655
|
+
parserInput.forget();
|
|
1656
|
+
return body;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
var body;
|
|
1660
|
+
parserInput.save();
|
|
1661
|
+
if (!parserInput.$str("(")) {
|
|
1662
|
+
parserInput.restore();
|
|
1663
|
+
return ;
|
|
1664
|
+
}
|
|
1665
|
+
body = tryConditionFollowedByParenthesis(this);
|
|
1666
|
+
if (body) {
|
|
1667
|
+
parserInput.forget();
|
|
1668
|
+
return body;
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
body = this.atomicCondition();
|
|
1672
|
+
if (!body) {
|
|
1673
|
+
parserInput.restore();
|
|
1674
|
+
return ;
|
|
1675
|
+
}
|
|
1676
|
+
if (!parserInput.$char(')')) {
|
|
1677
|
+
parserInput.restore("expected ')' got '" + parserInput.currentChar() + "'");
|
|
1678
|
+
return ;
|
|
1679
|
+
}
|
|
1680
|
+
parserInput.forget();
|
|
1681
|
+
return body;
|
|
1682
|
+
},
|
|
1683
|
+
atomicCondition: function () {
|
|
1684
|
+
var entities = this.entities, index = parserInput.i, a, b, c, op;
|
|
1598
1685
|
|
|
1599
|
-
if (parserInput.$str("not")) { negate = true; }
|
|
1600
|
-
expectChar('(');
|
|
1601
1686
|
a = this.addition() || entities.keyword() || entities.quoted();
|
|
1602
1687
|
if (a) {
|
|
1603
1688
|
if (parserInput.$char('>')) {
|
|
@@ -1626,15 +1711,14 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1626
1711
|
if (op) {
|
|
1627
1712
|
b = this.addition() || entities.keyword() || entities.quoted();
|
|
1628
1713
|
if (b) {
|
|
1629
|
-
c = new(tree.Condition)(op, a, b, index,
|
|
1714
|
+
c = new(tree.Condition)(op, a, b, index, false);
|
|
1630
1715
|
} else {
|
|
1631
1716
|
error('expected expression');
|
|
1632
1717
|
}
|
|
1633
1718
|
} else {
|
|
1634
|
-
c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index,
|
|
1719
|
+
c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, false);
|
|
1635
1720
|
}
|
|
1636
|
-
|
|
1637
|
-
return parserInput.$str("and") ? new(tree.Condition)('and', c, this.condition()) : c;
|
|
1721
|
+
return c;
|
|
1638
1722
|
}
|
|
1639
1723
|
},
|
|
1640
1724
|
|
|
@@ -1651,7 +1735,7 @@ var Parser = function Parser(context, imports, fileInfo) {
|
|
|
1651
1735
|
|
|
1652
1736
|
var o = this.sub() || entities.dimension() ||
|
|
1653
1737
|
entities.color() || entities.variable() ||
|
|
1654
|
-
entities.call();
|
|
1738
|
+
entities.call() || entities.colorKeyword();
|
|
1655
1739
|
|
|
1656
1740
|
if (negate) {
|
|
1657
1741
|
o.parensInOp = true;
|
|
@@ -39,6 +39,7 @@ module.exports = function(root, options) {
|
|
|
39
39
|
var preEvalVisitors = [],
|
|
40
40
|
visitors = [
|
|
41
41
|
new visitor.JoinSelectorVisitor(),
|
|
42
|
+
new visitor.MarkVisibleSelectorsVisitor(true),
|
|
42
43
|
new visitor.ExtendVisitor(),
|
|
43
44
|
new visitor.ToCSSVisitor({compress: Boolean(options.compress)})
|
|
44
45
|
], i;
|