index.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. 'use strict';
  2. const colors = { enabled: true, visible: true, styles: {}, keys: {} };
  3. if ('FORCE_COLOR' in process.env) {
  4. colors.enabled = process.env.FORCE_COLOR !== '0';
  5. }
  6. const ansi = style => {
  7. style.open = `\u001b[${style.codes[0]}m`;
  8. style.close = `\u001b[${style.codes[1]}m`;
  9. style.regex = new RegExp(`\\u001b\\[${style.codes[1]}m`, 'g');
  10. return style;
  11. };
  12. const wrap = (style, str, nl) => {
  13. let { open, close, regex } = style;
  14. str = open + (str.includes(close) ? str.replace(regex, close + open) : str) + close;
  15. // see https://github.com/chalk/chalk/pull/92, thanks to the
  16. // chalk contributors for this fix. However, we've confirmed that
  17. // this issue is also present in Windows terminals
  18. return nl ? str.replace(/\r?\n/g, `${close}$&${open}`) : str;
  19. };
  20. const style = (input, stack) => {
  21. if (input === '' || input == null) return '';
  22. if (colors.enabled === false) return input;
  23. if (colors.visible === false) return '';
  24. let str = '' + input;
  25. let nl = str.includes('\n');
  26. let n = stack.length;
  27. while (n-- > 0) str = wrap(colors.styles[stack[n]], str, nl);
  28. return str;
  29. };
  30. const define = (name, codes, type) => {
  31. colors.styles[name] = ansi({ name, codes });
  32. let t = colors.keys[type] || (colors.keys[type] = []);
  33. t.push(name);
  34. Reflect.defineProperty(colors, name, {
  35. get() {
  36. let color = input => style(input, color.stack);
  37. Reflect.setPrototypeOf(color, colors);
  38. color.stack = this.stack ? this.stack.concat(name) : [name];
  39. return color;
  40. }
  41. });
  42. };
  43. define('reset', [0, 0], 'modifier');
  44. define('bold', [1, 22], 'modifier');
  45. define('dim', [2, 22], 'modifier');
  46. define('italic', [3, 23], 'modifier');
  47. define('underline', [4, 24], 'modifier');
  48. define('inverse', [7, 27], 'modifier');
  49. define('hidden', [8, 28], 'modifier');
  50. define('strikethrough', [9, 29], 'modifier');
  51. define('black', [30, 39], 'color');
  52. define('red', [31, 39], 'color');
  53. define('green', [32, 39], 'color');
  54. define('yellow', [33, 39], 'color');
  55. define('blue', [34, 39], 'color');
  56. define('magenta', [35, 39], 'color');
  57. define('cyan', [36, 39], 'color');
  58. define('white', [37, 39], 'color');
  59. define('gray', [90, 39], 'color');
  60. define('grey', [90, 39], 'color');
  61. define('bgBlack', [40, 49], 'bg');
  62. define('bgRed', [41, 49], 'bg');
  63. define('bgGreen', [42, 49], 'bg');
  64. define('bgYellow', [43, 49], 'bg');
  65. define('bgBlue', [44, 49], 'bg');
  66. define('bgMagenta', [45, 49], 'bg');
  67. define('bgCyan', [46, 49], 'bg');
  68. define('bgWhite', [47, 49], 'bg');
  69. define('blackBright', [90, 39], 'bright');
  70. define('redBright', [91, 39], 'bright');
  71. define('greenBright', [92, 39], 'bright');
  72. define('yellowBright', [93, 39], 'bright');
  73. define('blueBright', [94, 39], 'bright');
  74. define('magentaBright', [95, 39], 'bright');
  75. define('cyanBright', [96, 39], 'bright');
  76. define('whiteBright', [97, 39], 'bright');
  77. define('bgBlackBright', [100, 49], 'bgBright');
  78. define('bgRedBright', [101, 49], 'bgBright');
  79. define('bgGreenBright', [102, 49], 'bgBright');
  80. define('bgYellowBright', [103, 49], 'bgBright');
  81. define('bgBlueBright', [104, 49], 'bgBright');
  82. define('bgMagentaBright', [105, 49], 'bgBright');
  83. define('bgCyanBright', [106, 49], 'bgBright');
  84. define('bgWhiteBright', [107, 49], 'bgBright');
  85. /* eslint-disable no-control-regex */
  86. // this is a modified, optimized version of
  87. // https://github.com/chalk/ansi-regex (MIT License)
  88. const re = colors.ansiRegex = /[\u001b\u009b][[\]#;?()]*(?:(?:(?:[^\W_]*;?[^\W_]*)\u0007)|(?:(?:[0-9]{1,4}(;[0-9]{0,4})*)?[~0-9=<>cf-nqrtyA-PRZ]))/g;
  89. colors.hasColor = colors.hasAnsi = str => {
  90. re.lastIndex = 0;
  91. return !!str && typeof str === 'string' && re.test(str);
  92. };
  93. colors.unstyle = str => {
  94. re.lastIndex = 0;
  95. return typeof str === 'string' ? str.replace(re, '') : str;
  96. };
  97. colors.none = colors.clear = colors.noop = str => str; // no-op, for programmatic usage
  98. colors.stripColor = colors.unstyle;
  99. colors.symbols = require('./symbols');
  100. colors.define = define;
  101. module.exports = colors;