webpackbar icon indicating copy to clipboard operation
webpackbar copied to clipboard

erase the prev lines length

Open LIUeng opened this issue 4 years ago • 4 comments

problem description

  1. when the process.stderr.columns less than console.log('xxxxxx') string width, extra lines log, wrap line normal;
  2. the prevLineCount variable length calculate error;
  3. cause the terminal stdout occurs many whitespace lines;

source code

// LogUpdate -> render
const data = ansiEscapes.eraseLines(this.prevLineCount) + wrappedLines + '\n' + this.extraLines;
this.write(data);
// it's my problem === length is not true
this.prevLineCount = data.split('\n').length;

could you calculate length below?

this.prevLineCount = data.split('\n').length;
this.extraLines.split('\n').forEach(str => {
  if (str.length > this.columns) {
    this.prevLineCount += 1
  }
});

That's all, thank you!

LIUeng avatar Aug 27 '21 02:08 LIUeng

Hi @LIUeng. Nice find sure it would be nice idea doing wrap aware line-count. Do you mind opening a PR for fix?

pi0 avatar Aug 27 '21 09:08 pi0

Hi @LIUeng. Nice find sure it would be nice idea doing wrap aware line-count. Do you mind opening a PR for fix?

I'm sorry too late reply! Yes, I'am pleasure fix the problem!

LIUeng avatar Aug 30 '21 07:08 LIUeng

I was just experiencing this bug where extra whitespace lines are added for each line update when showing progress. Looking forward to seeing this addressed. Thanks @LIUeng

TSMMark avatar Sep 15 '21 17:09 TSMMark

Here is my patch if anyone is interested. generated using https://github.com/ds300/patch-package

basically, wrapped lines needs to be taken into account when counting the lines, to get the correct line length you need to strip the ascii-escapes.

This works, however it might slip up when resizing the window because prevLineCount may not be updated during resize and re-render will briefly have the wrong count, it might add or remove lines. it's a rare occurrence though and should be ok.

diff --git a/node_modules/webpackbar/dist/webpackbar.js b/node_modules/webpackbar/dist/webpackbar.js
index 2ece25a..7ff3aca 100644
--- a/node_modules/webpackbar/dist/webpackbar.js
+++ b/node_modules/webpackbar/dist/webpackbar.js
@@ -22,6 +22,23 @@ const textTable__default = /*#__PURE__*/_interopDefaultLegacy(textTable);
 const ansiEscapes__default = /*#__PURE__*/_interopDefaultLegacy(ansiEscapes);
 const wrapAnsi__default = /*#__PURE__*/_interopDefaultLegacy(wrapAnsi);
 
+function ansiRegex({onlyFirst = false} = {}) {
+	const pattern = [
+		'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
+		'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))'
+	].join('|');
+
+	return new RegExp(pattern, onlyFirst ? undefined : 'g');
+}
+
+function stripAnsi(string) {
+	if (typeof string !== 'string') {
+		throw new TypeError(`Expected a \`string\`, got \`${typeof string}\``);
+	}
+
+	return string.replace(ansiRegex(), '');
+}
+
 function first(arr) {
   return arr[0];
 }
@@ -136,7 +153,9 @@ class LogUpdate {
     });
     const data = ansiEscapes__default['default'].eraseLines(this.prevLineCount) + wrappedLines + "\n" + this.extraLines;
     this.write(data);
-    this.prevLineCount = data.split("\n").length;
+    this.prevLineCount = stripAnsi(data).split("\n")
+                    .map(l => l.length == 0 ? 1 : Math.ceil(l.length / this.columns))
+                    .reduce((a, b) => a+b);
   }
   get columns() {
     return (process.stderr.columns || 80) - 2;
@@ -159,8 +178,12 @@ class LogUpdate {
     this.extraLines = "";
   }
   _onData(data) {
-    const str = String(data);
-    const lines = str.split("\n").length - 1;
+    const str = stripAnsi(data);
+    const lines = str
+                    .split("\n")
+                    .map(l => l.length == 0 ? 1 : Math.ceil(l.length / this.columns))
+                    .reduce((a, b) => a+b) - 1;
+
     if (lines > 0) {
       this.prevLineCount += lines;
       this.extraLines += data;
@@ -468,7 +491,10 @@ class WebpackBarPlugin extends webpack.ProgressPlugin {
     super({activeModules: true});
     this.options = Object.assign({}, DEFAULTS, options);
     this.handler = (percent, message, ...details) => {
-      this.updateProgress(percent, message, details);
+      // Webpack is initilizing the progress way too early
+      if (percent > 0.01){
+        this.updateProgress(percent, message, details);
+      }
     };
     const _reporters = Array.from(this.options.reporters || []).concat(this.options.reporter).filter(Boolean).map((reporter) => {
       if (Array.isArray(reporter)) {

serkanyersen avatar Nov 04 '21 02:11 serkanyersen