index.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. 'use strict';
  2. const ANSI_BACKGROUND_OFFSET = 10;
  3. const wrapAnsi256 = (offset = 0) => code => `\u001B[${38 + offset};5;${code}m`;
  4. const wrapAnsi16m = (offset = 0) => (red, green, blue) => `\u001B[${38 + offset};2;${red};${green};${blue}m`;
  5. function assembleStyles() {
  6. const codes = new Map();
  7. const styles = {
  8. modifier: {
  9. reset: [0, 0],
  10. // 21 isn't widely supported and 22 does the same thing
  11. bold: [1, 22],
  12. dim: [2, 22],
  13. italic: [3, 23],
  14. underline: [4, 24],
  15. overline: [53, 55],
  16. inverse: [7, 27],
  17. hidden: [8, 28],
  18. strikethrough: [9, 29]
  19. },
  20. color: {
  21. black: [30, 39],
  22. red: [31, 39],
  23. green: [32, 39],
  24. yellow: [33, 39],
  25. blue: [34, 39],
  26. magenta: [35, 39],
  27. cyan: [36, 39],
  28. white: [37, 39],
  29. // Bright color
  30. blackBright: [90, 39],
  31. redBright: [91, 39],
  32. greenBright: [92, 39],
  33. yellowBright: [93, 39],
  34. blueBright: [94, 39],
  35. magentaBright: [95, 39],
  36. cyanBright: [96, 39],
  37. whiteBright: [97, 39]
  38. },
  39. bgColor: {
  40. bgBlack: [40, 49],
  41. bgRed: [41, 49],
  42. bgGreen: [42, 49],
  43. bgYellow: [43, 49],
  44. bgBlue: [44, 49],
  45. bgMagenta: [45, 49],
  46. bgCyan: [46, 49],
  47. bgWhite: [47, 49],
  48. // Bright color
  49. bgBlackBright: [100, 49],
  50. bgRedBright: [101, 49],
  51. bgGreenBright: [102, 49],
  52. bgYellowBright: [103, 49],
  53. bgBlueBright: [104, 49],
  54. bgMagentaBright: [105, 49],
  55. bgCyanBright: [106, 49],
  56. bgWhiteBright: [107, 49]
  57. }
  58. };
  59. // Alias bright black as gray (and grey)
  60. styles.color.gray = styles.color.blackBright;
  61. styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
  62. styles.color.grey = styles.color.blackBright;
  63. styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
  64. for (const [groupName, group] of Object.entries(styles)) {
  65. for (const [styleName, style] of Object.entries(group)) {
  66. styles[styleName] = {
  67. open: `\u001B[${style[0]}m`,
  68. close: `\u001B[${style[1]}m`
  69. };
  70. group[styleName] = styles[styleName];
  71. codes.set(style[0], style[1]);
  72. }
  73. Object.defineProperty(styles, groupName, {
  74. value: group,
  75. enumerable: false
  76. });
  77. }
  78. Object.defineProperty(styles, 'codes', {
  79. value: codes,
  80. enumerable: false
  81. });
  82. styles.color.close = '\u001B[39m';
  83. styles.bgColor.close = '\u001B[49m';
  84. styles.color.ansi256 = wrapAnsi256();
  85. styles.color.ansi16m = wrapAnsi16m();
  86. styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
  87. styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
  88. // From https://github.com/Qix-/color-convert/blob/3f0e0d4e92e235796ccb17f6e85c72094a651f49/conversions.js
  89. Object.defineProperties(styles, {
  90. rgbToAnsi256: {
  91. value: (red, green, blue) => {
  92. // We use the extended greyscale palette here, with the exception of
  93. // black and white. normal palette only has 4 greyscale shades.
  94. if (red === green && green === blue) {
  95. if (red < 8) {
  96. return 16;
  97. }
  98. if (red > 248) {
  99. return 231;
  100. }
  101. return Math.round(((red - 8) / 247) * 24) + 232;
  102. }
  103. return 16 +
  104. (36 * Math.round(red / 255 * 5)) +
  105. (6 * Math.round(green / 255 * 5)) +
  106. Math.round(blue / 255 * 5);
  107. },
  108. enumerable: false
  109. },
  110. hexToRgb: {
  111. value: hex => {
  112. const matches = /(?<colorString>[a-f\d]{6}|[a-f\d]{3})/i.exec(hex.toString(16));
  113. if (!matches) {
  114. return [0, 0, 0];
  115. }
  116. let {colorString} = matches.groups;
  117. if (colorString.length === 3) {
  118. colorString = colorString.split('').map(character => character + character).join('');
  119. }
  120. const integer = Number.parseInt(colorString, 16);
  121. return [
  122. (integer >> 16) & 0xFF,
  123. (integer >> 8) & 0xFF,
  124. integer & 0xFF
  125. ];
  126. },
  127. enumerable: false
  128. },
  129. hexToAnsi256: {
  130. value: hex => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
  131. enumerable: false
  132. }
  133. });
  134. return styles;
  135. }
  136. // Make the export immutable
  137. Object.defineProperty(module, 'exports', {
  138. enumerable: true,
  139. get: assembleStyles
  140. });