@reliverse/relico 1.4.0 → 1.4.1

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,13 +1,110 @@
1
+ /* @reliverse/relico - Tiny, type-safe terminal color library with chainable API
2
+ - Levels: 0 (off), 1 (ANSI 8/bright), 2 (ANSI 256), 3 (Truecolor)
3
+ - Named palettes (std, web, grayscale), Bright & Pastel variants, bg-variants
4
+ - Chainable: re.bold.red.underline("text"), chain(re.bold, re.red)("text")
5
+ - Multiline-safe: styles applied per line with reset to prevent bleed
6
+ */
7
+
8
+ type ColorLevel = 0 | 1 | 2 | 3;
9
+
10
+ interface Rgb {
11
+ r: number;
12
+ g: number;
13
+ b: number;
14
+ }
15
+
16
+ type SgrOp =
17
+ | { kind: "style"; open: number[] } // closed by global reset at line end
18
+ | { kind: "fg-basic"; idx: number; bright: boolean }
19
+ | { kind: "bg-basic"; idx: number; bright: boolean }
20
+ | { kind: "fg-256"; code: number }
21
+ | { kind: "bg-256"; code: number }
22
+ | { kind: "fg-true"; rgb: Rgb }
23
+ | { kind: "bg-true"; rgb: Rgb };
24
+
25
+ type ApplyInput = string | number;
26
+
27
+ type FormatCallable = ((input: ApplyInput) => string) & { readonly [OP_SYMBOL]: SgrOp[] };
28
+
29
+ export type BaseColorName =
30
+ | "black"
31
+ | "red"
32
+ | "green"
33
+ | "yellow"
34
+ | "blue"
35
+ | "magenta"
36
+ | "cyan"
37
+ | "white"
38
+ | "gray"
39
+ | "orange"
40
+ | "pink"
41
+ | "purple"
42
+ | "teal"
43
+ | "lime"
44
+ | "brown"
45
+ | "navy"
46
+ | "maroon"
47
+ | "olive"
48
+ | "silver";
49
+
50
+ export type ColorName = BaseColorName | BrightColorName | BgColorName;
51
+
52
+ export type BrightColorName =
53
+ | "blackBright"
54
+ | "redBright"
55
+ | "greenBright"
56
+ | "yellowBright"
57
+ | "blueBright"
58
+ | "magentaBright"
59
+ | "cyanBright"
60
+ | "whiteBright"
61
+ | "orangeBright"
62
+ | "pinkBright"
63
+ | "purpleBright"
64
+ | "tealBright"
65
+ | "limeBright"
66
+ | "brownBright"
67
+ | "navyBright"
68
+ | "maroonBright"
69
+ | "oliveBright"
70
+ | "silverBright";
71
+
72
+ export type BgColorName = `bg${Capitalize<BaseColorName>}` | `bg${Capitalize<BrightColorName>}`;
73
+
74
+ export type ReStyleKey =
75
+ | "reset"
76
+ | "bold"
77
+ | "dim"
78
+ | "italic"
79
+ | "underline"
80
+ | "inverse"
81
+ | "hidden"
82
+ | "strikethrough";
83
+
84
+ export type Re = FormatCallable & {
85
+ readonly [K in ReStyleKey]: Re;
86
+ } & {
87
+ readonly [K in ColorName]: Re;
88
+ } & {
89
+ readonly [K in BgColorName]: Re;
90
+ };
91
+
1
92
  const ESC = "\x1B[";
2
93
  const RESET = `${ESC}0m`;
3
- const OP_SYMBOL = Symbol("re.ops");
94
+ const OP_SYMBOL: unique symbol = Symbol("re.ops");
95
+
96
+ // Color level constants
4
97
  const COLOR_LEVEL_OFF = 0;
5
98
  const COLOR_LEVEL_BASIC = 1;
6
99
  const COLOR_LEVEL_256 = 2;
7
100
  const COLOR_LEVEL_TRUECOLOR = 3;
101
+
102
+ // RGB and byte constants
8
103
  const MIN_BYTE = 0;
9
104
  const MAX_BYTE = 255;
10
105
  const WHITE_RGB = 255;
106
+
107
+ // ANSI 256 color constants
11
108
  const ANSI_256_GRAYSCALE_MIN = 8;
12
109
  const ANSI_256_GRAYSCALE_MAX = 248;
13
110
  const ANSI_256_BASE_OFFSET = 16;
@@ -18,10 +115,14 @@ const ANSI_256_BRIGHT_THRESHOLD = 231;
18
115
  const ANSI_256_RGB_LEVELS = 5;
19
116
  const ANSI_256_RGB_RED_MULTIPLIER = 36;
20
117
  const ANSI_256_RGB_GREEN_MULTIPLIER = 6;
118
+
119
+ // SGR code constants
21
120
  const SGR_FG_BASE = 30;
22
121
  const SGR_BG_BASE = 40;
23
122
  const SGR_FG_BRIGHT_BASE = 90;
24
123
  const SGR_BG_BRIGHT_BASE = 100;
124
+
125
+ // Style SGR codes
25
126
  const SGR_RESET = 0;
26
127
  const SGR_BOLD = 1;
27
128
  const SGR_DIM = 2;
@@ -30,25 +131,41 @@ const SGR_UNDERLINE = 4;
30
131
  const SGR_INVERSE = 7;
31
132
  const SGR_HIDDEN = 8;
32
133
  const SGR_STRIKETHROUGH = 9;
134
+
135
+ // Hex parsing constants
33
136
  const HEX_BYTE_LENGTH = 2;
34
137
  const HEX_RED_START = 0;
35
138
  const HEX_GREEN_START = 2;
36
139
  const HEX_BLUE_START = 4;
37
140
  const HEX_BLUE_END = 6;
38
141
  const HEX_RADIX = 16;
142
+
143
+ // String processing constants
39
144
  const BRIGHT_SUFFIX_LENGTH = 6;
40
145
  const BG_PREFIX_LENGTH = 2;
41
146
  const BG_COLOR_START = 3;
147
+
148
+ // Color mixing constants
42
149
  const BRIGHT_MIX_FACTOR = 0.25;
150
+
151
+ // Regex constants
43
152
  const BRIGHT_SUFFIX_REGEX = /Bright$/u;
44
- let CURRENT_LEVEL = COLOR_LEVEL_TRUECOLOR;
45
- export const setColorLevel = (level) => {
46
- if (level !== COLOR_LEVEL_OFF && level !== COLOR_LEVEL_BASIC && level !== COLOR_LEVEL_256 && level !== COLOR_LEVEL_TRUECOLOR) {
153
+
154
+ let CURRENT_LEVEL: ColorLevel = COLOR_LEVEL_TRUECOLOR;
155
+
156
+ export const setColorLevel = (level: ColorLevel): void => {
157
+ if (
158
+ level !== COLOR_LEVEL_OFF &&
159
+ level !== COLOR_LEVEL_BASIC &&
160
+ level !== COLOR_LEVEL_256 &&
161
+ level !== COLOR_LEVEL_TRUECOLOR
162
+ ) {
47
163
  throw new Error("Invalid color level");
48
164
  }
49
165
  CURRENT_LEVEL = level;
50
166
  };
51
- const clampByte = (n) => {
167
+
168
+ const clampByte = (n: number): number => {
52
169
  if (!Number.isFinite(n)) {
53
170
  return MIN_BYTE;
54
171
  }
@@ -60,26 +177,24 @@ const clampByte = (n) => {
60
177
  }
61
178
  return Math.round(n);
62
179
  };
63
- const BASIC8 = [
64
- { r: 0, g: 0, b: 0 },
65
- // black
66
- { r: 205, g: 0, b: 0 },
67
- // red
68
- { r: 0, g: 205, b: 0 },
69
- // green
70
- { r: 205, g: 205, b: 0 },
71
- // yellow
72
- { r: 0, g: 0, b: 238 },
73
- // blue
74
- { r: 205, g: 0, b: 205 },
75
- // magenta
76
- { r: 0, g: 205, b: 205 },
77
- // cyan
78
- { r: 229, g: 229, b: 229 }
79
- // white (light gray)
180
+
181
+ // Base 8-color RGB anchors (non-bright)
182
+ const BASIC8: Rgb[] = [
183
+ { r: 0, g: 0, b: 0 }, // black
184
+ { r: 205, g: 0, b: 0 }, // red
185
+ { r: 0, g: 205, b: 0 }, // green
186
+ { r: 205, g: 205, b: 0 }, // yellow
187
+ { r: 0, g: 0, b: 238 }, // blue
188
+ { r: 205, g: 0, b: 205 }, // magenta
189
+ { r: 0, g: 205, b: 205 }, // cyan
190
+ { r: 229, g: 229, b: 229 }, // white (light gray)
80
191
  ];
81
- const sgr = (codes) => `${ESC}${codes.join(";")}m`;
82
- const nearestBasicIndex = (rgb) => {
192
+
193
+ // SGR code builders
194
+ const sgr = (codes: number[]): string => `${ESC}${codes.join(";")}m`;
195
+
196
+ // RGB → closest of BASIC8 index (0..7)
197
+ const nearestBasicIndex = (rgb: Rgb): number => {
83
198
  let best = 0;
84
199
  let bestDist = Number.POSITIVE_INFINITY;
85
200
  for (let i = 0; i < BASIC8.length; i++) {
@@ -95,7 +210,10 @@ const nearestBasicIndex = (rgb) => {
95
210
  }
96
211
  return best;
97
212
  };
98
- const rgbToAnsi256 = (rgb) => {
213
+
214
+ // RGB → ANSI 256 index
215
+ const rgbToAnsi256 = (rgb: Rgb): number => {
216
+ // Try grayscale if r≈g≈b
99
217
  if (rgb.r === rgb.g && rgb.g === rgb.b) {
100
218
  if (rgb.r < ANSI_256_GRAYSCALE_MIN) {
101
219
  return ANSI_256_BASE_OFFSET;
@@ -104,16 +222,20 @@ const rgbToAnsi256 = (rgb) => {
104
222
  return ANSI_256_BRIGHT_THRESHOLD;
105
223
  }
106
224
  const step = Math.round(
107
- (rgb.r - ANSI_256_GRAYSCALE_MIN) / ANSI_256_GRAYSCALE_RANGE * ANSI_256_GRAYSCALE_STEPS
225
+ ((rgb.r - ANSI_256_GRAYSCALE_MIN) / ANSI_256_GRAYSCALE_RANGE) * ANSI_256_GRAYSCALE_STEPS,
108
226
  );
109
227
  return ANSI_256_GRAYSCALE_BASE + step;
110
228
  }
111
- const r = Math.round(rgb.r / MAX_BYTE * ANSI_256_RGB_LEVELS);
112
- const g = Math.round(rgb.g / MAX_BYTE * ANSI_256_RGB_LEVELS);
113
- const b = Math.round(rgb.b / MAX_BYTE * ANSI_256_RGB_LEVELS);
114
- return ANSI_256_BASE_OFFSET + ANSI_256_RGB_RED_MULTIPLIER * r + ANSI_256_RGB_GREEN_MULTIPLIER * g + b;
229
+ const r = Math.round((rgb.r / MAX_BYTE) * ANSI_256_RGB_LEVELS);
230
+ const g = Math.round((rgb.g / MAX_BYTE) * ANSI_256_RGB_LEVELS);
231
+ const b = Math.round((rgb.b / MAX_BYTE) * ANSI_256_RGB_LEVELS);
232
+ return (
233
+ ANSI_256_BASE_OFFSET + ANSI_256_RGB_RED_MULTIPLIER * r + ANSI_256_RGB_GREEN_MULTIPLIER * g + b
234
+ );
115
235
  };
116
- const NAMED_COLORS = {
236
+
237
+ // Color data
238
+ const NAMED_COLORS: Record<BaseColorName, string> = {
117
239
  black: "#000000",
118
240
  red: "#ff0000",
119
241
  green: "#00ff00",
@@ -132,27 +254,34 @@ const NAMED_COLORS = {
132
254
  navy: "#000080",
133
255
  maroon: "#800000",
134
256
  olive: "#808000",
135
- silver: "#c0c0c0"
257
+ silver: "#c0c0c0",
136
258
  };
137
- const mixWithWhite = (rgb, factor) => {
259
+
260
+ const mixWithWhite = (rgb: Rgb, factor: number): Rgb => {
138
261
  const t = factor;
139
262
  return {
140
263
  r: clampByte(rgb.r * (1 - t) + WHITE_RGB * t),
141
264
  g: clampByte(rgb.g * (1 - t) + WHITE_RGB * t),
142
- b: clampByte(rgb.b * (1 - t) + WHITE_RGB * t)
265
+ b: clampByte(rgb.b * (1 - t) + WHITE_RGB * t),
143
266
  };
144
267
  };
145
- const fromNamed = (name) => {
268
+
269
+ const fromNamed = (name: BaseColorName): Rgb => {
146
270
  const hex = NAMED_COLORS[name];
147
271
  if (!hex || typeof hex !== "string") {
272
+ // Return black as fallback for invalid color names
148
273
  return { r: 0, g: 0, b: 0 };
149
274
  }
275
+ // Simple hex to RGB conversion for named colors only
150
276
  const clean = hex.startsWith("#") ? hex.slice(1) : hex;
151
277
  if (clean.length !== HEX_BLUE_END && clean.length !== 3) {
278
+ // Return black as fallback for invalid hex format
152
279
  return { r: 0, g: 0, b: 0 };
153
280
  }
154
- let rHex, gHex, bHex;
281
+
282
+ let rHex: string, gHex: string, bHex: string;
155
283
  if (clean.length === 3) {
284
+ // Expand short hex format (e.g., "abc" -> "aabbcc")
156
285
  rHex = clean[0].repeat(2);
157
286
  gHex = clean[1].repeat(2);
158
287
  bHex = clean[2].repeat(2);
@@ -161,38 +290,48 @@ const fromNamed = (name) => {
161
290
  gHex = clean.slice(HEX_GREEN_START, HEX_BLUE_START);
162
291
  bHex = clean.slice(HEX_BLUE_START, HEX_BLUE_END);
163
292
  }
293
+
164
294
  const r = Number.parseInt(rHex, HEX_RADIX);
165
295
  const g = Number.parseInt(gHex, HEX_RADIX);
166
296
  const b = Number.parseInt(bHex, HEX_RADIX);
297
+
298
+ // Validate parsed RGB values
167
299
  if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
168
300
  return { r: 0, g: 0, b: 0 };
169
301
  }
302
+
170
303
  return { r, g, b };
171
304
  };
172
- const toBaseName = (compound) => {
305
+
306
+ const toBaseName = (compound: BrightColorName): BaseColorName => {
173
307
  if (!compound || typeof compound !== "string") {
174
- return "black";
308
+ return "black"; // fallback for invalid input
175
309
  }
176
310
  const base = compound.replace(BRIGHT_SUFFIX_REGEX, "");
177
311
  if (!base) {
178
- return "black";
312
+ return "black"; // fallback for empty result
179
313
  }
180
314
  const key = base.charAt(0).toLowerCase() + base.slice(1);
181
- return key;
315
+ return key as BaseColorName;
182
316
  };
183
- const parseColorName = (name) => {
317
+
318
+ const parseColorName = (name: ColorName): { rgb: Rgb; wantBright: boolean } => {
184
319
  if (!name || typeof name !== "string") {
320
+ // Return black as fallback for invalid input
185
321
  return { rgb: { r: 0, g: 0, b: 0 }, wantBright: false };
186
322
  }
323
+
187
324
  if (name.endsWith("Bright")) {
188
- const base = toBaseName(name);
325
+ const base = toBaseName(name as BrightColorName);
189
326
  const rgb = fromNamed(base);
327
+ // Lighten a bit in high levels; level 1 will use bright SGR
190
328
  const rgbAdj = mixWithWhite(rgb, BRIGHT_MIX_FACTOR);
191
329
  return { rgb: rgbAdj, wantBright: true };
192
330
  }
193
- return { rgb: fromNamed(name), wantBright: false };
331
+ return { rgb: fromNamed(name as BaseColorName), wantBright: false };
194
332
  };
195
- const openForOp = (op) => {
333
+
334
+ const openForOp = (op: SgrOp): string => {
196
335
  if (CURRENT_LEVEL === COLOR_LEVEL_OFF) {
197
336
  return "";
198
337
  }
@@ -215,7 +354,8 @@ const openForOp = (op) => {
215
354
  return "";
216
355
  }
217
356
  };
218
- const opsToOpen = (ops) => {
357
+
358
+ const opsToOpen = (ops: SgrOp[]): string => {
219
359
  if (CURRENT_LEVEL === COLOR_LEVEL_OFF) {
220
360
  return "";
221
361
  }
@@ -225,17 +365,25 @@ const opsToOpen = (ops) => {
225
365
  }
226
366
  return out;
227
367
  };
228
- const applyOpsToText = (ops, input) => {
368
+
369
+ // Optimized multiline processing with fewer allocations and branches
370
+ const applyOpsToText = (ops: SgrOp[], input: ApplyInput): string => {
229
371
  const text = String(input);
230
372
  if (CURRENT_LEVEL === COLOR_LEVEL_OFF || ops.length === 0 || text.length === 0) {
231
373
  return text;
232
374
  }
375
+
233
376
  const open = opsToOpen(ops);
377
+
378
+ // Fast path for single-line text (most common case)
234
379
  if (!text.includes("\n")) {
235
380
  return `${open}${text}${RESET}`;
236
381
  }
382
+
383
+ // Optimized multiline handling with pre-calculated string lengths
237
384
  const lines = text.split("\n");
238
385
  const result = new Array(lines.length);
386
+
239
387
  for (let i = 0; i < lines.length; i++) {
240
388
  const line = lines[i];
241
389
  if (line.endsWith("\r")) {
@@ -244,9 +392,12 @@ const applyOpsToText = (ops, input) => {
244
392
  result[i] = `${open}${line}${RESET}`;
245
393
  }
246
394
  }
395
+
247
396
  return result.join("\n");
248
397
  };
249
- const mkFgOpsFromRgb = (rgb, wantBright = false) => {
398
+
399
+ // Build operations for a color request according to CURRENT_LEVEL
400
+ const mkFgOpsFromRgb = (rgb: Rgb, wantBright = false): SgrOp[] => {
250
401
  if (CURRENT_LEVEL === COLOR_LEVEL_BASIC) {
251
402
  const idx = nearestBasicIndex(rgb);
252
403
  return [{ kind: "fg-basic", idx, bright: wantBright }];
@@ -256,7 +407,8 @@ const mkFgOpsFromRgb = (rgb, wantBright = false) => {
256
407
  }
257
408
  return [{ kind: "fg-true", rgb }];
258
409
  };
259
- const mkBgOpsFromRgb = (rgb, wantBright = false) => {
410
+
411
+ const mkBgOpsFromRgb = (rgb: Rgb, wantBright = false): SgrOp[] => {
260
412
  if (CURRENT_LEVEL === COLOR_LEVEL_BASIC) {
261
413
  const idx = nearestBasicIndex(rgb);
262
414
  return [{ kind: "bg-basic", idx, bright: wantBright }];
@@ -266,7 +418,9 @@ const mkBgOpsFromRgb = (rgb, wantBright = false) => {
266
418
  }
267
419
  return [{ kind: "bg-true", rgb }];
268
420
  };
269
- const STYLE_TABLE = {
421
+
422
+ // Style ops
423
+ const STYLE_TABLE: Record<ReStyleKey, SgrOp> = {
270
424
  reset: { kind: "style", open: [SGR_RESET] },
271
425
  bold: { kind: "style", open: [SGR_BOLD] },
272
426
  dim: { kind: "style", open: [SGR_DIM] },
@@ -274,9 +428,11 @@ const STYLE_TABLE = {
274
428
  underline: { kind: "style", open: [SGR_UNDERLINE] },
275
429
  inverse: { kind: "style", open: [SGR_INVERSE] },
276
430
  hidden: { kind: "style", open: [SGR_HIDDEN] },
277
- strikethrough: { kind: "style", open: [SGR_STRIKETHROUGH] }
431
+ strikethrough: { kind: "style", open: [SGR_STRIKETHROUGH] },
278
432
  };
279
- const STYLE_KEYS = /* @__PURE__ */ new Set([
433
+
434
+ // Lookup maps
435
+ const STYLE_KEYS = new Set([
280
436
  "reset",
281
437
  "bold",
282
438
  "dim",
@@ -284,72 +440,93 @@ const STYLE_KEYS = /* @__PURE__ */ new Set([
284
440
  "underline",
285
441
  "inverse",
286
442
  "hidden",
287
- "strikethrough"
443
+ "strikethrough",
288
444
  ]);
289
- const isColorKey = (key) => {
445
+
446
+ // Direct color/bg key checks
447
+ const isColorKey = (key: string): boolean => {
290
448
  if (!key || typeof key !== "string") {
291
449
  return false;
292
450
  }
451
+ // Base colors and extended colors
293
452
  if (key in NAMED_COLORS) {
294
453
  return true;
295
454
  }
455
+ // Bright variants
296
456
  if (key.endsWith("Bright") && key.length > BRIGHT_SUFFIX_LENGTH) {
297
457
  const baseName = key.slice(0, -BRIGHT_SUFFIX_LENGTH);
298
458
  return baseName in NAMED_COLORS;
299
459
  }
300
460
  return false;
301
461
  };
302
- const isBgKey = (key) => {
462
+
463
+ const isBgKey = (key: string): boolean => {
303
464
  if (!key || typeof key !== "string" || !key.startsWith("bg") || key.length <= BG_PREFIX_LENGTH) {
304
465
  return false;
305
466
  }
306
467
  const colorPart = key.charAt(BG_PREFIX_LENGTH).toLowerCase() + key.slice(BG_COLOR_START);
307
468
  return isColorKey(colorPart);
308
469
  };
309
- const callableProxy = (ops) => {
310
- const base = ((input) => applyOpsToText(ops, input));
470
+
471
+ // Proxy with performance through pre-computed lookups
472
+ const callableProxy = (ops: SgrOp[]): Re => {
473
+ const base = ((input: ApplyInput) => applyOpsToText(ops, input)) as FormatCallable;
311
474
  Object.defineProperty(base, OP_SYMBOL, {
312
475
  value: ops,
313
476
  enumerable: false,
314
477
  configurable: false,
315
- writable: false
478
+ writable: false,
316
479
  });
317
- return new Proxy(base, {
480
+
481
+ return new Proxy(base as unknown as Re, {
318
482
  apply(_target, _thisArg, argArray) {
319
- const [input] = argArray;
483
+ const [input] = argArray as [ApplyInput];
320
484
  return applyOpsToText(ops, input);
321
485
  },
322
486
  get(_target, prop) {
323
487
  const key = String(prop);
488
+
489
+ // Ops extractor for chain()
324
490
  if (prop === OP_SYMBOL) {
325
491
  return ops;
326
492
  }
493
+
494
+ // Fast path for styles using Set lookup
327
495
  if (STYLE_KEYS.has(key)) {
328
- const op = STYLE_TABLE[key];
496
+ const op = STYLE_TABLE[key as ReStyleKey];
329
497
  return callableProxy([...ops, op]);
330
498
  }
499
+
500
+ // Fast path for colors
331
501
  if (isBgKey(key)) {
332
- const raw = key.slice(BG_PREFIX_LENGTH);
502
+ const raw = key.slice(BG_PREFIX_LENGTH); // remove 'bg'
333
503
  if (!raw) {
334
- return callableProxy(ops);
504
+ return callableProxy(ops); // no-op for empty color name
335
505
  }
336
506
  const colorName = raw.charAt(0).toLowerCase() + raw.slice(1);
337
- const { rgb, wantBright } = parseColorName(colorName);
507
+ const { rgb, wantBright } = parseColorName(colorName as ColorName);
338
508
  return callableProxy([...ops, ...mkBgOpsFromRgb(rgb, wantBright)]);
339
509
  }
510
+
340
511
  if (isColorKey(key)) {
341
- const { rgb, wantBright } = parseColorName(key);
512
+ const { rgb, wantBright } = parseColorName(key as ColorName);
342
513
  return callableProxy([...ops, ...mkFgOpsFromRgb(rgb, wantBright)]);
343
514
  }
515
+
516
+ // Unknown key → return self (no-op), keeps chain resilient
344
517
  return callableProxy(ops);
345
- }
518
+ },
346
519
  });
347
520
  };
348
- export const re = callableProxy([]);
349
- export const chain = (...parts) => {
350
- const collected = [];
521
+
522
+ // Public root
523
+ export const re: Re = callableProxy([]);
524
+
525
+ // chain(re.bold, re.red, re.underline)("text")
526
+ export const chain = (...parts: FormatCallable[]): Re => {
527
+ const collected: SgrOp[] = [];
351
528
  for (const p of parts) {
352
- const ops = p[OP_SYMBOL];
529
+ const ops = (p as FormatCallable)[OP_SYMBOL] as SgrOp[] | undefined;
353
530
  if (ops && ops.length > 0) {
354
531
  for (const op of ops) {
355
532
  collected.push(op);
package/tsconfig.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "compilerOptions": {
3
+ "paths": {
4
+ "~/*": ["./src/*"],
5
+ "@/*": ["example/*"]
6
+ },
7
+ "baseUrl": ".",
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "target": "ESNext",
11
+ "lib": ["ESNext"],
12
+ "allowJs": true,
13
+ "resolveJsonModule": true,
14
+ "moduleDetection": "force",
15
+ "isolatedModules": true,
16
+ "verbatimModuleSyntax": true,
17
+ "strict": true,
18
+ "noUncheckedIndexedAccess": true,
19
+ "noImplicitOverride": true,
20
+ "module": "preserve",
21
+ "moduleResolution": "bundler",
22
+ "noEmit": true,
23
+ "exactOptionalPropertyTypes": false,
24
+ "noFallthroughCasesInSwitch": false,
25
+ "noImplicitAny": false,
26
+ "noImplicitReturns": false,
27
+ "noUnusedLocals": false,
28
+ "noUnusedParameters": false,
29
+ "strictNullChecks": false
30
+ },
31
+ "include": ["src/**/*.ts", "reliverse.ts", "reltypes.ts"],
32
+ "exclude": ["node_modules", "dist*"]
33
+ }
package/bin/mod.d.ts DELETED
@@ -1,51 +0,0 @@
1
- type ColorLevel = 0 | 1 | 2 | 3;
2
- interface Rgb {
3
- r: number;
4
- g: number;
5
- b: number;
6
- }
7
- type SgrOp = {
8
- kind: "style";
9
- open: number[];
10
- } | {
11
- kind: "fg-basic";
12
- idx: number;
13
- bright: boolean;
14
- } | {
15
- kind: "bg-basic";
16
- idx: number;
17
- bright: boolean;
18
- } | {
19
- kind: "fg-256";
20
- code: number;
21
- } | {
22
- kind: "bg-256";
23
- code: number;
24
- } | {
25
- kind: "fg-true";
26
- rgb: Rgb;
27
- } | {
28
- kind: "bg-true";
29
- rgb: Rgb;
30
- };
31
- type ApplyInput = string | number;
32
- type FormatCallable = ((input: ApplyInput) => string) & {
33
- readonly [OP_SYMBOL]: SgrOp[];
34
- };
35
- export type BaseColorName = "black" | "red" | "green" | "yellow" | "blue" | "magenta" | "cyan" | "white" | "gray" | "orange" | "pink" | "purple" | "teal" | "lime" | "brown" | "navy" | "maroon" | "olive" | "silver";
36
- export type ColorName = BaseColorName | BrightColorName | BgColorName;
37
- export type BrightColorName = "blackBright" | "redBright" | "greenBright" | "yellowBright" | "blueBright" | "magentaBright" | "cyanBright" | "whiteBright" | "orangeBright" | "pinkBright" | "purpleBright" | "tealBright" | "limeBright" | "brownBright" | "navyBright" | "maroonBright" | "oliveBright" | "silverBright";
38
- export type BgColorName = `bg${Capitalize<BaseColorName>}` | `bg${Capitalize<BrightColorName>}`;
39
- export type ReStyleKey = "reset" | "bold" | "dim" | "italic" | "underline" | "inverse" | "hidden" | "strikethrough";
40
- export type Re = FormatCallable & {
41
- readonly [K in ReStyleKey]: Re;
42
- } & {
43
- readonly [K in ColorName]: Re;
44
- } & {
45
- readonly [K in BgColorName]: Re;
46
- };
47
- declare const OP_SYMBOL: unique symbol;
48
- export declare const setColorLevel: (level: ColorLevel) => void;
49
- export declare const re: Re;
50
- export declare const chain: (...parts: FormatCallable[]) => Re;
51
- export {};