Search code examples
javascriptnode.jsobjecthexansi-escape

Red is colorless, orange is red, yellow is orange - Object value fetching and using colors output


I know the title is weird but if you read this, you'll understand what I actually meant.

So, there's my code:

const colors = {
  Red: 0xff0000,
  Orange: 0xffa500,
  Yellow: 0xffff00,
  Green: 0x008000,
  Blue: 0x0000ff,
  Indigo: 0x4b0082,
  Violet: 0xee82ee,
  Purple: 0x8c03fc
}

function ColorNameError(prefix, ...message) {
  Error.call(this);
  this.message = `[${prefix}]: ${message.join(" ")}`;
  this.name = "ColorNameError";
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, ColorNameError);
  }
}

ColorNameError.prototype = Object.create(Error.prototype);

function colorNames(colors) {
  if (typeof colors === "undefined") {
    throw new ColorNameError("NoObjectProvided", "No colors object provided.");
  }
  if (typeof colors !== "object") {
    throw new ColorNameError(
      "TypeError",
      `
  Expected colors to be an "object" but got "${typeof colors}" instead.`
    );
  }
  var colorNames = Object.keys(colors);
  var formattedColors = "";
  var responseTime = new Date();
  for (var i = 0; i < colorNames.length; i++) {
    var colorName = colorNames[i];
    var colorValue = colors[colorName];
    var ansiColor = hexToAnsi(colorValue);
    formattedColors += `\x1b[1m${colorName}\x1b[0m ${ansiColor}${ansiColor}\n`;
  }
  var totalColors = colorNames.length;
  var elapsedTime = new Date() - responseTime;
  formattedColors += `\u001b[1mTotal Colors: \u001b[36m${totalColors}\u001b[0m\n\u001b[1mResponse Time: \u001b[33m${elapsedTime}ms\u001b[0m`;

  return formattedColors;
}

/**
 *
 * @param {HexValueInput} hexValue
 * @returns {ansiCode} ansiCode
 */

function hexToAnsi(hexValue) {
  var hexString = hexValue.toString(16).padStart(6, "0");
  var r = parseInt(hexString.substring(0, 2), 16);
  var g = parseInt(hexString.substring(2, 4), 16);
  var b = parseInt(hexString.substring(4, 6), 16);
  var ansiColorCode =
    16 +
    36 * Math.round((r / 255) * 5) +
    6 * Math.round((g / 255) * 5) +
    Math.round((b / 255) * 5);
  return `\u001b[38;5;${ansiColorCode}m`;
}

It was supposed to log the color names from the colors object and the color was supposed to be the value of the color name like the Red key in the object was supposed to be the color Red as its value is Red hex. But instead of Red it is colorless like no color but the twist is, the next color Orange is Red! Like look at the screenshot

Screenshot


Solution

  • I believe the problem lies in this line of code:

    formattedColors += `\x1b[1m${colorName}\x1b[0m ${ansiColor}${ansiColor}\n`;
    

    The ${ansiColor}represents the escape sequence for changing the color

    This \x1b[1m represents the text to format bright

    This \x1b[0m represents to reset ( in order to set new color in next iteration )

    What you are doing wrong is that you have to apply the escape sequence before the actual text. Your sequence is one iteration ahead because you are applying ${ansiColor} at the end.

    I think this should do the trick, change this line:

    formattedColors += `\x1b[1m${ansiColor}${colorName}\x1b[0m\n`; //bright + colorEscape + colorName + reset
    

    Refer this article: How to change node.js's console font color?