less 1.2.2 → 1.3.3
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/.npmignore +1 -0
- package/CHANGELOG.md +118 -0
- package/CONTRIBUTING.md +50 -0
- package/Makefile +14 -2
- package/benchmark/benchmark.less +11 -11
- package/benchmark/less-benchmark.js +1 -1
- package/bin/lessc +77 -21
- package/build/amd.js +6 -0
- package/build/ecma-5.js +120 -0
- package/build/header.js +7 -0
- package/build/require-rhino.js +7 -0
- package/build/require.js +7 -0
- package/lib/less/browser.js +192 -53
- package/lib/less/colors.js +1 -0
- package/lib/less/functions.js +159 -10
- package/lib/less/index.js +125 -56
- package/lib/less/lessc_helper.js +62 -0
- package/lib/less/parser.js +391 -154
- package/lib/less/rhino.js +84 -23
- package/lib/less/tree/anonymous.js +15 -1
- package/lib/less/tree/assignment.js +3 -1
- package/lib/less/tree/call.js +12 -6
- package/lib/less/tree/color.js +10 -0
- package/lib/less/tree/dimension.js +3 -1
- package/lib/less/tree/directive.js +10 -10
- package/lib/less/tree/element.js +8 -7
- package/lib/less/tree/import.js +17 -14
- package/lib/less/tree/media.js +121 -0
- package/lib/less/tree/mixin.js +133 -45
- package/lib/less/tree/operation.js +5 -0
- package/lib/less/tree/quoted.js +15 -1
- package/lib/less/tree/ratio.js +13 -0
- package/lib/less/tree/rule.js +7 -0
- package/lib/less/tree/ruleset.js +236 -37
- package/lib/less/tree/selector.js +21 -11
- package/lib/less/tree/unicode-descriptor.js +13 -0
- package/lib/less/tree/url.js +16 -14
- package/lib/less/tree/variable.js +13 -1
- package/lib/less/tree.js +28 -0
- package/package.json +13 -3
- package/test/browser/common.js +74 -0
- package/test/browser/css/relative-urls/urls.css +36 -0
- package/test/browser/css/rootpath/urls.css +36 -0
- package/test/browser/css/rootpath-relative/urls.css +36 -0
- package/test/browser/css/urls.css +36 -0
- package/test/browser/jasmine-html.js +681 -0
- package/test/browser/jasmine.css +82 -0
- package/test/browser/jasmine.js +2600 -0
- package/test/browser/less/imports/urls.less +4 -0
- package/test/browser/less/imports/urls2.less +4 -0
- package/test/browser/less/relative-urls/urls.less +33 -0
- package/test/browser/less/rootpath/urls.less +33 -0
- package/test/browser/less/rootpath-relative/urls.less +33 -0
- package/test/browser/less/urls.less +33 -0
- package/test/browser/phantom-runner.js +139 -0
- package/test/browser/runner-browser.js +3 -0
- package/test/browser/runner-main.js +15 -0
- package/test/browser/runner-relative-urls.js +4 -0
- package/test/browser/runner-rootpath-relative.js +5 -0
- package/test/browser/runner-rootpath.js +4 -0
- package/test/browser/template.htm +10 -0
- package/test/browser-test-prepare.js +29 -0
- package/test/css/charsets.css +1 -0
- package/test/css/colors.css +22 -0
- package/test/css/comments.css +7 -0
- package/test/css/css-3.css +57 -2
- package/test/css/css-escapes.css +4 -0
- package/test/css/css.css +11 -11
- package/test/css/debug/linenumbers-all.css +43 -0
- package/test/css/debug/linenumbers-comments.css +35 -0
- package/test/css/debug/linenumbers-mediaquery.css +35 -0
- package/test/css/functions.css +59 -2
- package/test/css/ie-filters.css +7 -3
- package/test/css/import-once.css +3 -0
- package/test/css/import.css +7 -9
- package/test/css/javascript.css +3 -2
- package/test/css/media.css +168 -0
- package/test/css/mixins-args.css +35 -4
- package/test/css/mixins-guards.css +13 -0
- package/test/css/mixins-important.css +21 -0
- package/test/css/mixins-named-args.css +27 -0
- package/test/css/mixins-pattern.css +4 -6
- package/test/css/mixins.css +50 -0
- package/test/css/scope.css +20 -0
- package/test/css/selectors.css +76 -0
- package/test/css/static-urls/urls.css +42 -0
- package/test/css/strings.css +2 -2
- package/test/css/urls.css +42 -0
- package/test/css/variables.css +0 -1
- package/test/css/whitespace.css +4 -0
- package/test/less/charsets.less +3 -0
- package/test/less/colors.less +27 -0
- package/test/less/comments.less +12 -0
- package/test/less/css-3.less +54 -6
- package/test/less/css-escapes.less +6 -1
- package/test/less/css.less +14 -12
- package/test/less/debug/import/test.less +25 -0
- package/test/less/debug/linenumbers.less +23 -0
- package/test/less/errors/bad-variable-declaration1.less +1 -0
- package/test/less/errors/bad-variable-declaration1.txt +2 -0
- package/test/less/errors/comment-in-selector.less +1 -0
- package/test/less/errors/comment-in-selector.txt +2 -0
- package/test/less/errors/import-missing.less +1 -0
- package/test/less/errors/import-missing.txt +3 -0
- package/test/less/errors/import-no-semi.less +1 -0
- package/test/less/errors/import-no-semi.txt +2 -0
- package/test/less/errors/import-subfolder1.less +1 -0
- package/test/less/errors/import-subfolder1.txt +3 -0
- package/test/less/errors/import-subfolder2.less +1 -0
- package/test/less/errors/import-subfolder2.txt +2 -0
- package/test/less/errors/imports/import-subfolder1.less +1 -0
- package/test/less/errors/imports/import-subfolder2.less +1 -0
- package/test/less/errors/imports/import-test.less +4 -0
- package/test/less/errors/imports/subfolder/mixin-not-defined.less +1 -0
- package/test/less/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
- package/test/less/errors/javascript-error.less +3 -0
- package/test/less/errors/javascript-error.txt +4 -0
- package/test/less/errors/mixed-mixin-definition-args-1.less +6 -0
- package/test/less/errors/mixed-mixin-definition-args-1.txt +4 -0
- package/test/less/errors/mixed-mixin-definition-args-2.less +6 -0
- package/test/less/errors/mixed-mixin-definition-args-2.txt +4 -0
- package/test/less/errors/mixin-not-defined.less +11 -0
- package/test/less/errors/mixin-not-defined.txt +3 -0
- package/test/less/errors/mixin-not-matched.less +6 -0
- package/test/less/errors/mixin-not-matched.txt +3 -0
- package/test/less/errors/mixin-not-matched2.less +6 -0
- package/test/less/errors/mixin-not-matched2.txt +3 -0
- package/test/less/errors/parse-error-curly-bracket.less +1 -0
- package/test/less/errors/parse-error-curly-bracket.txt +2 -0
- package/test/less/errors/parse-error-missing-bracket.less +2 -0
- package/test/less/errors/parse-error-missing-bracket.txt +2 -0
- package/test/less/errors/parse-error-with-import.less +13 -0
- package/test/less/errors/parse-error-with-import.txt +4 -0
- package/test/less/errors/property-ie5-hack.less +3 -0
- package/test/less/errors/property-ie5-hack.txt +4 -0
- package/test/less/errors/recursive-variable.less +1 -0
- package/test/less/errors/recursive-variable.txt +2 -0
- package/test/less/functions.less +64 -2
- package/test/less/ie-filters.less +7 -0
- package/test/less/import/deeper/import-once-test-a.less +1 -0
- package/test/less/import/import-and-relative-paths-test.less +6 -0
- package/test/less/import/import-charset-test.less +1 -0
- package/test/less/import/import-once-test-c.less +6 -0
- package/test/less/import/import-test-a.less +1 -0
- package/test/less/import/import-test-c.less +0 -1
- package/test/less/import/imports/font.less +8 -0
- package/test/less/import/imports/logo.less +5 -0
- package/test/less/import/urls.less +1 -0
- package/test/less/import-once.less +4 -0
- package/test/less/import.less +2 -1
- package/test/less/javascript.less +4 -2
- package/test/less/media.less +169 -1
- package/test/less/mixins-args.less +54 -11
- package/test/less/mixins-guards.less +30 -0
- package/test/less/mixins-important.less +4 -0
- package/test/less/mixins-named-args.less +36 -0
- package/test/less/mixins-pattern.less +3 -0
- package/test/less/mixins.less +47 -0
- package/test/less/scope.less +48 -1
- package/test/less/selectors.less +88 -0
- package/test/less/static-urls/urls.less +33 -0
- package/test/less/strings.less +1 -1
- package/test/less/urls.less +33 -0
- package/test/less/variables.less +0 -1
- package/test/less/whitespace.less +7 -0
- package/test/less-test.js +145 -36
- package/bench.css +0 -5943
- package/benchmark/b1.less +0 -3980
- package/dist/less-1.1.0.js +0 -2695
- package/dist/less-1.1.0.min.js +0 -16
- package/dist/less-1.1.1.js +0 -2710
- package/dist/less-1.1.1.min.js +0 -16
- package/dist/less-1.1.2.js +0 -2712
- package/dist/less-1.1.2.min.js +0 -16
- package/dist/less-1.1.3.js +0 -2721
- package/dist/less-1.1.3.min.js +0 -16
- package/dist/less-1.1.4.js +0 -2769
- package/dist/less-1.1.4.min.js +0 -16
- package/dist/less-1.1.5.js +0 -2805
- package/dist/less-1.1.5.min.js +0 -9
- package/dist/less-1.1.6.js +0 -3004
- package/dist/less-1.1.6.min.js +0 -9
- package/dist/less-1.2.0.js +0 -3293
- package/dist/less-1.2.0.min.js +0 -9
- package/dist/less-1.2.1.js +0 -3318
- package/dist/less-1.2.1.min.js +0 -9
- package/dist/less-1.2.2.js +0 -3337
- package/dist/less-1.2.2.min.js +0 -9
- package/dist/less-rhino-1.1.3.js +0 -2460
- package/dist/less-rhino-1.1.5.js +0 -2481
- package/foo.less +0 -2
- package/lib/less/cssmin.js +0 -355
- package/test/html/index.html +0 -10
- package/test/html/less.js +0 -3333
- package/test/html/lib.less +0 -2
- package/test/html/styles.less +0 -8
- package/x.less +0 -4
package/lib/less/parser.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var less, tree;
|
|
1
|
+
var less, tree, charset;
|
|
2
2
|
|
|
3
3
|
if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") {
|
|
4
4
|
// Rhino
|
|
@@ -65,17 +65,25 @@ less.Parser = function Parser(env) {
|
|
|
65
65
|
|
|
66
66
|
var that = this;
|
|
67
67
|
|
|
68
|
+
// Top parser on an import tree must be sure there is one "env"
|
|
69
|
+
// which will then be passed arround by reference.
|
|
70
|
+
var env = env || { };
|
|
71
|
+
// env.contents and files must be passed arround with top env
|
|
72
|
+
if (!env.contents) { env.contents = {}; }
|
|
73
|
+
env.rootpath = env.rootpath || ''; // env.rootpath must be initialized to '' if not provided
|
|
74
|
+
if (!env.files) { env.files = {}; }
|
|
75
|
+
|
|
68
76
|
// This function is called after all files
|
|
69
77
|
// have been imported through `@import`.
|
|
70
78
|
var finish = function () {};
|
|
71
79
|
|
|
72
80
|
var imports = this.imports = {
|
|
73
|
-
paths: env
|
|
74
|
-
queue: [],
|
|
75
|
-
files:
|
|
76
|
-
contents:
|
|
77
|
-
mime: env
|
|
78
|
-
error: null,
|
|
81
|
+
paths: env.paths || [], // Search paths, when importing
|
|
82
|
+
queue: [], // Files which haven't been imported yet
|
|
83
|
+
files: env.files, // Holds the imported parse trees
|
|
84
|
+
contents: env.contents, // Holds the imported file contents
|
|
85
|
+
mime: env.mime, // MIME type of .less files
|
|
86
|
+
error: null, // Error in parsing/evaluating an import
|
|
79
87
|
push: function (path, callback) {
|
|
80
88
|
var that = this;
|
|
81
89
|
this.queue.push(path);
|
|
@@ -83,15 +91,18 @@ less.Parser = function Parser(env) {
|
|
|
83
91
|
//
|
|
84
92
|
// Import a file asynchronously
|
|
85
93
|
//
|
|
86
|
-
less.Parser.importer(path, this.paths, function (e, root,
|
|
94
|
+
less.Parser.importer(path, this.paths, function (e, root, fullPath) {
|
|
87
95
|
that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue
|
|
88
|
-
|
|
89
|
-
|
|
96
|
+
|
|
97
|
+
var imported = fullPath in that.files;
|
|
98
|
+
|
|
99
|
+
that.files[fullPath] = root; // Store the root
|
|
90
100
|
|
|
91
101
|
if (e && !that.error) { that.error = e }
|
|
92
|
-
callback(e, root);
|
|
93
102
|
|
|
94
|
-
|
|
103
|
+
callback(e, root, imported);
|
|
104
|
+
|
|
105
|
+
if (that.queue.length === 0) { finish(that.error) } // Call `finish` if we're done importing
|
|
95
106
|
}, env);
|
|
96
107
|
}
|
|
97
108
|
};
|
|
@@ -105,11 +116,16 @@ less.Parser = function Parser(env) {
|
|
|
105
116
|
current = i;
|
|
106
117
|
}
|
|
107
118
|
}
|
|
119
|
+
function isWhitespace(c) {
|
|
120
|
+
// Could change to \s?
|
|
121
|
+
var code = c.charCodeAt(0);
|
|
122
|
+
return code === 32 || code === 10 || code === 9;
|
|
123
|
+
}
|
|
108
124
|
//
|
|
109
125
|
// Parse from a token, regexp or string, and move forward if match
|
|
110
126
|
//
|
|
111
127
|
function $(tok) {
|
|
112
|
-
var match, args, length,
|
|
128
|
+
var match, args, length, index, k;
|
|
113
129
|
|
|
114
130
|
//
|
|
115
131
|
// Non-terminal
|
|
@@ -142,18 +158,7 @@ less.Parser = function Parser(env) {
|
|
|
142
158
|
// grammar is mostly white-space insensitive.
|
|
143
159
|
//
|
|
144
160
|
if (match) {
|
|
145
|
-
|
|
146
|
-
endIndex = i + chunks[j].length - length;
|
|
147
|
-
|
|
148
|
-
while (i < endIndex) {
|
|
149
|
-
c = input.charCodeAt(i);
|
|
150
|
-
if (! (c === 32 || c === 10 || c === 9)) { break }
|
|
151
|
-
i++;
|
|
152
|
-
}
|
|
153
|
-
chunks[j] = chunks[j].slice(length + (i - mem));
|
|
154
|
-
current = i;
|
|
155
|
-
|
|
156
|
-
if (chunks[j].length === 0 && j < chunks.length - 1) { j++ }
|
|
161
|
+
skipWhitespace(length);
|
|
157
162
|
|
|
158
163
|
if(typeof(match) === 'string') {
|
|
159
164
|
return match;
|
|
@@ -163,6 +168,23 @@ less.Parser = function Parser(env) {
|
|
|
163
168
|
}
|
|
164
169
|
}
|
|
165
170
|
|
|
171
|
+
function skipWhitespace(length) {
|
|
172
|
+
var oldi = i, oldj = j,
|
|
173
|
+
endIndex = i + chunks[j].length,
|
|
174
|
+
mem = i += length;
|
|
175
|
+
|
|
176
|
+
while (i < endIndex) {
|
|
177
|
+
if (! isWhitespace(input.charAt(i))) { break }
|
|
178
|
+
i++;
|
|
179
|
+
}
|
|
180
|
+
chunks[j] = chunks[j].slice(length + (i - mem));
|
|
181
|
+
current = i;
|
|
182
|
+
|
|
183
|
+
if (chunks[j].length === 0 && j < chunks.length - 1) { j++ }
|
|
184
|
+
|
|
185
|
+
return oldi !== i || oldj !== j;
|
|
186
|
+
}
|
|
187
|
+
|
|
166
188
|
function expect(arg, msg) {
|
|
167
189
|
var result = $(arg);
|
|
168
190
|
if (! result) {
|
|
@@ -174,7 +196,10 @@ less.Parser = function Parser(env) {
|
|
|
174
196
|
}
|
|
175
197
|
|
|
176
198
|
function error(msg, type) {
|
|
177
|
-
|
|
199
|
+
var e = new Error(msg);
|
|
200
|
+
e.index = i;
|
|
201
|
+
e.type = type || 'Syntax';
|
|
202
|
+
throw e;
|
|
178
203
|
}
|
|
179
204
|
|
|
180
205
|
// Same as $(), but don't change the state of the parser,
|
|
@@ -191,17 +216,9 @@ less.Parser = function Parser(env) {
|
|
|
191
216
|
}
|
|
192
217
|
}
|
|
193
218
|
|
|
194
|
-
function basename(pathname) {
|
|
195
|
-
if (less.mode === 'node') {
|
|
196
|
-
return require('path').basename(pathname);
|
|
197
|
-
} else {
|
|
198
|
-
return pathname.match(/[^\/]+$/)[0];
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
219
|
function getInput(e, env) {
|
|
203
220
|
if (e.filename && env.filename && (e.filename !== env.filename)) {
|
|
204
|
-
return parser.imports.contents[
|
|
221
|
+
return parser.imports.contents[e.filename];
|
|
205
222
|
} else {
|
|
206
223
|
return input;
|
|
207
224
|
}
|
|
@@ -216,6 +233,20 @@ less.Parser = function Parser(env) {
|
|
|
216
233
|
column: column };
|
|
217
234
|
}
|
|
218
235
|
|
|
236
|
+
function getFileName(e) {
|
|
237
|
+
if(less.mode === 'browser' || less.mode === 'rhino')
|
|
238
|
+
return e.filename;
|
|
239
|
+
else
|
|
240
|
+
return require('path').resolve(e.filename);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function getDebugInfo(index, inputStream, e) {
|
|
244
|
+
return {
|
|
245
|
+
lineNumber: getLocation(index, inputStream).line + 1,
|
|
246
|
+
fileName: getFileName(e)
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
219
250
|
function LessError(e, env) {
|
|
220
251
|
var input = getInput(e, env),
|
|
221
252
|
loc = getLocation(e.index, input),
|
|
@@ -228,8 +259,8 @@ less.Parser = function Parser(env) {
|
|
|
228
259
|
this.filename = e.filename || env.filename;
|
|
229
260
|
this.index = e.index;
|
|
230
261
|
this.line = typeof(line) === 'number' ? line + 1 : null;
|
|
231
|
-
this.callLine = e.call && (getLocation(e.call, input) + 1);
|
|
232
|
-
this.callExtract = lines[getLocation(e.call, input)];
|
|
262
|
+
this.callLine = e.call && (getLocation(e.call, input).line + 1);
|
|
263
|
+
this.callExtract = lines[getLocation(e.call, input).line];
|
|
233
264
|
this.stack = e.stack;
|
|
234
265
|
this.column = col;
|
|
235
266
|
this.extract = [
|
|
@@ -265,18 +296,21 @@ less.Parser = function Parser(env) {
|
|
|
265
296
|
i = j = current = furthest = 0;
|
|
266
297
|
input = str.replace(/\r\n/g, '\n');
|
|
267
298
|
|
|
299
|
+
// Remove potential UTF Byte Order Mark
|
|
300
|
+
input = input.replace(/^\uFEFF/, '');
|
|
301
|
+
|
|
268
302
|
// Split the input into chunks.
|
|
269
303
|
chunks = (function (chunks) {
|
|
270
304
|
var j = 0,
|
|
271
|
-
skip = /[^"'`\{\}\/\(\)\\]+/g,
|
|
305
|
+
skip = /(?:@\{[\w-]+\}|[^"'`\{\}\/\(\)\\])+/g,
|
|
272
306
|
comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g,
|
|
273
|
-
string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[
|
|
307
|
+
string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`]|\\.)*)`/g,
|
|
274
308
|
level = 0,
|
|
275
309
|
match,
|
|
276
310
|
chunk = chunks[0],
|
|
277
311
|
inParam;
|
|
278
312
|
|
|
279
|
-
for (var i = 0, c, cc; i < input.length;
|
|
313
|
+
for (var i = 0, c, cc; i < input.length;) {
|
|
280
314
|
skip.lastIndex = i;
|
|
281
315
|
if (match = skip.exec(input)) {
|
|
282
316
|
if (match.index === i) {
|
|
@@ -291,7 +325,7 @@ less.Parser = function Parser(env) {
|
|
|
291
325
|
if (match.index === i) {
|
|
292
326
|
i += match[0].length;
|
|
293
327
|
chunk.push(match[0]);
|
|
294
|
-
|
|
328
|
+
continue;
|
|
295
329
|
}
|
|
296
330
|
}
|
|
297
331
|
|
|
@@ -302,12 +336,12 @@ less.Parser = function Parser(env) {
|
|
|
302
336
|
if (match.index === i) {
|
|
303
337
|
i += match[0].length;
|
|
304
338
|
chunk.push(match[0]);
|
|
305
|
-
|
|
339
|
+
continue;
|
|
306
340
|
}
|
|
307
341
|
}
|
|
308
342
|
}
|
|
309
343
|
}
|
|
310
|
-
|
|
344
|
+
|
|
311
345
|
switch (c) {
|
|
312
346
|
case '{': if (! inParam) { level ++; chunk.push(c); break }
|
|
313
347
|
case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break }
|
|
@@ -315,12 +349,14 @@ less.Parser = function Parser(env) {
|
|
|
315
349
|
case ')': if ( inParam) { inParam = false; chunk.push(c); break }
|
|
316
350
|
default: chunk.push(c);
|
|
317
351
|
}
|
|
352
|
+
|
|
353
|
+
i++;
|
|
318
354
|
}
|
|
319
|
-
if (level
|
|
355
|
+
if (level != 0) {
|
|
320
356
|
error = new(LessError)({
|
|
321
|
-
index: i,
|
|
357
|
+
index: i-1,
|
|
322
358
|
type: 'Parse',
|
|
323
|
-
message: "missing closing `}`",
|
|
359
|
+
message: (level > 0) ? "missing closing `}`" : "missing opening `{`",
|
|
324
360
|
filename: env.filename
|
|
325
361
|
}, env);
|
|
326
362
|
}
|
|
@@ -329,7 +365,7 @@ less.Parser = function Parser(env) {
|
|
|
329
365
|
})([[]]);
|
|
330
366
|
|
|
331
367
|
if (error) {
|
|
332
|
-
return callback(error);
|
|
368
|
+
return callback(error, env);
|
|
333
369
|
}
|
|
334
370
|
|
|
335
371
|
// Start with the primary rule.
|
|
@@ -380,7 +416,7 @@ less.Parser = function Parser(env) {
|
|
|
380
416
|
|
|
381
417
|
try {
|
|
382
418
|
var css = evaluate.call(this, { frames: frames })
|
|
383
|
-
.toCSS([], { compress: options.compress || false });
|
|
419
|
+
.toCSS([], { compress: options.compress || false, dumpLineNumbers: env.dumpLineNumbers });
|
|
384
420
|
} catch (e) {
|
|
385
421
|
throw new(LessError)(e, env);
|
|
386
422
|
}
|
|
@@ -391,7 +427,7 @@ less.Parser = function Parser(env) {
|
|
|
391
427
|
}
|
|
392
428
|
|
|
393
429
|
if (options.yuicompress && less.mode === 'node') {
|
|
394
|
-
return require('
|
|
430
|
+
return require('ycssmin').cssmin(css);
|
|
395
431
|
} else if (options.compress) {
|
|
396
432
|
return css.replace(/(\s)+/g, "$1");
|
|
397
433
|
} else {
|
|
@@ -431,7 +467,11 @@ less.Parser = function Parser(env) {
|
|
|
431
467
|
}
|
|
432
468
|
|
|
433
469
|
if (this.imports.queue.length > 0) {
|
|
434
|
-
finish = function () {
|
|
470
|
+
finish = function (e) {
|
|
471
|
+
e = error || e;
|
|
472
|
+
if (e) callback(e);
|
|
473
|
+
else callback(null, root);
|
|
474
|
+
};
|
|
435
475
|
} else {
|
|
436
476
|
callback(error, root);
|
|
437
477
|
}
|
|
@@ -487,7 +527,7 @@ less.Parser = function Parser(env) {
|
|
|
487
527
|
|
|
488
528
|
while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) ||
|
|
489
529
|
$(this.mixin.call) || $(this.comment) || $(this.directive))
|
|
490
|
-
|| $(/^[\s\n]+/)) {
|
|
530
|
+
|| $(/^[\s\n]+/) || $(/^;+/)) {
|
|
491
531
|
node && root.push(node);
|
|
492
532
|
}
|
|
493
533
|
return root;
|
|
@@ -538,7 +578,7 @@ less.Parser = function Parser(env) {
|
|
|
538
578
|
keyword: function () {
|
|
539
579
|
var k;
|
|
540
580
|
|
|
541
|
-
if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) {
|
|
581
|
+
if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) {
|
|
542
582
|
if (tree.colors.hasOwnProperty(k)) {
|
|
543
583
|
// detect named color
|
|
544
584
|
return new(tree.Color)(tree.colors[k].slice(1));
|
|
@@ -559,16 +599,22 @@ less.Parser = function Parser(env) {
|
|
|
559
599
|
// The arguments are parsed with the `entities.arguments` parser.
|
|
560
600
|
//
|
|
561
601
|
call: function () {
|
|
562
|
-
var name, args, index = i;
|
|
602
|
+
var name, nameLC, args, alpha_ret, index = i;
|
|
563
603
|
|
|
564
604
|
if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return;
|
|
565
605
|
|
|
566
|
-
name = name[1]
|
|
606
|
+
name = name[1];
|
|
607
|
+
nameLC = name.toLowerCase();
|
|
567
608
|
|
|
568
|
-
if (
|
|
609
|
+
if (nameLC === 'url') { return null }
|
|
569
610
|
else { i += name.length }
|
|
570
611
|
|
|
571
|
-
if (
|
|
612
|
+
if (nameLC === 'alpha') {
|
|
613
|
+
alpha_ret = $(this.alpha);
|
|
614
|
+
if(typeof alpha_ret !== 'undefined') {
|
|
615
|
+
return alpha_ret;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
572
618
|
|
|
573
619
|
$('('); // Parse the '(' and consume whitespace.
|
|
574
620
|
|
|
@@ -588,9 +634,11 @@ less.Parser = function Parser(env) {
|
|
|
588
634
|
return args;
|
|
589
635
|
},
|
|
590
636
|
literal: function () {
|
|
591
|
-
return $(this.entities.
|
|
637
|
+
return $(this.entities.ratio) ||
|
|
638
|
+
$(this.entities.dimension) ||
|
|
592
639
|
$(this.entities.color) ||
|
|
593
|
-
$(this.entities.quoted)
|
|
640
|
+
$(this.entities.quoted) ||
|
|
641
|
+
$(this.entities.unicodeDescriptor);
|
|
594
642
|
},
|
|
595
643
|
|
|
596
644
|
// Assignments are argument entities for calls.
|
|
@@ -618,26 +666,12 @@ less.Parser = function Parser(env) {
|
|
|
618
666
|
|
|
619
667
|
if (input.charAt(i) !== 'u' || !$(/^url\(/)) return;
|
|
620
668
|
value = $(this.entities.quoted) || $(this.entities.variable) ||
|
|
621
|
-
$(
|
|
669
|
+
$(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/) || "";
|
|
622
670
|
|
|
623
671
|
expect(')');
|
|
624
672
|
|
|
625
|
-
return new(tree.URL)((value.value
|
|
626
|
-
? value : new(tree.Anonymous)(value),
|
|
627
|
-
},
|
|
628
|
-
|
|
629
|
-
dataURI: function () {
|
|
630
|
-
var obj;
|
|
631
|
-
|
|
632
|
-
if ($(/^data:/)) {
|
|
633
|
-
obj = {};
|
|
634
|
-
obj.mime = $(/^[^\/]+\/[^,;)]+/) || '';
|
|
635
|
-
obj.charset = $(/^;\s*charset=[^,;)]+/) || '';
|
|
636
|
-
obj.base64 = $(/^;\s*base64/) || '';
|
|
637
|
-
obj.data = $(/^,\s*[^)]+/);
|
|
638
|
-
|
|
639
|
-
if (obj.data) { return obj }
|
|
640
|
-
}
|
|
673
|
+
return new(tree.URL)((value.value != null || value instanceof tree.Variable)
|
|
674
|
+
? value : new(tree.Anonymous)(value), env.rootpath);
|
|
641
675
|
},
|
|
642
676
|
|
|
643
677
|
//
|
|
@@ -656,6 +690,15 @@ less.Parser = function Parser(env) {
|
|
|
656
690
|
}
|
|
657
691
|
},
|
|
658
692
|
|
|
693
|
+
// A variable entity useing the protective {} e.g. @{var}
|
|
694
|
+
variableCurly: function () {
|
|
695
|
+
var name, curly, index = i;
|
|
696
|
+
|
|
697
|
+
if (input.charAt(i) === '@' && (curly = $(/^@\{([\w-]+)\}/))) {
|
|
698
|
+
return new(tree.Variable)("@" + curly[1], index, env.filename);
|
|
699
|
+
}
|
|
700
|
+
},
|
|
701
|
+
|
|
659
702
|
//
|
|
660
703
|
// A Hexadecimal color
|
|
661
704
|
//
|
|
@@ -666,7 +709,7 @@ less.Parser = function Parser(env) {
|
|
|
666
709
|
color: function () {
|
|
667
710
|
var rgb;
|
|
668
711
|
|
|
669
|
-
if (input.charAt(i) === '#' && (rgb = $(/^#([
|
|
712
|
+
if (input.charAt(i) === '#' && (rgb = $(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
|
|
670
713
|
return new(tree.Color)(rgb[1]);
|
|
671
714
|
}
|
|
672
715
|
},
|
|
@@ -678,13 +721,41 @@ less.Parser = function Parser(env) {
|
|
|
678
721
|
//
|
|
679
722
|
dimension: function () {
|
|
680
723
|
var value, c = input.charCodeAt(i);
|
|
681
|
-
|
|
724
|
+
//Is the first char of the dimension 0-9, '.', '+' or '-'
|
|
725
|
+
if ((c > 57 || c < 43) || c === 47 || c == 44) return;
|
|
682
726
|
|
|
683
|
-
if (value = $(/^(
|
|
727
|
+
if (value = $(/^([+-]?\d*\.?\d+)(px|%|em|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn|dpi|dpcm|dppx|rem|vw|vh|vmin|vm|ch)?/)) {
|
|
684
728
|
return new(tree.Dimension)(value[1], value[2]);
|
|
685
729
|
}
|
|
686
730
|
},
|
|
687
731
|
|
|
732
|
+
//
|
|
733
|
+
// A Ratio
|
|
734
|
+
//
|
|
735
|
+
// 16/9
|
|
736
|
+
//
|
|
737
|
+
ratio: function () {
|
|
738
|
+
var value, c = input.charCodeAt(i);
|
|
739
|
+
if (c > 57 || c < 48) return;
|
|
740
|
+
|
|
741
|
+
if (value = $(/^(\d+\/\d+)/)) {
|
|
742
|
+
return new(tree.Ratio)(value[1]);
|
|
743
|
+
}
|
|
744
|
+
},
|
|
745
|
+
|
|
746
|
+
//
|
|
747
|
+
// A unicode descriptor, as is used in unicode-range
|
|
748
|
+
//
|
|
749
|
+
// U+0?? or U+00A1-00A9
|
|
750
|
+
//
|
|
751
|
+
unicodeDescriptor: function () {
|
|
752
|
+
var ud;
|
|
753
|
+
|
|
754
|
+
if (ud = $(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/)) {
|
|
755
|
+
return new(tree.UnicodeDescriptor)(ud[0]);
|
|
756
|
+
}
|
|
757
|
+
},
|
|
758
|
+
|
|
688
759
|
//
|
|
689
760
|
// JavaScript code to be evaluated
|
|
690
761
|
//
|
|
@@ -727,9 +798,13 @@ less.Parser = function Parser(env) {
|
|
|
727
798
|
|
|
728
799
|
if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return;
|
|
729
800
|
|
|
801
|
+
save();
|
|
802
|
+
|
|
730
803
|
if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) {
|
|
731
804
|
return new(tree.Shorthand)(a, b);
|
|
732
805
|
}
|
|
806
|
+
|
|
807
|
+
restore();
|
|
733
808
|
},
|
|
734
809
|
|
|
735
810
|
//
|
|
@@ -748,15 +823,70 @@ less.Parser = function Parser(env) {
|
|
|
748
823
|
// selector for now.
|
|
749
824
|
//
|
|
750
825
|
call: function () {
|
|
751
|
-
var elements = [], e, c, args, index = i, s = input.charAt(i), important = false;
|
|
826
|
+
var elements = [], e, c, argsSemiColon = [], argsComma = [], args, delim, arg, nameLoop, expressions, isSemiColonSeperated, expressionContainsNamed, index = i, s = input.charAt(i), name, value, important = false;
|
|
752
827
|
|
|
753
828
|
if (s !== '.' && s !== '#') { return }
|
|
829
|
+
|
|
830
|
+
save(); // stop us absorbing part of an invalid selector
|
|
754
831
|
|
|
755
|
-
while (e = $(/^[#.](?:[\w-]|\\(?:[
|
|
832
|
+
while (e = $(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)) {
|
|
756
833
|
elements.push(new(tree.Element)(c, e, i));
|
|
757
834
|
c = $('>');
|
|
758
835
|
}
|
|
759
|
-
$('(')
|
|
836
|
+
if ($('(')) {
|
|
837
|
+
expressions = [];
|
|
838
|
+
while (arg = $(this.expression)) {
|
|
839
|
+
nameLoop = null;
|
|
840
|
+
value = arg;
|
|
841
|
+
|
|
842
|
+
// Variable
|
|
843
|
+
if (arg.value.length == 1) {
|
|
844
|
+
var val = arg.value[0];
|
|
845
|
+
if (val instanceof tree.Variable) {
|
|
846
|
+
if ($(':')) {
|
|
847
|
+
if (expressions.length > 0) {
|
|
848
|
+
if (isSemiColonSeperated) {
|
|
849
|
+
error("Cannot mix ; and , as delimiter types");
|
|
850
|
+
}
|
|
851
|
+
expressionContainsNamed = true;
|
|
852
|
+
}
|
|
853
|
+
value = expect(this.expression);
|
|
854
|
+
nameLoop = (name = val.name);
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
expressions.push(value);
|
|
860
|
+
|
|
861
|
+
argsComma.push({ name: nameLoop, value: value });
|
|
862
|
+
|
|
863
|
+
if ($(',')) {
|
|
864
|
+
continue;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
if ($(';') || isSemiColonSeperated) {
|
|
868
|
+
|
|
869
|
+
if (expressionContainsNamed) {
|
|
870
|
+
error("Cannot mix ; and , as delimiter types");
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
isSemiColonSeperated = true;
|
|
874
|
+
|
|
875
|
+
if (expressions.length > 1) {
|
|
876
|
+
value = new(tree.Value)(expressions);
|
|
877
|
+
}
|
|
878
|
+
argsSemiColon.push({ name: name, value: value });
|
|
879
|
+
|
|
880
|
+
name = null;
|
|
881
|
+
expressions = [];
|
|
882
|
+
expressionContainsNamed = false;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
expect(')');
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
args = isSemiColonSeperated ? argsSemiColon : argsComma;
|
|
760
890
|
|
|
761
891
|
if ($(this.important)) {
|
|
762
892
|
important = true;
|
|
@@ -765,6 +895,8 @@ less.Parser = function Parser(env) {
|
|
|
765
895
|
if (elements.length > 0 && ($(';') || peek('}'))) {
|
|
766
896
|
return new(tree.mixin.Call)(elements, args, index, env.filename, important);
|
|
767
897
|
}
|
|
898
|
+
|
|
899
|
+
restore();
|
|
768
900
|
},
|
|
769
901
|
|
|
770
902
|
//
|
|
@@ -787,31 +919,51 @@ less.Parser = function Parser(env) {
|
|
|
787
919
|
// the `{...}` block.
|
|
788
920
|
//
|
|
789
921
|
definition: function () {
|
|
790
|
-
var name, params = [], match, ruleset, param, value, cond;
|
|
922
|
+
var name, params = [], match, ruleset, param, value, cond, variadic = false;
|
|
791
923
|
if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') ||
|
|
792
|
-
peek(/^[^{]
|
|
924
|
+
peek(/^[^{]*\}/)) return;
|
|
793
925
|
|
|
794
926
|
save();
|
|
795
927
|
|
|
796
|
-
if (match = $(/^([#.](?:[\w-]|\\(?:[
|
|
928
|
+
if (match = $(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)) {
|
|
797
929
|
name = match[1];
|
|
798
930
|
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
931
|
+
do {
|
|
932
|
+
$(this.comment);
|
|
933
|
+
if (input.charAt(i) === '.' && $(/^\.{3}/)) {
|
|
934
|
+
variadic = true;
|
|
935
|
+
params.push({ variadic: true });
|
|
936
|
+
break;
|
|
937
|
+
} else if (param = $(this.entities.variable) || $(this.entities.literal)
|
|
938
|
+
|| $(this.entities.keyword)) {
|
|
939
|
+
// Variable
|
|
940
|
+
if (param instanceof tree.Variable) {
|
|
941
|
+
if ($(':')) {
|
|
942
|
+
value = expect(this.expression, 'expected expression');
|
|
943
|
+
params.push({ name: param.name, value: value });
|
|
944
|
+
} else if ($(/^\.{3}/)) {
|
|
945
|
+
params.push({ name: param.name, variadic: true });
|
|
946
|
+
variadic = true;
|
|
947
|
+
break;
|
|
948
|
+
} else {
|
|
949
|
+
params.push({ name: param.name });
|
|
950
|
+
}
|
|
806
951
|
} else {
|
|
807
|
-
params.push({
|
|
952
|
+
params.push({ value: param });
|
|
808
953
|
}
|
|
809
954
|
} else {
|
|
810
|
-
|
|
955
|
+
break;
|
|
811
956
|
}
|
|
812
|
-
|
|
957
|
+
} while ($(',') || $(';'))
|
|
958
|
+
|
|
959
|
+
// .mixincall("@{a}");
|
|
960
|
+
// looks a bit like a mixin definition.. so we have to be nice and restore
|
|
961
|
+
if (!$(')')) {
|
|
962
|
+
furthest = i;
|
|
963
|
+
restore();
|
|
813
964
|
}
|
|
814
|
-
|
|
965
|
+
|
|
966
|
+
$(this.comment);
|
|
815
967
|
|
|
816
968
|
if ($(/^when/)) { // Guard
|
|
817
969
|
cond = expect(this.conditions, 'expected condition');
|
|
@@ -820,7 +972,7 @@ less.Parser = function Parser(env) {
|
|
|
820
972
|
ruleset = $(this.block);
|
|
821
973
|
|
|
822
974
|
if (ruleset) {
|
|
823
|
-
return new(tree.mixin.Definition)(name, params, ruleset, cond);
|
|
975
|
+
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
|
|
824
976
|
} else {
|
|
825
977
|
restore();
|
|
826
978
|
}
|
|
@@ -834,7 +986,7 @@ less.Parser = function Parser(env) {
|
|
|
834
986
|
//
|
|
835
987
|
entity: function () {
|
|
836
988
|
return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) ||
|
|
837
|
-
$(this.entities.call) || $(this.entities.keyword)
|
|
989
|
+
$(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) ||
|
|
838
990
|
$(this.comment);
|
|
839
991
|
},
|
|
840
992
|
|
|
@@ -878,18 +1030,22 @@ less.Parser = function Parser(env) {
|
|
|
878
1030
|
var e, t, c, v;
|
|
879
1031
|
|
|
880
1032
|
c = $(this.combinator);
|
|
881
|
-
|
|
882
|
-
|
|
1033
|
+
|
|
1034
|
+
e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
|
|
1035
|
+
$('*') || $('&') || $(this.attribute) || $(/^\([^()@]+\)/) || $(/^[\.#](?=@)/) || $(this.entities.variableCurly);
|
|
883
1036
|
|
|
884
1037
|
if (! e) {
|
|
885
|
-
|
|
1038
|
+
if ($('(')) {
|
|
1039
|
+
if ((v = ($(this.entities.variableCurly) ||
|
|
1040
|
+
$(this.entities.variable) ||
|
|
1041
|
+
$(this.selector))) &&
|
|
1042
|
+
$(')')) {
|
|
1043
|
+
e = new(tree.Paren)(v);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
886
1046
|
}
|
|
887
1047
|
|
|
888
1048
|
if (e) { return new(tree.Element)(c, e, i) }
|
|
889
|
-
|
|
890
|
-
if (c.value && c.value.charAt(0) === '&') {
|
|
891
|
-
return new(tree.Element)(c, null, i);
|
|
892
|
-
}
|
|
893
1049
|
},
|
|
894
1050
|
|
|
895
1051
|
//
|
|
@@ -904,23 +1060,11 @@ less.Parser = function Parser(env) {
|
|
|
904
1060
|
combinator: function () {
|
|
905
1061
|
var match, c = input.charAt(i);
|
|
906
1062
|
|
|
907
|
-
if (c === '>' || c === '+' || c === '~') {
|
|
1063
|
+
if (c === '>' || c === '+' || c === '~' || c === '|') {
|
|
908
1064
|
i++;
|
|
909
|
-
while (input.charAt(i)
|
|
1065
|
+
while (input.charAt(i).match(/\s/)) { i++ }
|
|
910
1066
|
return new(tree.Combinator)(c);
|
|
911
|
-
} else if (
|
|
912
|
-
match = '&';
|
|
913
|
-
i++;
|
|
914
|
-
if(input.charAt(i) === ' ') {
|
|
915
|
-
match = '& ';
|
|
916
|
-
}
|
|
917
|
-
while (input.charAt(i) === ' ') { i++ }
|
|
918
|
-
return new(tree.Combinator)(match);
|
|
919
|
-
} else if (c === ':' && input.charAt(i + 1) === ':') {
|
|
920
|
-
i += 2;
|
|
921
|
-
while (input.charAt(i) === ' ') { i++ }
|
|
922
|
-
return new(tree.Combinator)('::');
|
|
923
|
-
} else if (input.charAt(i - 1) === ' ') {
|
|
1067
|
+
} else if (input.charAt(i - 1).match(/\s/)) {
|
|
924
1068
|
return new(tree.Combinator)(" ");
|
|
925
1069
|
} else {
|
|
926
1070
|
return new(tree.Combinator)(null);
|
|
@@ -938,23 +1082,27 @@ less.Parser = function Parser(env) {
|
|
|
938
1082
|
selector: function () {
|
|
939
1083
|
var sel, e, elements = [], c, match;
|
|
940
1084
|
|
|
1085
|
+
// depreciated, will be removed soon
|
|
1086
|
+
if ($('(')) {
|
|
1087
|
+
sel = $(this.entity);
|
|
1088
|
+
if (!$(')')) { return null; }
|
|
1089
|
+
return new(tree.Selector)([new(tree.Element)('', sel, i)]);
|
|
1090
|
+
}
|
|
1091
|
+
|
|
941
1092
|
while (e = $(this.element)) {
|
|
942
1093
|
c = input.charAt(i);
|
|
943
1094
|
elements.push(e)
|
|
944
|
-
if (c === '{' || c === '}' || c === ';' || c === ',') { break }
|
|
1095
|
+
if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break }
|
|
945
1096
|
}
|
|
946
1097
|
|
|
947
1098
|
if (elements.length > 0) { return new(tree.Selector)(elements) }
|
|
948
1099
|
},
|
|
949
|
-
tag: function () {
|
|
950
|
-
return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*');
|
|
951
|
-
},
|
|
952
1100
|
attribute: function () {
|
|
953
1101
|
var attr = '', key, val, op;
|
|
954
1102
|
|
|
955
1103
|
if (! $('[')) return;
|
|
956
1104
|
|
|
957
|
-
if (key = $(/^[
|
|
1105
|
+
if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) {
|
|
958
1106
|
if ((op = $(/^[|~*$^]?=/)) &&
|
|
959
1107
|
(val = $(this.entities.quoted) || $(/^[\w-]+/))) {
|
|
960
1108
|
attr = [key, op, val.toCSS ? val.toCSS() : val].join('');
|
|
@@ -972,7 +1120,6 @@ less.Parser = function Parser(env) {
|
|
|
972
1120
|
//
|
|
973
1121
|
block: function () {
|
|
974
1122
|
var content;
|
|
975
|
-
|
|
976
1123
|
if ($('{') && (content = $(this.primary)) && $('}')) {
|
|
977
1124
|
return content;
|
|
978
1125
|
}
|
|
@@ -982,9 +1129,13 @@ less.Parser = function Parser(env) {
|
|
|
982
1129
|
// div, .class, body > p {...}
|
|
983
1130
|
//
|
|
984
1131
|
ruleset: function () {
|
|
985
|
-
var selectors = [], s, rules, match;
|
|
1132
|
+
var selectors = [], s, rules, match, debugInfo;
|
|
1133
|
+
|
|
986
1134
|
save();
|
|
987
1135
|
|
|
1136
|
+
if (env.dumpLineNumbers)
|
|
1137
|
+
debugInfo = getDebugInfo(i, input, env);
|
|
1138
|
+
|
|
988
1139
|
while (s = $(this.selector)) {
|
|
989
1140
|
selectors.push(s);
|
|
990
1141
|
$(this.comment);
|
|
@@ -993,7 +1144,10 @@ less.Parser = function Parser(env) {
|
|
|
993
1144
|
}
|
|
994
1145
|
|
|
995
1146
|
if (selectors.length > 0 && (rules = $(this.block))) {
|
|
996
|
-
|
|
1147
|
+
var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports);
|
|
1148
|
+
if (env.dumpLineNumbers)
|
|
1149
|
+
ruleset.debugInfo = debugInfo;
|
|
1150
|
+
return ruleset;
|
|
997
1151
|
} else {
|
|
998
1152
|
// Backtrack
|
|
999
1153
|
furthest = i;
|
|
@@ -1038,17 +1192,23 @@ less.Parser = function Parser(env) {
|
|
|
1038
1192
|
//
|
|
1039
1193
|
"import": function () {
|
|
1040
1194
|
var path, features, index = i;
|
|
1041
|
-
|
|
1042
|
-
|
|
1195
|
+
|
|
1196
|
+
save();
|
|
1197
|
+
|
|
1198
|
+
var dir = $(/^@import(?:-(once))?\s+/);
|
|
1199
|
+
|
|
1200
|
+
if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) {
|
|
1043
1201
|
features = $(this.mediaFeatures);
|
|
1044
1202
|
if ($(';')) {
|
|
1045
|
-
return new(tree.Import)(path, imports, features, index);
|
|
1203
|
+
return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath);
|
|
1046
1204
|
}
|
|
1047
1205
|
}
|
|
1206
|
+
|
|
1207
|
+
restore();
|
|
1048
1208
|
},
|
|
1049
1209
|
|
|
1050
1210
|
mediaFeature: function () {
|
|
1051
|
-
var nodes = [];
|
|
1211
|
+
var e, p, nodes = [];
|
|
1052
1212
|
|
|
1053
1213
|
do {
|
|
1054
1214
|
if (e = $(this.entities.keyword)) {
|
|
@@ -1074,22 +1234,35 @@ less.Parser = function Parser(env) {
|
|
|
1074
1234
|
},
|
|
1075
1235
|
|
|
1076
1236
|
mediaFeatures: function () {
|
|
1077
|
-
var
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1237
|
+
var e, features = [];
|
|
1238
|
+
|
|
1239
|
+
do {
|
|
1240
|
+
if (e = $(this.mediaFeature)) {
|
|
1241
|
+
features.push(e);
|
|
1242
|
+
if (! $(',')) { break }
|
|
1243
|
+
} else if (e = $(this.entities.variable)) {
|
|
1244
|
+
features.push(e);
|
|
1245
|
+
if (! $(',')) { break }
|
|
1246
|
+
}
|
|
1247
|
+
} while (e);
|
|
1248
|
+
|
|
1082
1249
|
return features.length > 0 ? features : null;
|
|
1083
1250
|
},
|
|
1084
1251
|
|
|
1085
1252
|
media: function () {
|
|
1086
|
-
var features;
|
|
1253
|
+
var features, rules, media, debugInfo;
|
|
1254
|
+
|
|
1255
|
+
if (env.dumpLineNumbers)
|
|
1256
|
+
debugInfo = getDebugInfo(i, input, env);
|
|
1087
1257
|
|
|
1088
1258
|
if ($(/^@media/)) {
|
|
1089
1259
|
features = $(this.mediaFeatures);
|
|
1090
1260
|
|
|
1091
1261
|
if (rules = $(this.block)) {
|
|
1092
|
-
|
|
1262
|
+
media = new(tree.Media)(rules, features);
|
|
1263
|
+
if(env.dumpLineNumbers)
|
|
1264
|
+
media.debugInfo = debugInfo;
|
|
1265
|
+
return media;
|
|
1093
1266
|
}
|
|
1094
1267
|
}
|
|
1095
1268
|
},
|
|
@@ -1100,26 +1273,81 @@ less.Parser = function Parser(env) {
|
|
|
1100
1273
|
// @charset "utf-8";
|
|
1101
1274
|
//
|
|
1102
1275
|
directive: function () {
|
|
1103
|
-
var name, value, rules,
|
|
1276
|
+
var name, value, rules, identifier, e, nodes, nonVendorSpecificName,
|
|
1277
|
+
hasBlock, hasIdentifier, hasExpression;
|
|
1104
1278
|
|
|
1105
1279
|
if (input.charAt(i) !== '@') return;
|
|
1106
1280
|
|
|
1107
1281
|
if (value = $(this['import']) || $(this.media)) {
|
|
1108
1282
|
return value;
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
save();
|
|
1286
|
+
|
|
1287
|
+
name = $(/^@[a-z-]+/);
|
|
1288
|
+
|
|
1289
|
+
if (!name) return;
|
|
1290
|
+
|
|
1291
|
+
nonVendorSpecificName = name;
|
|
1292
|
+
if (name.charAt(1) == '-' && name.indexOf('-', 2) > 0) {
|
|
1293
|
+
nonVendorSpecificName = "@" + name.slice(name.indexOf('-', 2) + 1);
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
switch(nonVendorSpecificName) {
|
|
1297
|
+
case "@font-face":
|
|
1298
|
+
hasBlock = true;
|
|
1299
|
+
break;
|
|
1300
|
+
case "@viewport":
|
|
1301
|
+
case "@top-left":
|
|
1302
|
+
case "@top-left-corner":
|
|
1303
|
+
case "@top-center":
|
|
1304
|
+
case "@top-right":
|
|
1305
|
+
case "@top-right-corner":
|
|
1306
|
+
case "@bottom-left":
|
|
1307
|
+
case "@bottom-left-corner":
|
|
1308
|
+
case "@bottom-center":
|
|
1309
|
+
case "@bottom-right":
|
|
1310
|
+
case "@bottom-right-corner":
|
|
1311
|
+
case "@left-top":
|
|
1312
|
+
case "@left-middle":
|
|
1313
|
+
case "@left-bottom":
|
|
1314
|
+
case "@right-top":
|
|
1315
|
+
case "@right-middle":
|
|
1316
|
+
case "@right-bottom":
|
|
1317
|
+
hasBlock = true;
|
|
1318
|
+
break;
|
|
1319
|
+
case "@page":
|
|
1320
|
+
case "@document":
|
|
1321
|
+
case "@supports":
|
|
1322
|
+
case "@keyframes":
|
|
1323
|
+
hasBlock = true;
|
|
1324
|
+
hasIdentifier = true;
|
|
1325
|
+
break;
|
|
1326
|
+
case "@namespace":
|
|
1327
|
+
hasExpression = true;
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
if (hasIdentifier) {
|
|
1332
|
+
name += " " + ($(/^[^{]+/) || '').trim();
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
if (hasBlock)
|
|
1336
|
+
{
|
|
1111
1337
|
if (rules = $(this.block)) {
|
|
1112
|
-
return new(tree.Directive)(name
|
|
1338
|
+
return new(tree.Directive)(name, rules);
|
|
1113
1339
|
}
|
|
1114
|
-
} else
|
|
1115
|
-
if (
|
|
1116
|
-
|
|
1117
|
-
|
|
1340
|
+
} else {
|
|
1341
|
+
if ((value = hasExpression ? $(this.expression) : $(this.entity)) && $(';')) {
|
|
1342
|
+
var directive = new(tree.Directive)(name, value);
|
|
1343
|
+
if (env.dumpLineNumbers) {
|
|
1344
|
+
directive.debugInfo = getDebugInfo(i, input, env);
|
|
1118
1345
|
}
|
|
1119
|
-
|
|
1120
|
-
return new(tree.Directive)(name, value);
|
|
1346
|
+
return directive;
|
|
1121
1347
|
}
|
|
1122
1348
|
}
|
|
1349
|
+
|
|
1350
|
+
restore();
|
|
1123
1351
|
},
|
|
1124
1352
|
font: function () {
|
|
1125
1353
|
var value = [], expression = [], weight, shorthand, font, e;
|
|
@@ -1173,7 +1401,7 @@ less.Parser = function Parser(env) {
|
|
|
1173
1401
|
multiplication: function () {
|
|
1174
1402
|
var m, a, op, operation;
|
|
1175
1403
|
if (m = $(this.operand)) {
|
|
1176
|
-
while (!peek(
|
|
1404
|
+
while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) {
|
|
1177
1405
|
operation = new(tree.Operation)(op, [operation || m, a]);
|
|
1178
1406
|
}
|
|
1179
1407
|
return operation || m;
|
|
@@ -1182,7 +1410,7 @@ less.Parser = function Parser(env) {
|
|
|
1182
1410
|
addition: function () {
|
|
1183
1411
|
var m, a, op, operation;
|
|
1184
1412
|
if (m = $(this.multiplication)) {
|
|
1185
|
-
while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1)
|
|
1413
|
+
while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) &&
|
|
1186
1414
|
(a = $(this.multiplication))) {
|
|
1187
1415
|
operation = new(tree.Operation)(op, [operation || m, a]);
|
|
1188
1416
|
}
|
|
@@ -1254,7 +1482,7 @@ less.Parser = function Parser(env) {
|
|
|
1254
1482
|
property: function () {
|
|
1255
1483
|
var name;
|
|
1256
1484
|
|
|
1257
|
-
if (name = $(/^(\*?-?[-
|
|
1485
|
+
if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) {
|
|
1258
1486
|
return name[1];
|
|
1259
1487
|
}
|
|
1260
1488
|
}
|
|
@@ -1267,17 +1495,26 @@ if (less.mode === 'browser' || less.mode === 'rhino') {
|
|
|
1267
1495
|
// Used by `@import` directives
|
|
1268
1496
|
//
|
|
1269
1497
|
less.Parser.importer = function (path, paths, callback, env) {
|
|
1270
|
-
if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) {
|
|
1498
|
+
if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) {
|
|
1271
1499
|
path = paths[0] + path;
|
|
1272
1500
|
}
|
|
1273
1501
|
// We pass `true` as 3rd argument, to force the reload of the import.
|
|
1274
1502
|
// This is so we can get the syntax tree as opposed to just the CSS output,
|
|
1275
1503
|
// as we need this to evaluate the current stylesheet.
|
|
1276
|
-
loadStyleSheet({
|
|
1504
|
+
loadStyleSheet({
|
|
1505
|
+
href: path,
|
|
1506
|
+
title: path,
|
|
1507
|
+
type: env.mime,
|
|
1508
|
+
contents: env.contents,
|
|
1509
|
+
files: env.files,
|
|
1510
|
+
rootpath: env.rootpath,
|
|
1511
|
+
entryPath: env.entryPath,
|
|
1512
|
+
relativeUrls: env.relativeUrls },
|
|
1513
|
+
function (e, root, data, sheet, _, path) {
|
|
1277
1514
|
if (e && typeof(env.errback) === "function") {
|
|
1278
1515
|
env.errback.call(null, path, paths, callback, env);
|
|
1279
1516
|
} else {
|
|
1280
|
-
callback.
|
|
1517
|
+
callback.call(null, e, root, path);
|
|
1281
1518
|
}
|
|
1282
1519
|
}, true);
|
|
1283
1520
|
};
|