less 2.0.8 → 2.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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.
|