@reliverse/relico 1.0.1 → 1.0.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 +43 -1
- package/bin/main.d.ts +130 -0
- package/bin/main.js +361 -0
- package/package.json +43 -69
- package/dist-npm/main.d.ts +0 -79
- package/dist-npm/main.js +0 -269
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</a>
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
|
-
**@reliverse/relico is
|
|
14
|
+
**@reliverse/relico is an accessible and modern terminal color formatting library** that provides a type-safe and flexible way to add colors and styles to your command-line output. Built with TypeScript and TypeBox for enhanced reliability and developer experience.
|
|
15
15
|
|
|
16
16
|
## Installation
|
|
17
17
|
|
|
@@ -19,6 +19,48 @@
|
|
|
19
19
|
bun add @reliverse/relico # Replace "bun" with npm, pnpm, or yarn if desired
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
**Configure `relico.config.ts`**:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { defineConfig } from "@reliverse/relico";
|
|
26
|
+
|
|
27
|
+
export default defineConfig({
|
|
28
|
+
// Set the color level: 3 for truecolor
|
|
29
|
+
colorLevel: 3,
|
|
30
|
+
// Choose the theme: "primary" or "secondary"
|
|
31
|
+
theme: "secondary",
|
|
32
|
+
// Override specific colors
|
|
33
|
+
// Use Intellisense to see the available colors
|
|
34
|
+
customColors: {
|
|
35
|
+
blue: ["#5f87ff", "#5f87ff"],
|
|
36
|
+
red: ["#ff5555", "#ff0000"],
|
|
37
|
+
green: ["#00ff00", "#00cc00"],
|
|
38
|
+
// Note: The following text formatting
|
|
39
|
+
// colors can be defined only via ANSI:
|
|
40
|
+
// reset: ["\x1b[0m", "\x1b[0m"],
|
|
41
|
+
// bold: ["\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m"],
|
|
42
|
+
// dim: ["\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m"],
|
|
43
|
+
// italic: ["\x1b[3m", "\x1b[23m"],
|
|
44
|
+
// underline: ["\x1b[4m", "\x1b[24m"],
|
|
45
|
+
// inverse: ["\x1b[7m", "\x1b[27m"],
|
|
46
|
+
// hidden: ["\x1b[8m", "\x1b[28m"],
|
|
47
|
+
// strikethrough: ["\x1b[9m", "\x1b[29m"],
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**To load config (example)**:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Initialize user config, so you override any relico's default settings
|
|
56
|
+
function main() {
|
|
57
|
+
console.log(re.blue("Loading user config..."));
|
|
58
|
+
await initUserConfig();
|
|
59
|
+
console.log(re.blue("If this blue log looks different than line above, then config is loaded successfully. Yay! 🎉"));
|
|
60
|
+
}
|
|
61
|
+
main();
|
|
62
|
+
```
|
|
63
|
+
|
|
22
64
|
## Key Features
|
|
23
65
|
|
|
24
66
|
- **Smart Terminal Detection**: Automatically detects terminal type and color support level
|
package/bin/main.d.ts
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/** A color definition: [primary, secondary, optional replacement]. */
|
|
2
|
+
export type ColorDefinition = [string, string, string?];
|
|
3
|
+
/** A list of default color keys. */
|
|
4
|
+
export declare const defaultColorKeys: readonly ["reset", "bold", "dim", "italic", "underline", "inverse", "hidden", "strikethrough", "black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "gray", "bgBlack", "bgRed", "bgGreen", "bgYellow", "bgBlue", "bgMagenta", "bgCyan", "bgWhite", "blackBright", "redBright", "greenBright", "yellowBright", "blueBright", "magentaBright", "cyanBright", "whiteBright", "bgBlackBright", "bgRedBright", "bgGreenBright", "bgYellowBright", "bgBlueBright", "bgMagentaBright", "bgCyanBright", "bgWhiteBright"];
|
|
5
|
+
export type DefaultColorKeys = (typeof defaultColorKeys)[number];
|
|
6
|
+
/** A map of custom color definitions. IntelliSense will suggest only valid keys. */
|
|
7
|
+
export type ColorMap = Partial<Record<DefaultColorKeys, ColorDefinition>>;
|
|
8
|
+
/**
|
|
9
|
+
* `relico.config.ts` configuration options.
|
|
10
|
+
*/
|
|
11
|
+
export type RelicoConfig = {
|
|
12
|
+
/**
|
|
13
|
+
* Determines which ANSI mode is used:
|
|
14
|
+
* - 0: no color
|
|
15
|
+
* - 1: basic ANSI (8 colors)
|
|
16
|
+
* - 2: 256 color palette
|
|
17
|
+
* - 3: 24-bit truecolor
|
|
18
|
+
*/
|
|
19
|
+
colorLevel?: 0 | 1 | 2 | 3;
|
|
20
|
+
/**
|
|
21
|
+
* Theme to use for color definitions.
|
|
22
|
+
* - "primary": primary theme
|
|
23
|
+
* - "secondary": secondary theme
|
|
24
|
+
*/
|
|
25
|
+
theme?: "primary" | "secondary";
|
|
26
|
+
/**
|
|
27
|
+
* Custom color definitions.
|
|
28
|
+
* - Use IntelliSense to see available colors.
|
|
29
|
+
* - Theming: ["primary", "secondary"]
|
|
30
|
+
*/
|
|
31
|
+
customColors?: ColorMap;
|
|
32
|
+
};
|
|
33
|
+
export type IRelicoColors = {
|
|
34
|
+
reset(text: string | number): string;
|
|
35
|
+
bold(text: string | number): string;
|
|
36
|
+
dim(text: string | number): string;
|
|
37
|
+
italic(text: string | number): string;
|
|
38
|
+
underline(text: string | number): string;
|
|
39
|
+
inverse(text: string | number): string;
|
|
40
|
+
hidden(text: string | number): string;
|
|
41
|
+
strikethrough(text: string | number): string;
|
|
42
|
+
black(text: string | number): string;
|
|
43
|
+
red(text: string | number): string;
|
|
44
|
+
green(text: string | number): string;
|
|
45
|
+
yellow(text: string | number): string;
|
|
46
|
+
blue(text: string | number): string;
|
|
47
|
+
magenta(text: string | number): string;
|
|
48
|
+
cyan(text: string | number): string;
|
|
49
|
+
white(text: string | number): string;
|
|
50
|
+
gray(text: string | number): string;
|
|
51
|
+
bgBlack(text: string | number): string;
|
|
52
|
+
bgRed(text: string | number): string;
|
|
53
|
+
bgGreen(text: string | number): string;
|
|
54
|
+
bgYellow(text: string | number): string;
|
|
55
|
+
bgBlue(text: string | number): string;
|
|
56
|
+
bgMagenta(text: string | number): string;
|
|
57
|
+
bgCyan(text: string | number): string;
|
|
58
|
+
bgWhite(text: string | number): string;
|
|
59
|
+
blackBright(text: string | number): string;
|
|
60
|
+
redBright(text: string | number): string;
|
|
61
|
+
greenBright(text: string | number): string;
|
|
62
|
+
yellowBright(text: string | number): string;
|
|
63
|
+
blueBright(text: string | number): string;
|
|
64
|
+
magentaBright(text: string | number): string;
|
|
65
|
+
cyanBright(text: string | number): string;
|
|
66
|
+
whiteBright(text: string | number): string;
|
|
67
|
+
bgBlackBright(text: string | number): string;
|
|
68
|
+
bgRedBright(text: string | number): string;
|
|
69
|
+
bgGreenBright(text: string | number): string;
|
|
70
|
+
bgYellowBright(text: string | number): string;
|
|
71
|
+
bgBlueBright(text: string | number): string;
|
|
72
|
+
bgMagentaBright(text: string | number): string;
|
|
73
|
+
bgCyanBright(text: string | number): string;
|
|
74
|
+
bgWhiteBright(text: string | number): string;
|
|
75
|
+
[k: string]: (text: string | number) => string;
|
|
76
|
+
};
|
|
77
|
+
export declare const re: IRelicoColors;
|
|
78
|
+
/**
|
|
79
|
+
* Configures the library with a partial or complete
|
|
80
|
+
* `RelicoConfig`. Invalid fields are just ignored.
|
|
81
|
+
*/
|
|
82
|
+
export declare function configure(userInput: unknown): void;
|
|
83
|
+
/** Returns a color function by name (or `reset` or identity if not found). */
|
|
84
|
+
export declare function getColor(name: string): (text: string | number) => string;
|
|
85
|
+
/** Colorizes text with a color function. */
|
|
86
|
+
export declare function colorize(name: string, text: string | number): string;
|
|
87
|
+
/** Sets the color level (0=none, 1=basic, 2=256, 3=truecolor). */
|
|
88
|
+
export declare function setColorLevel(level: 0 | 1 | 2 | 3): void;
|
|
89
|
+
/** Returns a custom "rgb" color function if level is truecolor, otherwise identity. */
|
|
90
|
+
export declare function rgb(r: number, g: number, b: number): (text: string | number) => string;
|
|
91
|
+
export type ColorSupport = {
|
|
92
|
+
isColorSupported: boolean;
|
|
93
|
+
isForced: boolean;
|
|
94
|
+
isDisabled: boolean;
|
|
95
|
+
terminalName: string;
|
|
96
|
+
};
|
|
97
|
+
export declare const colorSupport: ColorSupport;
|
|
98
|
+
export declare function initUserConfig(): Promise<void>;
|
|
99
|
+
/**
|
|
100
|
+
* Provides type safety and IntelliSense for user configuration.
|
|
101
|
+
* Example usage in `relico.config.ts`:
|
|
102
|
+
* ```ts
|
|
103
|
+
* import { defineConfig } from "@reliverse/relico-cfg";
|
|
104
|
+
* export default defineConfig({
|
|
105
|
+
* // Set the color level: 3 for truecolor
|
|
106
|
+
* colorLevel: 3,
|
|
107
|
+
* // Choose the theme: "primary" or "secondary"
|
|
108
|
+
* theme: "secondary",
|
|
109
|
+
* // Override specific colors
|
|
110
|
+
* // - Use Intellisense to see the available colors
|
|
111
|
+
* // - Theming: ["primary", "secondary"]
|
|
112
|
+
* customColors: {
|
|
113
|
+
* blue: ["#5f87ff", "#5f87ff"],
|
|
114
|
+
* red: ["#ff5555", "#ff0000"],
|
|
115
|
+
* green: ["#00ff00", "#00cc00"],
|
|
116
|
+
* // Note: The following text formatting
|
|
117
|
+
* // colors can be defined only via ANSI:
|
|
118
|
+
* // reset: ["\x1b[0m", "\x1b[0m"],
|
|
119
|
+
* // bold: ["\x1b[1m", "\x1b[22m", "\x1b[22m\x1b[1m"],
|
|
120
|
+
* // dim: ["\x1b[2m", "\x1b[22m", "\x1b[22m\x1b[2m"],
|
|
121
|
+
* // italic: ["\x1b[3m", "\x1b[23m"],
|
|
122
|
+
* // underline: ["\x1b[4m", "\x1b[24m"],
|
|
123
|
+
* // inverse: ["\x1b[7m", "\x1b[27m"],
|
|
124
|
+
* // hidden: ["\x1b[8m", "\x1b[28m"],
|
|
125
|
+
* // strikethrough: ["\x1b[9m", "\x1b[29m"],
|
|
126
|
+
* },
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export declare function defineConfig(config: RelicoConfig): RelicoConfig;
|
package/bin/main.js
ADDED
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
import { getCurrentTerminalName } from "@reliverse/runtime";
|
|
2
|
+
import { env, isWindows } from "@reliverse/runtime";
|
|
3
|
+
import { loadConfig } from "c12";
|
|
4
|
+
export const defaultColorKeys = [
|
|
5
|
+
"reset",
|
|
6
|
+
"bold",
|
|
7
|
+
"dim",
|
|
8
|
+
"italic",
|
|
9
|
+
"underline",
|
|
10
|
+
"inverse",
|
|
11
|
+
"hidden",
|
|
12
|
+
"strikethrough",
|
|
13
|
+
"black",
|
|
14
|
+
"red",
|
|
15
|
+
"green",
|
|
16
|
+
"yellow",
|
|
17
|
+
"blue",
|
|
18
|
+
"magenta",
|
|
19
|
+
"cyan",
|
|
20
|
+
"white",
|
|
21
|
+
"gray",
|
|
22
|
+
"bgBlack",
|
|
23
|
+
"bgRed",
|
|
24
|
+
"bgGreen",
|
|
25
|
+
"bgYellow",
|
|
26
|
+
"bgBlue",
|
|
27
|
+
"bgMagenta",
|
|
28
|
+
"bgCyan",
|
|
29
|
+
"bgWhite",
|
|
30
|
+
"blackBright",
|
|
31
|
+
"redBright",
|
|
32
|
+
"greenBright",
|
|
33
|
+
"yellowBright",
|
|
34
|
+
"blueBright",
|
|
35
|
+
"magentaBright",
|
|
36
|
+
"cyanBright",
|
|
37
|
+
"whiteBright",
|
|
38
|
+
"bgBlackBright",
|
|
39
|
+
"bgRedBright",
|
|
40
|
+
"bgGreenBright",
|
|
41
|
+
"bgYellowBright",
|
|
42
|
+
"bgBlueBright",
|
|
43
|
+
"bgMagentaBright",
|
|
44
|
+
"bgCyanBright",
|
|
45
|
+
"bgWhiteBright"
|
|
46
|
+
];
|
|
47
|
+
const argv = typeof process === "undefined" ? [] : process.argv;
|
|
48
|
+
const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
|
|
49
|
+
const isForced = "FORCE_COLOR" in env || argv.includes("--color");
|
|
50
|
+
const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
|
|
51
|
+
const isCompatibleTerminal = typeof process !== "undefined" && Boolean(process.stdout) && Boolean(process.stdout.isTTY) && env.TERM !== "dumb";
|
|
52
|
+
const colorterm = (env.COLORTERM ?? "").toLowerCase();
|
|
53
|
+
const supportsTrueColor = colorterm === "truecolor" || colorterm === "24bit";
|
|
54
|
+
function detectColorLevel() {
|
|
55
|
+
if (isDisabled) return 0;
|
|
56
|
+
if (isForced) return 3;
|
|
57
|
+
if (supportsTrueColor) return 3;
|
|
58
|
+
if (isWindows) return 2;
|
|
59
|
+
if (isCI) return 2;
|
|
60
|
+
if (isCompatibleTerminal) return 2;
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
const baseColors = {
|
|
64
|
+
// Text formatting
|
|
65
|
+
reset: ["\x1B[0m", "\x1B[0m"],
|
|
66
|
+
bold: ["\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"],
|
|
67
|
+
dim: ["\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"],
|
|
68
|
+
italic: ["\x1B[3m", "\x1B[23m"],
|
|
69
|
+
underline: ["\x1B[4m", "\x1B[24m"],
|
|
70
|
+
inverse: ["\x1B[7m", "\x1B[27m"],
|
|
71
|
+
hidden: ["\x1B[8m", "\x1B[28m"],
|
|
72
|
+
strikethrough: ["\x1B[9m", "\x1B[29m"],
|
|
73
|
+
// Foreground colors.
|
|
74
|
+
black: ["#000000", "#000000"],
|
|
75
|
+
red: ["#ff5555", "#ff0000"],
|
|
76
|
+
green: ["#00ff00", "#00ff00"],
|
|
77
|
+
yellow: ["#ffff00", "#ffff00"],
|
|
78
|
+
blue: ["#0000ff", "#0000ff"],
|
|
79
|
+
magenta: ["#ff00ff", "#ff00ff"],
|
|
80
|
+
cyan: ["#00ffff", "#00ffff"],
|
|
81
|
+
white: ["#ffffff", "#ffffff"],
|
|
82
|
+
gray: ["#808080", "#808080"],
|
|
83
|
+
// Background colors.
|
|
84
|
+
bgBlack: ["#000000", "#000000"],
|
|
85
|
+
bgRed: ["#ff5555", "#ff0000"],
|
|
86
|
+
bgGreen: ["#00ff00", "#00ff00"],
|
|
87
|
+
bgYellow: ["#ffff00", "#ffff00"],
|
|
88
|
+
bgBlue: ["#0000ff", "#0000ff"],
|
|
89
|
+
bgMagenta: ["#ff00ff", "#ff00ff"],
|
|
90
|
+
bgCyan: ["#00ffff", "#00ffff"],
|
|
91
|
+
bgWhite: ["#ffffff", "#ffffff"],
|
|
92
|
+
// Bright colors.
|
|
93
|
+
blackBright: ["#000000", "#000000"],
|
|
94
|
+
redBright: ["#ff5555", "#ff5555"],
|
|
95
|
+
greenBright: ["#50fa7b", "#50fa7b"],
|
|
96
|
+
yellowBright: ["#f1fa8c", "#f1fa8c"],
|
|
97
|
+
blueBright: ["#24bdff", "#24bdff"],
|
|
98
|
+
magentaBright: ["#ff79c6", "#ff79c6"],
|
|
99
|
+
cyanBright: ["#8be9fd", "#8be9fd"],
|
|
100
|
+
whiteBright: ["#ffffff", "#ffffff"],
|
|
101
|
+
// Bright background colors.
|
|
102
|
+
bgBlackBright: ["#000000", "#000000"],
|
|
103
|
+
bgRedBright: ["#ff5555", "#ff5555"],
|
|
104
|
+
bgGreenBright: ["#50fa7b", "#50fa7b"],
|
|
105
|
+
bgYellowBright: ["#f1fa8c", "#f1fa8c"],
|
|
106
|
+
bgBlueBright: ["#24bdff", "#24bdff"],
|
|
107
|
+
bgMagentaBright: ["#ff79c6", "#ff79c6"],
|
|
108
|
+
bgCyanBright: ["#8be9fd", "#8be9fd"],
|
|
109
|
+
bgWhiteBright: ["#ffffff", "#ffffff"]
|
|
110
|
+
};
|
|
111
|
+
const windowsTerminalColors = {
|
|
112
|
+
...baseColors,
|
|
113
|
+
red: ["#ff5555", "#ff5555"],
|
|
114
|
+
green: ["#50fa7b", "#50fa7b"],
|
|
115
|
+
yellow: ["#f1fa8c", "#f1fa8c"],
|
|
116
|
+
blue: ["#6272a4", "#6272a4"],
|
|
117
|
+
magenta: ["#ff79c6", "#ff79c6"],
|
|
118
|
+
cyan: ["#8be9fd", "#8be9fd"]
|
|
119
|
+
};
|
|
120
|
+
let config = {
|
|
121
|
+
colorLevel: detectColorLevel(),
|
|
122
|
+
theme: "primary"
|
|
123
|
+
// default theme; can be overridden in user config
|
|
124
|
+
};
|
|
125
|
+
let colorMap = {};
|
|
126
|
+
let colorFunctions = {};
|
|
127
|
+
function hexToRGB(hex) {
|
|
128
|
+
if (hex.startsWith("#")) {
|
|
129
|
+
hex = hex.slice(1);
|
|
130
|
+
}
|
|
131
|
+
if (hex.length === 3) {
|
|
132
|
+
hex = hex.split("").map((c) => c + c).join("");
|
|
133
|
+
}
|
|
134
|
+
if (hex.length !== 6) {
|
|
135
|
+
throw new Error(`Invalid hex color: ${hex}`);
|
|
136
|
+
}
|
|
137
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
138
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
139
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
140
|
+
return { r, g, b };
|
|
141
|
+
}
|
|
142
|
+
function hexToAnsiParts(hex, isBg = false) {
|
|
143
|
+
const { r, g, b } = hexToRGB(hex);
|
|
144
|
+
const open = isBg ? `\x1B[48;2;${r};${g};${b}m` : `\x1B[38;2;${r};${g};${b}m`;
|
|
145
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
146
|
+
return { open, close };
|
|
147
|
+
}
|
|
148
|
+
function hexToAnsi256(hex, isBg = false) {
|
|
149
|
+
const { r, g, b } = hexToRGB(hex);
|
|
150
|
+
const r5 = Math.round(r / 51);
|
|
151
|
+
const g5 = Math.round(g / 51);
|
|
152
|
+
const b5 = Math.round(b / 51);
|
|
153
|
+
const index = 16 + 36 * r5 + 6 * g5 + b5;
|
|
154
|
+
return isBg ? `\x1B[48;5;${index}m` : `\x1B[38;5;${index}m`;
|
|
155
|
+
}
|
|
156
|
+
const basicColors = [
|
|
157
|
+
{ name: "black", rgb: { r: 0, g: 0, b: 0 }, fg: 30, bg: 40 },
|
|
158
|
+
{ name: "red", rgb: { r: 205, g: 0, b: 0 }, fg: 31, bg: 41 },
|
|
159
|
+
{ name: "green", rgb: { r: 0, g: 205, b: 0 }, fg: 32, bg: 42 },
|
|
160
|
+
{ name: "yellow", rgb: { r: 205, g: 205, b: 0 }, fg: 33, bg: 43 },
|
|
161
|
+
{ name: "blue", rgb: { r: 0, g: 0, b: 238 }, fg: 34, bg: 44 },
|
|
162
|
+
{ name: "magenta", rgb: { r: 205, g: 0, b: 205 }, fg: 35, bg: 45 },
|
|
163
|
+
{ name: "cyan", rgb: { r: 0, g: 205, b: 205 }, fg: 36, bg: 46 },
|
|
164
|
+
{ name: "white", rgb: { r: 229, g: 229, b: 229 }, fg: 37, bg: 47 }
|
|
165
|
+
];
|
|
166
|
+
function hexToAnsiBasic(hex, isBg = false) {
|
|
167
|
+
const { r, g, b } = hexToRGB(hex);
|
|
168
|
+
let bestMatch = basicColors[0];
|
|
169
|
+
let bestDistance = Number.MAX_VALUE;
|
|
170
|
+
for (const color of basicColors) {
|
|
171
|
+
const dr = r - color.rgb.r;
|
|
172
|
+
const dg = g - color.rgb.g;
|
|
173
|
+
const db = b - color.rgb.b;
|
|
174
|
+
const distance = dr * dr + dg * dg + db * db;
|
|
175
|
+
if (distance < bestDistance) {
|
|
176
|
+
bestDistance = distance;
|
|
177
|
+
bestMatch = color;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
const code = isBg ? bestMatch.bg : bestMatch.fg;
|
|
181
|
+
return `\x1B[${code}m`;
|
|
182
|
+
}
|
|
183
|
+
function convertColorDefinition(key, def) {
|
|
184
|
+
const isBg = key.toLowerCase().startsWith("bg");
|
|
185
|
+
const theme = config.theme ?? "primary";
|
|
186
|
+
const chosen = theme === "primary" ? def[0] : def[1];
|
|
187
|
+
function convert(str) {
|
|
188
|
+
if (!str.startsWith("#")) return str;
|
|
189
|
+
if (config.colorLevel === 3) {
|
|
190
|
+
return hexToAnsiParts(str, isBg).open;
|
|
191
|
+
}
|
|
192
|
+
if (config.colorLevel === 2) {
|
|
193
|
+
return hexToAnsi256(str, isBg);
|
|
194
|
+
}
|
|
195
|
+
if (config.colorLevel === 1) {
|
|
196
|
+
return hexToAnsiBasic(str, isBg);
|
|
197
|
+
}
|
|
198
|
+
return "";
|
|
199
|
+
}
|
|
200
|
+
const openConverted = convert(chosen);
|
|
201
|
+
const close = isBg ? "\x1B[49m" : "\x1B[39m";
|
|
202
|
+
const rep = def[2] ? def[2].startsWith("#") ? convert(def[2]) : def[2] : void 0;
|
|
203
|
+
return [openConverted, close, rep];
|
|
204
|
+
}
|
|
205
|
+
function buildColorMap(cfg) {
|
|
206
|
+
const terminalName = getCurrentTerminalName();
|
|
207
|
+
const isWinTerm = terminalName === "Windows Terminal";
|
|
208
|
+
if (cfg.colorLevel === 0) {
|
|
209
|
+
const noColorMap = {};
|
|
210
|
+
for (const k of Object.keys(baseColors)) {
|
|
211
|
+
noColorMap[k] = ["", "", ""];
|
|
212
|
+
}
|
|
213
|
+
return noColorMap;
|
|
214
|
+
}
|
|
215
|
+
let builtIn = { ...baseColors };
|
|
216
|
+
if (cfg.customColors) {
|
|
217
|
+
for (const [k, v] of Object.entries(cfg.customColors)) {
|
|
218
|
+
builtIn[k] = v;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
if (isWinTerm && cfg.colorLevel === 3) {
|
|
222
|
+
builtIn = { ...windowsTerminalColors, ...builtIn };
|
|
223
|
+
}
|
|
224
|
+
for (const key of Object.keys(builtIn)) {
|
|
225
|
+
builtIn[key] = convertColorDefinition(key, builtIn[key]);
|
|
226
|
+
}
|
|
227
|
+
return builtIn;
|
|
228
|
+
}
|
|
229
|
+
function createFormatter(open, close, replace = open) {
|
|
230
|
+
const escapedClose = close.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
|
|
231
|
+
const regex = new RegExp(escapedClose, "g");
|
|
232
|
+
return (input) => {
|
|
233
|
+
const stringed = String(input);
|
|
234
|
+
return open + stringed.replace(regex, replace) + close;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function identityColor(text) {
|
|
238
|
+
return String(text);
|
|
239
|
+
}
|
|
240
|
+
const typedRe = {
|
|
241
|
+
reset: identityColor,
|
|
242
|
+
bold: identityColor,
|
|
243
|
+
dim: identityColor,
|
|
244
|
+
italic: identityColor,
|
|
245
|
+
underline: identityColor,
|
|
246
|
+
inverse: identityColor,
|
|
247
|
+
hidden: identityColor,
|
|
248
|
+
strikethrough: identityColor,
|
|
249
|
+
black: identityColor,
|
|
250
|
+
red: identityColor,
|
|
251
|
+
green: identityColor,
|
|
252
|
+
yellow: identityColor,
|
|
253
|
+
blue: identityColor,
|
|
254
|
+
magenta: identityColor,
|
|
255
|
+
cyan: identityColor,
|
|
256
|
+
white: identityColor,
|
|
257
|
+
gray: identityColor,
|
|
258
|
+
bgBlack: identityColor,
|
|
259
|
+
bgRed: identityColor,
|
|
260
|
+
bgGreen: identityColor,
|
|
261
|
+
bgYellow: identityColor,
|
|
262
|
+
bgBlue: identityColor,
|
|
263
|
+
bgMagenta: identityColor,
|
|
264
|
+
bgCyan: identityColor,
|
|
265
|
+
bgWhite: identityColor,
|
|
266
|
+
blackBright: identityColor,
|
|
267
|
+
redBright: identityColor,
|
|
268
|
+
greenBright: identityColor,
|
|
269
|
+
yellowBright: identityColor,
|
|
270
|
+
blueBright: identityColor,
|
|
271
|
+
magentaBright: identityColor,
|
|
272
|
+
cyanBright: identityColor,
|
|
273
|
+
whiteBright: identityColor,
|
|
274
|
+
bgBlackBright: identityColor,
|
|
275
|
+
bgRedBright: identityColor,
|
|
276
|
+
bgGreenBright: identityColor,
|
|
277
|
+
bgYellowBright: identityColor,
|
|
278
|
+
bgBlueBright: identityColor,
|
|
279
|
+
bgMagentaBright: identityColor,
|
|
280
|
+
bgCyanBright: identityColor,
|
|
281
|
+
bgWhiteBright: identityColor
|
|
282
|
+
};
|
|
283
|
+
export const re = typedRe;
|
|
284
|
+
function refreshTypedRe() {
|
|
285
|
+
for (const colorName of Object.keys(typedRe)) {
|
|
286
|
+
typedRe[colorName] = identityColor;
|
|
287
|
+
}
|
|
288
|
+
for (const [k, fn] of Object.entries(colorFunctions)) {
|
|
289
|
+
typedRe[k] = fn;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
function initColorFunctions() {
|
|
293
|
+
colorFunctions = {};
|
|
294
|
+
if (config.colorLevel === 0) {
|
|
295
|
+
for (const k of Object.keys(baseColors)) {
|
|
296
|
+
colorFunctions[k] = identityColor;
|
|
297
|
+
}
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
for (const [key, [open, close, replace]] of Object.entries(colorMap)) {
|
|
301
|
+
colorFunctions[key] = createFormatter(open, close, replace ?? open);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
function rebuild() {
|
|
305
|
+
colorMap = buildColorMap(config);
|
|
306
|
+
initColorFunctions();
|
|
307
|
+
refreshTypedRe();
|
|
308
|
+
}
|
|
309
|
+
rebuild();
|
|
310
|
+
export function configure(userInput) {
|
|
311
|
+
let newConfig;
|
|
312
|
+
if (typeof userInput === "object" && userInput !== null) {
|
|
313
|
+
newConfig = { ...config, ...userInput };
|
|
314
|
+
} else {
|
|
315
|
+
newConfig = { ...config };
|
|
316
|
+
}
|
|
317
|
+
config = newConfig;
|
|
318
|
+
rebuild();
|
|
319
|
+
}
|
|
320
|
+
export function getColor(name) {
|
|
321
|
+
const maybeFn = colorFunctions[name];
|
|
322
|
+
if (maybeFn) return maybeFn;
|
|
323
|
+
const resetFn = colorFunctions.reset;
|
|
324
|
+
if (resetFn) return resetFn;
|
|
325
|
+
return identityColor;
|
|
326
|
+
}
|
|
327
|
+
export function colorize(name, text) {
|
|
328
|
+
const fn = getColor(name);
|
|
329
|
+
return fn(text);
|
|
330
|
+
}
|
|
331
|
+
export function setColorLevel(level) {
|
|
332
|
+
configure({ colorLevel: level });
|
|
333
|
+
}
|
|
334
|
+
export function rgb(r, g, b) {
|
|
335
|
+
if (config.colorLevel === 3) {
|
|
336
|
+
const open = `\x1B[38;2;${r};${g};${b}m`;
|
|
337
|
+
const close = "\x1B[39m";
|
|
338
|
+
return createFormatter(open, close);
|
|
339
|
+
}
|
|
340
|
+
return identityColor;
|
|
341
|
+
}
|
|
342
|
+
export const colorSupport = {
|
|
343
|
+
isColorSupported: getConfig().colorLevel !== 0,
|
|
344
|
+
isForced,
|
|
345
|
+
isDisabled,
|
|
346
|
+
terminalName: getCurrentTerminalName()
|
|
347
|
+
};
|
|
348
|
+
export async function initUserConfig() {
|
|
349
|
+
try {
|
|
350
|
+
const { config: userConfig } = await loadConfig({ name: "relico" });
|
|
351
|
+
configure(userConfig);
|
|
352
|
+
} catch (err) {
|
|
353
|
+
console.warn("Failed to load user config via c12:", err);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
export function defineConfig(config2) {
|
|
357
|
+
return config2;
|
|
358
|
+
}
|
|
359
|
+
function getConfig() {
|
|
360
|
+
return { ...config };
|
|
361
|
+
}
|
package/package.json
CHANGED
|
@@ -1,82 +1,56 @@
|
|
|
1
1
|
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@reliverse/runtime": "^1.0.3",
|
|
4
|
+
"bun-types": "^1.2.8",
|
|
5
|
+
"c12": "^3.0.2",
|
|
6
|
+
"pathe": "^2.0.3"
|
|
7
|
+
},
|
|
8
|
+
"description": "@reliverse/relico is doing its best to improve your terminal colorization experience by leveraging TypeScript and TypeBox for enhanced reliability and type safety.",
|
|
9
|
+
"homepage": "https://docs.reliverse.org",
|
|
10
|
+
"license": "MIT",
|
|
2
11
|
"name": "@reliverse/relico",
|
|
3
|
-
"version": "1.0.1",
|
|
4
|
-
"author": "reliverse",
|
|
5
12
|
"type": "module",
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"build:jsr": "bun build.optim.ts --jsr",
|
|
12
|
-
"build": "bun build:npm && bun build:jsr",
|
|
13
|
-
"pub:npm": "bun build.publish.ts",
|
|
14
|
-
"pub:jsr": "bun build.publish.ts --jsr",
|
|
15
|
-
"pub:dry": "bun build.publish.ts --dry-run",
|
|
16
|
-
"pub": "bun publish.ts",
|
|
17
|
-
"typecheck": "tsc --noEmit",
|
|
18
|
-
"lint": "eslint --cache --fix .",
|
|
19
|
-
"lint:i": "eslint --inspect-config",
|
|
20
|
-
"format": "biome check --write .",
|
|
21
|
-
"attw": "bunx @arethetypeswrong/cli",
|
|
22
|
-
"unpub": "npm unpublish",
|
|
23
|
-
"test": "vitest",
|
|
24
|
-
"knip": "knip",
|
|
25
|
-
"latest": "bun update --latest"
|
|
26
|
-
},
|
|
27
|
-
"publishConfig": {
|
|
28
|
-
"access": "public"
|
|
13
|
+
"version": "1.0.2",
|
|
14
|
+
"author": "reliverse",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"email": "blefnk@gmail.com",
|
|
17
|
+
"url": "https://github.com/reliverse/relico/issues"
|
|
29
18
|
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"reliverse"
|
|
21
|
+
],
|
|
30
22
|
"repository": {
|
|
31
23
|
"type": "git",
|
|
32
24
|
"url": "git+https://github.com/reliverse/relico.git"
|
|
33
25
|
},
|
|
34
|
-
"types": "./dist-npm/main.d.ts",
|
|
35
|
-
"module": "./dist-npm/main.js",
|
|
36
|
-
"main": "./dist-npm/main.js",
|
|
37
|
-
"exports": {
|
|
38
|
-
"import": "./dist-npm/main.js",
|
|
39
|
-
"types": "./dist-npm/main.d.ts"
|
|
40
|
-
},
|
|
41
|
-
"bugs": {
|
|
42
|
-
"url": "https://github.com/reliverse/relico/issues",
|
|
43
|
-
"email": "blefnk@gmail.com"
|
|
44
|
-
},
|
|
45
|
-
"files": ["package.json", "README.md", "LICENSE.md", "dist-npm"],
|
|
46
|
-
"homepage": "https://github.com/reliverse/relico",
|
|
47
|
-
"keywords": ["cli", "reliverse"],
|
|
48
|
-
"license": "MIT",
|
|
49
|
-
"dependencies": {
|
|
50
|
-
"@reliverse/runtime": "^1.0.2",
|
|
51
|
-
"@sinclair/typebox": "^0.34.14",
|
|
52
|
-
"bun-types": "^1.2.0",
|
|
53
|
-
"confbox": "^0.1.8",
|
|
54
|
-
"destr": "^2.0.3",
|
|
55
|
-
"fs-extra": "^11.3.0",
|
|
56
|
-
"globby": "^14.0.2",
|
|
57
|
-
"mri": "^1.2.0",
|
|
58
|
-
"pathe": "^2.0.2"
|
|
59
|
-
},
|
|
60
26
|
"devDependencies": {
|
|
61
|
-
"@arethetypeswrong/cli": "^0.17.3",
|
|
62
27
|
"@biomejs/biome": "1.9.4",
|
|
63
|
-
"@eslint/js": "^9.
|
|
64
|
-
"@
|
|
65
|
-
"@eslint
|
|
66
|
-
"@
|
|
67
|
-
"@types/
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"citty": "^0.1.6",
|
|
72
|
-
"eslint": "^9.19.0",
|
|
73
|
-
"eslint-plugin-perfectionist": "^4.7.0",
|
|
74
|
-
"execa": "^9.5.2",
|
|
28
|
+
"@eslint/js": "^9.23.0",
|
|
29
|
+
"@reliverse/relidler-cfg": "^1.1.3",
|
|
30
|
+
"@stylistic/eslint-plugin": "^4.2.0",
|
|
31
|
+
"@types/bun": "^1.2.8",
|
|
32
|
+
"@types/node": "^22.13.14",
|
|
33
|
+
"eslint": "^9.23.0",
|
|
34
|
+
"eslint-plugin-no-relative-import-paths": "^1.6.1",
|
|
35
|
+
"eslint-plugin-perfectionist": "^4.10.1",
|
|
75
36
|
"jiti": "^2.4.2",
|
|
76
|
-
"knip": "^5.
|
|
77
|
-
"typescript": "^5.
|
|
78
|
-
"typescript-eslint": "^8.
|
|
79
|
-
"
|
|
80
|
-
|
|
37
|
+
"knip": "^5.46.4",
|
|
38
|
+
"typescript": "^5.8.2",
|
|
39
|
+
"typescript-eslint": "^8.29.0",
|
|
40
|
+
"vitest": "^3.1.1"
|
|
41
|
+
},
|
|
42
|
+
"exports": {
|
|
43
|
+
".": "./bin/main.js"
|
|
44
|
+
},
|
|
45
|
+
"files": [
|
|
46
|
+
"bin",
|
|
47
|
+
"package.json",
|
|
48
|
+
"README.md",
|
|
49
|
+
"LICENSE"
|
|
50
|
+
],
|
|
51
|
+
"main": "./bin/main.js",
|
|
52
|
+
"module": "./bin/main.js",
|
|
53
|
+
"publishConfig": {
|
|
54
|
+
"access": "public"
|
|
81
55
|
}
|
|
82
56
|
}
|
package/dist-npm/main.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Static } from "@sinclair/typebox";
|
|
2
|
-
export declare const ColorDefinitionSchema: import("@sinclair/typebox").TTuple<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TString, import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>]>;
|
|
3
|
-
export declare const ColorMapSchema: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TTuple<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TString, import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>]>>;
|
|
4
|
-
export declare const RelicoConfigSchema: import("@sinclair/typebox").TObject<{
|
|
5
|
-
colorLevel: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<0>, import("@sinclair/typebox").TLiteral<1>, import("@sinclair/typebox").TLiteral<2>, import("@sinclair/typebox").TLiteral<3>]>>;
|
|
6
|
-
customColors: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TTuple<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TString, import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>]>>>;
|
|
7
|
-
}>;
|
|
8
|
-
export type RelicoConfig = Static<typeof RelicoConfigSchema>;
|
|
9
|
-
/**
|
|
10
|
-
* Configures the library with a partial or complete `RelicoConfig`.
|
|
11
|
-
* For any invalid fields, a warning is shown and they are ignored.
|
|
12
|
-
*/
|
|
13
|
-
export declare function configure(userInput: unknown): void;
|
|
14
|
-
/** Returns a read-only copy of the current configuration. */
|
|
15
|
-
export declare function getConfig(): RelicoConfig;
|
|
16
|
-
/** Returns a color function by name (or `reset` or identity if not found). */
|
|
17
|
-
export declare function getColor(name: string): (text: string | number) => string;
|
|
18
|
-
/** Colorize text with a color function. */
|
|
19
|
-
export declare function colorize(name: string, text: string | number): string;
|
|
20
|
-
/** Set the color level (0=none,1=basic,2=256,3=truecolor). */
|
|
21
|
-
export declare function setColorLevel(level: 0 | 1 | 2 | 3): void;
|
|
22
|
-
/** Returns a custom "rgb" color function if level=3, otherwise identity. */
|
|
23
|
-
export declare function rgb(r: number, g: number, b: number): (text: string | number) => string;
|
|
24
|
-
export type IRelicoColors = {
|
|
25
|
-
reset(text: string | number): string;
|
|
26
|
-
bold(text: string | number): string;
|
|
27
|
-
dim(text: string | number): string;
|
|
28
|
-
italic(text: string | number): string;
|
|
29
|
-
underline(text: string | number): string;
|
|
30
|
-
inverse(text: string | number): string;
|
|
31
|
-
hidden(text: string | number): string;
|
|
32
|
-
strikethrough(text: string | number): string;
|
|
33
|
-
black(text: string | number): string;
|
|
34
|
-
red(text: string | number): string;
|
|
35
|
-
green(text: string | number): string;
|
|
36
|
-
yellow(text: string | number): string;
|
|
37
|
-
blue(text: string | number): string;
|
|
38
|
-
magenta(text: string | number): string;
|
|
39
|
-
cyan(text: string | number): string;
|
|
40
|
-
white(text: string | number): string;
|
|
41
|
-
gray(text: string | number): string;
|
|
42
|
-
bgBlack(text: string | number): string;
|
|
43
|
-
bgRed(text: string | number): string;
|
|
44
|
-
bgGreen(text: string | number): string;
|
|
45
|
-
bgYellow(text: string | number): string;
|
|
46
|
-
bgBlue(text: string | number): string;
|
|
47
|
-
bgMagenta(text: string | number): string;
|
|
48
|
-
bgCyan(text: string | number): string;
|
|
49
|
-
bgWhite(text: string | number): string;
|
|
50
|
-
blackBright(text: string | number): string;
|
|
51
|
-
redBright(text: string | number): string;
|
|
52
|
-
greenBright(text: string | number): string;
|
|
53
|
-
yellowBright(text: string | number): string;
|
|
54
|
-
blueBright(text: string | number): string;
|
|
55
|
-
magentaBright(text: string | number): string;
|
|
56
|
-
cyanBright(text: string | number): string;
|
|
57
|
-
whiteBright(text: string | number): string;
|
|
58
|
-
bgBlackBright(text: string | number): string;
|
|
59
|
-
bgRedBright(text: string | number): string;
|
|
60
|
-
bgGreenBright(text: string | number): string;
|
|
61
|
-
bgYellowBright(text: string | number): string;
|
|
62
|
-
bgBlueBright(text: string | number): string;
|
|
63
|
-
bgMagentaBright(text: string | number): string;
|
|
64
|
-
bgCyanBright(text: string | number): string;
|
|
65
|
-
bgWhiteBright(text: string | number): string;
|
|
66
|
-
[k: string]: (text: string | number) => string;
|
|
67
|
-
};
|
|
68
|
-
/**
|
|
69
|
-
* The typed `re` object with all known color methods
|
|
70
|
-
* plus user-defined ones (index signature).
|
|
71
|
-
*/
|
|
72
|
-
export declare const re: IRelicoColors;
|
|
73
|
-
export type ColorSupport = {
|
|
74
|
-
isColorSupported: boolean;
|
|
75
|
-
isForced: boolean;
|
|
76
|
-
isDisabled: boolean;
|
|
77
|
-
terminalName: string;
|
|
78
|
-
};
|
|
79
|
-
export declare const colorSupport: ColorSupport;
|
package/dist-npm/main.js
DELETED
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import { getCurrentTerminalName } from "@reliverse/runtime";
|
|
2
|
-
import { env, isWindows } from "@reliverse/runtime";
|
|
3
|
-
import { Type } from "@sinclair/typebox";
|
|
4
|
-
import { Value } from "@sinclair/typebox/value";
|
|
5
|
-
export const ColorDefinitionSchema = Type.Tuple([
|
|
6
|
-
Type.String(),
|
|
7
|
-
Type.String(),
|
|
8
|
-
Type.Optional(Type.String())
|
|
9
|
-
]);
|
|
10
|
-
export const ColorMapSchema = Type.Record(Type.String(), ColorDefinitionSchema);
|
|
11
|
-
export const RelicoConfigSchema = Type.Object(
|
|
12
|
-
{
|
|
13
|
-
colorLevel: Type.Optional(
|
|
14
|
-
Type.Union([
|
|
15
|
-
Type.Literal(0),
|
|
16
|
-
Type.Literal(1),
|
|
17
|
-
Type.Literal(2),
|
|
18
|
-
Type.Literal(3)
|
|
19
|
-
])
|
|
20
|
-
),
|
|
21
|
-
customColors: Type.Optional(ColorMapSchema)
|
|
22
|
-
},
|
|
23
|
-
{ additionalProperties: false }
|
|
24
|
-
);
|
|
25
|
-
const argv = typeof process === "undefined" ? [] : process.argv;
|
|
26
|
-
const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
|
|
27
|
-
const isForced = "FORCE_COLOR" in env || argv.includes("--color");
|
|
28
|
-
const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
|
|
29
|
-
const isCompatibleTerminal = typeof process !== "undefined" && Boolean(process.stdout) && Boolean(process.stdout.isTTY) && env["TERM"] !== "dumb";
|
|
30
|
-
const colorterm = (env["COLORTERM"] ?? "").toLowerCase();
|
|
31
|
-
const supportsTrueColor = colorterm === "truecolor" || colorterm === "24bit";
|
|
32
|
-
function detectColorLevel() {
|
|
33
|
-
if (isDisabled) return 0;
|
|
34
|
-
if (isForced) return 3;
|
|
35
|
-
if (supportsTrueColor) return 3;
|
|
36
|
-
if (isWindows) return 2;
|
|
37
|
-
if (isCI) return 2;
|
|
38
|
-
if (isCompatibleTerminal) {
|
|
39
|
-
return 2;
|
|
40
|
-
}
|
|
41
|
-
return 0;
|
|
42
|
-
}
|
|
43
|
-
const baseColors = {
|
|
44
|
-
reset: ["\x1B[0m", "\x1B[0m"],
|
|
45
|
-
bold: ["\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"],
|
|
46
|
-
dim: ["\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"],
|
|
47
|
-
italic: ["\x1B[3m", "\x1B[23m"],
|
|
48
|
-
underline: ["\x1B[4m", "\x1B[24m"],
|
|
49
|
-
inverse: ["\x1B[7m", "\x1B[27m"],
|
|
50
|
-
hidden: ["\x1B[8m", "\x1B[28m"],
|
|
51
|
-
strikethrough: ["\x1B[9m", "\x1B[29m"],
|
|
52
|
-
black: ["\x1B[30m", "\x1B[39m"],
|
|
53
|
-
red: ["\x1B[31m", "\x1B[39m"],
|
|
54
|
-
green: ["\x1B[32m", "\x1B[39m"],
|
|
55
|
-
yellow: ["\x1B[33m", "\x1B[39m"],
|
|
56
|
-
blue: ["\x1B[34m", "\x1B[39m"],
|
|
57
|
-
magenta: ["\x1B[35m", "\x1B[39m"],
|
|
58
|
-
cyan: ["\x1B[36m", "\x1B[39m"],
|
|
59
|
-
white: ["\x1B[37m", "\x1B[39m"],
|
|
60
|
-
gray: ["\x1B[90m", "\x1B[39m"],
|
|
61
|
-
bgBlack: ["\x1B[40m", "\x1B[49m"],
|
|
62
|
-
bgRed: ["\x1B[41m", "\x1B[49m"],
|
|
63
|
-
bgGreen: ["\x1B[42m", "\x1B[49m"],
|
|
64
|
-
bgYellow: ["\x1B[43m", "\x1B[49m"],
|
|
65
|
-
bgBlue: ["\x1B[44m", "\x1B[49m"],
|
|
66
|
-
bgMagenta: ["\x1B[45m", "\x1B[49m"],
|
|
67
|
-
bgCyan: ["\x1B[46m", "\x1B[49m"],
|
|
68
|
-
bgWhite: ["\x1B[47m", "\x1B[49m"],
|
|
69
|
-
blackBright: ["\x1B[90m", "\x1B[39m"],
|
|
70
|
-
redBright: ["\x1B[91m", "\x1B[39m"],
|
|
71
|
-
greenBright: ["\x1B[92m", "\x1B[39m"],
|
|
72
|
-
yellowBright: ["\x1B[93m", "\x1B[39m"],
|
|
73
|
-
blueBright: ["\x1B[94m", "\x1B[39m"],
|
|
74
|
-
magentaBright: ["\x1B[95m", "\x1B[39m"],
|
|
75
|
-
cyanBright: ["\x1B[96m", "\x1B[39m"],
|
|
76
|
-
whiteBright: ["\x1B[97m", "\x1B[39m"],
|
|
77
|
-
bgBlackBright: ["\x1B[100m", "\x1B[49m"],
|
|
78
|
-
bgRedBright: ["\x1B[101m", "\x1B[49m"],
|
|
79
|
-
bgGreenBright: ["\x1B[102m", "\x1B[49m"],
|
|
80
|
-
bgYellowBright: ["\x1B[103m", "\x1B[49m"],
|
|
81
|
-
bgBlueBright: ["\x1B[104m", "\x1B[49m"],
|
|
82
|
-
bgMagentaBright: ["\x1B[105m", "\x1B[49m"],
|
|
83
|
-
bgCyanBright: ["\x1B[106m", "\x1B[49m"],
|
|
84
|
-
bgWhiteBright: ["\x1B[107m", "\x1B[49m"]
|
|
85
|
-
};
|
|
86
|
-
const windowsTerminalColors = {
|
|
87
|
-
...baseColors,
|
|
88
|
-
red: ["\x1B[38;2;255;85;85m", "\x1B[39m"],
|
|
89
|
-
green: ["\x1B[38;2;80;250;123m", "\x1B[39m"],
|
|
90
|
-
yellow: ["\x1B[38;2;241;250;140m", "\x1B[39m"],
|
|
91
|
-
blue: ["\x1B[38;2;98;114;164m", "\x1B[39m"],
|
|
92
|
-
magenta: ["\x1B[38;2;255;121;198m", "\x1B[39m"],
|
|
93
|
-
cyan: ["\x1B[38;2;139;233;253m", "\x1B[39m"]
|
|
94
|
-
};
|
|
95
|
-
let config = {
|
|
96
|
-
colorLevel: detectColorLevel()
|
|
97
|
-
};
|
|
98
|
-
let colorMap = {};
|
|
99
|
-
let colorFunctions = {};
|
|
100
|
-
function replaceClose(str, close, replace, index) {
|
|
101
|
-
let result = "";
|
|
102
|
-
let cursor = 0;
|
|
103
|
-
let i = index;
|
|
104
|
-
while (i !== -1) {
|
|
105
|
-
result += str.substring(cursor, i) + replace;
|
|
106
|
-
cursor = i + close.length;
|
|
107
|
-
i = str.indexOf(close, cursor);
|
|
108
|
-
}
|
|
109
|
-
return result + str.substring(cursor);
|
|
110
|
-
}
|
|
111
|
-
function createFormatter(open, close, replace = open) {
|
|
112
|
-
return (input) => {
|
|
113
|
-
const stringed = String(input);
|
|
114
|
-
const idx = stringed.indexOf(close, open.length);
|
|
115
|
-
if (idx !== -1) {
|
|
116
|
-
return open + replaceClose(stringed, close, replace, idx) + close;
|
|
117
|
-
}
|
|
118
|
-
return open + stringed + close;
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
function buildColorMap(cfg) {
|
|
122
|
-
const terminalName = getCurrentTerminalName();
|
|
123
|
-
const isWinTerm = terminalName === "Windows Terminal";
|
|
124
|
-
if (cfg.colorLevel === 0) {
|
|
125
|
-
const map = {};
|
|
126
|
-
for (const k of Object.keys(baseColors)) {
|
|
127
|
-
map[k] = ["", "", ""];
|
|
128
|
-
}
|
|
129
|
-
return map;
|
|
130
|
-
}
|
|
131
|
-
let builtIn;
|
|
132
|
-
if (isWinTerm && cfg.colorLevel === 3) {
|
|
133
|
-
builtIn = { ...windowsTerminalColors };
|
|
134
|
-
} else {
|
|
135
|
-
builtIn = { ...baseColors };
|
|
136
|
-
}
|
|
137
|
-
if (cfg.customColors) {
|
|
138
|
-
for (const [k, v] of Object.entries(cfg.customColors)) {
|
|
139
|
-
builtIn[k] = v;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
return builtIn;
|
|
143
|
-
}
|
|
144
|
-
function initColorFunctions() {
|
|
145
|
-
colorFunctions = {};
|
|
146
|
-
if (config.colorLevel === 0) {
|
|
147
|
-
for (const k of Object.keys(baseColors)) {
|
|
148
|
-
colorFunctions[k] = identityColor;
|
|
149
|
-
}
|
|
150
|
-
return;
|
|
151
|
-
}
|
|
152
|
-
for (const [key, [open, close, replace]] of Object.entries(colorMap)) {
|
|
153
|
-
colorFunctions[key] = createFormatter(open, close, replace ?? open);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
function rebuild() {
|
|
157
|
-
colorMap = buildColorMap(config);
|
|
158
|
-
initColorFunctions();
|
|
159
|
-
}
|
|
160
|
-
function identityColor(text) {
|
|
161
|
-
return String(text);
|
|
162
|
-
}
|
|
163
|
-
rebuild();
|
|
164
|
-
export function configure(userInput) {
|
|
165
|
-
let newObj = null;
|
|
166
|
-
if (typeof userInput === "object" && userInput !== null) {
|
|
167
|
-
newObj = { ...config, ...userInput };
|
|
168
|
-
} else {
|
|
169
|
-
newObj = { ...config };
|
|
170
|
-
}
|
|
171
|
-
try {
|
|
172
|
-
const parsed = Value.Cast(RelicoConfigSchema, newObj);
|
|
173
|
-
config = parsed;
|
|
174
|
-
} catch (err) {
|
|
175
|
-
console.warn("Invalid relico config:", err);
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
rebuild();
|
|
179
|
-
}
|
|
180
|
-
export function getConfig() {
|
|
181
|
-
return { ...config };
|
|
182
|
-
}
|
|
183
|
-
export function getColor(name) {
|
|
184
|
-
const maybeFn = colorFunctions[name];
|
|
185
|
-
if (maybeFn) return maybeFn;
|
|
186
|
-
const resetFn = colorFunctions["reset"];
|
|
187
|
-
if (resetFn) return resetFn;
|
|
188
|
-
return identityColor;
|
|
189
|
-
}
|
|
190
|
-
export function colorize(name, text) {
|
|
191
|
-
const fn = getColor(name);
|
|
192
|
-
return fn(text);
|
|
193
|
-
}
|
|
194
|
-
export function setColorLevel(level) {
|
|
195
|
-
configure({ colorLevel: level });
|
|
196
|
-
}
|
|
197
|
-
export function rgb(r, g, b) {
|
|
198
|
-
if (config.colorLevel === 3) {
|
|
199
|
-
const open = `\x1B[38;2;${String(r)};${String(g)};${String(b)}m`;
|
|
200
|
-
const close = "\x1B[39m";
|
|
201
|
-
return createFormatter(open, close);
|
|
202
|
-
}
|
|
203
|
-
return identityColor;
|
|
204
|
-
}
|
|
205
|
-
const typedRe = {
|
|
206
|
-
reset: identityColor,
|
|
207
|
-
bold: identityColor,
|
|
208
|
-
dim: identityColor,
|
|
209
|
-
italic: identityColor,
|
|
210
|
-
underline: identityColor,
|
|
211
|
-
inverse: identityColor,
|
|
212
|
-
hidden: identityColor,
|
|
213
|
-
strikethrough: identityColor,
|
|
214
|
-
black: identityColor,
|
|
215
|
-
red: identityColor,
|
|
216
|
-
green: identityColor,
|
|
217
|
-
yellow: identityColor,
|
|
218
|
-
blue: identityColor,
|
|
219
|
-
magenta: identityColor,
|
|
220
|
-
cyan: identityColor,
|
|
221
|
-
white: identityColor,
|
|
222
|
-
gray: identityColor,
|
|
223
|
-
bgBlack: identityColor,
|
|
224
|
-
bgRed: identityColor,
|
|
225
|
-
bgGreen: identityColor,
|
|
226
|
-
bgYellow: identityColor,
|
|
227
|
-
bgBlue: identityColor,
|
|
228
|
-
bgMagenta: identityColor,
|
|
229
|
-
bgCyan: identityColor,
|
|
230
|
-
bgWhite: identityColor,
|
|
231
|
-
blackBright: identityColor,
|
|
232
|
-
redBright: identityColor,
|
|
233
|
-
greenBright: identityColor,
|
|
234
|
-
yellowBright: identityColor,
|
|
235
|
-
blueBright: identityColor,
|
|
236
|
-
magentaBright: identityColor,
|
|
237
|
-
cyanBright: identityColor,
|
|
238
|
-
whiteBright: identityColor,
|
|
239
|
-
bgBlackBright: identityColor,
|
|
240
|
-
bgRedBright: identityColor,
|
|
241
|
-
bgGreenBright: identityColor,
|
|
242
|
-
bgYellowBright: identityColor,
|
|
243
|
-
bgBlueBright: identityColor,
|
|
244
|
-
bgMagentaBright: identityColor,
|
|
245
|
-
bgCyanBright: identityColor,
|
|
246
|
-
bgWhiteBright: identityColor
|
|
247
|
-
};
|
|
248
|
-
function refreshTypedRe() {
|
|
249
|
-
for (const colorName of Object.keys(typedRe)) {
|
|
250
|
-
typedRe[colorName] = identityColor;
|
|
251
|
-
}
|
|
252
|
-
for (const [k, fn] of Object.entries(colorFunctions)) {
|
|
253
|
-
typedRe[k] = fn;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
const originalRebuild = rebuild;
|
|
257
|
-
function newRebuild() {
|
|
258
|
-
originalRebuild();
|
|
259
|
-
refreshTypedRe();
|
|
260
|
-
}
|
|
261
|
-
rebuild = newRebuild;
|
|
262
|
-
newRebuild();
|
|
263
|
-
export const re = typedRe;
|
|
264
|
-
export const colorSupport = {
|
|
265
|
-
isColorSupported: getConfig().colorLevel !== 0,
|
|
266
|
-
isForced,
|
|
267
|
-
isDisabled,
|
|
268
|
-
terminalName: getCurrentTerminalName()
|
|
269
|
-
};
|