less 2.3.0 → 2.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/less/js/.gitignore +7 -0
- data/lib/less/js/.npmignore +1 -0
- data/lib/less/js/CHANGELOG.md +118 -0
- data/lib/less/js/CONTRIBUTING.md +50 -0
- data/lib/less/js/Makefile +14 -2
- data/lib/less/js/bin/lessc +72 -21
- data/lib/less/js/dist/less-1.3.1.js +4011 -0
- data/lib/less/js/dist/less-1.3.1.min.js +9 -0
- data/lib/less/js/dist/less-1.3.2.js +4401 -0
- data/lib/less/js/dist/less-1.3.2.min.js +9 -0
- data/lib/less/js/dist/less-1.3.3.js +4413 -0
- data/lib/less/js/dist/less-1.3.3.min.js +9 -0
- data/lib/less/js/dist/less-rhino-1.3.1.js +3725 -0
- data/lib/less/js/dist/less-rhino-1.3.2.js +3990 -0
- data/lib/less/js/dist/less-rhino-1.3.3.js +4002 -0
- data/lib/less/js/lib/less/browser.js +192 -53
- data/lib/less/js/lib/less/colors.js +1 -0
- data/lib/less/js/lib/less/functions.js +159 -10
- data/lib/less/js/lib/less/index.js +124 -56
- data/lib/less/js/lib/less/lessc_helper.js +62 -0
- data/lib/less/js/lib/less/parser.js +352 -135
- data/lib/less/js/lib/less/rhino.js +84 -23
- data/lib/less/js/lib/less/tree.js +28 -0
- data/lib/less/js/lib/less/tree/anonymous.js +15 -1
- data/lib/less/js/lib/less/tree/assignment.js +3 -1
- data/lib/less/js/lib/less/tree/call.js +12 -6
- data/lib/less/js/lib/less/tree/color.js +10 -0
- data/lib/less/js/lib/less/tree/dimension.js +3 -1
- data/lib/less/js/lib/less/tree/directive.js +9 -5
- data/lib/less/js/lib/less/tree/element.js +8 -6
- data/lib/less/js/lib/less/tree/import.js +16 -13
- data/lib/less/js/lib/less/tree/media.js +16 -9
- data/lib/less/js/lib/less/tree/mixin.js +123 -46
- data/lib/less/js/lib/less/tree/operation.js +5 -0
- data/lib/less/js/lib/less/tree/quoted.js +15 -1
- data/lib/less/js/lib/less/tree/ratio.js +13 -0
- data/lib/less/js/lib/less/tree/rule.js +7 -0
- data/lib/less/js/lib/less/tree/ruleset.js +232 -34
- data/lib/less/js/lib/less/tree/selector.js +21 -11
- data/lib/less/js/lib/less/tree/unicode-descriptor.js +13 -0
- data/lib/less/js/lib/less/tree/url.js +16 -14
- data/lib/less/js/lib/less/tree/variable.js +13 -1
- data/lib/less/js/package.json +13 -3
- data/lib/less/js/test/browser-test-prepare.js +29 -0
- data/lib/less/js/test/browser/common.js +74 -0
- data/lib/less/js/test/browser/css/relative-urls/urls.css +36 -0
- data/lib/less/js/test/browser/css/rootpath-relative/urls.css +36 -0
- data/lib/less/js/test/browser/css/rootpath/urls.css +36 -0
- data/lib/less/js/test/browser/css/urls.css +36 -0
- data/lib/less/js/test/browser/jasmine-html.js +681 -0
- data/lib/less/js/test/browser/jasmine.css +82 -0
- data/lib/less/js/test/browser/jasmine.js +2600 -0
- data/lib/less/js/test/browser/less/imports/urls.less +4 -0
- data/lib/less/js/test/browser/less/imports/urls2.less +4 -0
- data/lib/less/js/test/browser/less/relative-urls/urls.less +33 -0
- data/lib/less/js/test/browser/less/rootpath-relative/urls.less +33 -0
- data/lib/less/js/test/browser/less/rootpath/urls.less +33 -0
- data/lib/less/js/test/browser/less/urls.less +33 -0
- data/lib/less/js/test/browser/phantom-runner.js +139 -0
- data/lib/less/js/test/browser/runner-browser.js +3 -0
- data/lib/less/js/test/browser/runner-main.js +15 -0
- data/lib/less/js/test/browser/runner-relative-urls.js +4 -0
- data/lib/less/js/test/browser/runner-rootpath-relative.js +5 -0
- data/lib/less/js/test/browser/runner-rootpath.js +4 -0
- data/lib/less/js/test/browser/template.htm +10 -0
- data/lib/less/js/test/css/charsets.css +1 -0
- data/lib/less/js/test/css/colors.css +22 -0
- data/lib/less/js/test/css/comments.css +7 -0
- data/lib/less/js/test/css/css-3.css +57 -2
- data/lib/less/js/test/css/css-escapes.css +4 -0
- data/lib/less/js/test/css/css.css +11 -11
- data/lib/less/js/test/css/debug/linenumbers-all.css +43 -0
- data/lib/less/js/test/css/debug/linenumbers-comments.css +35 -0
- data/lib/less/js/test/css/debug/linenumbers-mediaquery.css +35 -0
- data/lib/less/js/test/css/functions.css +59 -2
- data/lib/less/js/test/css/ie-filters.css +7 -3
- data/lib/less/js/test/css/import-once.css +3 -0
- data/lib/less/js/test/css/import.css +7 -9
- data/lib/less/js/test/css/javascript.css +3 -2
- data/lib/less/js/test/css/media.css +116 -0
- data/lib/less/js/test/css/mixins-args.css +23 -4
- data/lib/less/js/test/css/mixins-guards.css +13 -0
- data/lib/less/js/test/css/mixins-important.css +21 -0
- data/lib/less/js/test/css/mixins-named-args.css +27 -0
- data/lib/less/js/test/css/mixins.css +50 -0
- data/lib/less/js/test/css/scope.css +20 -0
- data/lib/less/js/test/css/selectors.css +64 -0
- data/lib/less/js/test/css/static-urls/urls.css +42 -0
- data/lib/less/js/test/css/strings.css +2 -2
- data/lib/less/js/test/css/urls.css +42 -0
- data/lib/less/js/test/css/variables.css +0 -1
- data/lib/less/js/test/css/whitespace.css +4 -0
- data/lib/less/js/test/less-test.js +145 -36
- data/lib/less/js/test/less/charsets.less +3 -0
- data/lib/less/js/test/less/colors.less +27 -0
- data/lib/less/js/test/less/comments.less +12 -0
- data/lib/less/js/test/less/css-3.less +54 -6
- data/lib/less/js/test/less/css-escapes.less +6 -1
- data/lib/less/js/test/less/css.less +14 -12
- data/lib/less/js/test/less/debug/import/test.less +25 -0
- data/lib/less/js/test/less/debug/linenumbers.less +23 -0
- data/lib/less/js/test/less/errors/bad-variable-declaration1.less +1 -0
- data/lib/less/js/test/less/errors/bad-variable-declaration1.txt +2 -0
- data/lib/less/js/test/less/errors/comment-in-selector.less +1 -0
- data/lib/less/js/test/less/errors/comment-in-selector.txt +2 -0
- data/lib/less/js/test/less/errors/import-missing.less +1 -0
- data/lib/less/js/test/less/errors/import-missing.txt +3 -0
- data/lib/less/js/test/less/errors/import-no-semi.less +1 -0
- data/lib/less/js/test/less/errors/import-no-semi.txt +2 -0
- data/lib/less/js/test/less/errors/import-subfolder1.less +1 -0
- data/lib/less/js/test/less/errors/import-subfolder1.txt +3 -0
- data/lib/less/js/test/less/errors/import-subfolder2.less +1 -0
- data/lib/less/js/test/less/errors/import-subfolder2.txt +2 -0
- data/lib/less/js/test/less/errors/imports/import-subfolder1.less +1 -0
- data/lib/less/js/test/less/errors/imports/import-subfolder2.less +1 -0
- data/lib/less/js/test/less/errors/imports/import-test.less +4 -0
- data/lib/less/js/test/less/errors/imports/subfolder/mixin-not-defined.less +1 -0
- data/lib/less/js/test/less/errors/imports/subfolder/parse-error-curly-bracket.less +1 -0
- data/lib/less/js/test/less/errors/javascript-error.less +3 -0
- data/lib/less/js/test/less/errors/javascript-error.txt +4 -0
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.less +6 -0
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-1.txt +4 -0
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.less +6 -0
- data/lib/less/js/test/less/errors/mixed-mixin-definition-args-2.txt +4 -0
- data/lib/less/js/test/less/errors/mixin-not-defined.less +11 -0
- data/lib/less/js/test/less/errors/mixin-not-defined.txt +3 -0
- data/lib/less/js/test/less/errors/mixin-not-matched.less +6 -0
- data/lib/less/js/test/less/errors/mixin-not-matched.txt +3 -0
- data/lib/less/js/test/less/errors/mixin-not-matched2.less +6 -0
- data/lib/less/js/test/less/errors/mixin-not-matched2.txt +3 -0
- data/lib/less/js/test/less/errors/parse-error-curly-bracket.less +1 -0
- data/lib/less/js/test/less/errors/parse-error-curly-bracket.txt +2 -0
- data/lib/less/js/test/less/errors/parse-error-missing-bracket.less +2 -0
- data/lib/less/js/test/less/errors/parse-error-missing-bracket.txt +2 -0
- data/lib/less/js/test/less/errors/parse-error-with-import.less +13 -0
- data/lib/less/js/test/less/errors/parse-error-with-import.txt +4 -0
- data/lib/less/js/test/less/errors/property-ie5-hack.less +3 -0
- data/lib/less/js/test/less/errors/property-ie5-hack.txt +4 -0
- data/lib/less/js/test/less/errors/recursive-variable.less +1 -0
- data/lib/less/js/test/less/errors/recursive-variable.txt +2 -0
- data/lib/less/js/test/less/functions.less +64 -2
- data/lib/less/js/test/less/ie-filters.less +7 -0
- data/lib/less/js/test/less/import-once.less +4 -0
- data/lib/less/js/test/less/import.less +2 -1
- data/lib/less/js/test/less/import/deeper/import-once-test-a.less +1 -0
- data/lib/less/js/test/less/import/import-and-relative-paths-test.less +6 -0
- data/lib/less/js/test/less/import/import-charset-test.less +1 -0
- data/lib/less/js/test/less/import/import-once-test-c.less +6 -0
- data/lib/less/js/test/less/import/import-test-a.less +1 -0
- data/lib/less/js/test/less/import/import-test-c.less +0 -1
- data/lib/less/js/test/less/import/imports/font.less +8 -0
- data/lib/less/js/test/less/import/imports/logo.less +5 -0
- data/lib/less/js/test/less/import/urls.less +1 -0
- data/lib/less/js/test/less/javascript.less +4 -2
- data/lib/less/js/test/less/media.less +120 -0
- data/lib/less/js/test/less/mixins-args.less +40 -10
- data/lib/less/js/test/less/mixins-guards.less +30 -0
- data/lib/less/js/test/less/mixins-important.less +4 -0
- data/lib/less/js/test/less/mixins-named-args.less +36 -0
- data/lib/less/js/test/less/mixins.less +47 -0
- data/lib/less/js/test/less/scope.less +48 -1
- data/lib/less/js/test/less/selectors.less +81 -0
- data/lib/less/js/test/less/static-urls/urls.less +33 -0
- data/lib/less/js/test/less/strings.less +1 -1
- data/lib/less/js/test/less/urls.less +33 -0
- data/lib/less/js/test/less/variables.less +0 -1
- data/lib/less/js/test/less/whitespace.less +7 -0
- data/lib/less/version.rb +1 -1
- metadata +101 -4
- data/lib/less/js/CHANGELOG +0 -41
- data/lib/less/js/lib/less/cssmin.js +0 -355
@@ -1,9 +1,11 @@
|
|
1
1
|
var path = require('path'),
|
2
2
|
sys = require('util'),
|
3
|
+
url = require('url'),
|
4
|
+
http = require('http'),
|
3
5
|
fs = require('fs');
|
4
6
|
|
5
7
|
var less = {
|
6
|
-
version: [1, 3,
|
8
|
+
version: [1, 3, 3],
|
7
9
|
Parser: require('./parser').Parser,
|
8
10
|
importer: require('./parser').importer,
|
9
11
|
tree: require('./tree'),
|
@@ -33,20 +35,19 @@ var less = {
|
|
33
35
|
return ee;
|
34
36
|
}
|
35
37
|
},
|
36
|
-
|
38
|
+
formatError: function(ctx, options) {
|
37
39
|
options = options || {};
|
38
40
|
|
39
41
|
var message = "";
|
40
42
|
var extract = ctx.extract;
|
41
43
|
var error = [];
|
42
|
-
var stylize = options.color ?
|
43
|
-
|
44
|
-
if (options.silent) { return }
|
44
|
+
var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str };
|
45
45
|
|
46
|
-
|
46
|
+
// only output a stack if it isn't a less error
|
47
|
+
if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red') }
|
47
48
|
|
48
|
-
if (!ctx.hasOwnProperty('index')) {
|
49
|
-
return
|
49
|
+
if (!ctx.hasOwnProperty('index') || !extract) {
|
50
|
+
return ctx.stack || ctx.message;
|
50
51
|
}
|
51
52
|
|
52
53
|
if (typeof(extract[0]) === 'string') {
|
@@ -62,18 +63,25 @@ var less = {
|
|
62
63
|
if (typeof(extract[2]) === 'string') {
|
63
64
|
error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
|
64
65
|
}
|
65
|
-
error = error.join('\n') + '\
|
66
|
+
error = error.join('\n') + stylize('', 'reset') + '\n';
|
66
67
|
|
67
68
|
message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
|
68
69
|
ctx.filename && (message += stylize(' in ', 'red') + ctx.filename +
|
69
70
|
stylize(':' + ctx.line + ':' + ctx.column, 'grey'));
|
70
71
|
|
71
|
-
|
72
|
+
message += '\n' + error;
|
72
73
|
|
73
74
|
if (ctx.callLine) {
|
74
|
-
|
75
|
-
|
75
|
+
message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
|
76
|
+
message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
|
76
77
|
}
|
78
|
+
|
79
|
+
return message;
|
80
|
+
},
|
81
|
+
writeError: function (ctx, options) {
|
82
|
+
options = options || {};
|
83
|
+
if (options.silent) { return }
|
84
|
+
sys.error(less.formatError(ctx, options));
|
77
85
|
}
|
78
86
|
};
|
79
87
|
|
@@ -83,44 +91,121 @@ var less = {
|
|
83
91
|
'call', 'url', 'alpha', 'import',
|
84
92
|
'mixin', 'comment', 'anonymous', 'value',
|
85
93
|
'javascript', 'assignment', 'condition', 'paren',
|
86
|
-
'media'
|
94
|
+
'media', 'ratio', 'unicode-descriptor'
|
87
95
|
].forEach(function (n) {
|
88
96
|
require('./tree/' + n);
|
89
97
|
});
|
90
98
|
|
99
|
+
|
100
|
+
var isUrlRe = /^(?:https?:)?\/\//i;
|
101
|
+
|
91
102
|
less.Parser.importer = function (file, paths, callback, env) {
|
92
|
-
var pathname;
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
103
|
+
var pathname, dirname, data;
|
104
|
+
|
105
|
+
function parseFile(e, data) {
|
106
|
+
if (e) return callback(e);
|
107
|
+
|
108
|
+
var rootpath = env.rootpath,
|
109
|
+
j = file.lastIndexOf('/');
|
110
|
+
|
111
|
+
// Pass on an updated rootpath if path of imported file is relative and file
|
112
|
+
// is in a (sub|sup) directory
|
113
|
+
//
|
114
|
+
// Examples:
|
115
|
+
// - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
|
116
|
+
// then rootpath should become 'less/module/nav/'
|
117
|
+
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
|
118
|
+
// then rootpath should become 'less/../'
|
119
|
+
if(env.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) {
|
120
|
+
rootpath = rootpath + file.slice(0, j+1); // append (sub|sup) directory path of imported file
|
105
121
|
}
|
106
|
-
}
|
107
|
-
|
108
|
-
if (pathname) {
|
109
|
-
fs.readFile(pathname, 'utf-8', function(e, data) {
|
110
|
-
if (e) return callback(e);
|
111
122
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
123
|
+
env.contents[pathname] = data; // Updating top importing parser content cache.
|
124
|
+
new(less.Parser)({
|
125
|
+
paths: [dirname].concat(paths),
|
126
|
+
filename: pathname,
|
127
|
+
contents: env.contents,
|
128
|
+
files: env.files,
|
129
|
+
syncImport: env.syncImport,
|
130
|
+
relativeUrls: env.relativeUrls,
|
131
|
+
rootpath: rootpath,
|
132
|
+
dumpLineNumbers: env.dumpLineNumbers
|
133
|
+
}).parse(data, function (e, root) {
|
134
|
+
callback(e, root, pathname);
|
135
|
+
});
|
136
|
+
};
|
137
|
+
|
138
|
+
var isUrl = isUrlRe.test( file );
|
139
|
+
if (isUrl || isUrlRe.test(paths[0])) {
|
140
|
+
|
141
|
+
var urlStr = isUrl ? file : url.resolve(paths[0], file),
|
142
|
+
urlObj = url.parse(urlStr),
|
143
|
+
req = {
|
144
|
+
host: urlObj.hostname,
|
145
|
+
port: urlObj.port || 80,
|
146
|
+
path: urlObj.pathname + (urlObj.search||'')
|
147
|
+
};
|
148
|
+
|
149
|
+
http.get(req, function (res) {
|
150
|
+
var body = '';
|
151
|
+
res.on('data', function (chunk) {
|
152
|
+
body += chunk.toString();
|
153
|
+
});
|
154
|
+
res.on('end', function () {
|
155
|
+
if (res.statusCode === 404) {
|
156
|
+
callback({ type: 'File', message: "resource '" + urlStr + "' was not found\n" });
|
157
|
+
}
|
158
|
+
if (!body) {
|
159
|
+
sys.error( 'Warning: Empty body (HTTP '+ res.statusCode + ') returned by "' + urlStr +'"' );
|
160
|
+
}
|
161
|
+
pathname = urlStr;
|
162
|
+
dirname = urlObj.protocol +'//'+ urlObj.host + urlObj.pathname.replace(/[^\/]*$/, '');
|
163
|
+
parseFile(null, body);
|
117
164
|
});
|
165
|
+
}).on('error', function (err) {
|
166
|
+
callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ err +"\n" });
|
118
167
|
});
|
168
|
+
|
119
169
|
} else {
|
120
|
-
|
121
|
-
|
170
|
+
|
171
|
+
// TODO: Undo this at some point,
|
172
|
+
// or use different approach.
|
173
|
+
var paths = [].concat(paths);
|
174
|
+
paths.push('.');
|
175
|
+
|
176
|
+
for (var i = 0; i < paths.length; i++) {
|
177
|
+
try {
|
178
|
+
pathname = path.join(paths[i], file);
|
179
|
+
fs.statSync(pathname);
|
180
|
+
break;
|
181
|
+
} catch (e) {
|
182
|
+
pathname = null;
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
186
|
+
paths = paths.slice(0, paths.length - 1);
|
187
|
+
|
188
|
+
if (!pathname) {
|
189
|
+
|
190
|
+
if (typeof(env.errback) === "function") {
|
191
|
+
env.errback(file, paths, callback);
|
192
|
+
} else {
|
193
|
+
callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
|
194
|
+
}
|
195
|
+
return;
|
196
|
+
}
|
197
|
+
|
198
|
+
dirname = path.dirname(pathname);
|
199
|
+
|
200
|
+
if (env.syncImport) {
|
201
|
+
try {
|
202
|
+
data = fs.readFileSync(pathname, 'utf-8');
|
203
|
+
parseFile(null, data);
|
204
|
+
} catch (e) {
|
205
|
+
parseFile(e);
|
206
|
+
}
|
122
207
|
} else {
|
123
|
-
|
208
|
+
fs.readFile(pathname, 'utf-8', parseFile);
|
124
209
|
}
|
125
210
|
}
|
126
211
|
}
|
@@ -129,20 +214,3 @@ require('./functions');
|
|
129
214
|
require('./colors');
|
130
215
|
|
131
216
|
for (var k in less) { exports[k] = less[k] }
|
132
|
-
|
133
|
-
// Stylize a string
|
134
|
-
function stylize(str, style) {
|
135
|
-
var styles = {
|
136
|
-
'bold' : [1, 22],
|
137
|
-
'inverse' : [7, 27],
|
138
|
-
'underline' : [4, 24],
|
139
|
-
'yellow' : [33, 39],
|
140
|
-
'green' : [32, 39],
|
141
|
-
'red' : [31, 39],
|
142
|
-
'grey' : [90, 39]
|
143
|
-
};
|
144
|
-
return '\033[' + styles[style][0] + 'm' + str +
|
145
|
-
'\033[' + styles[style][1] + 'm';
|
146
|
-
}
|
147
|
-
less.stylize = stylize;
|
148
|
-
|
@@ -0,0 +1,62 @@
|
|
1
|
+
// lessc_helper.js
|
2
|
+
//
|
3
|
+
// helper functions for lessc
|
4
|
+
sys = require('util');
|
5
|
+
|
6
|
+
var lessc_helper = {
|
7
|
+
|
8
|
+
//Stylize a string
|
9
|
+
stylize : function(str, style) {
|
10
|
+
var styles = {
|
11
|
+
'reset' : [0, 0],
|
12
|
+
'bold' : [1, 22],
|
13
|
+
'inverse' : [7, 27],
|
14
|
+
'underline' : [4, 24],
|
15
|
+
'yellow' : [33, 39],
|
16
|
+
'green' : [32, 39],
|
17
|
+
'red' : [31, 39],
|
18
|
+
'grey' : [90, 39]
|
19
|
+
};
|
20
|
+
return '\033[' + styles[style][0] + 'm' + str +
|
21
|
+
'\033[' + styles[style][1] + 'm';
|
22
|
+
},
|
23
|
+
|
24
|
+
//Print command line options
|
25
|
+
printUsage: function() {
|
26
|
+
sys.puts("usage: lessc [option option=parameter ...] <source> [destination]");
|
27
|
+
sys.puts("");
|
28
|
+
sys.puts("If source is set to `-' (dash or hyphen-minus), input is read from stdin.");
|
29
|
+
sys.puts("");
|
30
|
+
sys.puts("options:");
|
31
|
+
sys.puts(" -h, --help Print help (this message) and exit.");
|
32
|
+
sys.puts(" --include-path Set include paths. Separated by `:'. Use `;' on Windows.");
|
33
|
+
sys.puts(" --no-color Disable colorized output.");
|
34
|
+
sys.puts(" -s, --silent Suppress output of error messages.");
|
35
|
+
sys.puts(" --strict-imports Force evaluation of imports.");
|
36
|
+
sys.puts(" --verbose Be verbose.");
|
37
|
+
sys.puts(" -v, --version Print version number and exit.");
|
38
|
+
sys.puts(" -x, --compress Compress output by removing some whitespaces.");
|
39
|
+
sys.puts(" --yui-compress Compress output using ycssmin");
|
40
|
+
sys.puts(" -O0, -O1, -O2 Set the parser's optimization level. The lower");
|
41
|
+
sys.puts(" the number, the less nodes it will create in the");
|
42
|
+
sys.puts(" tree. This could matter for debugging, or if you");
|
43
|
+
sys.puts(" want to access the individual nodes in the tree.");
|
44
|
+
sys.puts(" --line-numbers=TYPE Outputs filename and line numbers.");
|
45
|
+
sys.puts(" TYPE can be either 'comments', which will output");
|
46
|
+
sys.puts(" the debug info within comments, 'mediaquery'");
|
47
|
+
sys.puts(" that will output the information within a fake");
|
48
|
+
sys.puts(" media query which is compatible with the SASS");
|
49
|
+
sys.puts(" format, and 'all' which will do both.");
|
50
|
+
sys.puts(" -rp, --rootpath Set rootpath for url rewriting in relative imports and urls.");
|
51
|
+
sys.puts(" Works with or withour the relative-urls option.");
|
52
|
+
sys.puts(" -ru, --relative-urls re-write relative urls to the base less file.");
|
53
|
+
sys.puts("");
|
54
|
+
sys.puts("Report bugs to: http://github.com/cloudhead/less.js/issues");
|
55
|
+
sys.puts("Home page: <http://lesscss.org/>");
|
56
|
+
}
|
57
|
+
|
58
|
+
|
59
|
+
}
|
60
|
+
|
61
|
+
// Exports helper functions
|
62
|
+
for (var h in lessc_helper) { exports[h] = lessc_helper[h] }
|
@@ -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),
|
@@ -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,23 +823,80 @@ 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;
|
763
893
|
}
|
764
894
|
|
765
895
|
if (elements.length > 0 && ($(';') || peek('}'))) {
|
766
|
-
return new(tree.mixin.Call)(elements, args
|
896
|
+
return new(tree.mixin.Call)(elements, args, index, env.filename, important);
|
767
897
|
}
|
898
|
+
|
899
|
+
restore();
|
768
900
|
},
|
769
901
|
|
770
902
|
//
|
@@ -789,16 +921,18 @@ less.Parser = function Parser(env) {
|
|
789
921
|
definition: function () {
|
790
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
931
|
do {
|
932
|
+
$(this.comment);
|
800
933
|
if (input.charAt(i) === '.' && $(/^\.{3}/)) {
|
801
934
|
variadic = true;
|
935
|
+
params.push({ variadic: true });
|
802
936
|
break;
|
803
937
|
} else if (param = $(this.entities.variable) || $(this.entities.literal)
|
804
938
|
|| $(this.entities.keyword)) {
|
@@ -820,9 +954,16 @@ less.Parser = function Parser(env) {
|
|
820
954
|
} else {
|
821
955
|
break;
|
822
956
|
}
|
823
|
-
} while ($(','))
|
957
|
+
} while ($(',') || $(';'))
|
824
958
|
|
825
|
-
|
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();
|
964
|
+
}
|
965
|
+
|
966
|
+
$(this.comment);
|
826
967
|
|
827
968
|
if ($(/^when/)) { // Guard
|
828
969
|
cond = expect(this.conditions, 'expected condition');
|
@@ -845,7 +986,7 @@ less.Parser = function Parser(env) {
|
|
845
986
|
//
|
846
987
|
entity: function () {
|
847
988
|
return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) ||
|
848
|
-
$(this.entities.call) || $(this.entities.keyword)
|
989
|
+
$(this.entities.call) || $(this.entities.keyword) ||$(this.entities.javascript) ||
|
849
990
|
$(this.comment);
|
850
991
|
},
|
851
992
|
|
@@ -889,18 +1030,22 @@ less.Parser = function Parser(env) {
|
|
889
1030
|
var e, t, c, v;
|
890
1031
|
|
891
1032
|
c = $(this.combinator);
|
892
|
-
|
893
|
-
|
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);
|
894
1036
|
|
895
1037
|
if (! e) {
|
896
|
-
|
1038
|
+
if ($('(')) {
|
1039
|
+
if ((v = ($(this.entities.variableCurly) ||
|
1040
|
+
$(this.entities.variable) ||
|
1041
|
+
$(this.selector))) &&
|
1042
|
+
$(')')) {
|
1043
|
+
e = new(tree.Paren)(v);
|
1044
|
+
}
|
1045
|
+
}
|
897
1046
|
}
|
898
1047
|
|
899
1048
|
if (e) { return new(tree.Element)(c, e, i) }
|
900
|
-
|
901
|
-
if (c.value && c.value.charAt(0) === '&') {
|
902
|
-
return new(tree.Element)(c, null, i);
|
903
|
-
}
|
904
1049
|
},
|
905
1050
|
|
906
1051
|
//
|
@@ -915,19 +1060,11 @@ less.Parser = function Parser(env) {
|
|
915
1060
|
combinator: function () {
|
916
1061
|
var match, c = input.charAt(i);
|
917
1062
|
|
918
|
-
if (c === '>' || c === '+' || c === '~') {
|
1063
|
+
if (c === '>' || c === '+' || c === '~' || c === '|') {
|
919
1064
|
i++;
|
920
|
-
while (input.charAt(i)
|
1065
|
+
while (input.charAt(i).match(/\s/)) { i++ }
|
921
1066
|
return new(tree.Combinator)(c);
|
922
|
-
} else if (
|
923
|
-
match = '&';
|
924
|
-
i++;
|
925
|
-
if(input.charAt(i) === ' ') {
|
926
|
-
match = '& ';
|
927
|
-
}
|
928
|
-
while (input.charAt(i) === ' ') { i++ }
|
929
|
-
return new(tree.Combinator)(match);
|
930
|
-
} else if (input.charAt(i - 1) === ' ') {
|
1067
|
+
} else if (input.charAt(i - 1).match(/\s/)) {
|
931
1068
|
return new(tree.Combinator)(" ");
|
932
1069
|
} else {
|
933
1070
|
return new(tree.Combinator)(null);
|
@@ -945,29 +1082,27 @@ less.Parser = function Parser(env) {
|
|
945
1082
|
selector: function () {
|
946
1083
|
var sel, e, elements = [], c, match;
|
947
1084
|
|
1085
|
+
// depreciated, will be removed soon
|
948
1086
|
if ($('(')) {
|
949
1087
|
sel = $(this.entity);
|
950
|
-
|
1088
|
+
if (!$(')')) { return null; }
|
951
1089
|
return new(tree.Selector)([new(tree.Element)('', sel, i)]);
|
952
1090
|
}
|
953
1091
|
|
954
1092
|
while (e = $(this.element)) {
|
955
1093
|
c = input.charAt(i);
|
956
1094
|
elements.push(e)
|
957
|
-
if (c === '{' || c === '}' || c === ';' || c === ',') { break }
|
1095
|
+
if (c === '{' || c === '}' || c === ';' || c === ',' || c === ')') { break }
|
958
1096
|
}
|
959
1097
|
|
960
1098
|
if (elements.length > 0) { return new(tree.Selector)(elements) }
|
961
1099
|
},
|
962
|
-
tag: function () {
|
963
|
-
return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*');
|
964
|
-
},
|
965
1100
|
attribute: function () {
|
966
1101
|
var attr = '', key, val, op;
|
967
1102
|
|
968
1103
|
if (! $('[')) return;
|
969
1104
|
|
970
|
-
if (key = $(/^[
|
1105
|
+
if (key = $(/^(?:[_A-Za-z0-9-]|\\.)+/) || $(this.entities.quoted)) {
|
971
1106
|
if ((op = $(/^[|~*$^]?=/)) &&
|
972
1107
|
(val = $(this.entities.quoted) || $(/^[\w-]+/))) {
|
973
1108
|
attr = [key, op, val.toCSS ? val.toCSS() : val].join('');
|
@@ -985,7 +1120,6 @@ less.Parser = function Parser(env) {
|
|
985
1120
|
//
|
986
1121
|
block: function () {
|
987
1122
|
var content;
|
988
|
-
|
989
1123
|
if ($('{') && (content = $(this.primary)) && $('}')) {
|
990
1124
|
return content;
|
991
1125
|
}
|
@@ -995,9 +1129,13 @@ less.Parser = function Parser(env) {
|
|
995
1129
|
// div, .class, body > p {...}
|
996
1130
|
//
|
997
1131
|
ruleset: function () {
|
998
|
-
var selectors = [], s, rules, match;
|
1132
|
+
var selectors = [], s, rules, match, debugInfo;
|
1133
|
+
|
999
1134
|
save();
|
1000
1135
|
|
1136
|
+
if (env.dumpLineNumbers)
|
1137
|
+
debugInfo = getDebugInfo(i, input, env);
|
1138
|
+
|
1001
1139
|
while (s = $(this.selector)) {
|
1002
1140
|
selectors.push(s);
|
1003
1141
|
$(this.comment);
|
@@ -1006,7 +1144,10 @@ less.Parser = function Parser(env) {
|
|
1006
1144
|
}
|
1007
1145
|
|
1008
1146
|
if (selectors.length > 0 && (rules = $(this.block))) {
|
1009
|
-
|
1147
|
+
var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports);
|
1148
|
+
if (env.dumpLineNumbers)
|
1149
|
+
ruleset.debugInfo = debugInfo;
|
1150
|
+
return ruleset;
|
1010
1151
|
} else {
|
1011
1152
|
// Backtrack
|
1012
1153
|
furthest = i;
|
@@ -1051,13 +1192,19 @@ less.Parser = function Parser(env) {
|
|
1051
1192
|
//
|
1052
1193
|
"import": function () {
|
1053
1194
|
var path, features, index = i;
|
1054
|
-
|
1055
|
-
|
1195
|
+
|
1196
|
+
save();
|
1197
|
+
|
1198
|
+
var dir = $(/^@import(?:-(once))?\s+/);
|
1199
|
+
|
1200
|
+
if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) {
|
1056
1201
|
features = $(this.mediaFeatures);
|
1057
1202
|
if ($(';')) {
|
1058
|
-
return new(tree.Import)(path, imports, features, index);
|
1203
|
+
return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index, env.rootpath);
|
1059
1204
|
}
|
1060
1205
|
}
|
1206
|
+
|
1207
|
+
restore();
|
1061
1208
|
},
|
1062
1209
|
|
1063
1210
|
mediaFeature: function () {
|
@@ -1088,7 +1235,7 @@ less.Parser = function Parser(env) {
|
|
1088
1235
|
|
1089
1236
|
mediaFeatures: function () {
|
1090
1237
|
var e, features = [];
|
1091
|
-
|
1238
|
+
|
1092
1239
|
do {
|
1093
1240
|
if (e = $(this.mediaFeature)) {
|
1094
1241
|
features.push(e);
|
@@ -1098,18 +1245,24 @@ less.Parser = function Parser(env) {
|
|
1098
1245
|
if (! $(',')) { break }
|
1099
1246
|
}
|
1100
1247
|
} while (e);
|
1101
|
-
|
1248
|
+
|
1102
1249
|
return features.length > 0 ? features : null;
|
1103
1250
|
},
|
1104
1251
|
|
1105
1252
|
media: function () {
|
1106
|
-
var features, rules;
|
1253
|
+
var features, rules, media, debugInfo;
|
1254
|
+
|
1255
|
+
if (env.dumpLineNumbers)
|
1256
|
+
debugInfo = getDebugInfo(i, input, env);
|
1107
1257
|
|
1108
1258
|
if ($(/^@media/)) {
|
1109
1259
|
features = $(this.mediaFeatures);
|
1110
1260
|
|
1111
1261
|
if (rules = $(this.block)) {
|
1112
|
-
|
1262
|
+
media = new(tree.Media)(rules, features);
|
1263
|
+
if(env.dumpLineNumbers)
|
1264
|
+
media.debugInfo = debugInfo;
|
1265
|
+
return media;
|
1113
1266
|
}
|
1114
1267
|
}
|
1115
1268
|
},
|
@@ -1120,26 +1273,81 @@ less.Parser = function Parser(env) {
|
|
1120
1273
|
// @charset "utf-8";
|
1121
1274
|
//
|
1122
1275
|
directive: function () {
|
1123
|
-
var name, value, rules,
|
1276
|
+
var name, value, rules, identifier, e, nodes, nonVendorSpecificName,
|
1277
|
+
hasBlock, hasIdentifier, hasExpression;
|
1124
1278
|
|
1125
1279
|
if (input.charAt(i) !== '@') return;
|
1126
1280
|
|
1127
1281
|
if (value = $(this['import']) || $(this.media)) {
|
1128
1282
|
return value;
|
1129
|
-
}
|
1130
|
-
|
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
|
+
{
|
1131
1337
|
if (rules = $(this.block)) {
|
1132
|
-
return new(tree.Directive)(name
|
1338
|
+
return new(tree.Directive)(name, rules);
|
1133
1339
|
}
|
1134
|
-
} else
|
1135
|
-
if (
|
1136
|
-
|
1137
|
-
|
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);
|
1138
1345
|
}
|
1139
|
-
|
1140
|
-
return new(tree.Directive)(name, value);
|
1346
|
+
return directive;
|
1141
1347
|
}
|
1142
1348
|
}
|
1349
|
+
|
1350
|
+
restore();
|
1143
1351
|
},
|
1144
1352
|
font: function () {
|
1145
1353
|
var value = [], expression = [], weight, shorthand, font, e;
|
@@ -1193,7 +1401,7 @@ less.Parser = function Parser(env) {
|
|
1193
1401
|
multiplication: function () {
|
1194
1402
|
var m, a, op, operation;
|
1195
1403
|
if (m = $(this.operand)) {
|
1196
|
-
while (!peek(
|
1404
|
+
while (!peek(/^\/[*\/]/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) {
|
1197
1405
|
operation = new(tree.Operation)(op, [operation || m, a]);
|
1198
1406
|
}
|
1199
1407
|
return operation || m;
|
@@ -1202,7 +1410,7 @@ less.Parser = function Parser(env) {
|
|
1202
1410
|
addition: function () {
|
1203
1411
|
var m, a, op, operation;
|
1204
1412
|
if (m = $(this.multiplication)) {
|
1205
|
-
while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1)
|
1413
|
+
while ((op = $(/^[-+]\s+/) || (!isWhitespace(input.charAt(i - 1)) && ($('+') || $('-')))) &&
|
1206
1414
|
(a = $(this.multiplication))) {
|
1207
1415
|
operation = new(tree.Operation)(op, [operation || m, a]);
|
1208
1416
|
}
|
@@ -1274,7 +1482,7 @@ less.Parser = function Parser(env) {
|
|
1274
1482
|
property: function () {
|
1275
1483
|
var name;
|
1276
1484
|
|
1277
|
-
if (name = $(/^(\*?-?[-
|
1485
|
+
if (name = $(/^(\*?-?[_a-z0-9-]+)\s*:/)) {
|
1278
1486
|
return name[1];
|
1279
1487
|
}
|
1280
1488
|
}
|
@@ -1287,17 +1495,26 @@ if (less.mode === 'browser' || less.mode === 'rhino') {
|
|
1287
1495
|
// Used by `@import` directives
|
1288
1496
|
//
|
1289
1497
|
less.Parser.importer = function (path, paths, callback, env) {
|
1290
|
-
if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) {
|
1498
|
+
if (!/^([a-z-]+:)?\//.test(path) && paths.length > 0) {
|
1291
1499
|
path = paths[0] + path;
|
1292
1500
|
}
|
1293
1501
|
// We pass `true` as 3rd argument, to force the reload of the import.
|
1294
1502
|
// This is so we can get the syntax tree as opposed to just the CSS output,
|
1295
1503
|
// as we need this to evaluate the current stylesheet.
|
1296
|
-
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) {
|
1297
1514
|
if (e && typeof(env.errback) === "function") {
|
1298
1515
|
env.errback.call(null, path, paths, callback, env);
|
1299
1516
|
} else {
|
1300
|
-
callback.
|
1517
|
+
callback.call(null, e, root, path);
|
1301
1518
|
}
|
1302
1519
|
}, true);
|
1303
1520
|
};
|