Skip to content

Commit e2575ce

Browse files
committed
Move error formatting logic to LessError
1 parent badb72f commit e2575ce

File tree

4 files changed

+92
-67
lines changed

4 files changed

+92
-67
lines changed

bin/lessc

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ var less = require('../lib/less-node'),
3737
modifyVars: null,
3838
urlArgs: '',
3939
plugins: plugins
40-
};
40+
};
4141

4242
if (less.options) {
4343
for (var i = 0, keys = Object.keys(options); i < keys.length; i++) {
@@ -310,7 +310,11 @@ function render() {
310310
}
311311
},
312312
function(err) {
313-
less.writeError(err, options);
313+
if (!options.silent) {
314+
console.error(err.toString({
315+
stylize: options.color && less.lesscHelper.stylize
316+
}));
317+
}
314318
process.exitCode = 1;
315319
});
316320
};

lib/less-node/index.js

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -14,62 +14,6 @@ less.FileManager = FileManager;
1414
less.UrlFileManager = UrlFileManager;
1515
less.options = less.options || {};
1616

17-
less.formatError = function(ctx, options) {
18-
options = options || {};
19-
20-
var message = "";
21-
var extract = ctx.extract;
22-
var error = [];
23-
var stylize = options.color ? lesscHelper.stylize : function (str) { return str; };
24-
25-
// only output a stack if it isn't a less error
26-
if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }
27-
28-
if (!ctx.hasOwnProperty('index') || !extract) {
29-
return ctx.stack || ctx.message;
30-
}
31-
32-
if (typeof extract[0] === 'string') {
33-
error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
34-
}
35-
36-
if (typeof extract[1] === 'string') {
37-
var errorTxt = ctx.line + ' ';
38-
if (extract[1]) {
39-
errorTxt += extract[1].slice(0, ctx.column) +
40-
stylize(stylize(stylize(extract[1].substr(ctx.column, 1), 'bold') +
41-
extract[1].slice(ctx.column + 1), 'red'), 'inverse');
42-
}
43-
error.push(errorTxt);
44-
}
45-
46-
if (typeof extract[2] === 'string') {
47-
error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
48-
}
49-
error = error.join('\n') + stylize('', 'reset') + '\n';
50-
51-
message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
52-
if (ctx.filename) {
53-
message += stylize(' in ', 'red') + ctx.filename +
54-
stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey');
55-
}
56-
57-
message += '\n' + error;
58-
59-
if (ctx.callLine) {
60-
message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
61-
message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
62-
}
63-
64-
return message;
65-
};
66-
67-
less.writeError = function (ctx, options) {
68-
options = options || {};
69-
if (options.silent) { return; }
70-
console.error(less.formatError(ctx, options));
71-
};
72-
7317
// provide image-size functionality
7418
require('./image-size')(less.environment);
7519

lib/less/less-error.js

Lines changed: 80 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,27 @@
1-
var utils = require("./utils");
2-
1+
var utils = require('./utils');
2+
/**
3+
* This is a centralized class of any error that could be thrown internally (mostly by the parser).
4+
* Besides standard .message it keeps some additional data like a path to the file where the error
5+
* occurred along with line and column numbers.
6+
*
7+
* @class
8+
* @extends Error
9+
* @type {module.LessError}
10+
*
11+
* @prop {string} type
12+
* @prop {string} filename
13+
* @prop {number} index
14+
* @prop {number} line
15+
* @prop {number} column
16+
* @prop {number} callLine
17+
* @prop {number} callExtract
18+
* @prop {string[]} extract
19+
*
20+
* @param {Object} e - An error object to wrap around or just a descriptive object
21+
* @param {Object} importManager - An instance of ImportManager (see import-manager.js)
22+
* @param {string} [currentFilename]
23+
*/
324
var LessError = module.exports = function LessError(e, importManager, currentFilename) {
4-
525
Error.call(this);
626

727
var filename = e.filename || currentFilename;
@@ -40,3 +60,60 @@ if (typeof Object.create === 'undefined') {
4060
}
4161

4262
LessError.prototype.constructor = LessError;
63+
64+
/**
65+
* An overridden version of the default Object.prototype.toString
66+
* which uses additional information to create a helpful message.
67+
*
68+
* @param {Object} options
69+
* @returns {string}
70+
*/
71+
LessError.prototype.toString = function(options) {
72+
options = options || {};
73+
74+
var message = '';
75+
var extract = this.extract;
76+
var error = [];
77+
var stylize = function (str) { return str; };
78+
if (options.stylize) {
79+
var type = typeof options.stylize;
80+
if (type !== 'function') {
81+
throw Error('options.stylize should be a function, got a ' + type + '!');
82+
}
83+
stylize = options.stylize;
84+
}
85+
86+
if (typeof extract[0] === 'string') {
87+
error.push(stylize((this.line - 1) + ' ' + extract[0], 'grey'));
88+
}
89+
90+
if (typeof extract[1] === 'string') {
91+
var errorTxt = this.line + ' ';
92+
if (extract[1]) {
93+
errorTxt += extract[1].slice(0, this.column) +
94+
stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') +
95+
extract[1].slice(this.column + 1), 'red'), 'inverse');
96+
}
97+
error.push(errorTxt);
98+
}
99+
100+
if (typeof extract[2] === 'string') {
101+
error.push(stylize((this.line + 1) + ' ' + extract[2], 'grey'));
102+
}
103+
error = error.join('\n') + stylize('', 'reset') + '\n';
104+
105+
message += stylize(this.type + 'Error: ' + this.message, 'red');
106+
if (this.filename) {
107+
message += stylize(' in ', 'red') + this.filename +
108+
stylize(' on line ' + this.line + ', column ' + (this.column + 1) + ':', 'grey');
109+
}
110+
111+
message += '\n' + error;
112+
113+
if (this.callLine) {
114+
message += stylize('from ', 'red') + (this.filename || '') + '/n';
115+
message += stylize(this.callLine, 'grey') + ' ' + this.callExtract + '/n';
116+
}
117+
118+
return message;
119+
};

test/less-test.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -136,20 +136,20 @@ module.exports = function() {
136136

137137
function testErrors(name, err, compiledLess, doReplacements, sourcemap, baseFolder) {
138138
fs.readFile(path.join(baseFolder, name) + '.txt', 'utf8', function (e, expectedErr) {
139-
process.stdout.write("- " + path.join(baseFolder, name) + ": ");
139+
process.stdout.write('- ' + path.join(baseFolder, name) + ": ");
140140
expectedErr = doReplacements(expectedErr, baseFolder);
141141
if (!err) {
142142
if (compiledLess) {
143-
fail("No Error", 'red');
143+
fail('No Error', 'red');
144144
} else {
145-
fail("No Error, No Output");
145+
fail('No Error, No Output');
146146
}
147147
} else {
148-
var errMessage = less.formatError(err);
148+
var errMessage = err.toString();
149149
if (errMessage === expectedErr) {
150150
ok('OK');
151151
} else {
152-
difference("FAIL", expectedErr, errMessage);
152+
difference('FAIL', expectedErr, errMessage);
153153
}
154154
}
155155
});
@@ -254,7 +254,7 @@ module.exports = function() {
254254
var doubleCallCheck = false;
255255
queue(function() {
256256
toCSS(options, path.join(baseFolder, foldername + file), function (err, result) {
257-
257+
258258
if (doubleCallCheck) {
259259
totalTests++;
260260
fail("less is calling back twice");

0 commit comments

Comments
 (0)