parcel-bundler
Version:
Blazing fast, zero configuration web application bundler
214 lines (178 loc) • 4.79 kB
JavaScript
const chalk = require('chalk');
const readline = require('readline');
const prettyError = require('./utils/prettyError');
const emoji = require('./utils/emoji');
const {countBreaks} = require('grapheme-breaker');
const stripAnsi = require('strip-ansi');
class Logger {
constructor(options) {
this.lines = 0;
this.statusLine = null;
this.setOptions(options);
}
setOptions(options) {
this.logLevel =
options && isNaN(options.logLevel) === false
? Number(options.logLevel)
: 3;
this.color =
options && typeof options.color === 'boolean'
? options.color
: chalk.supportsColor;
this.chalk = new chalk.constructor({enabled: this.color});
this.isTest =
options && typeof options.isTest === 'boolean'
? options.isTest
: process.env.NODE_ENV === 'test';
}
countLines(message) {
return message.split('\n').reduce((p, line) => {
if (process.stdout.columns) {
return p + Math.ceil((line.length || 1) / process.stdout.columns);
}
return p + 1;
}, 0);
}
writeRaw(message) {
this.lines += this.countLines(message) - 1;
process.stdout.write(message);
}
write(message, persistent = false) {
if (!persistent) {
this.lines += this.countLines(message);
}
this._log(message);
}
log(message) {
if (this.logLevel < 3) {
return;
}
this.write(message);
}
persistent(message) {
if (this.logLevel < 3) {
return;
}
this.write(this.chalk.bold(message), true);
}
warn(err) {
if (this.logLevel < 2) {
return;
}
let {message, stack} = prettyError(err, {color: this.color});
this.write(this.chalk.yellow(`${emoji.warning} ${message}`));
if (stack) {
this.write(stack);
}
}
error(err) {
if (this.logLevel < 1) {
return;
}
let {message, stack} = prettyError(err, {color: this.color});
this.status(emoji.error, message, 'red');
if (stack) {
this.write(stack);
}
}
clear() {
if (!this.color || this.isTest) {
return;
}
while (this.lines > 0) {
readline.clearLine(process.stdout, 0);
readline.moveCursor(process.stdout, 0, -1);
this.lines--;
}
readline.cursorTo(process.stdout, 0);
this.statusLine = null;
}
writeLine(line, msg) {
if (!this.color) {
return this.log(msg);
}
let n = this.lines - line;
let stdout = process.stdout;
readline.cursorTo(stdout, 0);
readline.moveCursor(stdout, 0, -n);
stdout.write(msg);
readline.clearLine(stdout, 1);
readline.cursorTo(stdout, 0);
readline.moveCursor(stdout, 0, n);
}
status(emoji, message, color = 'gray') {
if (this.logLevel < 3) {
return;
}
let hasStatusLine = this.statusLine != null;
if (!hasStatusLine) {
this.statusLine = this.lines;
}
this.writeLine(
this.statusLine,
this.chalk[color].bold(`${emoji} ${message}`)
);
if (!hasStatusLine) {
process.stdout.write('\n');
this.lines++;
}
}
handleMessage(options) {
this[options.method](...options.args);
}
_log(message) {
console.log(message);
}
table(columns, table) {
// Measure column widths
let colWidths = [];
for (let row of table) {
let i = 0;
for (let item of row) {
colWidths[i] = Math.max(colWidths[i] || 0, stringWidth(item));
i++;
}
}
// Render rows
for (let row of table) {
let items = row.map((item, i) => {
// Add padding between columns unless the alignment is the opposite to the
// next column and pad to the column width.
let padding =
!columns[i + 1] || columns[i + 1].align === columns[i].align ? 4 : 0;
return pad(item, colWidths[i] + padding, columns[i].align);
});
this.log(items.join(''));
}
}
}
// Pad a string with spaces on either side
function pad(text, length, align = 'left') {
let pad = ' '.repeat(length - stringWidth(text));
if (align === 'right') {
return pad + text;
}
return text + pad;
}
// Count visible characters in a string
function stringWidth(string) {
return countBreaks(stripAnsi('' + string));
}
// If we are in a worker, make a proxy class which will
// send the logger calls to the main process via IPC.
// These are handled in WorkerFarm and directed to handleMessage above.
if (process.send) {
class LoggerProxy {}
for (let method of Object.getOwnPropertyNames(Logger.prototype)) {
LoggerProxy.prototype[method] = (...args) => {
process.send({
type: 'logger',
method,
args
});
};
}
module.exports = new LoggerProxy();
} else {
module.exports = new Logger();
}