utils.cjs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. 'use strict';
  2. const tty = require('node:tty');
  3. function _interopNamespaceCompat(e) {
  4. if (e && typeof e === 'object' && 'default' in e) return e;
  5. const n = Object.create(null);
  6. if (e) {
  7. for (const k in e) {
  8. n[k] = e[k];
  9. }
  10. }
  11. n.default = e;
  12. return n;
  13. }
  14. const tty__namespace = /*#__PURE__*/_interopNamespaceCompat(tty);
  15. const {
  16. env = {},
  17. argv = [],
  18. platform = ""
  19. } = typeof process === "undefined" ? {} : process;
  20. const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
  21. const isForced = "FORCE_COLOR" in env || argv.includes("--color");
  22. const isWindows = platform === "win32";
  23. const isDumbTerminal = env.TERM === "dumb";
  24. const isCompatibleTerminal = tty__namespace && tty__namespace.isatty && tty__namespace.isatty(1) && env.TERM && !isDumbTerminal;
  25. const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
  26. const isColorSupported = !isDisabled && (isForced || isWindows && !isDumbTerminal || isCompatibleTerminal || isCI);
  27. function replaceClose(index, string, close, replace, head = string.slice(0, Math.max(0, index)) + replace, tail = string.slice(Math.max(0, index + close.length)), next = tail.indexOf(close)) {
  28. return head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
  29. }
  30. function clearBleed(index, string, open, close, replace) {
  31. return index < 0 ? open + string + close : open + replaceClose(index, string, close, replace) + close;
  32. }
  33. function filterEmpty(open, close, replace = open, at = open.length + 1) {
  34. return (string) => string || !(string === "" || string === void 0) ? clearBleed(
  35. ("" + string).indexOf(close, at),
  36. string,
  37. open,
  38. close,
  39. replace
  40. ) : "";
  41. }
  42. function init(open, close, replace) {
  43. return filterEmpty(`\x1B[${open}m`, `\x1B[${close}m`, replace);
  44. }
  45. const colorDefs = {
  46. reset: init(0, 0),
  47. bold: init(1, 22, "\x1B[22m\x1B[1m"),
  48. dim: init(2, 22, "\x1B[22m\x1B[2m"),
  49. italic: init(3, 23),
  50. underline: init(4, 24),
  51. inverse: init(7, 27),
  52. hidden: init(8, 28),
  53. strikethrough: init(9, 29),
  54. black: init(30, 39),
  55. red: init(31, 39),
  56. green: init(32, 39),
  57. yellow: init(33, 39),
  58. blue: init(34, 39),
  59. magenta: init(35, 39),
  60. cyan: init(36, 39),
  61. white: init(37, 39),
  62. gray: init(90, 39),
  63. bgBlack: init(40, 49),
  64. bgRed: init(41, 49),
  65. bgGreen: init(42, 49),
  66. bgYellow: init(43, 49),
  67. bgBlue: init(44, 49),
  68. bgMagenta: init(45, 49),
  69. bgCyan: init(46, 49),
  70. bgWhite: init(47, 49),
  71. blackBright: init(90, 39),
  72. redBright: init(91, 39),
  73. greenBright: init(92, 39),
  74. yellowBright: init(93, 39),
  75. blueBright: init(94, 39),
  76. magentaBright: init(95, 39),
  77. cyanBright: init(96, 39),
  78. whiteBright: init(97, 39),
  79. bgBlackBright: init(100, 49),
  80. bgRedBright: init(101, 49),
  81. bgGreenBright: init(102, 49),
  82. bgYellowBright: init(103, 49),
  83. bgBlueBright: init(104, 49),
  84. bgMagentaBright: init(105, 49),
  85. bgCyanBright: init(106, 49),
  86. bgWhiteBright: init(107, 49)
  87. };
  88. function createColors(useColor = isColorSupported) {
  89. return useColor ? colorDefs : Object.fromEntries(Object.keys(colorDefs).map((key) => [key, String]));
  90. }
  91. const colors = createColors();
  92. function getColor(color, fallback = "reset") {
  93. return colors[color] || colors[fallback];
  94. }
  95. function colorize(color, text) {
  96. return getColor(color)(text);
  97. }
  98. const ansiRegex = [
  99. "[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)",
  100. "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"
  101. ].join("|");
  102. function stripAnsi(text) {
  103. return text.replace(new RegExp(ansiRegex, "g"), "");
  104. }
  105. function centerAlign(str, len, space = " ") {
  106. const free = len - str.length;
  107. if (free <= 0) {
  108. return str;
  109. }
  110. const freeLeft = Math.floor(free / 2);
  111. let _str = "";
  112. for (let i = 0; i < len; i++) {
  113. _str += i < freeLeft || i >= freeLeft + str.length ? space : str[i - freeLeft];
  114. }
  115. return _str;
  116. }
  117. function rightAlign(str, len, space = " ") {
  118. const free = len - str.length;
  119. if (free <= 0) {
  120. return str;
  121. }
  122. let _str = "";
  123. for (let i = 0; i < len; i++) {
  124. _str += i < free ? space : str[i - free];
  125. }
  126. return _str;
  127. }
  128. function leftAlign(str, len, space = " ") {
  129. let _str = "";
  130. for (let i = 0; i < len; i++) {
  131. _str += i < str.length ? str[i] : space;
  132. }
  133. return _str;
  134. }
  135. function align(alignment, str, len, space = " ") {
  136. switch (alignment) {
  137. case "left": {
  138. return leftAlign(str, len, space);
  139. }
  140. case "right": {
  141. return rightAlign(str, len, space);
  142. }
  143. case "center": {
  144. return centerAlign(str, len, space);
  145. }
  146. default: {
  147. return str;
  148. }
  149. }
  150. }
  151. const boxStylePresets = {
  152. solid: {
  153. tl: "\u250C",
  154. tr: "\u2510",
  155. bl: "\u2514",
  156. br: "\u2518",
  157. h: "\u2500",
  158. v: "\u2502"
  159. },
  160. double: {
  161. tl: "\u2554",
  162. tr: "\u2557",
  163. bl: "\u255A",
  164. br: "\u255D",
  165. h: "\u2550",
  166. v: "\u2551"
  167. },
  168. doubleSingle: {
  169. tl: "\u2553",
  170. tr: "\u2556",
  171. bl: "\u2559",
  172. br: "\u255C",
  173. h: "\u2500",
  174. v: "\u2551"
  175. },
  176. doubleSingleRounded: {
  177. tl: "\u256D",
  178. tr: "\u256E",
  179. bl: "\u2570",
  180. br: "\u256F",
  181. h: "\u2500",
  182. v: "\u2551"
  183. },
  184. singleThick: {
  185. tl: "\u250F",
  186. tr: "\u2513",
  187. bl: "\u2517",
  188. br: "\u251B",
  189. h: "\u2501",
  190. v: "\u2503"
  191. },
  192. singleDouble: {
  193. tl: "\u2552",
  194. tr: "\u2555",
  195. bl: "\u2558",
  196. br: "\u255B",
  197. h: "\u2550",
  198. v: "\u2502"
  199. },
  200. singleDoubleRounded: {
  201. tl: "\u256D",
  202. tr: "\u256E",
  203. bl: "\u2570",
  204. br: "\u256F",
  205. h: "\u2550",
  206. v: "\u2502"
  207. },
  208. rounded: {
  209. tl: "\u256D",
  210. tr: "\u256E",
  211. bl: "\u2570",
  212. br: "\u256F",
  213. h: "\u2500",
  214. v: "\u2502"
  215. }
  216. };
  217. const defaultStyle = {
  218. borderColor: "white",
  219. borderStyle: "rounded",
  220. valign: "center",
  221. padding: 2,
  222. marginLeft: 1,
  223. marginTop: 1,
  224. marginBottom: 1
  225. };
  226. function box(text, _opts = {}) {
  227. const opts = {
  228. ..._opts,
  229. style: {
  230. ...defaultStyle,
  231. ..._opts.style
  232. }
  233. };
  234. const textLines = text.split("\n");
  235. const boxLines = [];
  236. const _color = getColor(opts.style.borderColor);
  237. const borderStyle = {
  238. ...typeof opts.style.borderStyle === "string" ? boxStylePresets[opts.style.borderStyle] || boxStylePresets.solid : opts.style.borderStyle
  239. };
  240. if (_color) {
  241. for (const key in borderStyle) {
  242. borderStyle[key] = _color(
  243. borderStyle[key]
  244. );
  245. }
  246. }
  247. const paddingOffset = opts.style.padding % 2 === 0 ? opts.style.padding : opts.style.padding + 1;
  248. const height = textLines.length + paddingOffset;
  249. const width = Math.max(...textLines.map((line) => line.length)) + paddingOffset;
  250. const widthOffset = width + paddingOffset;
  251. const leftSpace = opts.style.marginLeft > 0 ? " ".repeat(opts.style.marginLeft) : "";
  252. if (opts.style.marginTop > 0) {
  253. boxLines.push("".repeat(opts.style.marginTop));
  254. }
  255. if (opts.title) {
  256. const left = borderStyle.h.repeat(
  257. Math.floor((width - stripAnsi(opts.title).length) / 2)
  258. );
  259. const right = borderStyle.h.repeat(
  260. width - stripAnsi(opts.title).length - stripAnsi(left).length + paddingOffset
  261. );
  262. boxLines.push(
  263. `${leftSpace}${borderStyle.tl}${left}${opts.title}${right}${borderStyle.tr}`
  264. );
  265. } else {
  266. boxLines.push(
  267. `${leftSpace}${borderStyle.tl}${borderStyle.h.repeat(widthOffset)}${borderStyle.tr}`
  268. );
  269. }
  270. const valignOffset = opts.style.valign === "center" ? Math.floor((height - textLines.length) / 2) : opts.style.valign === "top" ? height - textLines.length - paddingOffset : height - textLines.length;
  271. for (let i = 0; i < height; i++) {
  272. if (i < valignOffset || i >= valignOffset + textLines.length) {
  273. boxLines.push(
  274. `${leftSpace}${borderStyle.v}${" ".repeat(widthOffset)}${borderStyle.v}`
  275. );
  276. } else {
  277. const line = textLines[i - valignOffset];
  278. const left = " ".repeat(paddingOffset);
  279. const right = " ".repeat(width - stripAnsi(line).length);
  280. boxLines.push(
  281. `${leftSpace}${borderStyle.v}${left}${line}${right}${borderStyle.v}`
  282. );
  283. }
  284. }
  285. boxLines.push(
  286. `${leftSpace}${borderStyle.bl}${borderStyle.h.repeat(widthOffset)}${borderStyle.br}`
  287. );
  288. if (opts.style.marginBottom > 0) {
  289. boxLines.push("".repeat(opts.style.marginBottom));
  290. }
  291. return boxLines.join("\n");
  292. }
  293. exports.align = align;
  294. exports.box = box;
  295. exports.centerAlign = centerAlign;
  296. exports.colorize = colorize;
  297. exports.colors = colors;
  298. exports.getColor = getColor;
  299. exports.leftAlign = leftAlign;
  300. exports.rightAlign = rightAlign;
  301. exports.stripAnsi = stripAnsi;