@reliverse/relinka 1.2.7 → 1.2.9

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.
@@ -1,29 +1,29 @@
1
+ import { re } from "@reliverse/relico";
1
2
  import gradient, { cristal, mind, passion, retro, vice } from "gradient-string";
2
3
  import { rainbow } from "gradient-string";
3
- import pc from "picocolors";
4
4
  export const colorMap = {
5
- // picocolors
5
+ // @reliverse/relico
6
6
  none: (text) => text,
7
- reset: pc.reset,
8
- bgCyan: pc.bgCyan,
9
- bgCyanBright: pc.bgCyanBright,
10
- black: pc.black,
11
- blue: pc.blue,
12
- blueBright: pc.blueBright,
13
- cyan: pc.cyan,
14
- cyanBright: pc.cyanBright,
15
- dim: pc.dim,
16
- gray: pc.gray,
17
- green: pc.green,
18
- greenBright: pc.greenBright,
19
- inverse: (text) => pc.bold(pc.inverse(text)),
20
- magenta: pc.magenta,
21
- magentaBright: pc.magentaBright,
22
- red: pc.red,
23
- redBright: pc.redBright,
24
- white: pc.white,
25
- yellow: pc.yellow,
26
- yellowBright: pc.yellowBright,
7
+ reset: re.reset,
8
+ bgCyan: re.bgCyan,
9
+ bgCyanBright: re.bgCyanBright,
10
+ black: re.black,
11
+ blue: re.blue,
12
+ blueBright: re.blueBright,
13
+ cyan: re.cyan,
14
+ cyanBright: re.cyanBright,
15
+ dim: re.dim,
16
+ gray: re.gray,
17
+ green: re.green,
18
+ greenBright: re.greenBright,
19
+ inverse: (text) => re.bold(re.inverse(text)),
20
+ magenta: re.magenta,
21
+ magentaBright: re.magentaBright,
22
+ red: re.red,
23
+ redBright: re.redBright,
24
+ white: re.white,
25
+ yellow: re.yellow,
26
+ yellowBright: re.yellowBright,
27
27
  // gradient-string
28
28
  cristalGradient: cristal,
29
29
  gradientGradient: gradient([
@@ -42,8 +42,8 @@ export const colorMap = {
42
42
  };
43
43
  export const typographyMap = {
44
44
  none: (text) => text,
45
- bold: pc.bold,
46
- italic: pc.italic,
47
- strikethrough: pc.strikethrough,
48
- underline: pc.underline
45
+ bold: re.bold,
46
+ italic: re.italic,
47
+ strikethrough: re.strikethrough,
48
+ underline: re.underline
49
49
  };
@@ -4,7 +4,7 @@ import { type VariantName } from "./variants.js";
4
4
  /**
5
5
  * Known symbol names that will have IntelliSense support
6
6
  */
7
- export type SymbolName = "pointer" | "start" | "middle" | "end" | "line" | "corner_top_right" | "step_active" | "step_error" | "info";
7
+ export type SymbolName = "pointer" | "start" | "middle" | "end" | "line" | "corner_top_right" | "step_active" | "step_error" | "info" | "success";
8
8
  export type FmtMsgOptions = {
9
9
  type: MsgType;
10
10
  title?: string;
@@ -54,14 +54,13 @@ export declare const symbols: {
54
54
  readonly success: string;
55
55
  };
56
56
  /**
57
- * Returns a colored vertical bar symbol.
57
+ * Returns a colored vertical bar symbol. Prevents gradient colors for bars.
58
58
  */
59
- export declare const bar: ({ borderColor, }: {
59
+ export declare const bar: ({ borderColor, }?: {
60
60
  borderColor?: ColorName;
61
61
  }) => string;
62
62
  /**
63
- * Formats a message line according to the given FmtMsgOptions.
64
- * Returns both the formatted text and the number of lines it would occupy.
63
+ * Main formatter function: builds the final text output based on FmtMsgOptions.
65
64
  */
66
65
  export declare function fmt(opts: FmtMsgOptions): {
67
66
  text: string;
@@ -83,7 +82,6 @@ export declare function msgUndoAll(): void;
83
82
  /**
84
83
  * Prints: "│ <text>" (two spaces after the bar).
85
84
  * If text is empty, it just prints "│".
86
- * If indent is 1, it prints "│ <text>" (one space).
87
- * If indent is 2, it prints "│ <text>" (two spaces), etc.
85
+ * If indent is 1, it prints "│ <text>", etc.
88
86
  */
89
87
  export declare function printLineBar(text: string, indent?: number): void;
@@ -1,4 +1,4 @@
1
- import pc from "picocolors";
1
+ import { re } from "@reliverse/relico";
2
2
  import wrapAnsi from "wrap-ansi";
3
3
  import { colorMap, typographyMap } from "./mapping.js";
4
4
  import { isUnicodeSupported } from "./platforms.js";
@@ -22,44 +22,35 @@ export const symbols = {
22
22
  info: u("\u2139", "i"),
23
23
  success: u("\u2705", "\u2713")
24
24
  };
25
- function wrapAndStyleText(input, typographyName, colorName, variantName, borderColor) {
26
- const adjustedWidth = getTerminalWidth();
27
- const wrappedText = wrapAnsi(input, adjustedWidth, {
28
- hard: false,
29
- trim: true
30
- });
31
- return wrappedText.split("\n").map((line) => {
32
- const isOption = line.startsWith(" ") || line.startsWith("[ ]") || line.startsWith("[x]");
33
- return applyStyles(
34
- line,
35
- colorName && !isOption ? colorName : void 0,
36
- typographyName && !isOption ? typographyName : void 0,
37
- variantName && variantName !== "none" ? variantName : void 0,
38
- borderColor
39
- );
40
- }).join("\n");
25
+ function wrapThenStyle(input, wrap, typographyName, colorName, variantName, borderColor) {
26
+ if (!input) return "";
27
+ const width = getTerminalWidth();
28
+ const wrappedText = wrap ? wrapAnsi(input, width, { hard: false, trim: true }) : input;
29
+ return wrappedText.split("\n").map(
30
+ (line) => applyStyles(line, colorName, typographyName, variantName, borderColor)
31
+ ).join("\n");
41
32
  }
42
33
  function applyStyles(text, colorName, typographyName, variantName, borderColor) {
43
34
  let styledText = text;
44
- if (!isValidVariant(variantName)) {
45
- if (colorName && colorMap[colorName]) {
46
- styledText = colorMap[colorName](styledText);
47
- }
48
- if (typographyName && typographyMap[typographyName]) {
49
- styledText = typographyMap[typographyName](styledText);
50
- }
51
- } else if (variantName) {
35
+ if (variantName && isValidVariant(variantName)) {
52
36
  styledText = variantMap[variantName](
53
37
  [styledText],
54
38
  void 0,
55
39
  borderColor
56
40
  ).toString();
41
+ return styledText;
42
+ }
43
+ if (colorName && colorMap[colorName]) {
44
+ styledText = colorMap[colorName](styledText);
45
+ }
46
+ if (typographyName && typographyMap[typographyName]) {
47
+ styledText = typographyMap[typographyName](styledText);
57
48
  }
58
49
  return styledText;
59
50
  }
60
51
  export const bar = ({
61
52
  borderColor = "dim"
62
- }) => {
53
+ } = {}) => {
63
54
  if (borderColor.endsWith("Gradient")) {
64
55
  console.error(
65
56
  "Gradient colors are not supported for bars. Please use a solid color instead."
@@ -71,22 +62,87 @@ export const bar = ({
71
62
  function countLines(text) {
72
63
  return text.split("\n").length;
73
64
  }
65
+ function getColoredSymbol(customSymbol, symbolName, symbolColor) {
66
+ if (customSymbol) {
67
+ return symbolColor && colorMap[symbolColor] ? colorMap[symbolColor](customSymbol) : customSymbol;
68
+ }
69
+ if (symbolName && symbols[symbolName]) {
70
+ return symbolColor && colorMap[symbolColor] ? colorMap[symbolColor](symbols[symbolName]) : symbols[symbolName];
71
+ }
72
+ return void 0;
73
+ }
74
+ function formatTitle(opts, borderTwoSpaces, borderError) {
75
+ let formattedTitle = "";
76
+ if (!opts.title) return formattedTitle;
77
+ const wrappedOrStyledTitle = wrapThenStyle(
78
+ opts.title,
79
+ opts.wrapTitle ?? true,
80
+ opts.titleTypography ?? "bold",
81
+ opts.titleColor ?? "cyan",
82
+ opts.titleVariant,
83
+ opts.borderColor
84
+ );
85
+ formattedTitle += wrappedOrStyledTitle;
86
+ if (opts.hint) {
87
+ const hintColor = opts.hintPlaceholderColor ?? "blue";
88
+ const wrappedHint = wrapThenStyle(
89
+ opts.hint,
90
+ opts.wrapTitle ?? true,
91
+ // same wrap logic as title by default
92
+ opts.hintTypography ?? "italic",
93
+ hintColor,
94
+ void 0,
95
+ opts.borderColor
96
+ );
97
+ formattedTitle += `
98
+ ${borderTwoSpaces}${wrappedHint}`;
99
+ }
100
+ if (opts.placeholder && opts.type === "M_GENERAL") {
101
+ const placeHolderColor = opts.hintPlaceholderColor ?? "blue";
102
+ formattedTitle += `
103
+ ${borderTwoSpaces}${colorMap[placeHolderColor](opts.placeholder)}`;
104
+ }
105
+ if (opts.errorMessage) {
106
+ const formattedError = applyStyles(
107
+ opts.errorMessage,
108
+ "red",
109
+ "bold",
110
+ void 0,
111
+ opts.borderColor
112
+ );
113
+ formattedTitle += `
114
+ ${borderError} ${formattedError}`;
115
+ }
116
+ return formattedTitle;
117
+ }
118
+ function formatContent(opts) {
119
+ if (!opts.content) return "";
120
+ return wrapThenStyle(
121
+ opts.content,
122
+ opts.wrapContent ?? true,
123
+ opts.contentTypography ?? "italic",
124
+ opts.contentColor ?? "dim",
125
+ opts.contentVariant,
126
+ opts.borderColor
127
+ );
128
+ }
74
129
  export function fmt(opts) {
75
130
  if (!opts.borderColor) {
76
131
  opts.borderColor = "dim";
77
132
  }
78
- const border = applyStyles(symbols.middle, opts.borderColor);
133
+ const borderColored = applyStyles(symbols.middle, opts.borderColor);
79
134
  const borderError = applyStyles(symbols.middle, "red");
80
- const borderWithSpace = `${border} `;
135
+ const borderTwoSpaces = `${borderColored} `;
81
136
  const prefixStartLine = opts.borderColor ? colorMap[opts.borderColor](symbols.start + symbols.line) : symbols.start + symbols.line;
82
137
  const prefixEndLine = opts.borderColor ? colorMap[opts.borderColor](symbols.end + symbols.line) : symbols.end + symbols.line;
83
138
  const lineLength = opts.horizontalLineLength === 0 ? getExactTerminalWidth() - 3 : opts.horizontalLineLength ?? getExactTerminalWidth() - 3;
84
139
  const suffixStartLine = opts.borderColor ? colorMap[opts.borderColor](`${symbols.line.repeat(lineLength)}\u22B1`) : `${symbols.line.repeat(lineLength)}\u22B1`;
85
140
  const suffixEndLine = opts.borderColor ? colorMap[opts.borderColor](`${symbols.line.repeat(lineLength)}\u22B1`) : `${symbols.line.repeat(lineLength)}\u22B1`;
86
- const MSG_CONFIGS = {
141
+ const computedSymbol = getColoredSymbol(opts.customSymbol, opts.symbol, opts.symbolColor) ?? re.green(symbols.step_active);
142
+ const MESSAGE_CONFIG_MAP = {
87
143
  M_NULL: {
88
144
  symbol: "",
89
- prefix: borderWithSpace,
145
+ prefix: borderTwoSpaces,
90
146
  suffix: "",
91
147
  newLineBefore: opts.addNewLineBefore ?? false,
92
148
  newLineAfter: opts.addNewLineAfter ?? false
@@ -100,7 +156,7 @@ export function fmt(opts) {
100
156
  },
101
157
  M_INFO_NULL: {
102
158
  symbol: "",
103
- prefix: borderWithSpace,
159
+ prefix: borderTwoSpaces,
104
160
  suffix: "",
105
161
  newLineBefore: opts.addNewLineBefore ?? false,
106
162
  newLineAfter: opts.addNewLineAfter ?? false
@@ -109,47 +165,49 @@ export function fmt(opts) {
109
165
  symbol: "",
110
166
  prefix: "",
111
167
  suffix: `
112
- ${borderWithSpace}`,
168
+ ${borderTwoSpaces}`,
113
169
  newLineBefore: opts.addNewLineBefore ?? false,
114
170
  newLineAfter: opts.addNewLineAfter ?? false
115
171
  },
116
172
  M_MIDDLE: {
117
173
  symbol: "",
118
- prefix: borderWithSpace,
174
+ prefix: borderTwoSpaces,
119
175
  suffix: "",
120
176
  newLineBefore: opts.addNewLineBefore ?? false,
121
177
  newLineAfter: opts.addNewLineAfter ?? false
122
178
  },
123
179
  M_GENERAL: {
124
- symbol: opts.customSymbol ? opts.symbolColor ? colorMap[opts.symbolColor](opts.customSymbol) : opts.customSymbol : opts.symbol ? opts.symbolColor ? colorMap[opts.symbolColor](symbols[opts.symbol]) : symbols[opts.symbol] : pc.green(symbols.step_active),
125
- prefix: borderWithSpace,
180
+ symbol: computedSymbol,
181
+ prefix: borderTwoSpaces,
126
182
  suffix: "",
127
183
  newLineBefore: opts.addNewLineBefore ?? false,
128
184
  newLineAfter: opts.addNewLineAfter ?? false
129
185
  },
130
186
  M_GENERAL_NULL: {
131
187
  symbol: "",
132
- prefix: borderWithSpace,
188
+ prefix: borderTwoSpaces,
133
189
  suffix: opts.placeholder ? colorMap[opts.hintPlaceholderColor ?? "blue"](opts.placeholder) : "",
134
190
  newLineBefore: opts.addNewLineBefore ?? false,
135
191
  newLineAfter: opts.addNewLineAfter ?? false
136
192
  },
137
193
  M_INFO: {
138
- symbol: opts.customSymbol ? opts.symbolColor ? colorMap[opts.symbolColor](opts.customSymbol) : opts.customSymbol : opts.symbol ? opts.symbolColor ? colorMap[opts.symbolColor](symbols[opts.symbol]) : symbols[opts.symbol] : pc.green(symbols.info),
139
- prefix: borderWithSpace,
194
+ symbol: computedSymbol || re.green(symbols.info),
195
+ prefix: borderTwoSpaces,
140
196
  suffix: "",
141
197
  newLineBefore: opts.addNewLineBefore ?? false,
142
198
  newLineAfter: opts.addNewLineAfter ?? true
143
199
  },
144
200
  M_ERROR: {
145
- symbol: opts.customSymbol ? opts.symbolColor ? colorMap[opts.symbolColor](opts.customSymbol) : opts.customSymbol : opts.symbol ? opts.symbolColor ? colorMap[opts.symbolColor](symbols[opts.symbol]) : symbols[opts.symbol] : pc.redBright(symbols.step_error),
146
- prefix: borderWithSpace,
201
+ symbol: computedSymbol || re.redBright(symbols.step_error),
202
+ prefix: borderTwoSpaces,
203
+ suffix: "",
147
204
  newLineBefore: opts.addNewLineBefore ?? false,
148
205
  newLineAfter: opts.addNewLineAfter ?? false
149
206
  },
150
207
  M_ERROR_NULL: {
151
208
  symbol: "",
152
- prefix: borderWithSpace,
209
+ prefix: borderTwoSpaces,
210
+ suffix: "",
153
211
  newLineBefore: opts.addNewLineBefore ?? false,
154
212
  newLineAfter: opts.addNewLineAfter ?? false
155
213
  },
@@ -162,111 +220,31 @@ ${borderWithSpace}`,
162
220
  },
163
221
  M_NEWLINE: {
164
222
  symbol: "",
165
- prefix: borderWithSpace,
223
+ prefix: borderTwoSpaces,
224
+ suffix: "",
166
225
  newLineBefore: opts.addNewLineBefore ?? false,
167
226
  newLineAfter: opts.addNewLineAfter ?? false
168
227
  }
169
228
  };
170
- const config = MSG_CONFIGS[opts.type];
229
+ const config = MESSAGE_CONFIG_MAP[opts.type];
171
230
  if (!config) {
172
231
  throw new Error(`Invalid message type: ${opts.type}`);
173
232
  }
174
- const {
175
- symbol = "",
176
- suffix = "",
177
- newLineBefore = false,
178
- newLineAfter = false
179
- } = config;
180
- function validateColorName(colorName) {
181
- if (!colorMap[colorName]) {
182
- throw new Error(`Invalid color name: ${colorName}`);
183
- }
184
- }
185
- let formattedTitle = "";
186
- if (opts.title) {
187
- const rawTitle = opts.title;
188
- if (opts.wrapTitle ?? true) {
189
- formattedTitle = wrapAndStyleText(
190
- rawTitle,
191
- opts.titleTypography ?? "bold",
192
- opts.titleColor ?? "cyan",
193
- opts.titleVariant,
194
- opts.borderColor
195
- );
196
- } else {
197
- formattedTitle = applyStyles(
198
- rawTitle,
199
- opts.titleColor ?? "cyan",
200
- opts.titleTypography ?? "bold",
201
- opts.titleVariant,
202
- opts.borderColor
203
- );
204
- }
205
- if (opts.hint) {
206
- const hintPlaceholderColor = opts.hintPlaceholderColor ?? "blue";
207
- if (opts.hintPlaceholderColor) {
208
- validateColorName(opts.hintPlaceholderColor);
209
- }
210
- const formattedHint = wrapAndStyleText(
211
- opts.hint,
212
- opts.hintTypography ?? "italic",
213
- hintPlaceholderColor,
214
- void 0,
215
- opts.borderColor
216
- );
217
- formattedTitle += `
218
- ${borderWithSpace}${formattedHint}`;
219
- }
220
- if (opts.placeholder && opts.type === "M_GENERAL") {
221
- formattedTitle += `
222
- ${borderWithSpace}${colorMap[opts.hintPlaceholderColor ?? "blue"](opts.placeholder)}`;
223
- }
224
- if (opts.errorMessage) {
225
- const formattedError = applyStyles(
226
- opts.errorMessage,
227
- "red",
228
- "bold",
229
- "",
230
- opts.borderColor
231
- );
232
- formattedTitle += `
233
- ${borderError} ${formattedError}`;
234
- }
235
- }
236
- let formattedContent = "";
237
- if (opts.content) {
238
- const rawContent = opts.content;
239
- if (opts.wrapContent ?? true) {
240
- formattedContent = wrapAndStyleText(
241
- rawContent,
242
- opts.contentTypography ?? "italic",
243
- opts.contentColor ?? "dim",
244
- opts.contentVariant,
245
- opts.borderColor
246
- );
247
- } else {
248
- formattedContent = applyStyles(
249
- rawContent,
250
- opts.contentColor ?? "dim",
251
- opts.contentTypography ?? "italic",
252
- opts.contentVariant,
253
- opts.borderColor
254
- );
255
- }
256
- }
233
+ const { symbol, suffix, newLineBefore, newLineAfter } = config;
234
+ const finalTitle = formatTitle(opts, borderTwoSpaces, borderError);
235
+ const finalContent = formatContent(opts);
257
236
  let text = "";
258
237
  if (opts.type === "M_BAR") {
259
238
  text = bar({ borderColor: opts.borderColor });
260
239
  } else {
261
- text = [formattedTitle, formattedContent].filter(Boolean).join(`
262
- `);
240
+ text = [finalTitle, finalContent].filter(Boolean).join("\n");
263
241
  }
264
242
  const fullText = [
265
243
  newLineBefore ? `
266
- ${borderWithSpace}` : "",
244
+ ${borderTwoSpaces}` : "",
267
245
  text,
268
246
  newLineAfter ? `
269
- ${borderWithSpace}` : "",
247
+ ${borderTwoSpaces}` : "",
270
248
  suffix
271
249
  ].filter(Boolean).join("");
272
250
  const lines = fullText.split("\n").map((line, index) => {
@@ -275,11 +253,12 @@ ${borderWithSpace}` : "",
275
253
  return `${prefixStartLine} ${line} ${suffixStartLine}`;
276
254
  }
277
255
  if (index === 1) {
278
- return borderWithSpace;
256
+ return borderTwoSpaces;
279
257
  }
280
258
  }
281
259
  if (opts.type === "M_END" && opts.border && index === 0) {
282
- return !opts.title ? "" : `${bar({ borderColor: opts.borderColor })} ${line}`;
260
+ if (!opts.title) return "";
261
+ return `${bar({ borderColor: opts.borderColor })} ${line}`;
283
262
  }
284
263
  if (!line.trim() || line.includes(symbols.middle)) {
285
264
  return line;
@@ -287,7 +266,7 @@ ${borderWithSpace}` : "",
287
266
  if (index === 0 && symbol) {
288
267
  return `${symbol} ${line}`;
289
268
  }
290
- return `${borderWithSpace}${line}`;
269
+ return `${config.prefix}${line}`;
291
270
  });
292
271
  if (opts.type === "M_END" && opts.border) {
293
272
  lines.push(`${prefixEndLine}${suffixEndLine}
@@ -300,8 +279,7 @@ ${borderWithSpace}` : "",
300
279
  const printedLineStack = [];
301
280
  export function msg(opts) {
302
281
  const { text, lineCount } = fmt(opts);
303
- process.stdout.write(text + `
304
- `);
282
+ process.stdout.write(text + "\n");
305
283
  printedLineStack.push(lineCount + 1);
306
284
  }
307
285
  export function msgUndo(count = 1) {
@@ -322,8 +300,8 @@ export function msgUndoAll() {
322
300
  }
323
301
  export function printLineBar(text, indent = 2) {
324
302
  if (text === "") {
325
- console.log(pc.dim("\u2502"));
326
- } else {
327
- console.log(`${pc.dim("\u2502")}${" ".repeat(indent)}${text}`);
303
+ console.log(re.dim("\u2502"));
304
+ return;
328
305
  }
306
+ console.log(`${re.dim("\u2502")}${" ".repeat(indent)}${text}`);
329
307
  }
@@ -0,0 +1,80 @@
1
+ import type { Static } from "@sinclair/typebox";
2
+ /** The entire relico config */
3
+ declare const RelicoConfigSchema: import("@sinclair/typebox").TObject<{
4
+ 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>]>>;
5
+ 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>]>>>;
6
+ }>;
7
+ export type RelicoConfig = Static<typeof RelicoConfigSchema>;
8
+ type BaseColorMap = {
9
+ reset: [string, string];
10
+ bold: [string, string, string];
11
+ dim: [string, string, string];
12
+ italic: [string, string];
13
+ underline: [string, string];
14
+ inverse: [string, string];
15
+ hidden: [string, string];
16
+ strikethrough: [string, string];
17
+ black: [string, string];
18
+ red: [string, string];
19
+ green: [string, string];
20
+ yellow: [string, string];
21
+ blue: [string, string];
22
+ magenta: [string, string];
23
+ cyan: [string, string];
24
+ white: [string, string];
25
+ gray: [string, string];
26
+ bgBlack: [string, string];
27
+ bgRed: [string, string];
28
+ bgGreen: [string, string];
29
+ bgYellow: [string, string];
30
+ bgBlue: [string, string];
31
+ bgMagenta: [string, string];
32
+ bgCyan: [string, string];
33
+ bgWhite: [string, string];
34
+ blackBright: [string, string];
35
+ redBright: [string, string];
36
+ greenBright: [string, string];
37
+ yellowBright: [string, string];
38
+ blueBright: [string, string];
39
+ magentaBright: [string, string];
40
+ cyanBright: [string, string];
41
+ whiteBright: [string, string];
42
+ bgBlackBright: [string, string];
43
+ bgRedBright: [string, string];
44
+ bgGreenBright: [string, string];
45
+ bgYellowBright: [string, string];
46
+ bgBlueBright: [string, string];
47
+ bgMagentaBright: [string, string];
48
+ bgCyanBright: [string, string];
49
+ bgWhiteBright: [string, string];
50
+ };
51
+ /**
52
+ * Allows user to update the relico config at runtime.
53
+ */
54
+ export declare function configure(userInput: unknown): void;
55
+ /** Return a read-only copy of current config */
56
+ export declare function getConfig(): RelicoConfig;
57
+ /** Retrieve a specific color function by name (or fallback to reset) */
58
+ export declare function getColor(name: string): (text: string | number) => string;
59
+ /** Colorize text with a named color function */
60
+ export declare function colorize(name: string, text: string | number): string;
61
+ /** Force-set the color level (0=none,1=basic,2=256,3=truecolor) */
62
+ export declare function setColorLevel(level: 0 | 1 | 2 | 3): void;
63
+ /**
64
+ * If truecolor is available (and level=3),
65
+ * return a custom rgb(...) color function. Otherwise identity.
66
+ */
67
+ export declare function rgb(r: number, g: number, b: number): (input: string | number) => string;
68
+ /** Type for the re object with explicit color properties */
69
+ type ReObject = {
70
+ [K in keyof BaseColorMap]: (text: string | number) => string;
71
+ };
72
+ /** Just a small proxy object returning the dynamic color functions */
73
+ export declare const re: ReObject;
74
+ export declare const colorSupport: {
75
+ isColorSupported: boolean;
76
+ isForced: boolean;
77
+ isDisabled: boolean;
78
+ terminalName: string;
79
+ };
80
+ export {};
@@ -0,0 +1,213 @@
1
+ import { Type } from "@sinclair/typebox";
2
+ import { Value } from "@sinclair/typebox/value";
3
+ import { env, isWindows } from "std-env";
4
+ import { getCurrentTerminalName } from "./platforms.js";
5
+ const ColorDefinitionSchema = Type.Tuple([
6
+ Type.String(),
7
+ Type.String(),
8
+ Type.Optional(Type.String())
9
+ ]);
10
+ const ColorMapSchema = Type.Record(Type.String(), ColorDefinitionSchema);
11
+ const RelicoConfigSchema = Type.Object(
12
+ {
13
+ // The level of color support (0=none, 1=basic, 2=256, 3=truecolor)
14
+ colorLevel: Type.Optional(
15
+ Type.Union([
16
+ Type.Literal(0),
17
+ Type.Literal(1),
18
+ Type.Literal(2),
19
+ Type.Literal(3)
20
+ ])
21
+ ),
22
+ // An optional set of overrides or new color definitions
23
+ customColors: Type.Optional(ColorMapSchema)
24
+ },
25
+ { additionalProperties: false }
26
+ );
27
+ const defaultConfig = {
28
+ colorLevel: void 0,
29
+ customColors: void 0
30
+ };
31
+ const { argv = [] } = typeof process === "undefined" ? {} : process;
32
+ const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
33
+ const isForced = "FORCE_COLOR" in env || argv.includes("--color");
34
+ const isCI = "CI" in env && ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
35
+ const isCompatibleTerminal = typeof process !== "undefined" && process.stdout && process.stdout.isTTY && env["TERM"] !== "dumb";
36
+ const colorterm = (env["COLORTERM"] || "").toLowerCase();
37
+ const supportsTrueColor = colorterm === "truecolor" || colorterm === "24bit";
38
+ function detectColorLevel() {
39
+ if (isDisabled) return 0;
40
+ if (isForced) return 3;
41
+ if (supportsTrueColor) return 3;
42
+ if (isWindows) return 2;
43
+ if (isCI) return 2;
44
+ if (isCompatibleTerminal) {
45
+ return 2;
46
+ }
47
+ return 0;
48
+ }
49
+ const baseColors = {
50
+ // Reset
51
+ reset: ["\x1B[0m", "\x1B[0m"],
52
+ // Styles
53
+ bold: ["\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"],
54
+ dim: ["\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"],
55
+ italic: ["\x1B[3m", "\x1B[23m"],
56
+ underline: ["\x1B[4m", "\x1B[24m"],
57
+ inverse: ["\x1B[7m", "\x1B[27m"],
58
+ hidden: ["\x1B[8m", "\x1B[28m"],
59
+ strikethrough: ["\x1B[9m", "\x1B[29m"],
60
+ // Basic
61
+ black: ["\x1B[30m", "\x1B[39m"],
62
+ red: ["\x1B[31m", "\x1B[39m"],
63
+ green: ["\x1B[32m", "\x1B[39m"],
64
+ yellow: ["\x1B[33m", "\x1B[39m"],
65
+ blue: ["\x1B[34m", "\x1B[39m"],
66
+ magenta: ["\x1B[35m", "\x1B[39m"],
67
+ cyan: ["\x1B[36m", "\x1B[39m"],
68
+ white: ["\x1B[37m", "\x1B[39m"],
69
+ gray: ["\x1B[90m", "\x1B[39m"],
70
+ // Background
71
+ bgBlack: ["\x1B[40m", "\x1B[49m"],
72
+ bgRed: ["\x1B[41m", "\x1B[49m"],
73
+ bgGreen: ["\x1B[42m", "\x1B[49m"],
74
+ bgYellow: ["\x1B[43m", "\x1B[49m"],
75
+ bgBlue: ["\x1B[44m", "\x1B[49m"],
76
+ bgMagenta: ["\x1B[45m", "\x1B[49m"],
77
+ bgCyan: ["\x1B[46m", "\x1B[49m"],
78
+ bgWhite: ["\x1B[47m", "\x1B[49m"],
79
+ // Bright
80
+ blackBright: ["\x1B[90m", "\x1B[39m"],
81
+ redBright: ["\x1B[91m", "\x1B[39m"],
82
+ greenBright: ["\x1B[92m", "\x1B[39m"],
83
+ yellowBright: ["\x1B[93m", "\x1B[39m"],
84
+ blueBright: ["\x1B[94m", "\x1B[39m"],
85
+ magentaBright: ["\x1B[95m", "\x1B[39m"],
86
+ cyanBright: ["\x1B[96m", "\x1B[39m"],
87
+ whiteBright: ["\x1B[97m", "\x1B[39m"],
88
+ // Bright background
89
+ bgBlackBright: ["\x1B[100m", "\x1B[49m"],
90
+ bgRedBright: ["\x1B[101m", "\x1B[49m"],
91
+ bgGreenBright: ["\x1B[102m", "\x1B[49m"],
92
+ bgYellowBright: ["\x1B[103m", "\x1B[49m"],
93
+ bgBlueBright: ["\x1B[104m", "\x1B[49m"],
94
+ bgMagentaBright: ["\x1B[105m", "\x1B[49m"],
95
+ bgCyanBright: ["\x1B[106m", "\x1B[49m"],
96
+ bgWhiteBright: ["\x1B[107m", "\x1B[49m"]
97
+ };
98
+ const windowsTerminalColors = {
99
+ ...baseColors,
100
+ red: ["\x1B[38;2;255;85;85m", "\x1B[39m"],
101
+ green: ["\x1B[38;2;80;250;123m", "\x1B[39m"],
102
+ yellow: ["\x1B[38;2;241;250;140m", "\x1B[39m"],
103
+ blue: ["\x1B[38;2;98;114;164m", "\x1B[39m"],
104
+ magenta: ["\x1B[38;2;255;121;198m", "\x1B[39m"],
105
+ cyan: ["\x1B[38;2;139;233;253m", "\x1B[39m"]
106
+ };
107
+ function replaceClose(str, close, replace, index) {
108
+ let result = "", cursor = 0;
109
+ do {
110
+ result += str.substring(cursor, index) + replace;
111
+ cursor = index + close.length;
112
+ index = str.indexOf(close, cursor);
113
+ } while (~index);
114
+ return result + str.substring(cursor);
115
+ }
116
+ function createFormatter(open, close, replace = open) {
117
+ return (input) => {
118
+ const string = String(input);
119
+ const idx = string.indexOf(close, open.length);
120
+ return ~idx ? open + replaceClose(string, close, replace, idx) + close : open + string + close;
121
+ };
122
+ }
123
+ let _config = {
124
+ ...defaultConfig,
125
+ colorLevel: detectColorLevel()
126
+ // initial detect
127
+ };
128
+ let _colorMap = {};
129
+ let _colorFunctions = {};
130
+ function buildColorMap(cfg) {
131
+ const terminalName = getCurrentTerminalName();
132
+ const isWinTerm = terminalName === "Windows Terminal";
133
+ if (cfg.colorLevel === 0) {
134
+ const map = {};
135
+ Object.keys(baseColors).forEach((k) => {
136
+ map[k] = ["", "", ""];
137
+ });
138
+ return map;
139
+ }
140
+ const builtIn = isWinTerm && cfg.colorLevel === 3 ? { ...windowsTerminalColors } : { ...baseColors };
141
+ if (cfg.customColors) {
142
+ for (const [k, v] of Object.entries(cfg.customColors)) {
143
+ builtIn[k] = v;
144
+ }
145
+ }
146
+ return builtIn;
147
+ }
148
+ function initColorFunctions() {
149
+ _colorFunctions = {};
150
+ if (_config.colorLevel === 0) {
151
+ for (const k of Object.keys(baseColors)) {
152
+ _colorFunctions[k] = (text) => String(text);
153
+ }
154
+ return;
155
+ }
156
+ for (const [key, [open, close, replace]] of Object.entries(_colorMap)) {
157
+ _colorFunctions[key] = createFormatter(open, close, replace);
158
+ }
159
+ }
160
+ function rebuild() {
161
+ _colorMap = buildColorMap(_config);
162
+ initColorFunctions();
163
+ }
164
+ rebuild();
165
+ export function configure(userInput) {
166
+ const newObj = typeof userInput === "object" && userInput !== null ? { ..._config, ...userInput } : { ..._config };
167
+ try {
168
+ const parsed = Value.Cast(RelicoConfigSchema, newObj);
169
+ _config = parsed;
170
+ } catch (err) {
171
+ console.warn("Invalid relico config:", err);
172
+ return;
173
+ }
174
+ rebuild();
175
+ }
176
+ export function getConfig() {
177
+ return { ..._config };
178
+ }
179
+ function identityColor(text) {
180
+ return String(text);
181
+ }
182
+ export function getColor(name) {
183
+ return _colorFunctions[name] || _colorFunctions["reset"] || identityColor;
184
+ }
185
+ export function colorize(name, text) {
186
+ const fn = getColor(name);
187
+ return fn(text);
188
+ }
189
+ export function setColorLevel(level) {
190
+ configure({ colorLevel: level });
191
+ }
192
+ export function rgb(r, g, b) {
193
+ if (_config.colorLevel === 3) {
194
+ const open = `\x1B[38;2;${r};${g};${b}m`;
195
+ const close = "\x1B[39m";
196
+ return createFormatter(open, close);
197
+ }
198
+ return identityColor;
199
+ }
200
+ export const re = new Proxy(
201
+ {},
202
+ {
203
+ get(_target, prop) {
204
+ return getColor(prop);
205
+ }
206
+ }
207
+ );
208
+ export const colorSupport = {
209
+ isColorSupported: getConfig().colorLevel !== 0,
210
+ isForced,
211
+ isDisabled,
212
+ terminalName: getCurrentTerminalName()
213
+ };
@@ -2,7 +2,7 @@ import isUnicodeSupported from "is-unicode-supported";
2
2
  import stringWidth from "string-width";
3
3
  import { BasicReporter } from "../../components/reporters/basic.js";
4
4
  import { box } from "../../utils/box.js";
5
- import { colors } from "../../utils/color.js";
5
+ import { colors } from "../../utils/deprecatedColors.js";
6
6
  import { parseStack } from "../../utils/error.js";
7
7
  import { stripAnsi } from "../../utils/string.js";
8
8
  export const TYPE_COLOR_MAP = {
@@ -1,4 +1,4 @@
1
- import { getColor } from "./color.js";
1
+ import { getColor } from "./deprecatedColors.js";
2
2
  import { stripAnsi } from "./string.js";
3
3
  const boxStylePresets = {
4
4
  solid: {
@@ -1,3 +1,3 @@
1
1
  export * from "../utils/box.js";
2
- export * from "../utils/color.js";
2
+ export * from "../utils/deprecatedColors.js";
3
3
  export { stripAnsi, centerAlign, rightAlign, leftAlign, align, } from "../utils/string.js";
@@ -1,5 +1,5 @@
1
1
  export * from "../utils/box.js";
2
- export * from "../utils/color.js";
2
+ export * from "../utils/deprecatedColors.js";
3
3
  export {
4
4
  stripAnsi,
5
5
  centerAlign,
@@ -1,4 +1,4 @@
1
- import { type ColorName } from "./color.js";
1
+ import { type ColorName } from "./deprecatedColors.js";
2
2
  export type TreeItemObject = {
3
3
  /**
4
4
  * Text of the item
@@ -1,4 +1,4 @@
1
- import { colorize } from "./color.js";
1
+ import { colorize } from "./deprecatedColors.js";
2
2
  export function formatTree(items, options) {
3
3
  options = {
4
4
  prefix: " ",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reliverse/relinka",
3
- "version": "1.2.7",
3
+ "version": "1.2.9",
4
4
  "author": "blefnk",
5
5
  "type": "module",
6
6
  "description": "@reliverse/relinka is a powerful logger for your terminal.",
@@ -56,31 +56,34 @@
56
56
  "license": "MIT",
57
57
  "dependencies": {
58
58
  "@figliolia/chalk-animation": "^1.0.4",
59
- "@sinclair/typebox": "^0.34.13",
59
+ "@reliverse/relico": "^1.0.0",
60
+ "@sinclair/typebox": "^0.34.14",
60
61
  "ansi-diff-stream": "^1.2.1",
61
62
  "ansi-escapes": "^7.0.0",
62
63
  "chalk": "^5.4.1",
63
64
  "cli-spinners": "^3.2.0",
64
65
  "cli-styles": "^1.0.0",
65
66
  "cli-width": "^4.1.0",
67
+ "confbox": "^0.1.8",
66
68
  "defu": "^6.1.4",
69
+ "destr": "^2.0.3",
67
70
  "detect-package-manager": "^3.0.2",
68
71
  "external-editor": "^3.1.0",
69
72
  "fast-glob": "^3.3.3",
70
73
  "figlet": "^1.8.0",
71
- "fs-extra": "^11.2.0",
74
+ "fs-extra": "^11.3.0",
72
75
  "get-pixels": "^3.3.3",
73
76
  "globby": "^14.0.2",
74
77
  "gradient-string": "^3.0.0",
75
78
  "is-unicode-supported": "^2.1.0",
76
79
  "kleur": "^4.1.5",
77
80
  "log-update": "^6.1.0",
81
+ "mri": "^1.2.0",
78
82
  "mute-stream": "^2.0.0",
79
83
  "node-emoji": "^2.2.0",
80
- "nypm": "^0.4.1",
84
+ "nypm": "^0.5.0",
81
85
  "ora": "^8.1.1",
82
- "pathe": "^2.0.1",
83
- "picocolors": "^1.1.1",
86
+ "pathe": "^2.0.2",
84
87
  "precision": "^1.0.1",
85
88
  "seventh": "^0.9.2",
86
89
  "signal-exit": "^4.1.0",
@@ -96,19 +99,19 @@
96
99
  "devDependencies": {
97
100
  "@arethetypeswrong/cli": "^0.17.3",
98
101
  "@biomejs/biome": "1.9.4",
99
- "@cspell/dict-npm": "^5.1.22",
102
+ "@cspell/dict-npm": "^5.1.23",
100
103
  "@eslint/js": "^9.18.0",
101
- "@eslint/json": "^0.9.0",
104
+ "@eslint/json": "^0.9.1",
102
105
  "@eslint/markdown": "^6.2.1",
103
106
  "@stylistic/eslint-plugin": "^2.13.0",
104
107
  "@types/ansi-diff-stream": "^1.2.3",
105
- "@types/bun": "^1.1.16",
108
+ "@types/bun": "^1.1.18",
106
109
  "@types/chalk-animation": "^1.6.3",
107
110
  "@types/eslint__js": "^8.42.3",
108
111
  "@types/figlet": "^1.7.0",
109
112
  "@types/fs-extra": "^11.0.4",
110
113
  "@types/mute-stream": "^0.0.4",
111
- "@types/node": "^22.10.6",
114
+ "@types/node": "^22.10.7",
112
115
  "@types/sentencer": "^0.2.3",
113
116
  "@types/signal-exit": "^3.0.4",
114
117
  "@types/strip-comments": "^2.0.4",
@@ -116,18 +119,18 @@
116
119
  "c12": "^2.0.1",
117
120
  "citty": "^0.1.6",
118
121
  "eslint": "^9.18.0",
119
- "eslint-plugin-perfectionist": "^4.6.0",
122
+ "eslint-plugin-perfectionist": "^4.7.0",
120
123
  "execa": "^9.5.2",
121
124
  "jiti": "^2.4.2",
122
- "knip": "^5.42.0",
125
+ "knip": "^5.42.3",
123
126
  "mock-stdin": "^1.0.0",
124
127
  "printj": "^1.3.1",
125
128
  "sentencer": "^0.2.1",
126
129
  "strip-comments": "^2.0.1",
127
130
  "tsx": "^4.19.2",
128
131
  "typescript": "^5.7.3",
129
- "typescript-eslint": "^8.20.0",
132
+ "typescript-eslint": "^8.21.0",
130
133
  "unbuild": "^3.3.1",
131
- "vitest": "^2.1.8"
134
+ "vitest": "^3.0.3"
132
135
  }
133
- }
136
+ }