webpack-progress-plugin
Version:
198 lines (176 loc) • 5.53 kB
JavaScript
var AnsiEscapes = require('ansi-escapes');
var AnsiStyles = require('ansi-styles');
var webpack = require('webpack');
require('object.assign').shim();
var bold = AnsiStyles.bold;
var inverse = AnsiStyles.inverse;
var red = AnsiStyles.red;
var yellow = AnsiStyles.yellow;
var green = AnsiStyles.green;
var blue = AnsiStyles.blue;
var magenta = AnsiStyles.magenta;
var cyan = AnsiStyles.cyan;
var bgRed = AnsiStyles.bgRed;
var bgYellow = AnsiStyles.bgYellow;
var bgGreen = AnsiStyles.bgGreen;
var bgBlue = AnsiStyles.bgBlue;
var cursorUp = AnsiEscapes.cursorUp;
var cursorDown = AnsiEscapes.cursorDown;
var eraseEndLine = AnsiEscapes.eraseEndLine;
var width = 50;
var stdoutLineCount = 0;
function wrap(color, text) {
return color.open + text + color.close;
}
function prepareNyan(nyan, colorMap, mapColors) {
return nyan.map(function(row, idx) {
return row.split('').reduce(function (arr, chr, j) {
var color = colorMap[idx][j];
var last = arr[arr.length - 1];
if (last && last.colorCode === color) {
last.text += chr;
return arr;
} else {
return arr.concat({
colorCode: color,
color: mapColors[color] || function(t) { return t; },
text: chr
});
}
}, []);
});
}
var nyanProgress = prepareNyan([
' ,--------, ',
' │▗▝ ▞ ▝ ˄---˄ ',
'~│ ▞ ▞ ❬.◕‿‿◕.❭',
' `w-w---- w w '
], [
' ggggggggggg ',
' gMMMMMMMggggg ',
'ggMMMMMMgwwwwwwg',
' gggggggggggg '
], {
g: function(t) { return t; },
M: function(t) { return wrap(bold, wrap(magenta, wrap(inverse, t))); },
w: function(t) { return wrap(bold, t); }
});
var nyanSuccess = prepareNyan([
' ,--------, ,------.',
' │▗▝ ▞ ▝ ˄---˄ / Nyan! |',
'~│ ▞ ▞ ❬.◕‿‿◕.❭--------’',
' `w-w---- w w '
], [
' ggggggggggg wwwwwwww',
' gMMMMMMMggggg wwwwwwwww',
'ggMMMMMMgwwwwwwgwwwwwwwww',
' gggggggggggg '
], {
g: function(t) { return t; },
M: function(t) { return wrap(bold, wrap(magenta, wrap(inverse, t))); },
w: function(t) { return wrap(bold, t); }
});
var rainbow = [
[
function(t) { return wrap(red, t); },
function(t) { return t.replace(/./g, ' '); }
],
[
function(t) { return wrap(bgRed, wrap(yellow, t)); },
function(t) { return wrap(bold, wrap(red, wrap(bgRed, t))); }
],
[
function(t) { return wrap(bgYellow, wrap(green, t)); },
function(t) { return wrap(bold, wrap(yellow, wrap(bgYellow, t))); }
],
[
function(t) { return wrap(bgGreen, wrap(blue, t)); },
function(t) { return wrap(bold, wrap(green, wrap(bgGreen, t))); }
],
[
function(t) { return wrap(inverse, wrap(blue, t)); },
function(t) { return wrap(bold, wrap(blue, wrap(bgBlue, t))); }
]
];
function drawRainbow(colors, width, step) {
var wave = ['\u2584', '\u2591'];
var text = '';
var line = '';
var idx = step;
for (var i = 0; i < width; i++) {
text += wave[idx % 2];
if((step + i) % 4 === 0) {
line += colors[idx % 2](text);
text = '';
idx++;
}
}
return text ? line + colors[idx % 2](text) : line;
}
function drawNyan(nyan, line, idx) {
return nyan[idx].reduce(function(l, obj) {
return l + obj.color(obj.text);
}, line);
}
function onProgress(progress, message, step, isInProgress, options) {
var progressWidth = Math.ceil(progress * width);
if (isInProgress)
options.logger(cursorUp(rainbow.length + stdoutLineCount + 2));
for (var i = 0; i < rainbow.length; i++) {
var line = drawRainbow(rainbow[i], progressWidth, step);
var nyanLine = i + ((step % 8 < 4) ? -1 : 0);
if (nyanLine < 4 && nyanLine >= 0) {
line = drawNyan(progress === 1 ? nyanSuccess : nyanProgress, line, nyanLine);
}
options.logger(line + eraseEndLine);
}
options.logger(wrap(cyan, message) + eraseEndLine +
(isInProgress && stdoutLineCount ? cursorDown(stdoutLineCount) : ''));
}
module.exports = function NyanProgressPlugin(options) {
var timer = 0;
var shift = 0;
var originalStdoutWrite;
var isPrintingProgress = false;
var isStarted = false;
var startTime = 0;
options = Object.assign({
debounceInterval: 180,
logger: console.log.bind(console), // eslint-disable-line no-console
hookStdout: true
}, options);
if (options.hookStdout) {
originalStdoutWrite = process.stdout.write;
process.stdout.write = function(msg) {
originalStdoutWrite.apply(process.stdout, arguments);
if (isStarted && !isPrintingProgress) {
stdoutLineCount += msg.split('\n').length - 1;
}
}
}
return new webpack.ProgressPlugin(function(progress, message) {
var now = new Date().getTime();
if (progress === 0) {
onProgress(progress, message, shift++, false, options);
startTime = now;
isStarted = true;
} if (progress === 1) {
isPrintingProgress = true;
var endTimeMessage = '(build time: ' + (now - startTime) / 1000 + ' seconds)';
onProgress(progress, message + ' ' + endTimeMessage, shift++, true, options);
isPrintingProgress = false;
if (originalStdoutWrite) {
process.stdout.write = originalStdoutWrite;
}
stdoutLineCount = 0;
isStarted = false;
}
else if (now - timer > options.debounceInterval) {
timer = now;
isPrintingProgress = true;
onProgress(progress, message, shift++, true, options);
isPrintingProgress = false;
}
});
};
;