@reliverse/relico 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -100
- package/bin/mod.d.ts +364 -0
- package/bin/mod.js +1187 -0
- package/bin/utils.d.ts +4 -0
- package/bin/utils.js +10 -0
- package/package.json +16 -15
- package/bin/main.d.ts +0 -124
- package/bin/main.js +0 -369
package/bin/mod.js
ADDED
|
@@ -0,0 +1,1187 @@
|
|
|
1
|
+
import { getCurrentTerminalName } from "@reliverse/runtime";
|
|
2
|
+
import { env, isWindows } from "@reliverse/runtime";
|
|
3
|
+
import { loadConfig } from "c12";
|
|
4
|
+
import { shouldNeverHappen } from "./utils.js";
|
|
5
|
+
export const defaultColorKeys = [
|
|
6
|
+
// Text formatting
|
|
7
|
+
"reset",
|
|
8
|
+
"bold",
|
|
9
|
+
"dim",
|
|
10
|
+
"italic",
|
|
11
|
+
"underline",
|
|
12
|
+
"inverse",
|
|
13
|
+
"hidden",
|
|
14
|
+
"strikethrough",
|
|
15
|
+
// Standard colors
|
|
16
|
+
"black",
|
|
17
|
+
"red",
|
|
18
|
+
"green",
|
|
19
|
+
"yellow",
|
|
20
|
+
"blue",
|
|
21
|
+
"magenta",
|
|
22
|
+
"cyan",
|
|
23
|
+
"white",
|
|
24
|
+
"gray",
|
|
25
|
+
// Background colors
|
|
26
|
+
"bgBlack",
|
|
27
|
+
"bgRed",
|
|
28
|
+
"bgGreen",
|
|
29
|
+
"bgYellow",
|
|
30
|
+
"bgBlue",
|
|
31
|
+
"bgMagenta",
|
|
32
|
+
"bgCyan",
|
|
33
|
+
"bgWhite",
|
|
34
|
+
// Bright colors
|
|
35
|
+
"blackBright",
|
|
36
|
+
"redBright",
|
|
37
|
+
"greenBright",
|
|
38
|
+
"yellowBright",
|
|
39
|
+
"blueBright",
|
|
40
|
+
"magentaBright",
|
|
41
|
+
"cyanBright",
|
|
42
|
+
"whiteBright",
|
|
43
|
+
// Bright background colors
|
|
44
|
+
"bgBlackBright",
|
|
45
|
+
"bgRedBright",
|
|
46
|
+
"bgGreenBright",
|
|
47
|
+
"bgYellowBright",
|
|
48
|
+
"bgBlueBright",
|
|
49
|
+
"bgMagentaBright",
|
|
50
|
+
"bgCyanBright",
|
|
51
|
+
"bgWhiteBright",
|
|
52
|
+
// Extended color palette - pastel variants
|
|
53
|
+
"redPastel",
|
|
54
|
+
"greenPastel",
|
|
55
|
+
"yellowPastel",
|
|
56
|
+
"bluePastel",
|
|
57
|
+
"magentaPastel",
|
|
58
|
+
"cyanPastel",
|
|
59
|
+
// Extended background pastels
|
|
60
|
+
"bgRedPastel",
|
|
61
|
+
"bgGreenPastel",
|
|
62
|
+
"bgYellowPastel",
|
|
63
|
+
"bgBluePastel",
|
|
64
|
+
"bgMagentaPastel",
|
|
65
|
+
"bgCyanPastel",
|
|
66
|
+
// Web colors
|
|
67
|
+
"orange",
|
|
68
|
+
"pink",
|
|
69
|
+
"purple",
|
|
70
|
+
"teal",
|
|
71
|
+
"lime",
|
|
72
|
+
"brown",
|
|
73
|
+
"navy",
|
|
74
|
+
"maroon",
|
|
75
|
+
"olive",
|
|
76
|
+
"silver",
|
|
77
|
+
// Background web colors
|
|
78
|
+
"bgOrange",
|
|
79
|
+
"bgPink",
|
|
80
|
+
"bgPurple",
|
|
81
|
+
"bgTeal",
|
|
82
|
+
"bgLime",
|
|
83
|
+
"bgBrown",
|
|
84
|
+
"bgNavy",
|
|
85
|
+
"bgMaroon",
|
|
86
|
+
"bgOlive",
|
|
87
|
+
"bgSilver",
|
|
88
|
+
// Grayscale variants
|
|
89
|
+
"gray10",
|
|
90
|
+
"gray20",
|
|
91
|
+
"gray30",
|
|
92
|
+
"gray40",
|
|
93
|
+
"gray50",
|
|
94
|
+
"gray60",
|
|
95
|
+
"gray70",
|
|
96
|
+
"gray80",
|
|
97
|
+
"gray90"
|
|
98
|
+
];
|
|
99
|
+
const argv = typeof process === "undefined" ? [] : process.argv;
|
|
100
|
+
const isDisabled = Boolean(env.NO_COLOR) || argv.includes("--no-color");
|
|
101
|
+
const isForced = Boolean(env.FORCE_COLOR) || argv.includes("--color");
|
|
102
|
+
const isCI = Boolean(
|
|
103
|
+
env.CI && (env.GITHUB_ACTIONS || env.GITLAB_CI || env.CIRCLECI)
|
|
104
|
+
);
|
|
105
|
+
const isOtherCI = Boolean(
|
|
106
|
+
env.CI && (env.TRAVIS || env.APPVEYOR || env.JENKINS_URL || env.BITBUCKET_BUILD_NUMBER || env.TEAMCITY_VERSION)
|
|
107
|
+
);
|
|
108
|
+
const isCompatibleTerminal = typeof process !== "undefined" && Boolean(process.stdout?.isTTY) && env.TERM !== "dumb";
|
|
109
|
+
const colorterm = (env.COLORTERM ?? "").toLowerCase();
|
|
110
|
+
const term = (env.TERM ?? "").toLowerCase();
|
|
111
|
+
const supportsTrueColor = colorterm === "truecolor" || colorterm === "24bit" || term === "xterm-kitty" || term === "wezterm" || term === "iterm2" || term.includes("256color");
|
|
112
|
+
function detectColorLevel() {
|
|
113
|
+
if (isDisabled) return 0;
|
|
114
|
+
if (isForced) return 3;
|
|
115
|
+
if (supportsTrueColor) return 3;
|
|
116
|
+
if (isWindows && env.TERM_PROGRAM === "vscode") return 3;
|
|
117
|
+
if (isWindows && env.WT_SESSION) return 3;
|
|
118
|
+
if (isWindows) return 2;
|
|
119
|
+
if (isCI || isOtherCI) return 2;
|
|
120
|
+
if (isCompatibleTerminal) return 2;
|
|
121
|
+
return 0;
|
|
122
|
+
}
|
|
123
|
+
const namedColors = {
|
|
124
|
+
aliceblue: "#f0f8ff",
|
|
125
|
+
antiquewhite: "#faebd7",
|
|
126
|
+
aqua: "#00ffff",
|
|
127
|
+
aquamarine: "#7fffd4",
|
|
128
|
+
azure: "#f0ffff",
|
|
129
|
+
beige: "#f5f5dc",
|
|
130
|
+
bisque: "#ffe4c4",
|
|
131
|
+
blanchedalmond: "#ffebcd",
|
|
132
|
+
burlywood: "#deb887",
|
|
133
|
+
cadetblue: "#5f9ea0",
|
|
134
|
+
chocolate: "#d2691e",
|
|
135
|
+
coral: "#ff7f50",
|
|
136
|
+
cornflowerblue: "#6495ed",
|
|
137
|
+
crimson: "#dc143c",
|
|
138
|
+
darkblue: "#00008b",
|
|
139
|
+
darkcyan: "#008b8b",
|
|
140
|
+
darkgoldenrod: "#b8860b",
|
|
141
|
+
darkgray: "#a9a9a9",
|
|
142
|
+
darkgreen: "#006400",
|
|
143
|
+
darkkhaki: "#bdb76b",
|
|
144
|
+
darkmagenta: "#8b008b",
|
|
145
|
+
darkolivegreen: "#556b2f",
|
|
146
|
+
darkorange: "#ff8c00",
|
|
147
|
+
darkorchid: "#9932cc",
|
|
148
|
+
darkred: "#8b0000",
|
|
149
|
+
darksalmon: "#e9967a",
|
|
150
|
+
darkseagreen: "#8fbc8f",
|
|
151
|
+
darkslateblue: "#483d8b",
|
|
152
|
+
darkslategray: "#2f4f4f",
|
|
153
|
+
darkturquoise: "#00ced1",
|
|
154
|
+
darkviolet: "#9400d3",
|
|
155
|
+
deeppink: "#ff1493",
|
|
156
|
+
deepskyblue: "#00bfff",
|
|
157
|
+
dodgerblue: "#1e90ff",
|
|
158
|
+
firebrick: "#b22222",
|
|
159
|
+
floralwhite: "#fffaf0",
|
|
160
|
+
forestgreen: "#228b22",
|
|
161
|
+
fuchsia: "#ff00ff",
|
|
162
|
+
gainsboro: "#dcdcdc",
|
|
163
|
+
ghostwhite: "#f8f8ff",
|
|
164
|
+
gold: "#ffd700",
|
|
165
|
+
goldenrod: "#daa520",
|
|
166
|
+
greenyellow: "#adff2f",
|
|
167
|
+
honeydew: "#f0fff0",
|
|
168
|
+
hotpink: "#ff69b4",
|
|
169
|
+
indianred: "#cd5c5c",
|
|
170
|
+
indigo: "#4b0082",
|
|
171
|
+
ivory: "#fffff0",
|
|
172
|
+
khaki: "#f0e68c",
|
|
173
|
+
lavender: "#e6e6fa",
|
|
174
|
+
lavenderblush: "#fff0f5",
|
|
175
|
+
lawngreen: "#7cfc00",
|
|
176
|
+
lemonchiffon: "#fffacd",
|
|
177
|
+
lightblue: "#add8e6",
|
|
178
|
+
lightcoral: "#f08080",
|
|
179
|
+
lightcyan: "#e0ffff",
|
|
180
|
+
lightgoldenrodyellow: "#fafad2",
|
|
181
|
+
lightgray: "#d3d3d3",
|
|
182
|
+
lightgreen: "#90ee90",
|
|
183
|
+
lightpink: "#ffb6c1",
|
|
184
|
+
lightsalmon: "#ffa07a",
|
|
185
|
+
lightseagreen: "#20b2aa",
|
|
186
|
+
lightskyblue: "#87cefa",
|
|
187
|
+
lightslategray: "#778899",
|
|
188
|
+
lightsteelblue: "#b0c4de",
|
|
189
|
+
lightyellow: "#ffffe0",
|
|
190
|
+
linen: "#faf0e6",
|
|
191
|
+
mediumaquamarine: "#66cdaa",
|
|
192
|
+
mediumblue: "#0000cd",
|
|
193
|
+
mediumorchid: "#ba55d3",
|
|
194
|
+
mediumpurple: "#9370db",
|
|
195
|
+
mediumseagreen: "#3cb371",
|
|
196
|
+
mediumslateblue: "#7b68ee",
|
|
197
|
+
mediumspringgreen: "#00fa9a",
|
|
198
|
+
mediumturquoise: "#48d1cc",
|
|
199
|
+
mediumvioletred: "#c71585",
|
|
200
|
+
midnightblue: "#191970",
|
|
201
|
+
mintcream: "#f5fffa",
|
|
202
|
+
mistyrose: "#ffe4e1",
|
|
203
|
+
moccasin: "#ffe4b5",
|
|
204
|
+
navajowhite: "#ffdead",
|
|
205
|
+
oldlace: "#fdf5e6",
|
|
206
|
+
olivedrab: "#6b8e23",
|
|
207
|
+
orangered: "#ff4500",
|
|
208
|
+
orchid: "#da70d6",
|
|
209
|
+
palegoldenrod: "#eee8aa",
|
|
210
|
+
palegreen: "#98fb98",
|
|
211
|
+
paleturquoise: "#afeeee",
|
|
212
|
+
palevioletred: "#db7093",
|
|
213
|
+
papayawhip: "#ffefd5",
|
|
214
|
+
peachpuff: "#ffdab9",
|
|
215
|
+
peru: "#cd853f",
|
|
216
|
+
plum: "#dda0dd",
|
|
217
|
+
powderblue: "#b0e0e6",
|
|
218
|
+
rosybrown: "#bc8f8f",
|
|
219
|
+
royalblue: "#4169e1",
|
|
220
|
+
saddlebrown: "#8b4513",
|
|
221
|
+
salmon: "#fa8072",
|
|
222
|
+
sandybrown: "#f4a460",
|
|
223
|
+
seagreen: "#2e8b57",
|
|
224
|
+
seashell: "#fff5ee",
|
|
225
|
+
sienna: "#a0522d",
|
|
226
|
+
skyblue: "#87ceeb",
|
|
227
|
+
slateblue: "#6a5acd",
|
|
228
|
+
slategray: "#708090",
|
|
229
|
+
snow: "#fffafa",
|
|
230
|
+
springgreen: "#00ff7f",
|
|
231
|
+
steelblue: "#4682b4",
|
|
232
|
+
tan: "#d2b48c",
|
|
233
|
+
thistle: "#d8bfd8",
|
|
234
|
+
tomato: "#ff6347",
|
|
235
|
+
turquoise: "#40e0d0",
|
|
236
|
+
violet: "#ee82ee",
|
|
237
|
+
wheat: "#f5deb3",
|
|
238
|
+
whitesmoke: "#f5f5f5",
|
|
239
|
+
yellowgreen: "#9acd32"
|
|
240
|
+
};
|
|
241
|
+
const baseColors = {
|
|
242
|
+
// Text formatting
|
|
243
|
+
reset: ["\x1B[0m", "\x1B[0m"],
|
|
244
|
+
bold: ["\x1B[1m", "\x1B[22m"],
|
|
245
|
+
dim: ["\x1B[2m", "\x1B[22m"],
|
|
246
|
+
italic: ["\x1B[3m", "\x1B[23m"],
|
|
247
|
+
underline: ["\x1B[4m", "\x1B[24m"],
|
|
248
|
+
inverse: ["\x1B[7m", "\x1B[27m"],
|
|
249
|
+
hidden: ["\x1B[8m", "\x1B[28m"],
|
|
250
|
+
strikethrough: ["\x1B[9m", "\x1B[29m"],
|
|
251
|
+
// Foreground colors
|
|
252
|
+
black: ["#000000", "#000000"],
|
|
253
|
+
red: ["#ff5555", "#ff0000"],
|
|
254
|
+
green: ["#00ff00", "#00ff00"],
|
|
255
|
+
yellow: ["#ffff00", "#ffff00"],
|
|
256
|
+
blue: ["#0000ff", "#0000ff"],
|
|
257
|
+
magenta: ["#ff00ff", "#ff00ff"],
|
|
258
|
+
cyan: ["#00ffff", "#00ffff"],
|
|
259
|
+
white: ["#ffffff", "#ffffff"],
|
|
260
|
+
gray: ["#808080", "#808080"],
|
|
261
|
+
// Background colors
|
|
262
|
+
bgBlack: ["#000000", "#000000"],
|
|
263
|
+
bgRed: ["#ff5555", "#ff0000"],
|
|
264
|
+
bgGreen: ["#00ff00", "#00ff00"],
|
|
265
|
+
bgYellow: ["#ffff00", "#ffff00"],
|
|
266
|
+
bgBlue: ["#0000ff", "#0000ff"],
|
|
267
|
+
bgMagenta: ["#ff00ff", "#ff00ff"],
|
|
268
|
+
bgCyan: ["#00ffff", "#00ffff"],
|
|
269
|
+
bgWhite: ["#ffffff", "#ffffff"],
|
|
270
|
+
// Bright colors
|
|
271
|
+
blackBright: ["#000000", "#000000"],
|
|
272
|
+
redBright: ["#ff5555", "#ff5555"],
|
|
273
|
+
greenBright: ["#50fa7b", "#50fa7b"],
|
|
274
|
+
yellowBright: ["#f1fa8c", "#f1fa8c"],
|
|
275
|
+
blueBright: ["#24bdff", "#24bdff"],
|
|
276
|
+
magentaBright: ["#ff79c6", "#ff79c6"],
|
|
277
|
+
cyanBright: ["#8be9fd", "#8be9fd"],
|
|
278
|
+
whiteBright: ["#ffffff", "#ffffff"],
|
|
279
|
+
// Bright background colors
|
|
280
|
+
bgBlackBright: ["#000000", "#000000"],
|
|
281
|
+
bgRedBright: ["#ff5555", "#ff5555"],
|
|
282
|
+
bgGreenBright: ["#50fa7b", "#50fa7b"],
|
|
283
|
+
bgYellowBright: ["#f1fa8c", "#f1fa8c"],
|
|
284
|
+
bgBlueBright: ["#24bdff", "#24bdff"],
|
|
285
|
+
bgMagentaBright: ["#ff79c6", "#ff79c6"],
|
|
286
|
+
bgCyanBright: ["#8be9fd", "#8be9fd"],
|
|
287
|
+
bgWhiteBright: ["#ffffff", "#ffffff"],
|
|
288
|
+
// Extended color palette - pastel variants
|
|
289
|
+
redPastel: ["#ff9999", "#ffb3b3"],
|
|
290
|
+
greenPastel: ["#99ff99", "#b3ffb3"],
|
|
291
|
+
yellowPastel: ["#ffff99", "#ffffb3"],
|
|
292
|
+
bluePastel: ["#9999ff", "#b3b3ff"],
|
|
293
|
+
magentaPastel: ["#ff99ff", "#ffb3ff"],
|
|
294
|
+
cyanPastel: ["#99ffff", "#b3ffff"],
|
|
295
|
+
// Extended background pastels
|
|
296
|
+
bgRedPastel: ["#ff9999", "#ffb3b3"],
|
|
297
|
+
bgGreenPastel: ["#99ff99", "#b3ffb3"],
|
|
298
|
+
bgYellowPastel: ["#ffff99", "#ffffb3"],
|
|
299
|
+
bgBluePastel: ["#9999ff", "#b3b3ff"],
|
|
300
|
+
bgMagentaPastel: ["#ff99ff", "#ffb3ff"],
|
|
301
|
+
bgCyanPastel: ["#99ffff", "#b3ffff"],
|
|
302
|
+
// Web colors
|
|
303
|
+
orange: ["#ffa500", "#ff8c00"],
|
|
304
|
+
pink: ["#ffc0cb", "#ffb6c1"],
|
|
305
|
+
purple: ["#800080", "#9370db"],
|
|
306
|
+
teal: ["#008080", "#20b2aa"],
|
|
307
|
+
lime: ["#00ff00", "#32cd32"],
|
|
308
|
+
brown: ["#a52a2a", "#8b4513"],
|
|
309
|
+
navy: ["#000080", "#191970"],
|
|
310
|
+
maroon: ["#800000", "#8b0000"],
|
|
311
|
+
olive: ["#808000", "#6b8e23"],
|
|
312
|
+
silver: ["#c0c0c0", "#a9a9a9"],
|
|
313
|
+
// Background web colors
|
|
314
|
+
bgOrange: ["#ffa500", "#ff8c00"],
|
|
315
|
+
bgPink: ["#ffc0cb", "#ffb6c1"],
|
|
316
|
+
bgPurple: ["#800080", "#9370db"],
|
|
317
|
+
bgTeal: ["#008080", "#20b2aa"],
|
|
318
|
+
bgLime: ["#00ff00", "#32cd32"],
|
|
319
|
+
bgBrown: ["#a52a2a", "#8b4513"],
|
|
320
|
+
bgNavy: ["#000080", "#191970"],
|
|
321
|
+
bgMaroon: ["#800000", "#8b0000"],
|
|
322
|
+
bgOlive: ["#808000", "#6b8e23"],
|
|
323
|
+
bgSilver: ["#c0c0c0", "#a9a9a9"],
|
|
324
|
+
// Grayscale variants
|
|
325
|
+
gray10: ["#1a1a1a", "#1a1a1a"],
|
|
326
|
+
gray20: ["#333333", "#333333"],
|
|
327
|
+
gray30: ["#4d4d4d", "#4d4d4d"],
|
|
328
|
+
gray40: ["#666666", "#666666"],
|
|
329
|
+
gray50: ["#808080", "#808080"],
|
|
330
|
+
gray60: ["#999999", "#999999"],
|
|
331
|
+
gray70: ["#b3b3b3", "#b3b3b3"],
|
|
332
|
+
gray80: ["#cccccc", "#cccccc"],
|
|
333
|
+
gray90: ["#e6e6e6", "#e6e6e6"]
|
|
334
|
+
};
|
|
335
|
+
const restrictedKeys = /* @__PURE__ */ new Set([
|
|
336
|
+
"reset",
|
|
337
|
+
"bold",
|
|
338
|
+
"dim",
|
|
339
|
+
"italic",
|
|
340
|
+
"underline",
|
|
341
|
+
"inverse",
|
|
342
|
+
"hidden",
|
|
343
|
+
"strikethrough"
|
|
344
|
+
]);
|
|
345
|
+
let config = {
|
|
346
|
+
colorLevel: detectColorLevel(),
|
|
347
|
+
theme: "primary",
|
|
348
|
+
// default theme; can be overridden in user config
|
|
349
|
+
autoDetect: true
|
|
350
|
+
};
|
|
351
|
+
let colorMap = {};
|
|
352
|
+
let colorFunctions = {};
|
|
353
|
+
const colorConversionCache = /* @__PURE__ */ new Map();
|
|
354
|
+
const rgbCache = /* @__PURE__ */ new Map();
|
|
355
|
+
const formatterCache = /* @__PURE__ */ new Map();
|
|
356
|
+
const hexCache = /* @__PURE__ */ new Map();
|
|
357
|
+
function normalizeColor(color) {
|
|
358
|
+
if (!color || typeof color !== "string") return "#000000";
|
|
359
|
+
const cacheKey = color.toLowerCase();
|
|
360
|
+
const cached = hexCache.get(cacheKey);
|
|
361
|
+
if (cached) return cached;
|
|
362
|
+
let result;
|
|
363
|
+
if (cacheKey in namedColors) {
|
|
364
|
+
result = namedColors[cacheKey];
|
|
365
|
+
} else {
|
|
366
|
+
if (!color.startsWith("#") && /^[0-9a-f]{3,6}$/i.test(color)) {
|
|
367
|
+
result = `#${color}`;
|
|
368
|
+
} else {
|
|
369
|
+
result = color;
|
|
370
|
+
}
|
|
371
|
+
if (!/^#[0-9a-f]{3,8}$/i.test(result)) {
|
|
372
|
+
result = "#000000";
|
|
373
|
+
}
|
|
374
|
+
if (result.length === 4) {
|
|
375
|
+
result = `#${result[1]}${result[1]}${result[2]}${result[2]}${result[3]}${result[3]}`;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
hexCache.set(cacheKey, result);
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
function hexToRGB(hex2) {
|
|
382
|
+
const normalizedHex = normalizeColor(hex2);
|
|
383
|
+
const cacheKey = normalizedHex;
|
|
384
|
+
const cached = rgbCache.get(cacheKey);
|
|
385
|
+
if (cached) return cached;
|
|
386
|
+
try {
|
|
387
|
+
const r = Number.parseInt(normalizedHex.substring(1, 3), 16);
|
|
388
|
+
const g = Number.parseInt(normalizedHex.substring(3, 5), 16);
|
|
389
|
+
const b = Number.parseInt(normalizedHex.substring(5, 7), 16);
|
|
390
|
+
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
|
|
391
|
+
return { r: 0, g: 0, b: 0 };
|
|
392
|
+
}
|
|
393
|
+
const rgb2 = { r, g, b };
|
|
394
|
+
rgbCache.set(cacheKey, rgb2);
|
|
395
|
+
return rgb2;
|
|
396
|
+
} catch (_error) {
|
|
397
|
+
return { r: 0, g: 0, b: 0 };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
function hexToAnsiParts(hex2, isBg = false) {
|
|
401
|
+
const cacheKey = `${hex2}:${isBg}:truecolor`;
|
|
402
|
+
const cached = colorConversionCache.get(cacheKey);
|
|
403
|
+
if (cached) return cached;
|
|
404
|
+
const { r, g, b } = hexToRGB(hex2);
|
|
405
|
+
const open = isBg ? `\x1B[48;2;${r};${g};${b}m` : `\x1B[38;2;${r};${g};${b}m`;
|
|
406
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
407
|
+
const result = { open, close };
|
|
408
|
+
colorConversionCache.set(cacheKey, result);
|
|
409
|
+
return result;
|
|
410
|
+
}
|
|
411
|
+
function hexToAnsi256(hex2, isBg = false) {
|
|
412
|
+
const cacheKey = `${hex2}:${isBg}:256`;
|
|
413
|
+
const cached = colorConversionCache.get(cacheKey);
|
|
414
|
+
if (cached) return cached.open;
|
|
415
|
+
const { r, g, b } = hexToRGB(hex2);
|
|
416
|
+
if (r === g && g === b) {
|
|
417
|
+
let index2;
|
|
418
|
+
if (r < 8) {
|
|
419
|
+
index2 = 16;
|
|
420
|
+
} else if (r > 238) {
|
|
421
|
+
index2 = 231;
|
|
422
|
+
} else {
|
|
423
|
+
index2 = Math.round((r - 8) / 247 * 24) + 232;
|
|
424
|
+
}
|
|
425
|
+
const open2 = isBg ? `\x1B[48;5;${index2}m` : `\x1B[38;5;${index2}m`;
|
|
426
|
+
const close2 = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
427
|
+
colorConversionCache.set(cacheKey, { open: open2, close: close2 });
|
|
428
|
+
return open2;
|
|
429
|
+
}
|
|
430
|
+
const r5 = Math.round(r / 51);
|
|
431
|
+
const g5 = Math.round(g / 51);
|
|
432
|
+
const b5 = Math.round(b / 51);
|
|
433
|
+
const index = 16 + 36 * r5 + 6 * g5 + b5;
|
|
434
|
+
const open = isBg ? `\x1B[48;5;${index}m` : `\x1B[38;5;${index}m`;
|
|
435
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
436
|
+
colorConversionCache.set(cacheKey, { open, close });
|
|
437
|
+
return open;
|
|
438
|
+
}
|
|
439
|
+
const basicColors = [
|
|
440
|
+
{ name: "black", rgb: { r: 0, g: 0, b: 0 }, fg: 30, bg: 40 },
|
|
441
|
+
{ name: "red", rgb: { r: 205, g: 0, b: 0 }, fg: 31, bg: 41 },
|
|
442
|
+
{ name: "green", rgb: { r: 0, g: 205, b: 0 }, fg: 32, bg: 42 },
|
|
443
|
+
{ name: "yellow", rgb: { r: 205, g: 205, b: 0 }, fg: 33, bg: 43 },
|
|
444
|
+
{ name: "blue", rgb: { r: 0, g: 0, b: 238 }, fg: 34, bg: 44 },
|
|
445
|
+
{ name: "magenta", rgb: { r: 205, g: 0, b: 205 }, fg: 35, bg: 45 },
|
|
446
|
+
{ name: "cyan", rgb: { r: 0, g: 205, b: 205 }, fg: 36, bg: 46 },
|
|
447
|
+
{ name: "white", rgb: { r: 229, g: 229, b: 229 }, fg: 37, bg: 47 }
|
|
448
|
+
];
|
|
449
|
+
const baseStyles = {
|
|
450
|
+
reset: ["\x1B[0m", "\x1B[0m"],
|
|
451
|
+
bold: ["\x1B[1m", "\x1B[22m"],
|
|
452
|
+
dim: ["\x1B[2m", "\x1B[22m"],
|
|
453
|
+
italic: ["\x1B[3m", "\x1B[23m"],
|
|
454
|
+
underline: ["\x1B[4m", "\x1B[24m"],
|
|
455
|
+
inverse: ["\x1B[7m", "\x1B[27m"],
|
|
456
|
+
hidden: ["\x1B[8m", "\x1B[28m"],
|
|
457
|
+
strikethrough: ["\x1B[9m", "\x1B[29m"]
|
|
458
|
+
};
|
|
459
|
+
const colorDistances = /* @__PURE__ */ new Map();
|
|
460
|
+
function hexToAnsiBasic(hex2, isBg = false) {
|
|
461
|
+
const cacheKey = `${hex2}:${isBg}:basic`;
|
|
462
|
+
const cached = colorConversionCache.get(cacheKey);
|
|
463
|
+
if (cached) return cached.open;
|
|
464
|
+
const { r, g, b } = hexToRGB(hex2);
|
|
465
|
+
const distanceKey = `${r},${g},${b}`;
|
|
466
|
+
let distances;
|
|
467
|
+
if (colorDistances.has(distanceKey)) {
|
|
468
|
+
distances = colorDistances.get(distanceKey) ?? shouldNeverHappen(
|
|
469
|
+
"Relico expected to use a color cache, but it's missing."
|
|
470
|
+
);
|
|
471
|
+
} else {
|
|
472
|
+
distances = basicColors.map((color) => {
|
|
473
|
+
const dr = r - color.rgb.r;
|
|
474
|
+
const dg = g - color.rgb.g;
|
|
475
|
+
const db = b - color.rgb.b;
|
|
476
|
+
return dr * dr + dg * dg + db * db;
|
|
477
|
+
});
|
|
478
|
+
colorDistances.set(distanceKey, distances);
|
|
479
|
+
}
|
|
480
|
+
let bestMatchIndex = 0;
|
|
481
|
+
let bestDistance = distances[0];
|
|
482
|
+
for (let i = 1; i < distances.length; i++) {
|
|
483
|
+
if (distances[i] < bestDistance) {
|
|
484
|
+
bestDistance = distances[i];
|
|
485
|
+
bestMatchIndex = i;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
const bestMatch = basicColors[bestMatchIndex];
|
|
489
|
+
const code = isBg ? bestMatch.bg : bestMatch.fg;
|
|
490
|
+
const open = `\x1B[${code}m`;
|
|
491
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
492
|
+
colorConversionCache.set(cacheKey, { open, close });
|
|
493
|
+
return open;
|
|
494
|
+
}
|
|
495
|
+
function convertColorDefinition(key, def) {
|
|
496
|
+
const isBg = key.toLowerCase().startsWith("bg");
|
|
497
|
+
const theme = config.theme ?? "primary";
|
|
498
|
+
const chosen = theme === "primary" ? def[0] : def[1];
|
|
499
|
+
if (config.colorLevel === 0) {
|
|
500
|
+
return ["", ""];
|
|
501
|
+
}
|
|
502
|
+
if (chosen.startsWith("\x1B[")) {
|
|
503
|
+
return [chosen, isBg ? "\x1B[49m" : "\x1B[39m"];
|
|
504
|
+
}
|
|
505
|
+
const normalizedColor = normalizeColor(chosen);
|
|
506
|
+
let open;
|
|
507
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
508
|
+
switch (config.colorLevel) {
|
|
509
|
+
case 3:
|
|
510
|
+
open = hexToAnsiParts(normalizedColor, isBg).open;
|
|
511
|
+
break;
|
|
512
|
+
case 2:
|
|
513
|
+
open = hexToAnsi256(normalizedColor, isBg);
|
|
514
|
+
break;
|
|
515
|
+
case 1:
|
|
516
|
+
open = hexToAnsiBasic(normalizedColor, isBg);
|
|
517
|
+
break;
|
|
518
|
+
default:
|
|
519
|
+
open = "";
|
|
520
|
+
}
|
|
521
|
+
return [open, close];
|
|
522
|
+
}
|
|
523
|
+
function buildColorMap(cfg) {
|
|
524
|
+
if (cfg.colorLevel === 0) {
|
|
525
|
+
const noColorMap = {};
|
|
526
|
+
for (const k of Object.keys(baseColors)) {
|
|
527
|
+
noColorMap[k] = ["", ""];
|
|
528
|
+
}
|
|
529
|
+
return noColorMap;
|
|
530
|
+
}
|
|
531
|
+
const result = {};
|
|
532
|
+
for (const [key, value] of Object.entries(baseStyles)) {
|
|
533
|
+
result[key] = value;
|
|
534
|
+
}
|
|
535
|
+
for (const [key, value] of Object.entries(baseColors)) {
|
|
536
|
+
if (key in baseStyles) continue;
|
|
537
|
+
result[key] = convertColorDefinition(key, value);
|
|
538
|
+
}
|
|
539
|
+
if (cfg.customColors) {
|
|
540
|
+
for (const [k, v] of Object.entries(cfg.customColors)) {
|
|
541
|
+
if (!restrictedKeys.has(k)) {
|
|
542
|
+
result[k] = convertColorDefinition(k, v);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return result;
|
|
547
|
+
}
|
|
548
|
+
function createFormatter(open, close) {
|
|
549
|
+
if (!open && !close) {
|
|
550
|
+
return identityColor;
|
|
551
|
+
}
|
|
552
|
+
if (open === "" || close === "") {
|
|
553
|
+
return identityColor;
|
|
554
|
+
}
|
|
555
|
+
return (input) => {
|
|
556
|
+
const text = String(input);
|
|
557
|
+
if (!text) return text;
|
|
558
|
+
if (text.includes("\n")) {
|
|
559
|
+
return text.split("\n").map((line) => line ? open + line + close : line).join("\n");
|
|
560
|
+
}
|
|
561
|
+
return open + text + close;
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function identityColor(text) {
|
|
565
|
+
return String(text);
|
|
566
|
+
}
|
|
567
|
+
const identityObject = Object.fromEntries(
|
|
568
|
+
defaultColorKeys.map((key) => [key, identityColor])
|
|
569
|
+
);
|
|
570
|
+
export const re = identityObject;
|
|
571
|
+
function refreshTypedRe() {
|
|
572
|
+
Object.assign(re, colorFunctions);
|
|
573
|
+
}
|
|
574
|
+
function initColorFunctions() {
|
|
575
|
+
colorFunctions = {};
|
|
576
|
+
if (config.colorLevel === 0) {
|
|
577
|
+
for (const k of Object.keys(baseColors)) {
|
|
578
|
+
colorFunctions[k] = identityColor;
|
|
579
|
+
}
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
582
|
+
for (const [key, [open, close]] of Object.entries(colorMap)) {
|
|
583
|
+
const cacheKey = `formatter:${open}:${close}`;
|
|
584
|
+
if (formatterCache.has(cacheKey)) {
|
|
585
|
+
colorFunctions[key] = formatterCache.get(cacheKey) ?? shouldNeverHappen(
|
|
586
|
+
"Relico expected to use a formatter cache, but it's missing."
|
|
587
|
+
);
|
|
588
|
+
} else {
|
|
589
|
+
const formatter = createFormatter(open, close);
|
|
590
|
+
formatterCache.set(cacheKey, formatter);
|
|
591
|
+
colorFunctions[key] = formatter;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function rebuild() {
|
|
596
|
+
colorConversionCache.clear();
|
|
597
|
+
colorMap = buildColorMap(config);
|
|
598
|
+
initColorFunctions();
|
|
599
|
+
refreshTypedRe();
|
|
600
|
+
}
|
|
601
|
+
rebuild();
|
|
602
|
+
export function configure(userInput) {
|
|
603
|
+
if (typeof userInput !== "object" || userInput === null) {
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const input = userInput;
|
|
607
|
+
const newConfig = { ...config };
|
|
608
|
+
if (typeof input.colorLevel === "number" && [0, 1, 2, 3].includes(input.colorLevel)) {
|
|
609
|
+
newConfig.colorLevel = input.colorLevel;
|
|
610
|
+
} else if (input.autoDetect === true) {
|
|
611
|
+
newConfig.colorLevel = detectColorLevel();
|
|
612
|
+
}
|
|
613
|
+
if (input.theme === "primary" || input.theme === "secondary") {
|
|
614
|
+
newConfig.theme = input.theme;
|
|
615
|
+
}
|
|
616
|
+
if (input.customColors && typeof input.customColors === "object") {
|
|
617
|
+
newConfig.customColors = { ...input.customColors };
|
|
618
|
+
}
|
|
619
|
+
if (typeof input.autoDetect === "boolean") {
|
|
620
|
+
newConfig.autoDetect = input.autoDetect;
|
|
621
|
+
}
|
|
622
|
+
if (config.colorLevel !== newConfig.colorLevel || config.theme !== newConfig.theme || JSON.stringify(config.customColors) !== JSON.stringify(newConfig.customColors)) {
|
|
623
|
+
config = newConfig;
|
|
624
|
+
rebuild();
|
|
625
|
+
} else {
|
|
626
|
+
config = newConfig;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
export function getColor(name) {
|
|
630
|
+
return colorFunctions[name] || colorFunctions.reset || identityColor;
|
|
631
|
+
}
|
|
632
|
+
export function colorize(name, text) {
|
|
633
|
+
return getColor(name)(text);
|
|
634
|
+
}
|
|
635
|
+
export function setColorLevel(level) {
|
|
636
|
+
if (config.colorLevel !== level) {
|
|
637
|
+
configure({ colorLevel: level });
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
export function rgb(r, g, b) {
|
|
641
|
+
const nr = Math.max(0, Math.min(255, Math.round(r)));
|
|
642
|
+
const ng = Math.max(0, Math.min(255, Math.round(g)));
|
|
643
|
+
const nb = Math.max(0, Math.min(255, Math.round(b)));
|
|
644
|
+
const key = `rgb:${nr},${ng},${nb}`;
|
|
645
|
+
if (config.colorLevel === 0) {
|
|
646
|
+
return identityColor;
|
|
647
|
+
}
|
|
648
|
+
if (formatterCache.has(key)) {
|
|
649
|
+
return formatterCache.get(key);
|
|
650
|
+
}
|
|
651
|
+
let open;
|
|
652
|
+
const close = "\x1B[39m";
|
|
653
|
+
switch (config.colorLevel) {
|
|
654
|
+
case 3:
|
|
655
|
+
open = `\x1B[38;2;${nr};${ng};${nb}m`;
|
|
656
|
+
break;
|
|
657
|
+
case 2: {
|
|
658
|
+
const hexColor = `#${nr.toString(16).padStart(2, "0")}${ng.toString(16).padStart(2, "0")}${nb.toString(16).padStart(2, "0")}`;
|
|
659
|
+
open = hexToAnsi256(hexColor, false);
|
|
660
|
+
break;
|
|
661
|
+
}
|
|
662
|
+
case 1: {
|
|
663
|
+
const basicHexColor = `#${nr.toString(16).padStart(2, "0")}${ng.toString(16).padStart(2, "0")}${nb.toString(16).padStart(2, "0")}`;
|
|
664
|
+
open = hexToAnsiBasic(basicHexColor, false);
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
default:
|
|
668
|
+
return identityColor;
|
|
669
|
+
}
|
|
670
|
+
const formatter = createFormatter(open, close);
|
|
671
|
+
formatterCache.set(key, formatter);
|
|
672
|
+
return formatter;
|
|
673
|
+
}
|
|
674
|
+
export function bgRgb(r, g, b) {
|
|
675
|
+
const nr = Math.max(0, Math.min(255, Math.round(r)));
|
|
676
|
+
const ng = Math.max(0, Math.min(255, Math.round(g)));
|
|
677
|
+
const nb = Math.max(0, Math.min(255, Math.round(b)));
|
|
678
|
+
const key = `bgRgb:${nr},${ng},${nb}`;
|
|
679
|
+
if (config.colorLevel === 0) {
|
|
680
|
+
return identityColor;
|
|
681
|
+
}
|
|
682
|
+
if (formatterCache.has(key)) {
|
|
683
|
+
return formatterCache.get(key);
|
|
684
|
+
}
|
|
685
|
+
let open;
|
|
686
|
+
const close = "\x1B[49m";
|
|
687
|
+
switch (config.colorLevel) {
|
|
688
|
+
case 3:
|
|
689
|
+
open = `\x1B[48;2;${nr};${ng};${nb}m`;
|
|
690
|
+
break;
|
|
691
|
+
case 2: {
|
|
692
|
+
const hexColor = `#${nr.toString(16).padStart(2, "0")}${ng.toString(16).padStart(2, "0")}${nb.toString(16).padStart(2, "0")}`;
|
|
693
|
+
open = hexToAnsi256(hexColor, true);
|
|
694
|
+
break;
|
|
695
|
+
}
|
|
696
|
+
case 1: {
|
|
697
|
+
const basicHexColor = `#${nr.toString(16).padStart(2, "0")}${ng.toString(16).padStart(2, "0")}${nb.toString(16).padStart(2, "0")}`;
|
|
698
|
+
open = hexToAnsiBasic(basicHexColor, true);
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
default:
|
|
702
|
+
return identityColor;
|
|
703
|
+
}
|
|
704
|
+
const formatter = createFormatter(open, close);
|
|
705
|
+
formatterCache.set(key, formatter);
|
|
706
|
+
return formatter;
|
|
707
|
+
}
|
|
708
|
+
export function hex(color) {
|
|
709
|
+
if (config.colorLevel === 0) {
|
|
710
|
+
return identityColor;
|
|
711
|
+
}
|
|
712
|
+
const normalizedColor = normalizeColor(color);
|
|
713
|
+
const cacheKey = `hex:${normalizedColor}`;
|
|
714
|
+
if (formatterCache.has(cacheKey)) {
|
|
715
|
+
return formatterCache.get(cacheKey);
|
|
716
|
+
}
|
|
717
|
+
const { r, g, b } = hexToRGB(normalizedColor);
|
|
718
|
+
const formatter = rgb(r, g, b);
|
|
719
|
+
formatterCache.set(cacheKey, formatter);
|
|
720
|
+
return formatter;
|
|
721
|
+
}
|
|
722
|
+
export function bgHex(color) {
|
|
723
|
+
if (config.colorLevel === 0) {
|
|
724
|
+
return identityColor;
|
|
725
|
+
}
|
|
726
|
+
const normalizedColor = normalizeColor(color);
|
|
727
|
+
const cacheKey = `bgHex:${normalizedColor}`;
|
|
728
|
+
if (formatterCache.has(cacheKey)) {
|
|
729
|
+
return formatterCache.get(cacheKey);
|
|
730
|
+
}
|
|
731
|
+
const { r, g, b } = hexToRGB(normalizedColor);
|
|
732
|
+
const formatter = bgRgb(r, g, b);
|
|
733
|
+
formatterCache.set(cacheKey, formatter);
|
|
734
|
+
return formatter;
|
|
735
|
+
}
|
|
736
|
+
function hslToRgb(h, s, l) {
|
|
737
|
+
h = (h % 360 + 360) % 360;
|
|
738
|
+
s = Math.max(0, Math.min(100, s)) / 100;
|
|
739
|
+
l = Math.max(0, Math.min(100, l)) / 100;
|
|
740
|
+
if (s === 0) {
|
|
741
|
+
const val = Math.round(l * 255);
|
|
742
|
+
return { r: val, g: val, b: val };
|
|
743
|
+
}
|
|
744
|
+
const cacheKey = `hsl:${h.toFixed(1)},${s.toFixed(3)},${l.toFixed(3)}`;
|
|
745
|
+
if (rgbCache.has(cacheKey)) {
|
|
746
|
+
return rgbCache.get(cacheKey);
|
|
747
|
+
}
|
|
748
|
+
const c = (1 - Math.abs(2 * l - 1)) * s;
|
|
749
|
+
const x = c * (1 - Math.abs(h / 60 % 2 - 1));
|
|
750
|
+
const m = l - c / 2;
|
|
751
|
+
let r;
|
|
752
|
+
let g;
|
|
753
|
+
let b;
|
|
754
|
+
if (h < 60) {
|
|
755
|
+
[r, g, b] = [c, x, 0];
|
|
756
|
+
} else if (h < 120) {
|
|
757
|
+
[r, g, b] = [x, c, 0];
|
|
758
|
+
} else if (h < 180) {
|
|
759
|
+
[r, g, b] = [0, c, x];
|
|
760
|
+
} else if (h < 240) {
|
|
761
|
+
[r, g, b] = [0, x, c];
|
|
762
|
+
} else if (h < 300) {
|
|
763
|
+
[r, g, b] = [x, 0, c];
|
|
764
|
+
} else {
|
|
765
|
+
[r, g, b] = [c, 0, x];
|
|
766
|
+
}
|
|
767
|
+
const rgb2 = {
|
|
768
|
+
r: Math.round((r + m) * 255),
|
|
769
|
+
g: Math.round((g + m) * 255),
|
|
770
|
+
b: Math.round((b + m) * 255)
|
|
771
|
+
};
|
|
772
|
+
rgbCache.set(cacheKey, rgb2);
|
|
773
|
+
return rgb2;
|
|
774
|
+
}
|
|
775
|
+
export function hsl(h, s, l) {
|
|
776
|
+
if (config.colorLevel === 0) {
|
|
777
|
+
return identityColor;
|
|
778
|
+
}
|
|
779
|
+
const cacheKey = `hsl:${h},${s},${l}`;
|
|
780
|
+
if (formatterCache.has(cacheKey)) {
|
|
781
|
+
return formatterCache.get(cacheKey);
|
|
782
|
+
}
|
|
783
|
+
const { r, g, b } = hslToRgb(h, s, l);
|
|
784
|
+
const formatter = rgb(r, g, b);
|
|
785
|
+
formatterCache.set(cacheKey, formatter);
|
|
786
|
+
return formatter;
|
|
787
|
+
}
|
|
788
|
+
export function bgHsl(h, s, l) {
|
|
789
|
+
if (config.colorLevel === 0) {
|
|
790
|
+
return identityColor;
|
|
791
|
+
}
|
|
792
|
+
const cacheKey = `bghsl:${h},${s},${l}`;
|
|
793
|
+
if (formatterCache.has(cacheKey)) {
|
|
794
|
+
return formatterCache.get(cacheKey);
|
|
795
|
+
}
|
|
796
|
+
const { r, g, b } = hslToRgb(h, s, l);
|
|
797
|
+
const formatter = bgRgb(r, g, b);
|
|
798
|
+
formatterCache.set(cacheKey, formatter);
|
|
799
|
+
return formatter;
|
|
800
|
+
}
|
|
801
|
+
export function chain(...formatters) {
|
|
802
|
+
if (formatters.length === 0) return identityColor;
|
|
803
|
+
if (formatters.length === 1) return formatters[0];
|
|
804
|
+
if (config.colorLevel === 0) return identityColor;
|
|
805
|
+
const cacheKey = `chain:${formatters.map(
|
|
806
|
+
(f) => f.name || formatterCache.entries().next().value?.[0] || "custom"
|
|
807
|
+
).join(",")}`;
|
|
808
|
+
if (formatterCache.has(cacheKey)) {
|
|
809
|
+
return formatterCache.get(cacheKey);
|
|
810
|
+
}
|
|
811
|
+
const chainedFormatter = (text) => {
|
|
812
|
+
const str = String(text);
|
|
813
|
+
if (!str) return str;
|
|
814
|
+
if (str.includes("\n")) {
|
|
815
|
+
const lines = str.split("\n");
|
|
816
|
+
return lines.map((line) => {
|
|
817
|
+
if (!line) return line;
|
|
818
|
+
return formatters.reduce((result, formatter) => {
|
|
819
|
+
return formatter(result);
|
|
820
|
+
}, line);
|
|
821
|
+
}).join("\n");
|
|
822
|
+
}
|
|
823
|
+
return formatters.reduce((result, formatter) => {
|
|
824
|
+
return formatter(result);
|
|
825
|
+
}, str);
|
|
826
|
+
};
|
|
827
|
+
formatterCache.set(cacheKey, chainedFormatter);
|
|
828
|
+
return chainedFormatter;
|
|
829
|
+
}
|
|
830
|
+
export function rainbow(text, saturation = 100, lightness = 50, options) {
|
|
831
|
+
if (config.colorLevel === 0) {
|
|
832
|
+
return String(text);
|
|
833
|
+
}
|
|
834
|
+
const chars = String(text).split("");
|
|
835
|
+
if (chars.length === 0) return "";
|
|
836
|
+
const startHue = options?.startHue ?? 0;
|
|
837
|
+
const endHue = options?.endHue ?? 360;
|
|
838
|
+
const hueRange = ((endHue - startHue) % 360 + 360) % 360;
|
|
839
|
+
let result = "";
|
|
840
|
+
const hueStep = chars.length > 1 ? hueRange / (chars.length - 1) : 0;
|
|
841
|
+
const colorFormatters = [];
|
|
842
|
+
for (let i = 0; i < chars.length; i++) {
|
|
843
|
+
const hue = (startHue + i * hueStep) % 360;
|
|
844
|
+
colorFormatters.push(hsl(hue, saturation, lightness));
|
|
845
|
+
}
|
|
846
|
+
for (let i = 0; i < chars.length; i++) {
|
|
847
|
+
result += colorFormatters[i](chars[i]);
|
|
848
|
+
}
|
|
849
|
+
return result;
|
|
850
|
+
}
|
|
851
|
+
export function multiGradient(text, colors, options) {
|
|
852
|
+
if (config.colorLevel === 0 || colors.length === 0) {
|
|
853
|
+
return String(text);
|
|
854
|
+
}
|
|
855
|
+
if (colors.length === 1) {
|
|
856
|
+
return hex(colors[0])(text);
|
|
857
|
+
}
|
|
858
|
+
const chars = String(text).split("");
|
|
859
|
+
if (chars.length === 0) return "";
|
|
860
|
+
const smoothing = options?.smoothing ?? 1;
|
|
861
|
+
const distribution = options?.distribution ?? "even";
|
|
862
|
+
const rgbColors = colors.map(
|
|
863
|
+
(color) => hexToRGB(normalizeColor(color))
|
|
864
|
+
);
|
|
865
|
+
let result = "";
|
|
866
|
+
for (let i = 0; i < chars.length; i++) {
|
|
867
|
+
let gradientPos;
|
|
868
|
+
if (distribution === "weighted") {
|
|
869
|
+
gradientPos = (chars.length > 1 ? i / (chars.length - 1) : 0) ** smoothing;
|
|
870
|
+
} else {
|
|
871
|
+
gradientPos = chars.length > 1 ? i / (chars.length - 1) : 0;
|
|
872
|
+
}
|
|
873
|
+
const segmentCount = rgbColors.length - 1;
|
|
874
|
+
const segmentPos = gradientPos * segmentCount;
|
|
875
|
+
const segmentIndex = Math.min(Math.floor(segmentPos), segmentCount - 1);
|
|
876
|
+
const segmentOffset = segmentPos - segmentIndex;
|
|
877
|
+
const startColor = rgbColors[segmentIndex];
|
|
878
|
+
const endColor = rgbColors[segmentIndex + 1];
|
|
879
|
+
const r = Math.round(
|
|
880
|
+
startColor.r + segmentOffset * (endColor.r - startColor.r)
|
|
881
|
+
);
|
|
882
|
+
const g = Math.round(
|
|
883
|
+
startColor.g + segmentOffset * (endColor.g - startColor.g)
|
|
884
|
+
);
|
|
885
|
+
const b = Math.round(
|
|
886
|
+
startColor.b + segmentOffset * (endColor.b - startColor.b)
|
|
887
|
+
);
|
|
888
|
+
const colorFn = rgb(r, g, b);
|
|
889
|
+
result += colorFn(chars[i]);
|
|
890
|
+
}
|
|
891
|
+
return result;
|
|
892
|
+
}
|
|
893
|
+
export function gradient(text, startColor, endColor, options) {
|
|
894
|
+
return multiGradient(text, [startColor, endColor], options);
|
|
895
|
+
}
|
|
896
|
+
export function blend(color1, color2, ratio = 0.5) {
|
|
897
|
+
if (config.colorLevel === 0) return identityColor;
|
|
898
|
+
ratio = Math.max(0, Math.min(1, ratio));
|
|
899
|
+
if (ratio === 0) return hex(color1);
|
|
900
|
+
if (ratio === 1) return hex(color2);
|
|
901
|
+
const cacheKey = `blend:${normalizeColor(color1)}:${normalizeColor(
|
|
902
|
+
color2
|
|
903
|
+
)}:${ratio.toFixed(3)}`;
|
|
904
|
+
if (formatterCache.has(cacheKey)) {
|
|
905
|
+
return formatterCache.get(cacheKey);
|
|
906
|
+
}
|
|
907
|
+
const rgb1 = hexToRGB(normalizeColor(color1));
|
|
908
|
+
const rgb2 = hexToRGB(normalizeColor(color2));
|
|
909
|
+
const r = Math.round(rgb1.r * (1 - ratio) + rgb2.r * ratio);
|
|
910
|
+
const g = Math.round(rgb1.g * (1 - ratio) + rgb2.g * ratio);
|
|
911
|
+
const b = Math.round(rgb1.b * (1 - ratio) + rgb2.b * ratio);
|
|
912
|
+
const formatter = rgb(r, g, b);
|
|
913
|
+
formatterCache.set(cacheKey, formatter);
|
|
914
|
+
return formatter;
|
|
915
|
+
}
|
|
916
|
+
function getLuminance(r, g, b) {
|
|
917
|
+
const rsRGB = r / 255;
|
|
918
|
+
const gsRGB = g / 255;
|
|
919
|
+
const bsRGB = b / 255;
|
|
920
|
+
const R = rsRGB <= 0.03928 ? rsRGB / 12.92 : ((rsRGB + 0.055) / 1.055) ** 2.4;
|
|
921
|
+
const G = gsRGB <= 0.03928 ? gsRGB / 12.92 : ((gsRGB + 0.055) / 1.055) ** 2.4;
|
|
922
|
+
const B = bsRGB <= 0.03928 ? bsRGB / 12.92 : ((bsRGB + 0.055) / 1.055) ** 2.4;
|
|
923
|
+
return 0.2126 * R + 0.7152 * G + 0.0722 * B;
|
|
924
|
+
}
|
|
925
|
+
export function checkContrast(foreground, background = "#ffffff") {
|
|
926
|
+
const normalizedFg = normalizeColor(foreground);
|
|
927
|
+
const normalizedBg = normalizeColor(background);
|
|
928
|
+
const fgRGB = hexToRGB(normalizedFg);
|
|
929
|
+
const { r: bgR, g: bgG, b: bgB } = hexToRGB(normalizedBg);
|
|
930
|
+
const fgLuminance = getLuminance(fgRGB.r, fgRGB.g, fgRGB.b);
|
|
931
|
+
const bgLuminance = getLuminance(bgR, bgG, bgB);
|
|
932
|
+
const ratio = (Math.max(fgLuminance, bgLuminance) + 0.05) / (Math.min(fgLuminance, bgLuminance) + 0.05);
|
|
933
|
+
const roundedRatio = Math.round(ratio * 100) / 100;
|
|
934
|
+
return {
|
|
935
|
+
ratio: roundedRatio,
|
|
936
|
+
passesAA: roundedRatio >= 4.5,
|
|
937
|
+
passesAAA: roundedRatio >= 7,
|
|
938
|
+
passesAALarge: roundedRatio >= 3,
|
|
939
|
+
passesAAALarge: roundedRatio >= 4.5
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
export function getAccessibleColor(color, background = "#ffffff", targetRatio = 4.5) {
|
|
943
|
+
const normalizedColor = normalizeColor(color);
|
|
944
|
+
const normalizedBg = normalizeColor(background);
|
|
945
|
+
const { ratio } = checkContrast(normalizedColor, normalizedBg);
|
|
946
|
+
if (ratio >= targetRatio) {
|
|
947
|
+
return normalizedColor;
|
|
948
|
+
}
|
|
949
|
+
const { r, g, b } = hexToRGB(normalizedColor);
|
|
950
|
+
function rgbToHsl(r2, g2, b2) {
|
|
951
|
+
r2 /= 255;
|
|
952
|
+
g2 /= 255;
|
|
953
|
+
b2 /= 255;
|
|
954
|
+
const max = Math.max(r2, g2, b2);
|
|
955
|
+
const min = Math.min(r2, g2, b2);
|
|
956
|
+
let h2 = 0;
|
|
957
|
+
let s2 = 0;
|
|
958
|
+
const l2 = (max + min) / 2;
|
|
959
|
+
if (max !== min) {
|
|
960
|
+
const d = max - min;
|
|
961
|
+
s2 = l2 > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
962
|
+
switch (max) {
|
|
963
|
+
case r2:
|
|
964
|
+
h2 = (g2 - b2) / d + (g2 < b2 ? 6 : 0);
|
|
965
|
+
break;
|
|
966
|
+
case g2:
|
|
967
|
+
h2 = (b2 - r2) / d + 2;
|
|
968
|
+
break;
|
|
969
|
+
case b2:
|
|
970
|
+
h2 = (r2 - g2) / d + 4;
|
|
971
|
+
break;
|
|
972
|
+
}
|
|
973
|
+
h2 /= 6;
|
|
974
|
+
}
|
|
975
|
+
return [h2 * 360, s2 * 100, l2 * 100];
|
|
976
|
+
}
|
|
977
|
+
const [h, s, l] = rgbToHsl(r, g, b);
|
|
978
|
+
const { r: bgR, g: bgG, b: bgB } = hexToRGB(normalizedBg);
|
|
979
|
+
const bgLuminance = getLuminance(bgR, bgG, bgB);
|
|
980
|
+
const needsDarkening = bgLuminance > 0.5;
|
|
981
|
+
let low = needsDarkening ? 0 : l;
|
|
982
|
+
let high = needsDarkening ? l : 100;
|
|
983
|
+
let newL = l;
|
|
984
|
+
const currentRatio = ratio;
|
|
985
|
+
let bestL = newL;
|
|
986
|
+
let bestRatio = currentRatio;
|
|
987
|
+
for (let i = 0; i < 8; i++) {
|
|
988
|
+
newL = (low + high) / 2;
|
|
989
|
+
const { r: newR, g: newG, b: newB } = hslToRgb(h, s, newL);
|
|
990
|
+
const newHex = `#${newR.toString(16).padStart(2, "0")}${newG.toString(16).padStart(2, "0")}${newB.toString(16).padStart(2, "0")}`;
|
|
991
|
+
const { ratio: newRatio } = checkContrast(newHex, normalizedBg);
|
|
992
|
+
if (newRatio > bestRatio) {
|
|
993
|
+
bestRatio = newRatio;
|
|
994
|
+
bestL = newL;
|
|
995
|
+
}
|
|
996
|
+
if (Math.abs(newRatio - targetRatio) < 0.1 || Math.abs(high - low) < 0.5) {
|
|
997
|
+
break;
|
|
998
|
+
}
|
|
999
|
+
if (newRatio < targetRatio) {
|
|
1000
|
+
if (needsDarkening) {
|
|
1001
|
+
high = newL;
|
|
1002
|
+
} else {
|
|
1003
|
+
low = newL;
|
|
1004
|
+
}
|
|
1005
|
+
} else {
|
|
1006
|
+
if (needsDarkening) {
|
|
1007
|
+
low = newL;
|
|
1008
|
+
} else {
|
|
1009
|
+
high = newL;
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
const { r: finalR, g: finalG, b: finalB } = hslToRgb(h, s, bestL);
|
|
1014
|
+
return `#${finalR.toString(16).padStart(2, "0")}${finalG.toString(16).padStart(2, "0")}${finalB.toString(16).padStart(2, "0")}`;
|
|
1015
|
+
}
|
|
1016
|
+
function getConfig() {
|
|
1017
|
+
return { ...config };
|
|
1018
|
+
}
|
|
1019
|
+
export const colorSupport = {
|
|
1020
|
+
get isColorSupported() {
|
|
1021
|
+
return getConfig().colorLevel !== 0;
|
|
1022
|
+
},
|
|
1023
|
+
get colorLevel() {
|
|
1024
|
+
return getConfig().colorLevel;
|
|
1025
|
+
},
|
|
1026
|
+
isForced,
|
|
1027
|
+
isDisabled,
|
|
1028
|
+
terminalName: getCurrentTerminalName()
|
|
1029
|
+
};
|
|
1030
|
+
export function colorWrap(text, bgColorFn, textColorFn) {
|
|
1031
|
+
if (config.colorLevel === 0) {
|
|
1032
|
+
return String(text);
|
|
1033
|
+
}
|
|
1034
|
+
const str = String(text);
|
|
1035
|
+
if (!str) return str;
|
|
1036
|
+
const lines = str.split("\n");
|
|
1037
|
+
return lines.map((line) => {
|
|
1038
|
+
if (!line) return line;
|
|
1039
|
+
return textColorFn ? bgColorFn(textColorFn(line)) : bgColorFn(line);
|
|
1040
|
+
}).join("\n");
|
|
1041
|
+
}
|
|
1042
|
+
export function safeBg(color, text) {
|
|
1043
|
+
const colorFn = bgHex(normalizeColor(color));
|
|
1044
|
+
if (text !== void 0) {
|
|
1045
|
+
return colorWrap(String(text), colorFn);
|
|
1046
|
+
}
|
|
1047
|
+
return (innerText) => {
|
|
1048
|
+
return colorWrap(String(innerText), colorFn);
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
export function safeColor(bgColor, fgColor, text) {
|
|
1052
|
+
const normalizedBgColor = normalizeColor(bgColor);
|
|
1053
|
+
const normalizedFgColor = normalizeColor(fgColor);
|
|
1054
|
+
const bgColorFn = bgHex(normalizedBgColor);
|
|
1055
|
+
const fgColorFn = hex(normalizedFgColor);
|
|
1056
|
+
if (text !== void 0) {
|
|
1057
|
+
return colorWrap(String(text), bgColorFn, fgColorFn);
|
|
1058
|
+
}
|
|
1059
|
+
return (innerText) => {
|
|
1060
|
+
return colorWrap(String(innerText), bgColorFn, fgColorFn);
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
export function autoContrast(color, background = "#ffffff", targetRatio = 4.5) {
|
|
1064
|
+
if (config.colorLevel === 0) {
|
|
1065
|
+
return identityColor;
|
|
1066
|
+
}
|
|
1067
|
+
const accessibleColor = getAccessibleColor(color, background, targetRatio);
|
|
1068
|
+
return hex(accessibleColor);
|
|
1069
|
+
}
|
|
1070
|
+
export function createColorScheme(baseColor) {
|
|
1071
|
+
const color = normalizeColor(baseColor);
|
|
1072
|
+
const { r, g, b } = hexToRGB(color);
|
|
1073
|
+
function rgbToHsl(r2, g2, b2) {
|
|
1074
|
+
r2 /= 255;
|
|
1075
|
+
g2 /= 255;
|
|
1076
|
+
b2 /= 255;
|
|
1077
|
+
const max = Math.max(r2, g2, b2);
|
|
1078
|
+
const min = Math.min(r2, g2, b2);
|
|
1079
|
+
let h2 = 0;
|
|
1080
|
+
let s2 = 0;
|
|
1081
|
+
const l2 = (max + min) / 2;
|
|
1082
|
+
if (max !== min) {
|
|
1083
|
+
const d = max - min;
|
|
1084
|
+
s2 = l2 > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
1085
|
+
switch (max) {
|
|
1086
|
+
case r2:
|
|
1087
|
+
h2 = (g2 - b2) / d + (g2 < b2 ? 6 : 0);
|
|
1088
|
+
break;
|
|
1089
|
+
case g2:
|
|
1090
|
+
h2 = (b2 - r2) / d + 2;
|
|
1091
|
+
break;
|
|
1092
|
+
case b2:
|
|
1093
|
+
h2 = (r2 - g2) / d + 4;
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
h2 /= 6;
|
|
1097
|
+
}
|
|
1098
|
+
return [h2 * 360, s2 * 100, l2 * 100];
|
|
1099
|
+
}
|
|
1100
|
+
const [h, s, l] = rgbToHsl(r, g, b);
|
|
1101
|
+
return {
|
|
1102
|
+
base: hex(color),
|
|
1103
|
+
light: hsl(h, Math.max(0, s - 10), Math.min(100, l + 15)),
|
|
1104
|
+
dark: hsl(h, Math.min(100, s + 10), Math.max(0, l - 15)),
|
|
1105
|
+
bright: hsl(h, Math.min(100, s + 20), Math.min(95, l + 5)),
|
|
1106
|
+
pastel: hsl(h, Math.max(0, s - 30), Math.min(100, l + 20)),
|
|
1107
|
+
bg: bgHsl(h, Math.max(0, s - 10), Math.min(100, l + 30)),
|
|
1108
|
+
bgLight: bgHsl(h, Math.max(0, s - 30), Math.min(100, l + 40)),
|
|
1109
|
+
accent: hsl((h + 180) % 360, s, l)
|
|
1110
|
+
// Complementary color
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
export function highlight(text, bgColor, options) {
|
|
1114
|
+
if (config.colorLevel === 0) {
|
|
1115
|
+
return String(text);
|
|
1116
|
+
}
|
|
1117
|
+
const normalizedBg = normalizeColor(bgColor);
|
|
1118
|
+
const { r, g, b } = hexToRGB(normalizedBg);
|
|
1119
|
+
const bgLuminance = getLuminance(r, g, b);
|
|
1120
|
+
const textColor = bgLuminance > 0.5 ? "#000000" : "#ffffff";
|
|
1121
|
+
const padding = options?.padding ?? 0;
|
|
1122
|
+
const paddingStr = padding > 0 ? " ".repeat(padding) : "";
|
|
1123
|
+
const coloredText = safeColor(
|
|
1124
|
+
normalizedBg,
|
|
1125
|
+
textColor,
|
|
1126
|
+
`${paddingStr}${text}${paddingStr}`
|
|
1127
|
+
);
|
|
1128
|
+
if (options?.border) {
|
|
1129
|
+
const borderColor = options?.borderColor ?? normalizedBg;
|
|
1130
|
+
const width = String(text).length + padding * 2;
|
|
1131
|
+
const borderLine = bgHex(borderColor)(" ".repeat(width));
|
|
1132
|
+
return `${borderLine}
|
|
1133
|
+
${coloredText}
|
|
1134
|
+
${borderLine}`;
|
|
1135
|
+
}
|
|
1136
|
+
return coloredText;
|
|
1137
|
+
}
|
|
1138
|
+
export function link(text, url, color) {
|
|
1139
|
+
const colorFn = color ? hex(color) : re.blue;
|
|
1140
|
+
const escapedUrl = url.replace(/\)/g, "%29");
|
|
1141
|
+
return `\x1B]8;;${escapedUrl}\x1B\\${colorFn(text)}\x1B]8;;\x1B\\`;
|
|
1142
|
+
}
|
|
1143
|
+
export function colorizeJson(obj, options) {
|
|
1144
|
+
if (config.colorLevel === 0) {
|
|
1145
|
+
return JSON.stringify(obj, null, options?.indent ?? 2);
|
|
1146
|
+
}
|
|
1147
|
+
const indent = options?.indent ?? 2;
|
|
1148
|
+
const json = JSON.stringify(obj, null, options?.compact ? 0 : indent);
|
|
1149
|
+
return json.replace(/"(\\.|[^"\\])*"(?=\s*:)/g, (match) => re.cyan(match)).replace(
|
|
1150
|
+
/:\s*"(\\.|[^"\\])*"/g,
|
|
1151
|
+
(match) => `: ${re.green(match.slice(match.indexOf('"')))}`
|
|
1152
|
+
).replace(
|
|
1153
|
+
/:\s*\b(true|false|null)\b/g,
|
|
1154
|
+
(match) => `: ${re.yellow(match.slice(match.indexOf(":") + 1))}`
|
|
1155
|
+
).replace(
|
|
1156
|
+
/:\s*(-?\d+\.?\d*([eE][+-]?\d+)?)/g,
|
|
1157
|
+
(match) => `: ${re.magenta(match.slice(match.indexOf(":") + 1))}`
|
|
1158
|
+
);
|
|
1159
|
+
}
|
|
1160
|
+
export async function initUserConfig(programmaticConfig, userSettingsPrecedence = false) {
|
|
1161
|
+
try {
|
|
1162
|
+
const options = {
|
|
1163
|
+
name: "relico",
|
|
1164
|
+
// If user settings take precedence, programmaticConfig becomes defaults
|
|
1165
|
+
// Otherwise, it becomes overrides (higher priority)
|
|
1166
|
+
...userSettingsPrecedence ? { defaults: programmaticConfig || {} } : { overrides: programmaticConfig || {} },
|
|
1167
|
+
// Set sensible defaults if no user settings are present
|
|
1168
|
+
defaultConfig: {
|
|
1169
|
+
colorLevel: detectColorLevel(),
|
|
1170
|
+
theme: "primary",
|
|
1171
|
+
autoDetect: true
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
const { config: mergedConfig } = await loadConfig(options);
|
|
1175
|
+
if (mergedConfig && Object.keys(mergedConfig).length > 0) {
|
|
1176
|
+
configure(mergedConfig);
|
|
1177
|
+
}
|
|
1178
|
+
} catch (err) {
|
|
1179
|
+
console.warn("Failed to load user config via c12:", err);
|
|
1180
|
+
if (programmaticConfig) {
|
|
1181
|
+
configure(programmaticConfig);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
export function defineConfig(cfg) {
|
|
1186
|
+
return cfg;
|
|
1187
|
+
}
|