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
@@ -144,20 +144,63 @@ tree.functions = {
|
|
144
144
|
return new(tree.Quoted)('"' + str + '"', str);
|
145
145
|
},
|
146
146
|
round: function (n) {
|
147
|
+
return this._math('round', n);
|
148
|
+
},
|
149
|
+
ceil: function (n) {
|
150
|
+
return this._math('ceil', n);
|
151
|
+
},
|
152
|
+
floor: function (n) {
|
153
|
+
return this._math('floor', n);
|
154
|
+
},
|
155
|
+
_math: function (fn, n) {
|
147
156
|
if (n instanceof tree.Dimension) {
|
148
|
-
return new(tree.Dimension)(Math
|
157
|
+
return new(tree.Dimension)(Math[fn](number(n)), n.unit);
|
149
158
|
} else if (typeof(n) === 'number') {
|
150
|
-
return Math
|
159
|
+
return Math[fn](n);
|
151
160
|
} else {
|
152
|
-
|
153
|
-
error: "RuntimeError",
|
154
|
-
message: "math functions take numbers as parameters"
|
155
|
-
};
|
161
|
+
throw { type: "Argument", message: "argument must be a number" };
|
156
162
|
}
|
157
163
|
},
|
158
164
|
argb: function (color) {
|
159
165
|
return new(tree.Anonymous)(color.toARGB());
|
160
166
|
|
167
|
+
},
|
168
|
+
percentage: function (n) {
|
169
|
+
return new(tree.Dimension)(n.value * 100, '%');
|
170
|
+
},
|
171
|
+
color: function (n) {
|
172
|
+
if (n instanceof tree.Quoted) {
|
173
|
+
return new(tree.Color)(n.value.slice(1));
|
174
|
+
} else {
|
175
|
+
throw { type: "Argument", message: "argument must be a string" };
|
176
|
+
}
|
177
|
+
},
|
178
|
+
iscolor: function (n) {
|
179
|
+
return this._isa(n, tree.Color);
|
180
|
+
},
|
181
|
+
isnumber: function (n) {
|
182
|
+
return this._isa(n, tree.Dimension);
|
183
|
+
},
|
184
|
+
isstring: function (n) {
|
185
|
+
return this._isa(n, tree.Quoted);
|
186
|
+
},
|
187
|
+
iskeyword: function (n) {
|
188
|
+
return this._isa(n, tree.Keyword);
|
189
|
+
},
|
190
|
+
isurl: function (n) {
|
191
|
+
return this._isa(n, tree.URL);
|
192
|
+
},
|
193
|
+
ispixel: function (n) {
|
194
|
+
return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False;
|
195
|
+
},
|
196
|
+
ispercentage: function (n) {
|
197
|
+
return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False;
|
198
|
+
},
|
199
|
+
isem: function (n) {
|
200
|
+
return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False;
|
201
|
+
},
|
202
|
+
_isa: function (n, Type) {
|
203
|
+
return (n instanceof Type) ? tree.True : tree.False;
|
161
204
|
}
|
162
205
|
};
|
163
206
|
|
@@ -3,7 +3,7 @@ var path = require('path'),
|
|
3
3
|
fs = require('fs');
|
4
4
|
|
5
5
|
var less = {
|
6
|
-
version: [1,
|
6
|
+
version: [1, 2, 1],
|
7
7
|
Parser: require('./parser').Parser,
|
8
8
|
importer: require('./parser').importer,
|
9
9
|
tree: require('./tree'),
|
@@ -43,7 +43,9 @@ var less = {
|
|
43
43
|
|
44
44
|
if (options.silent) { return }
|
45
45
|
|
46
|
-
if (
|
46
|
+
if (ctx.stack) { return sys.error(stylize(ctx.stack, 'red')) }
|
47
|
+
|
48
|
+
if (!ctx.hasOwnProperty('index')) {
|
47
49
|
return sys.error(ctx.stack || ctx.message);
|
48
50
|
}
|
49
51
|
|
@@ -51,17 +53,20 @@ var less = {
|
|
51
53
|
error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
|
52
54
|
}
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
56
|
+
if (extract[1]) {
|
57
|
+
error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column)
|
58
|
+
+ stylize(stylize(stylize(extract[1][ctx.column], 'bold')
|
59
|
+
+ extract[1].slice(ctx.column + 1), 'red'), 'inverse'));
|
60
|
+
}
|
57
61
|
|
58
62
|
if (typeof(extract[2]) === 'string') {
|
59
63
|
error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
|
60
64
|
}
|
61
65
|
error = error.join('\n') + '\033[0m\n';
|
62
66
|
|
63
|
-
message += stylize(ctx.message, 'red');
|
64
|
-
ctx.filename && (message += stylize(' in ', 'red') + ctx.filename
|
67
|
+
message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
|
68
|
+
ctx.filename && (message += stylize(' in ', 'red') + ctx.filename +
|
69
|
+
stylize(':' + ctx.line + ':' + ctx.column, 'grey'));
|
65
70
|
|
66
71
|
sys.error(message, error);
|
67
72
|
|
@@ -69,16 +74,15 @@ var less = {
|
|
69
74
|
sys.error(stylize('from ', 'red') + (ctx.filename || ''));
|
70
75
|
sys.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract);
|
71
76
|
}
|
72
|
-
if (ctx.stack) { sys.error(stylize(ctx.stack, 'red')) }
|
73
77
|
}
|
74
78
|
};
|
75
79
|
|
76
|
-
['color', 'directive',
|
77
|
-
'keyword', 'variable',
|
78
|
-
'selector', 'quoted',
|
79
|
-
'call', 'url',
|
80
|
-
'mixin', 'comment',
|
81
|
-
'javascript', 'assignment'
|
80
|
+
['color', 'directive', 'operation', 'dimension',
|
81
|
+
'keyword', 'variable', 'ruleset', 'element',
|
82
|
+
'selector', 'quoted', 'expression', 'rule',
|
83
|
+
'call', 'url', 'alpha', 'import',
|
84
|
+
'mixin', 'comment', 'anonymous', 'value',
|
85
|
+
'javascript', 'assignment', 'condition', 'paren'
|
82
86
|
].forEach(function (n) {
|
83
87
|
require('./tree/' + n);
|
84
88
|
});
|
@@ -106,17 +110,16 @@ less.Parser.importer = function (file, paths, callback) {
|
|
106
110
|
paths: [path.dirname(pathname)].concat(paths),
|
107
111
|
filename: pathname
|
108
112
|
}).parse(data, function (e, root) {
|
109
|
-
|
110
|
-
callback(root);
|
113
|
+
callback(e, root, data);
|
111
114
|
});
|
112
115
|
});
|
113
116
|
} else {
|
114
|
-
|
115
|
-
process.exit(1);
|
117
|
+
callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
|
116
118
|
}
|
117
119
|
}
|
118
120
|
|
119
121
|
require('./functions');
|
122
|
+
require('./colors');
|
120
123
|
|
121
124
|
for (var k in less) { exports[k] = less[k] }
|
122
125
|
|
@@ -3,7 +3,8 @@ var less, tree;
|
|
3
3
|
if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") {
|
4
4
|
// Rhino
|
5
5
|
// Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88
|
6
|
-
less = {}
|
6
|
+
if (typeof(window) === 'undefined') { less = {} }
|
7
|
+
else { less = window.less = {} }
|
7
8
|
tree = less.tree = {};
|
8
9
|
less.mode = 'rhino';
|
9
10
|
} else if (typeof(window) === 'undefined') {
|
@@ -72,7 +73,9 @@ less.Parser = function Parser(env) {
|
|
72
73
|
paths: env && env.paths || [], // Search paths, when importing
|
73
74
|
queue: [], // Files which haven't been imported yet
|
74
75
|
files: {}, // Holds the imported parse trees
|
76
|
+
contents: {}, // Holds the imported file contents
|
75
77
|
mime: env && env.mime, // MIME type of .less files
|
78
|
+
error: null, // Error in parsing/evaluating an import
|
76
79
|
push: function (path, callback) {
|
77
80
|
var that = this;
|
78
81
|
this.queue.push(path);
|
@@ -80,11 +83,13 @@ less.Parser = function Parser(env) {
|
|
80
83
|
//
|
81
84
|
// Import a file asynchronously
|
82
85
|
//
|
83
|
-
less.Parser.importer(path, this.paths, function (root) {
|
86
|
+
less.Parser.importer(path, this.paths, function (e, root, contents) {
|
84
87
|
that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue
|
85
88
|
that.files[path] = root; // Store the root
|
89
|
+
that.contents[path] = contents;
|
86
90
|
|
87
|
-
|
91
|
+
if (e && !that.error) { that.error = e }
|
92
|
+
callback(e, root);
|
88
93
|
|
89
94
|
if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing
|
90
95
|
}, env);
|
@@ -158,6 +163,20 @@ less.Parser = function Parser(env) {
|
|
158
163
|
}
|
159
164
|
}
|
160
165
|
|
166
|
+
function expect(arg, msg) {
|
167
|
+
var result = $(arg);
|
168
|
+
if (! result) {
|
169
|
+
error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'"
|
170
|
+
: "unexpected token"));
|
171
|
+
} else {
|
172
|
+
return result;
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
function error(msg, type) {
|
177
|
+
throw { index: i, type: type || 'Syntax', message: msg };
|
178
|
+
}
|
179
|
+
|
161
180
|
// Same as $(), but don't change the state of the parser,
|
162
181
|
// just return the match.
|
163
182
|
function peek(tok) {
|
@@ -172,6 +191,46 @@ less.Parser = function Parser(env) {
|
|
172
191
|
}
|
173
192
|
}
|
174
193
|
|
194
|
+
function getInput(e, env) {
|
195
|
+
if (e.filename && env.filename && (e.filename !== env.filename)) {
|
196
|
+
return parser.imports.contents[e.filename];
|
197
|
+
} else {
|
198
|
+
return input;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
|
202
|
+
function getLocation(index, input) {
|
203
|
+
for (var n = index, column = -1;
|
204
|
+
n >= 0 && input.charAt(n) !== '\n';
|
205
|
+
n--) { column++ }
|
206
|
+
|
207
|
+
return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null,
|
208
|
+
column: column };
|
209
|
+
}
|
210
|
+
|
211
|
+
function LessError(e, env) {
|
212
|
+
var input = getInput(e, env),
|
213
|
+
loc = getLocation(e.index, input),
|
214
|
+
line = loc.line,
|
215
|
+
col = loc.column,
|
216
|
+
lines = input.split('\n');
|
217
|
+
|
218
|
+
this.type = e.type || 'Syntax';
|
219
|
+
this.message = e.message;
|
220
|
+
this.filename = e.filename || env.filename;
|
221
|
+
this.index = e.index;
|
222
|
+
this.line = typeof(line) === 'number' ? line + 1 : null;
|
223
|
+
this.callLine = e.call && (getLocation(e.call, input) + 1);
|
224
|
+
this.callExtract = lines[getLocation(e.call, input)];
|
225
|
+
this.stack = e.stack;
|
226
|
+
this.column = col;
|
227
|
+
this.extract = [
|
228
|
+
lines[line - 1],
|
229
|
+
lines[line],
|
230
|
+
lines[line + 1]
|
231
|
+
];
|
232
|
+
}
|
233
|
+
|
175
234
|
this.env = env = env || {};
|
176
235
|
|
177
236
|
// The optimization level dictates the thoroughness of the parser,
|
@@ -196,19 +255,18 @@ less.Parser = function Parser(env) {
|
|
196
255
|
var root, start, end, zone, line, lines, buff = [], c, error = null;
|
197
256
|
|
198
257
|
i = j = current = furthest = 0;
|
199
|
-
chunks = [];
|
200
258
|
input = str.replace(/\r\n/g, '\n');
|
201
259
|
|
202
260
|
// Split the input into chunks.
|
203
261
|
chunks = (function (chunks) {
|
204
262
|
var j = 0,
|
205
|
-
skip = /[^"'`\{\}\/\(\)]+/g,
|
263
|
+
skip = /[^"'`\{\}\/\(\)\\]+/g,
|
206
264
|
comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,
|
265
|
+
string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g,
|
207
266
|
level = 0,
|
208
267
|
match,
|
209
268
|
chunk = chunks[0],
|
210
|
-
inParam
|
211
|
-
inString;
|
269
|
+
inParam;
|
212
270
|
|
213
271
|
for (var i = 0, c, cc; i < input.length; i++) {
|
214
272
|
skip.lastIndex = i;
|
@@ -219,9 +277,17 @@ less.Parser = function Parser(env) {
|
|
219
277
|
}
|
220
278
|
}
|
221
279
|
c = input.charAt(i);
|
222
|
-
comment.lastIndex = i;
|
280
|
+
comment.lastIndex = string.lastIndex = i;
|
281
|
+
|
282
|
+
if (match = string.exec(input)) {
|
283
|
+
if (match.index === i) {
|
284
|
+
i += match[0].length;
|
285
|
+
chunk.push(match[0]);
|
286
|
+
c = input.charAt(i);
|
287
|
+
}
|
288
|
+
}
|
223
289
|
|
224
|
-
if (!
|
290
|
+
if (!inParam && c === '/') {
|
225
291
|
cc = input.charAt(i + 1);
|
226
292
|
if (cc === '/' || cc === '*') {
|
227
293
|
if (match = comment.exec(input)) {
|
@@ -234,34 +300,21 @@ less.Parser = function Parser(env) {
|
|
234
300
|
}
|
235
301
|
}
|
236
302
|
|
237
|
-
|
238
|
-
chunk.push(c);
|
239
|
-
|
240
|
-
chunk.push(c);
|
241
|
-
|
242
|
-
|
243
|
-
chunk.push(c);
|
244
|
-
inParam = true;
|
245
|
-
} else if (c === ')' && !inString && inParam) {
|
246
|
-
chunk.push(c);
|
247
|
-
inParam = false;
|
248
|
-
} else {
|
249
|
-
if (c === '"' || c === "'" || c === '`') {
|
250
|
-
if (! inString) {
|
251
|
-
inString = c;
|
252
|
-
} else {
|
253
|
-
inString = inString === c ? false : inString;
|
254
|
-
}
|
255
|
-
}
|
256
|
-
chunk.push(c);
|
303
|
+
switch (c) {
|
304
|
+
case '{': if (! inParam) { level ++; chunk.push(c); break }
|
305
|
+
case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break }
|
306
|
+
case '(': if (! inParam) { inParam = true; chunk.push(c); break }
|
307
|
+
case ')': if ( inParam) { inParam = false; chunk.push(c); break }
|
308
|
+
default: chunk.push(c);
|
257
309
|
}
|
258
310
|
}
|
259
311
|
if (level > 0) {
|
260
|
-
|
261
|
-
|
262
|
-
|
312
|
+
return callback(new(LessError)({
|
313
|
+
index: i,
|
314
|
+
type: 'Parse',
|
315
|
+
message: "missing closing `}`",
|
263
316
|
filename: env.filename
|
264
|
-
};
|
317
|
+
}, env));
|
265
318
|
}
|
266
319
|
|
267
320
|
return chunks.map(function (c) { return c.join('') });;
|
@@ -271,14 +324,18 @@ less.Parser = function Parser(env) {
|
|
271
324
|
// The whole syntax tree is held under a Ruleset node,
|
272
325
|
// with the `root` property set to true, so no `{}` are
|
273
326
|
// output. The callback is called when the input is parsed.
|
274
|
-
|
275
|
-
|
327
|
+
try {
|
328
|
+
root = new(tree.Ruleset)([], $(this.parsers.primary));
|
329
|
+
root.root = true;
|
330
|
+
} catch (e) {
|
331
|
+
return callback(new(LessError)(e, env));
|
332
|
+
}
|
276
333
|
|
277
334
|
root.toCSS = (function (evaluate) {
|
278
335
|
var line, lines, column;
|
279
336
|
|
280
337
|
return function (options, variables) {
|
281
|
-
var frames = [];
|
338
|
+
var frames = [], importError;
|
282
339
|
|
283
340
|
options = options || {};
|
284
341
|
//
|
@@ -313,39 +370,21 @@ less.Parser = function Parser(env) {
|
|
313
370
|
var css = evaluate.call(this, { frames: frames })
|
314
371
|
.toCSS([], { compress: options.compress || false });
|
315
372
|
} catch (e) {
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
throw {
|
324
|
-
type: e.type,
|
325
|
-
message: e.message,
|
326
|
-
filename: env.filename,
|
327
|
-
index: e.index,
|
328
|
-
line: typeof(line) === 'number' ? line + 1 : null,
|
329
|
-
callLine: e.call && (getLine(e.call) + 1),
|
330
|
-
callExtract: lines[getLine(e.call)],
|
331
|
-
stack: e.stack,
|
332
|
-
column: column,
|
333
|
-
extract: [
|
334
|
-
lines[line - 1],
|
335
|
-
lines[line],
|
336
|
-
lines[line + 1]
|
337
|
-
]
|
338
|
-
};
|
373
|
+
throw new(LessError)(e, env);
|
374
|
+
}
|
375
|
+
|
376
|
+
if ((importError = parser.imports.error)) { // Check if there was an error during importing
|
377
|
+
if (importError instanceof LessError) throw importError;
|
378
|
+
else throw new(LessError)(importError, env);
|
339
379
|
}
|
340
|
-
|
380
|
+
|
381
|
+
if (options.yuicompress && less.mode === 'node') {
|
382
|
+
return require('./cssmin').compressor.cssmin(css);
|
383
|
+
} else if (options.compress) {
|
341
384
|
return css.replace(/(\s)+/g, "$1");
|
342
385
|
} else {
|
343
386
|
return css;
|
344
387
|
}
|
345
|
-
|
346
|
-
function getLine(index) {
|
347
|
-
return index ? (input.slice(0, index).match(/\n/g) || "").length : null;
|
348
|
-
}
|
349
388
|
};
|
350
389
|
})(root.eval);
|
351
390
|
|
@@ -365,7 +404,7 @@ less.Parser = function Parser(env) {
|
|
365
404
|
for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ }
|
366
405
|
|
367
406
|
error = {
|
368
|
-
|
407
|
+
type: "Parse",
|
369
408
|
message: "Syntax Error on line " + line,
|
370
409
|
index: i,
|
371
410
|
filename: env.filename,
|
@@ -486,7 +525,15 @@ less.Parser = function Parser(env) {
|
|
486
525
|
//
|
487
526
|
keyword: function () {
|
488
527
|
var k;
|
489
|
-
|
528
|
+
|
529
|
+
if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) {
|
530
|
+
if (tree.colors.hasOwnProperty(k)) {
|
531
|
+
// detect named color
|
532
|
+
return new(tree.Color)(tree.colors[k].slice(1));
|
533
|
+
} else {
|
534
|
+
return new(tree.Keyword)(k);
|
535
|
+
}
|
536
|
+
}
|
490
537
|
},
|
491
538
|
|
492
539
|
//
|
@@ -517,7 +564,7 @@ less.Parser = function Parser(env) {
|
|
517
564
|
|
518
565
|
if (! $(')')) return;
|
519
566
|
|
520
|
-
if (name) { return new(tree.Call)(name, args, index) }
|
567
|
+
if (name) { return new(tree.Call)(name, args, index, env.filename) }
|
521
568
|
},
|
522
569
|
arguments: function () {
|
523
570
|
var args = [], arg;
|
@@ -560,7 +607,8 @@ less.Parser = function Parser(env) {
|
|
560
607
|
if (input.charAt(i) !== 'u' || !$(/^url\(/)) return;
|
561
608
|
value = $(this.entities.quoted) || $(this.entities.variable) ||
|
562
609
|
$(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || "";
|
563
|
-
|
610
|
+
|
611
|
+
expect(')');
|
564
612
|
|
565
613
|
return new(tree.URL)((value.value || value.data || value instanceof tree.Variable)
|
566
614
|
? value : new(tree.Anonymous)(value), imports.paths);
|
@@ -592,7 +640,7 @@ less.Parser = function Parser(env) {
|
|
592
640
|
var name, index = i;
|
593
641
|
|
594
642
|
if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) {
|
595
|
-
return new(tree.Variable)(name, index);
|
643
|
+
return new(tree.Variable)(name, index, env.filename);
|
596
644
|
}
|
597
645
|
},
|
598
646
|
|
@@ -620,7 +668,7 @@ less.Parser = function Parser(env) {
|
|
620
668
|
var value, c = input.charCodeAt(i);
|
621
669
|
if ((c > 57 || c < 45) || c === 47) return;
|
622
670
|
|
623
|
-
if (value = $(/^(-?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) {
|
671
|
+
if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) {
|
624
672
|
return new(tree.Dimension)(value[1], value[2]);
|
625
673
|
}
|
626
674
|
},
|
@@ -688,7 +736,7 @@ less.Parser = function Parser(env) {
|
|
688
736
|
// selector for now.
|
689
737
|
//
|
690
738
|
call: function () {
|
691
|
-
var elements = [], e, c, args, index = i, s = input.charAt(i);
|
739
|
+
var elements = [], e, c, args, index = i, s = input.charAt(i), important = false;
|
692
740
|
|
693
741
|
if (s !== '.' && s !== '#') { return }
|
694
742
|
|
@@ -698,8 +746,12 @@ less.Parser = function Parser(env) {
|
|
698
746
|
}
|
699
747
|
$('(') && (args = $(this.entities.arguments)) && $(')');
|
700
748
|
|
749
|
+
if ($(this.important)) {
|
750
|
+
important = true;
|
751
|
+
}
|
752
|
+
|
701
753
|
if (elements.length > 0 && ($(';') || peek('}'))) {
|
702
|
-
return new(tree.mixin.Call)(elements, args, index);
|
754
|
+
return new(tree.mixin.Call)(elements, args, index, env.filename, important);
|
703
755
|
}
|
704
756
|
},
|
705
757
|
|
@@ -723,11 +775,12 @@ less.Parser = function Parser(env) {
|
|
723
775
|
// the `{...}` block.
|
724
776
|
//
|
725
777
|
definition: function () {
|
726
|
-
var name, params = [], match, ruleset, param, value;
|
727
|
-
|
778
|
+
var name, params = [], match, ruleset, param, value, cond;
|
728
779
|
if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
|
729
780
|
peek(/^[^{]*(;|})/)) return;
|
730
781
|
|
782
|
+
save();
|
783
|
+
|
731
784
|
if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) {
|
732
785
|
name = match[1];
|
733
786
|
|
@@ -736,11 +789,8 @@ less.Parser = function Parser(env) {
|
|
736
789
|
// Variable
|
737
790
|
if (param instanceof tree.Variable) {
|
738
791
|
if ($(':')) {
|
739
|
-
|
740
|
-
|
741
|
-
} else {
|
742
|
-
throw new(Error)("Expected value");
|
743
|
-
}
|
792
|
+
value = expect(this.expression, 'expected expression');
|
793
|
+
params.push({ name: param.name, value: value });
|
744
794
|
} else {
|
745
795
|
params.push({ name: param.name });
|
746
796
|
}
|
@@ -749,12 +799,18 @@ less.Parser = function Parser(env) {
|
|
749
799
|
}
|
750
800
|
if (! $(',')) { break }
|
751
801
|
}
|
752
|
-
|
802
|
+
expect(')');
|
803
|
+
|
804
|
+
if ($(/^when/)) { // Guard
|
805
|
+
cond = expect(this.conditions, 'expected condition');
|
806
|
+
}
|
753
807
|
|
754
808
|
ruleset = $(this.block);
|
755
809
|
|
756
810
|
if (ruleset) {
|
757
|
-
return new(tree.mixin.Definition)(name, params, ruleset);
|
811
|
+
return new(tree.mixin.Definition)(name, params, ruleset, cond);
|
812
|
+
} else {
|
813
|
+
restore();
|
758
814
|
}
|
759
815
|
}
|
760
816
|
}
|
@@ -789,7 +845,7 @@ less.Parser = function Parser(env) {
|
|
789
845
|
|
790
846
|
if (! $(/^\(opacity=/i)) return;
|
791
847
|
if (value = $(/^\d+/) || $(this.entities.variable)) {
|
792
|
-
|
848
|
+
expect(')');
|
793
849
|
return new(tree.Alpha)(value);
|
794
850
|
}
|
795
851
|
},
|
@@ -807,12 +863,16 @@ less.Parser = function Parser(env) {
|
|
807
863
|
// and an element name, such as a tag a class, or `*`.
|
808
864
|
//
|
809
865
|
element: function () {
|
810
|
-
var e, t, c;
|
866
|
+
var e, t, c, v;
|
811
867
|
|
812
868
|
c = $(this.combinator);
|
813
869
|
e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) ||
|
814
870
|
$('*') || $(this.attribute) || $(/^\([^)@]+\)/);
|
815
871
|
|
872
|
+
if (! e) {
|
873
|
+
$('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v));
|
874
|
+
}
|
875
|
+
|
816
876
|
if (e) { return new(tree.Element)(c, e, i) }
|
817
877
|
|
818
878
|
if (c.value && c.value.charAt(0) === '&') {
|
@@ -965,11 +1025,60 @@ less.Parser = function Parser(env) {
|
|
965
1025
|
// stored in `import`, which we pass to the Import constructor.
|
966
1026
|
//
|
967
1027
|
"import": function () {
|
968
|
-
var path;
|
1028
|
+
var path, features, index = i;
|
969
1029
|
if ($(/^@import\s+/) &&
|
970
|
-
(path = $(this.entities.quoted) || $(this.entities.url))
|
971
|
-
$(
|
972
|
-
|
1030
|
+
(path = $(this.entities.quoted) || $(this.entities.url))) {
|
1031
|
+
features = $(this.mediaFeatures);
|
1032
|
+
if ($(';')) {
|
1033
|
+
return new(tree.Import)(path, imports, features, index);
|
1034
|
+
}
|
1035
|
+
}
|
1036
|
+
},
|
1037
|
+
|
1038
|
+
mediaFeature: function () {
|
1039
|
+
var nodes = [];
|
1040
|
+
|
1041
|
+
do {
|
1042
|
+
if (e = $(this.entities.keyword)) {
|
1043
|
+
nodes.push(e);
|
1044
|
+
} else if ($('(')) {
|
1045
|
+
p = $(this.property);
|
1046
|
+
e = $(this.entity);
|
1047
|
+
if ($(')')) {
|
1048
|
+
if (p && e) {
|
1049
|
+
nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true)));
|
1050
|
+
} else if (e) {
|
1051
|
+
nodes.push(new(tree.Paren)(e));
|
1052
|
+
} else {
|
1053
|
+
return null;
|
1054
|
+
}
|
1055
|
+
} else { return null }
|
1056
|
+
}
|
1057
|
+
} while (e);
|
1058
|
+
|
1059
|
+
if (nodes.length > 0) {
|
1060
|
+
return new(tree.Expression)(nodes);
|
1061
|
+
}
|
1062
|
+
},
|
1063
|
+
|
1064
|
+
mediaFeatures: function () {
|
1065
|
+
var f, features = [];
|
1066
|
+
while (f = $(this.mediaFeature)) {
|
1067
|
+
features.push(f);
|
1068
|
+
if (! $(',')) { break }
|
1069
|
+
}
|
1070
|
+
return features.length > 0 ? features : null;
|
1071
|
+
},
|
1072
|
+
|
1073
|
+
media: function () {
|
1074
|
+
var features;
|
1075
|
+
|
1076
|
+
if ($(/^@media/)) {
|
1077
|
+
features = $(this.mediaFeatures);
|
1078
|
+
|
1079
|
+
if (rules = $(this.block)) {
|
1080
|
+
return new(tree.Directive)('@media', rules, features);
|
1081
|
+
}
|
973
1082
|
}
|
974
1083
|
},
|
975
1084
|
|
@@ -979,13 +1088,13 @@ less.Parser = function Parser(env) {
|
|
979
1088
|
// @charset "utf-8";
|
980
1089
|
//
|
981
1090
|
directive: function () {
|
982
|
-
var name, value, rules, types;
|
1091
|
+
var name, value, rules, types, e, nodes;
|
983
1092
|
|
984
1093
|
if (input.charAt(i) !== '@') return;
|
985
1094
|
|
986
|
-
if (value = $(this['import'])) {
|
1095
|
+
if (value = $(this['import']) || $(this.media)) {
|
987
1096
|
return value;
|
988
|
-
} else if (name = $(/^@
|
1097
|
+
} else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) {
|
989
1098
|
types = ($(/^[^{]+/) || '').trim();
|
990
1099
|
if (rules = $(this.block)) {
|
991
1100
|
return new(tree.Directive)(name + " " + types, rules);
|
@@ -1052,7 +1161,7 @@ less.Parser = function Parser(env) {
|
|
1052
1161
|
multiplication: function () {
|
1053
1162
|
var m, a, op, operation;
|
1054
1163
|
if (m = $(this.operand)) {
|
1055
|
-
while ((op = ($('/') || $('*'))) && (a = $(this.operand))) {
|
1164
|
+
while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) {
|
1056
1165
|
operation = new(tree.Operation)(op, [operation || m, a]);
|
1057
1166
|
}
|
1058
1167
|
return operation || m;
|
@@ -1068,6 +1177,35 @@ less.Parser = function Parser(env) {
|
|
1068
1177
|
return operation || m;
|
1069
1178
|
}
|
1070
1179
|
},
|
1180
|
+
conditions: function () {
|
1181
|
+
var a, b, index = i, condition;
|
1182
|
+
|
1183
|
+
if (a = $(this.condition)) {
|
1184
|
+
while ($(',') && (b = $(this.condition))) {
|
1185
|
+
condition = new(tree.Condition)('or', condition || a, b, index);
|
1186
|
+
}
|
1187
|
+
return condition || a;
|
1188
|
+
}
|
1189
|
+
},
|
1190
|
+
condition: function () {
|
1191
|
+
var a, b, c, op, index = i, negate = false;
|
1192
|
+
|
1193
|
+
if ($(/^not/)) { negate = true }
|
1194
|
+
expect('(');
|
1195
|
+
if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) {
|
1196
|
+
if (op = $(/^(?:>=|=<|[<=>])/)) {
|
1197
|
+
if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) {
|
1198
|
+
c = new(tree.Condition)(op, a, b, index, negate);
|
1199
|
+
} else {
|
1200
|
+
error('expected expression');
|
1201
|
+
}
|
1202
|
+
} else {
|
1203
|
+
c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate);
|
1204
|
+
}
|
1205
|
+
expect(')');
|
1206
|
+
return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c;
|
1207
|
+
}
|
1208
|
+
},
|
1071
1209
|
|
1072
1210
|
//
|
1073
1211
|
// An operand is anything that can be part of an operation,
|
@@ -1117,7 +1255,7 @@ if (less.mode === 'browser' || less.mode === 'rhino') {
|
|
1117
1255
|
// Used by `@import` directives
|
1118
1256
|
//
|
1119
1257
|
less.Parser.importer = function (path, paths, callback, env) {
|
1120
|
-
if (
|
1258
|
+
if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) {
|
1121
1259
|
path = paths[0] + path;
|
1122
1260
|
}
|
1123
1261
|
// We pass `true` as 3rd argument, to force the reload of the import.
|