colorino 0.13.0 → 0.13.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 CHANGED
@@ -41,7 +41,7 @@ Colorino is different: it’s a "batteries-included" logging facade with beautif
41
41
 
42
42
  ## <a id="2"></a>Features
43
43
 
44
- - 🎨 **Smart Theming:** Automatically detects *dark/light* mode and applies a high‑contrast base palette by default (Dracula for dark, GitHub Light for light); opt into a coordinated theme preset when you want richer colors.
44
+ - 🎨 **Smart Theming:** Automatically detects _dark/light_ mode and applies a high‑contrast base palette by default (Dracula for dark, GitHub Light for light); opt into a coordinated theme preset when you want richer colors.
45
45
  - 🤘 **Graceful Color Degradation**: Accepts rich colors (hex/RGB) and automatically down‑samples to the best ANSI‑16/ANSI‑256/Truecolor match for the current environment.​
46
46
  - 🤝 **Familiar API:** If you know `console.log`, you already know Colorino: all standard log levels are supported.
47
47
  - 🔀 **Environment-Aware:** Works in **Node.js** (ANSI color and truecolor) and all major **Browsers** (CSS styles).
@@ -66,10 +66,10 @@ You can use Colorino directly in the browser without any build step.
66
66
  <html>
67
67
  <head>
68
68
  <script type="module">
69
- import { colorino } from 'https://unpkg.com/colorino/dist/browser.bundle.mjs';
69
+ import { colorino } from 'https://unpkg.com/colorino/dist/browser.bundle.mjs'
70
70
 
71
- colorino.info('Hello from the browser!');
72
- colorino.error('Something went wrong');
71
+ colorino.info('Hello from the browser!')
72
+ colorino.error('Something went wrong')
73
73
  </script>
74
74
  </head>
75
75
  <body></body>
@@ -119,9 +119,10 @@ Use the factory to create as many loggers as you want (each with its own palette
119
119
  import { createColorino } from 'colorino'
120
120
 
121
121
  const myLogger = createColorino(
122
- { // Palette (partial)
122
+ {
123
+ // Palette (partial)
123
124
  error: '#ff007b',
124
- info: '#3498db'
125
+ info: '#3498db',
125
126
  },
126
127
  { disableWarnings: true } // Options (see below)
127
128
  )
@@ -133,17 +134,17 @@ myLogger.info('Rebranded info!')
133
134
 
134
135
  `createColorino(palette?, options?)` accepts:
135
136
 
136
- | Option | Type | Default | Description |
137
- |-------------------|--------------------------------------|---------|-----------------------------------------------------------------------------|
138
- | `disableWarnings` | `boolean` | `false` | Suppress warnings when color support can't be detected or is disabled. |
139
- | `theme` | `ThemeOption` (see below) | `'auto'`| Control the active color theme or force a specific mode. |
140
- | `disableOscProbe` | `boolean` | `false` | Disable OSC 11 terminal theme probing (use only env heuristics for theme). |
141
- | `maxDepth` | `number` | `5` | Maximum depth when pretty-printing objects in log output. |
137
+ | Option | Type | Default | Description |
138
+ | ----------------- | ------------------------- | -------- | -------------------------------------------------------------------------- |
139
+ | `disableWarnings` | `boolean` | `false` | Suppress warnings when color support can't be detected or is disabled. |
140
+ | `theme` | `ThemeOption` (see below) | `'auto'` | Control the active color theme or force a specific mode. |
141
+ | `disableOscProbe` | `boolean` | `false` | Disable OSC 11 terminal theme probing (use only env heuristics for theme). |
142
+ | `maxDepth` | `number` | `5` | Maximum depth when pretty-printing objects in log output. |
142
143
 
143
144
  **`theme` accepts three types of values:**
144
145
 
145
146
  1. **`'auto'`** (Default): Automatically detects your terminal or browser theme (dark/light) and applies the matching default preset.
146
- When combined with `disableOscProbe: true`, only environment variables are used for theme detection (no OSC 11 probe).
147
+ When combined with `disableOscProbe: true`, only environment variables are used for theme detection (no OSC 11 probe).
147
148
  2. **`'dark' | 'light'`**: Forces the logger into a specific mode using the default preset for that mode.
148
149
  3. **`ThemeName`**: Forces a specific built-in palette (e.g., `'dracula'`).
149
150
 
@@ -151,12 +152,12 @@ When combined with `disableOscProbe: true`, only environment variables are used
151
152
 
152
153
  Pass any of these names to the `theme` option to use a specific palette:
153
154
 
154
- | Theme Name | Type | Description |
155
- |----------------------|-----------------|--------------------------------------------------|
156
- | `'dracula'` | **Dark** (High Contrast) | Vibrant pinks, purples, and cyans. |
157
- | `'catppuccin-mocha'` | **Dark** (Low Contrast) | Soothing pastel colors. |
158
- | `'github-light'` | **Light** (High Contrast)| Clean, sharp, high-contrast. |
159
- | `'catppuccin-latte'` | **Light** (Low Contrast) | Warm, cozy light mode with soft colors. |
155
+ | Theme Name | Type | Description |
156
+ | -------------------- | ------------------------- | --------------------------------------- |
157
+ | `'dracula'` | **Dark** (High Contrast) | Vibrant pinks, purples, and cyans. |
158
+ | `'catppuccin-mocha'` | **Dark** (Low Contrast) | Soothing pastel colors. |
159
+ | `'github-light'` | **Light** (High Contrast) | Clean, sharp, high-contrast. |
160
+ | `'catppuccin-latte'` | **Light** (Low Contrast) | Warm, cozy light mode with soft colors. |
160
161
 
161
162
  In auto mode, Colorino uses dracula in dark environments and github-light in light environments.
162
163
 
@@ -167,14 +168,14 @@ Set only the colors you care about; everything else uses the detected base theme
167
168
 
168
169
  ```typescript
169
170
  // Only customize error and warn
170
- const myLogger = createColorino({
171
+ const myLogger = createColorino({
171
172
  error: '#ff007b',
172
- warn: '#ffa500'
173
+ warn: '#ffa500',
173
174
  })
174
175
 
175
176
  // Detected dark terminal (uses dracula as base):
176
177
  // - error: #ff007b (your custom red)
177
- // - warn: #ffa500 (your custom orange)
178
+ // - warn: #ffa500 (your custom orange)
178
179
  // - info: #8be9fd (dracula cyan)
179
180
  // - log: #f8f8f2 (dracula foreground)
180
181
  // - debug: #bd93f9 (dracula purple)
@@ -202,10 +203,7 @@ Overlay your own colors on top of a built-in theme.
202
203
 
203
204
  ```typescript
204
205
  // Use GitHub Light but with a custom error color
205
- const myLogger = createColorino(
206
- { error: '#ff007b' },
207
- { theme: 'github-light' }
208
- )
206
+ const myLogger = createColorino({ error: '#ff007b' }, { theme: 'github-light' })
209
207
  ```
210
208
 
211
209
  **4. Force a specific mode (uses defaults):**
@@ -241,16 +239,16 @@ myLogger.info('Still styled by theme.') // Uses the default theme color
241
239
 
242
240
  Colorino auto-detects your environment and color support, but you can override behavior using these standard environment variables (compatible with Chalk):
243
241
 
244
- | Variable | Effect | Example |
245
- |-----------------|------------------------------------------------------------------------------------------|--------------------------------------|
246
- | `NO_COLOR` | Forces no color output | `NO_COLOR=1 node app.js` |
247
- | `FORCE_COLOR` | Forces color level: `0`=off, `1`=ANSI‑16, `2`=ANSI‑256, `3`=Truecolor | `FORCE_COLOR=3 node app.js` |
248
- | `CLICOLOR` | `"0"` disables color | `CLICOLOR=0 node app.js` |
249
- | `CLICOLOR_FORCE`| Non‑`"0"` value enables color even if not a TTY | `CLICOLOR_FORCE=1 node app.js` |
250
- | `TERM` | Terminal type; may influence color support | `TERM=xterm-256color` |
251
- | `COLORTERM` | `'truecolor'` or `'24bit'` enables truecolor | `COLORTERM=truecolor` |
252
- | `WT_SESSION` | Enables color detection for Windows Terminal | |
253
- | `CI` | Many CI platforms default to no color | `CI=1 node app.js` |
242
+ | Variable | Effect | Example |
243
+ | ---------------- | --------------------------------------------------------------------- | ------------------------------ |
244
+ | `NO_COLOR` | Forces no color output | `NO_COLOR=1 node app.js` |
245
+ | `FORCE_COLOR` | Forces color level: `0`=off, `1`=ANSI‑16, `2`=ANSI‑256, `3`=Truecolor | `FORCE_COLOR=3 node app.js` |
246
+ | `CLICOLOR` | `"0"` disables color | `CLICOLOR=0 node app.js` |
247
+ | `CLICOLOR_FORCE` | Non‑`"0"` value enables color even if not a TTY | `CLICOLOR_FORCE=1 node app.js` |
248
+ | `TERM` | Terminal type; may influence color support | `TERM=xterm-256color` |
249
+ | `COLORTERM` | `'truecolor'` or `'24bit'` enables truecolor | `COLORTERM=truecolor` |
250
+ | `WT_SESSION` | Enables color detection for Windows Terminal | |
251
+ | `CI` | Many CI platforms default to no color | `CI=1 node app.js` |
254
252
 
255
253
  ### <a id="5-6"></a>Colorize Helper (Manual Overrides)
256
254
 
@@ -269,13 +267,13 @@ When color is disabled (for example via `NO_COLOR=1` or lack of support), `color
269
267
 
270
268
  ## <a id="6"></a>Colorino vs. Chalk
271
269
 
272
- | Feature | 🎨 **Colorino** | 🖍️ **Chalk** |
273
- |--------------------------|----------------------------|-----------------|
274
- | Out-of-box logs | ✔ themed, all log levels | ✘ string styling|
275
- | Zero-config | ✔ | ✘ manual, per-use|
276
- | Node + browser | ✔ | ✘ (Node only) |
277
- | CSS console logs | ✔ | ✘ |
278
- | Extensible / Composable | ✔ (via factory) | ✘ |
270
+ | Feature | 🎨 **Colorino** | 🖍️ **Chalk** |
271
+ | ----------------------- | ------------------------ | ----------------- |
272
+ | Out-of-box logs | ✔ themed, all log levels | ✘ string styling |
273
+ | Zero-config | ✔ | ✘ manual, per-use |
274
+ | Node + browser | ✔ | ✘ (Node only) |
275
+ | CSS console logs | ✔ | ✘ |
276
+ | Extensible / Composable | ✔ (via factory) | ✘ |
279
277
 
280
278
  ## <a id="7"></a>API Reference
281
279
 
@@ -310,7 +308,12 @@ Colorino is designed for composition: create a base logger via `createColorino()
310
308
  This example prefixes every `.info()` and `.error()` call with best‑effort caller context (file/line) derived from a synthetic `Error` stack.
311
309
 
312
310
  ```ts
313
- import { createColorino, type Colorino, type ColorinoOptions, type Palette } from 'colorino'
311
+ import {
312
+ createColorino,
313
+ type Colorino,
314
+ type ColorinoOptions,
315
+ type Palette,
316
+ } from 'colorino'
314
317
 
315
318
  function getCallerContext(): string {
316
319
  const err = new Error()
@@ -334,15 +337,16 @@ function getCallerContext(): string {
334
337
 
335
338
  export function createContextLogger(
336
339
  palette?: Partial<Palette>,
337
- options?: ColorinoOptions,
340
+ options?: ColorinoOptions
338
341
  ): Colorino {
339
342
  const base = createColorino(palette, options)
340
343
 
341
344
  // Inherit all default methods from the base logger...
342
- const logger = Object.create(base) as Colorino // Object.create uses `base` as the prototype.
345
+ const logger = Object.create(base) as Colorino // Object.create uses `base` as the prototype.
343
346
 
344
347
  // ...and override only what you need.
345
- Object.assign(logger, { // Object.assign copies these methods onto `logger`.
348
+ Object.assign(logger, {
349
+ // Object.assign copies these methods onto `logger`.
346
350
  info(...args: unknown[]) {
347
351
  base.info(`[${getCallerContext()}]`, ...args)
348
352
  },
@@ -375,4 +379,4 @@ logger.error('Failed to load user', { id: 456 })
375
379
 
376
380
  ## <a id="10"></a>License
377
381
 
378
- [MIT](LICENSE.md)
382
+ [MIT](LICENSE.md)
@@ -59,9 +59,6 @@ var ColorLevel = /* @__PURE__ */ ((ColorLevel2) => {
59
59
  return ColorLevel2;
60
60
  })(ColorLevel || {});
61
61
 
62
- function isConsoleMethod(level) {
63
- return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
64
- }
65
62
  const ColorinoBrowserColorized = Symbol("colorino.browserColorized");
66
63
  const ColorinoBrowserObject = Symbol("colorino.browserObject");
67
64
 
@@ -152,26 +149,38 @@ class TypeValidator {
152
149
  static isNull(value) {
153
150
  return value === null;
154
151
  }
152
+ static isUndefined(value) {
153
+ return value === void 0;
154
+ }
155
+ static isNullOrUndefined(value) {
156
+ return value == null;
157
+ }
155
158
  static isObject(value) {
156
159
  return typeof value === "object" && value !== null;
157
160
  }
158
161
  static isString(value) {
159
- return typeof value === "string";
162
+ return typeof value === "string" || value instanceof String;
163
+ }
164
+ static isArray(value) {
165
+ return Array.isArray(value);
160
166
  }
161
167
  static isError(value) {
162
168
  return value instanceof Error;
163
169
  }
164
170
  static isBrowserColorizedArg(value) {
165
- return typeof value === "object" && value !== null && ColorinoBrowserColorized in value;
171
+ return TypeValidator.isObject(value) && ColorinoBrowserColorized in value;
166
172
  }
167
173
  static isBrowserObjectArg(value) {
168
- return typeof value === "object" && value !== null && ColorinoBrowserObject in value;
174
+ return TypeValidator.isObject(value) && ColorinoBrowserObject in value;
169
175
  }
170
176
  static isAnsiColoredString(value) {
171
- return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value);
177
+ return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value.toString());
172
178
  }
173
179
  static isFormattableObject(value) {
174
- return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value);
180
+ return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value) && !TypeValidator.isString(value);
181
+ }
182
+ static isConsoleMethod(level) {
183
+ return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
175
184
  }
176
185
  }
177
186
 
@@ -236,9 +245,6 @@ class MyColorino {
236
245
  }
237
246
  return `${ansiPrefix}${text}\x1B[0m`;
238
247
  }
239
- _isAnsiColoredString(value) {
240
- return typeof value === "string" && /\x1b\[[0-9;]*m/.test(value);
241
- }
242
248
  _applyResolvedTheme(resolvedTheme) {
243
249
  const themeOpt = this._options.theme ?? "auto";
244
250
  const baseThemeName = determineBaseTheme(themeOpt, resolvedTheme);
@@ -263,34 +269,35 @@ class MyColorino {
263
269
  }
264
270
  _formatValue(value, maxDepth = this._options.maxDepth ?? 5) {
265
271
  const seen = /* @__PURE__ */ new WeakSet();
272
+ const sanitizeArray = (items, currentDepth) => {
273
+ return items.map((item) => sanitize(item, currentDepth));
274
+ };
275
+ const sanitizeObject = (obj, currentDepth) => {
276
+ const result = {};
277
+ for (const key in obj) {
278
+ result[key] = sanitize(obj[key], currentDepth);
279
+ }
280
+ return result;
281
+ };
266
282
  const sanitize = (val, currentDepth) => {
267
- if (val == null || typeof val !== "object") return val;
283
+ if (TypeValidator.isNullOrUndefined(val) || !TypeValidator.isObject(val)) {
284
+ return val;
285
+ }
268
286
  if (seen.has(val)) return "[Circular]";
269
287
  seen.add(val);
270
288
  if (currentDepth >= maxDepth) return "[Object]";
271
- if (Array.isArray(val)) {
272
- return val.map((item) => sanitize(item, currentDepth + 1));
289
+ const nextDepth = currentDepth + 1;
290
+ if (TypeValidator.isArray(val)) {
291
+ return sanitizeArray(val, nextDepth);
273
292
  }
274
- const result = {};
275
- for (const key in val) {
276
- result[key] = sanitize(
277
- val[key],
278
- currentDepth + 1
279
- );
280
- }
281
- return result;
293
+ return sanitizeObject(val, nextDepth);
282
294
  };
283
295
  return JSON.stringify(sanitize(value, 0), null, 2);
284
296
  }
285
- _normalizeString(value) {
286
- if (value instanceof String) return value.valueOf();
287
- return value;
288
- }
289
297
  _processArgs(args) {
290
298
  const processedArgs = [];
291
299
  let previousWasObject = false;
292
- for (const rawArg of args) {
293
- const arg = this._normalizeString(rawArg);
300
+ for (const arg of args) {
294
301
  if (TypeValidator.isBrowserColorizedArg(arg)) {
295
302
  processedArgs.push(arg);
296
303
  previousWasObject = false;
@@ -327,8 +334,7 @@ ${arg}`);
327
334
  const cssArgs = [];
328
335
  const otherArgs = [];
329
336
  const paletteHex = this._palette[consoleMethod];
330
- for (const rawArg of args) {
331
- const arg = this._normalizeString(rawArg);
337
+ for (const arg of args) {
332
338
  if (TypeValidator.isBrowserColorizedArg(arg)) {
333
339
  formatParts.push(`%c${arg.text}`);
334
340
  cssArgs.push(`color:${arg.hex}`);
@@ -373,31 +379,21 @@ ${arg}`);
373
379
  }
374
380
  }
375
381
  _applyNodeColors(consoleMethod, args) {
376
- const coloredArgs = [...args];
377
- const firstStringIndex = coloredArgs.findIndex(
378
- (arg) => typeof arg === "string"
379
- );
380
- if (firstStringIndex === -1) {
381
- return coloredArgs;
382
- }
383
- const first = coloredArgs[firstStringIndex];
384
- if (this._isAnsiColoredString(first)) {
385
- return coloredArgs;
386
- }
387
- const hex = this._palette[consoleMethod];
388
- const ansiPrefix = this._toAnsiPrefix(hex);
389
- if (!ansiPrefix) {
390
- return coloredArgs;
391
- }
392
- coloredArgs[firstStringIndex] = `${ansiPrefix}${String(first)}\x1B[0m`;
393
- return coloredArgs;
382
+ const paletteHex = this._palette[consoleMethod];
383
+ const paletteAnsiPrefix = this._toAnsiPrefix(paletteHex);
384
+ if (!paletteAnsiPrefix) return args;
385
+ return args.map((arg) => {
386
+ if (!TypeValidator.isString(arg) || TypeValidator.isAnsiColoredString(arg))
387
+ return arg;
388
+ return `${paletteAnsiPrefix}${String(arg)}\x1B[0m`;
389
+ });
394
390
  }
395
391
  _output(consoleMethod, args) {
396
392
  if (consoleMethod === "trace") this._printCleanTrace(args);
397
393
  else console[consoleMethod](...args);
398
394
  }
399
395
  _out(level, args) {
400
- const consoleMethod = isConsoleMethod(level) ? level : "log";
396
+ const consoleMethod = TypeValidator.isConsoleMethod(level) ? level : "log";
401
397
  const processedArgs = this._processArgs(args);
402
398
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
403
399
  this._output(consoleMethod, processedArgs);
@@ -57,9 +57,6 @@ var ColorLevel = /* @__PURE__ */ ((ColorLevel2) => {
57
57
  return ColorLevel2;
58
58
  })(ColorLevel || {});
59
59
 
60
- function isConsoleMethod(level) {
61
- return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
62
- }
63
60
  const ColorinoBrowserColorized = Symbol("colorino.browserColorized");
64
61
  const ColorinoBrowserObject = Symbol("colorino.browserObject");
65
62
 
@@ -150,26 +147,38 @@ class TypeValidator {
150
147
  static isNull(value) {
151
148
  return value === null;
152
149
  }
150
+ static isUndefined(value) {
151
+ return value === void 0;
152
+ }
153
+ static isNullOrUndefined(value) {
154
+ return value == null;
155
+ }
153
156
  static isObject(value) {
154
157
  return typeof value === "object" && value !== null;
155
158
  }
156
159
  static isString(value) {
157
- return typeof value === "string";
160
+ return typeof value === "string" || value instanceof String;
161
+ }
162
+ static isArray(value) {
163
+ return Array.isArray(value);
158
164
  }
159
165
  static isError(value) {
160
166
  return value instanceof Error;
161
167
  }
162
168
  static isBrowserColorizedArg(value) {
163
- return typeof value === "object" && value !== null && ColorinoBrowserColorized in value;
169
+ return TypeValidator.isObject(value) && ColorinoBrowserColorized in value;
164
170
  }
165
171
  static isBrowserObjectArg(value) {
166
- return typeof value === "object" && value !== null && ColorinoBrowserObject in value;
172
+ return TypeValidator.isObject(value) && ColorinoBrowserObject in value;
167
173
  }
168
174
  static isAnsiColoredString(value) {
169
- return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value);
175
+ return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value.toString());
170
176
  }
171
177
  static isFormattableObject(value) {
172
- return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value);
178
+ return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value) && !TypeValidator.isString(value);
179
+ }
180
+ static isConsoleMethod(level) {
181
+ return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
173
182
  }
174
183
  }
175
184
 
@@ -234,9 +243,6 @@ class MyColorino {
234
243
  }
235
244
  return `${ansiPrefix}${text}\x1B[0m`;
236
245
  }
237
- _isAnsiColoredString(value) {
238
- return typeof value === "string" && /\x1b\[[0-9;]*m/.test(value);
239
- }
240
246
  _applyResolvedTheme(resolvedTheme) {
241
247
  const themeOpt = this._options.theme ?? "auto";
242
248
  const baseThemeName = determineBaseTheme(themeOpt, resolvedTheme);
@@ -261,34 +267,35 @@ class MyColorino {
261
267
  }
262
268
  _formatValue(value, maxDepth = this._options.maxDepth ?? 5) {
263
269
  const seen = /* @__PURE__ */ new WeakSet();
270
+ const sanitizeArray = (items, currentDepth) => {
271
+ return items.map((item) => sanitize(item, currentDepth));
272
+ };
273
+ const sanitizeObject = (obj, currentDepth) => {
274
+ const result = {};
275
+ for (const key in obj) {
276
+ result[key] = sanitize(obj[key], currentDepth);
277
+ }
278
+ return result;
279
+ };
264
280
  const sanitize = (val, currentDepth) => {
265
- if (val == null || typeof val !== "object") return val;
281
+ if (TypeValidator.isNullOrUndefined(val) || !TypeValidator.isObject(val)) {
282
+ return val;
283
+ }
266
284
  if (seen.has(val)) return "[Circular]";
267
285
  seen.add(val);
268
286
  if (currentDepth >= maxDepth) return "[Object]";
269
- if (Array.isArray(val)) {
270
- return val.map((item) => sanitize(item, currentDepth + 1));
287
+ const nextDepth = currentDepth + 1;
288
+ if (TypeValidator.isArray(val)) {
289
+ return sanitizeArray(val, nextDepth);
271
290
  }
272
- const result = {};
273
- for (const key in val) {
274
- result[key] = sanitize(
275
- val[key],
276
- currentDepth + 1
277
- );
278
- }
279
- return result;
291
+ return sanitizeObject(val, nextDepth);
280
292
  };
281
293
  return JSON.stringify(sanitize(value, 0), null, 2);
282
294
  }
283
- _normalizeString(value) {
284
- if (value instanceof String) return value.valueOf();
285
- return value;
286
- }
287
295
  _processArgs(args) {
288
296
  const processedArgs = [];
289
297
  let previousWasObject = false;
290
- for (const rawArg of args) {
291
- const arg = this._normalizeString(rawArg);
298
+ for (const arg of args) {
292
299
  if (TypeValidator.isBrowserColorizedArg(arg)) {
293
300
  processedArgs.push(arg);
294
301
  previousWasObject = false;
@@ -325,8 +332,7 @@ ${arg}`);
325
332
  const cssArgs = [];
326
333
  const otherArgs = [];
327
334
  const paletteHex = this._palette[consoleMethod];
328
- for (const rawArg of args) {
329
- const arg = this._normalizeString(rawArg);
335
+ for (const arg of args) {
330
336
  if (TypeValidator.isBrowserColorizedArg(arg)) {
331
337
  formatParts.push(`%c${arg.text}`);
332
338
  cssArgs.push(`color:${arg.hex}`);
@@ -371,31 +377,21 @@ ${arg}`);
371
377
  }
372
378
  }
373
379
  _applyNodeColors(consoleMethod, args) {
374
- const coloredArgs = [...args];
375
- const firstStringIndex = coloredArgs.findIndex(
376
- (arg) => typeof arg === "string"
377
- );
378
- if (firstStringIndex === -1) {
379
- return coloredArgs;
380
- }
381
- const first = coloredArgs[firstStringIndex];
382
- if (this._isAnsiColoredString(first)) {
383
- return coloredArgs;
384
- }
385
- const hex = this._palette[consoleMethod];
386
- const ansiPrefix = this._toAnsiPrefix(hex);
387
- if (!ansiPrefix) {
388
- return coloredArgs;
389
- }
390
- coloredArgs[firstStringIndex] = `${ansiPrefix}${String(first)}\x1B[0m`;
391
- return coloredArgs;
380
+ const paletteHex = this._palette[consoleMethod];
381
+ const paletteAnsiPrefix = this._toAnsiPrefix(paletteHex);
382
+ if (!paletteAnsiPrefix) return args;
383
+ return args.map((arg) => {
384
+ if (!TypeValidator.isString(arg) || TypeValidator.isAnsiColoredString(arg))
385
+ return arg;
386
+ return `${paletteAnsiPrefix}${String(arg)}\x1B[0m`;
387
+ });
392
388
  }
393
389
  _output(consoleMethod, args) {
394
390
  if (consoleMethod === "trace") this._printCleanTrace(args);
395
391
  else console[consoleMethod](...args);
396
392
  }
397
393
  _out(level, args) {
398
- const consoleMethod = isConsoleMethod(level) ? level : "log";
394
+ const consoleMethod = TypeValidator.isConsoleMethod(level) ? level : "log";
399
395
  const processedArgs = this._processArgs(args);
400
396
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
401
397
  this._output(consoleMethod, processedArgs);
package/dist/browser.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const inputValidator = require('./shared/colorino.Dcy2ipG7.cjs');
3
+ const inputValidator = require('./shared/colorino.DMgDgITw.cjs');
4
4
 
5
5
  class BrowserColorSupportDetector {
6
6
  constructor(_window, _navigator, _overrideTheme) {
package/dist/browser.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ColorLevel, t as themePalettes, M as MyColorino, I as InputValidator, d as determineBaseTheme } from './shared/colorino.DEvR4n1Y.mjs';
1
+ import { C as ColorLevel, t as themePalettes, M as MyColorino, I as InputValidator, d as determineBaseTheme } from './shared/colorino.vAejLjBp.mjs';
2
2
 
3
3
  class BrowserColorSupportDetector {
4
4
  constructor(_window, _navigator, _overrideTheme) {
package/dist/node.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- const inputValidator = require('./shared/colorino.Dcy2ipG7.cjs');
3
+ const inputValidator = require('./shared/colorino.DMgDgITw.cjs');
4
4
  const node_child_process = require('node:child_process');
5
5
  const node_url = require('node:url');
6
6
  const node_path = require('node:path');
package/dist/node.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ColorLevel, d as determineBaseTheme, t as themePalettes, M as MyColorino, I as InputValidator } from './shared/colorino.DEvR4n1Y.mjs';
1
+ import { C as ColorLevel, d as determineBaseTheme, t as themePalettes, M as MyColorino, I as InputValidator } from './shared/colorino.vAejLjBp.mjs';
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import { fileURLToPath } from 'node:url';
4
4
  import { dirname, join } from 'node:path';
@@ -59,9 +59,6 @@ var ColorLevel = /* @__PURE__ */ ((ColorLevel2) => {
59
59
  return ColorLevel2;
60
60
  })(ColorLevel || {});
61
61
 
62
- function isConsoleMethod(level) {
63
- return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
64
- }
65
62
  const ColorinoBrowserColorized = Symbol("colorino.browserColorized");
66
63
  const ColorinoBrowserObject = Symbol("colorino.browserObject");
67
64
 
@@ -152,26 +149,38 @@ class TypeValidator {
152
149
  static isNull(value) {
153
150
  return value === null;
154
151
  }
152
+ static isUndefined(value) {
153
+ return value === void 0;
154
+ }
155
+ static isNullOrUndefined(value) {
156
+ return value == null;
157
+ }
155
158
  static isObject(value) {
156
159
  return typeof value === "object" && value !== null;
157
160
  }
158
161
  static isString(value) {
159
- return typeof value === "string";
162
+ return typeof value === "string" || value instanceof String;
163
+ }
164
+ static isArray(value) {
165
+ return Array.isArray(value);
160
166
  }
161
167
  static isError(value) {
162
168
  return value instanceof Error;
163
169
  }
164
170
  static isBrowserColorizedArg(value) {
165
- return typeof value === "object" && value !== null && ColorinoBrowserColorized in value;
171
+ return TypeValidator.isObject(value) && ColorinoBrowserColorized in value;
166
172
  }
167
173
  static isBrowserObjectArg(value) {
168
- return typeof value === "object" && value !== null && ColorinoBrowserObject in value;
174
+ return TypeValidator.isObject(value) && ColorinoBrowserObject in value;
169
175
  }
170
176
  static isAnsiColoredString(value) {
171
- return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value);
177
+ return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value.toString());
172
178
  }
173
179
  static isFormattableObject(value) {
174
- return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value);
180
+ return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value) && !TypeValidator.isString(value);
181
+ }
182
+ static isConsoleMethod(level) {
183
+ return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
175
184
  }
176
185
  }
177
186
 
@@ -236,9 +245,6 @@ class MyColorino {
236
245
  }
237
246
  return `${ansiPrefix}${text}\x1B[0m`;
238
247
  }
239
- _isAnsiColoredString(value) {
240
- return typeof value === "string" && /\x1b\[[0-9;]*m/.test(value);
241
- }
242
248
  _applyResolvedTheme(resolvedTheme) {
243
249
  const themeOpt = this._options.theme ?? "auto";
244
250
  const baseThemeName = determineBaseTheme(themeOpt, resolvedTheme);
@@ -263,34 +269,35 @@ class MyColorino {
263
269
  }
264
270
  _formatValue(value, maxDepth = this._options.maxDepth ?? 5) {
265
271
  const seen = /* @__PURE__ */ new WeakSet();
272
+ const sanitizeArray = (items, currentDepth) => {
273
+ return items.map((item) => sanitize(item, currentDepth));
274
+ };
275
+ const sanitizeObject = (obj, currentDepth) => {
276
+ const result = {};
277
+ for (const key in obj) {
278
+ result[key] = sanitize(obj[key], currentDepth);
279
+ }
280
+ return result;
281
+ };
266
282
  const sanitize = (val, currentDepth) => {
267
- if (val == null || typeof val !== "object") return val;
283
+ if (TypeValidator.isNullOrUndefined(val) || !TypeValidator.isObject(val)) {
284
+ return val;
285
+ }
268
286
  if (seen.has(val)) return "[Circular]";
269
287
  seen.add(val);
270
288
  if (currentDepth >= maxDepth) return "[Object]";
271
- if (Array.isArray(val)) {
272
- return val.map((item) => sanitize(item, currentDepth + 1));
289
+ const nextDepth = currentDepth + 1;
290
+ if (TypeValidator.isArray(val)) {
291
+ return sanitizeArray(val, nextDepth);
273
292
  }
274
- const result = {};
275
- for (const key in val) {
276
- result[key] = sanitize(
277
- val[key],
278
- currentDepth + 1
279
- );
280
- }
281
- return result;
293
+ return sanitizeObject(val, nextDepth);
282
294
  };
283
295
  return JSON.stringify(sanitize(value, 0), null, 2);
284
296
  }
285
- _normalizeString(value) {
286
- if (value instanceof String) return value.valueOf();
287
- return value;
288
- }
289
297
  _processArgs(args) {
290
298
  const processedArgs = [];
291
299
  let previousWasObject = false;
292
- for (const rawArg of args) {
293
- const arg = this._normalizeString(rawArg);
300
+ for (const arg of args) {
294
301
  if (TypeValidator.isBrowserColorizedArg(arg)) {
295
302
  processedArgs.push(arg);
296
303
  previousWasObject = false;
@@ -327,8 +334,7 @@ ${arg}`);
327
334
  const cssArgs = [];
328
335
  const otherArgs = [];
329
336
  const paletteHex = this._palette[consoleMethod];
330
- for (const rawArg of args) {
331
- const arg = this._normalizeString(rawArg);
337
+ for (const arg of args) {
332
338
  if (TypeValidator.isBrowserColorizedArg(arg)) {
333
339
  formatParts.push(`%c${arg.text}`);
334
340
  cssArgs.push(`color:${arg.hex}`);
@@ -373,31 +379,21 @@ ${arg}`);
373
379
  }
374
380
  }
375
381
  _applyNodeColors(consoleMethod, args) {
376
- const coloredArgs = [...args];
377
- const firstStringIndex = coloredArgs.findIndex(
378
- (arg) => typeof arg === "string"
379
- );
380
- if (firstStringIndex === -1) {
381
- return coloredArgs;
382
- }
383
- const first = coloredArgs[firstStringIndex];
384
- if (this._isAnsiColoredString(first)) {
385
- return coloredArgs;
386
- }
387
- const hex = this._palette[consoleMethod];
388
- const ansiPrefix = this._toAnsiPrefix(hex);
389
- if (!ansiPrefix) {
390
- return coloredArgs;
391
- }
392
- coloredArgs[firstStringIndex] = `${ansiPrefix}${String(first)}\x1B[0m`;
393
- return coloredArgs;
382
+ const paletteHex = this._palette[consoleMethod];
383
+ const paletteAnsiPrefix = this._toAnsiPrefix(paletteHex);
384
+ if (!paletteAnsiPrefix) return args;
385
+ return args.map((arg) => {
386
+ if (!TypeValidator.isString(arg) || TypeValidator.isAnsiColoredString(arg))
387
+ return arg;
388
+ return `${paletteAnsiPrefix}${String(arg)}\x1B[0m`;
389
+ });
394
390
  }
395
391
  _output(consoleMethod, args) {
396
392
  if (consoleMethod === "trace") this._printCleanTrace(args);
397
393
  else console[consoleMethod](...args);
398
394
  }
399
395
  _out(level, args) {
400
- const consoleMethod = isConsoleMethod(level) ? level : "log";
396
+ const consoleMethod = TypeValidator.isConsoleMethod(level) ? level : "log";
401
397
  const processedArgs = this._processArgs(args);
402
398
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
403
399
  this._output(consoleMethod, processedArgs);
@@ -57,9 +57,6 @@ var ColorLevel = /* @__PURE__ */ ((ColorLevel2) => {
57
57
  return ColorLevel2;
58
58
  })(ColorLevel || {});
59
59
 
60
- function isConsoleMethod(level) {
61
- return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
62
- }
63
60
  const ColorinoBrowserColorized = Symbol("colorino.browserColorized");
64
61
  const ColorinoBrowserObject = Symbol("colorino.browserObject");
65
62
 
@@ -150,26 +147,38 @@ class TypeValidator {
150
147
  static isNull(value) {
151
148
  return value === null;
152
149
  }
150
+ static isUndefined(value) {
151
+ return value === void 0;
152
+ }
153
+ static isNullOrUndefined(value) {
154
+ return value == null;
155
+ }
153
156
  static isObject(value) {
154
157
  return typeof value === "object" && value !== null;
155
158
  }
156
159
  static isString(value) {
157
- return typeof value === "string";
160
+ return typeof value === "string" || value instanceof String;
161
+ }
162
+ static isArray(value) {
163
+ return Array.isArray(value);
158
164
  }
159
165
  static isError(value) {
160
166
  return value instanceof Error;
161
167
  }
162
168
  static isBrowserColorizedArg(value) {
163
- return typeof value === "object" && value !== null && ColorinoBrowserColorized in value;
169
+ return TypeValidator.isObject(value) && ColorinoBrowserColorized in value;
164
170
  }
165
171
  static isBrowserObjectArg(value) {
166
- return typeof value === "object" && value !== null && ColorinoBrowserObject in value;
172
+ return TypeValidator.isObject(value) && ColorinoBrowserObject in value;
167
173
  }
168
174
  static isAnsiColoredString(value) {
169
- return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value);
175
+ return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value.toString());
170
176
  }
171
177
  static isFormattableObject(value) {
172
- return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value);
178
+ return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value) && !TypeValidator.isString(value);
179
+ }
180
+ static isConsoleMethod(level) {
181
+ return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
173
182
  }
174
183
  }
175
184
 
@@ -234,9 +243,6 @@ class MyColorino {
234
243
  }
235
244
  return `${ansiPrefix}${text}\x1B[0m`;
236
245
  }
237
- _isAnsiColoredString(value) {
238
- return typeof value === "string" && /\x1b\[[0-9;]*m/.test(value);
239
- }
240
246
  _applyResolvedTheme(resolvedTheme) {
241
247
  const themeOpt = this._options.theme ?? "auto";
242
248
  const baseThemeName = determineBaseTheme(themeOpt, resolvedTheme);
@@ -261,34 +267,35 @@ class MyColorino {
261
267
  }
262
268
  _formatValue(value, maxDepth = this._options.maxDepth ?? 5) {
263
269
  const seen = /* @__PURE__ */ new WeakSet();
270
+ const sanitizeArray = (items, currentDepth) => {
271
+ return items.map((item) => sanitize(item, currentDepth));
272
+ };
273
+ const sanitizeObject = (obj, currentDepth) => {
274
+ const result = {};
275
+ for (const key in obj) {
276
+ result[key] = sanitize(obj[key], currentDepth);
277
+ }
278
+ return result;
279
+ };
264
280
  const sanitize = (val, currentDepth) => {
265
- if (val == null || typeof val !== "object") return val;
281
+ if (TypeValidator.isNullOrUndefined(val) || !TypeValidator.isObject(val)) {
282
+ return val;
283
+ }
266
284
  if (seen.has(val)) return "[Circular]";
267
285
  seen.add(val);
268
286
  if (currentDepth >= maxDepth) return "[Object]";
269
- if (Array.isArray(val)) {
270
- return val.map((item) => sanitize(item, currentDepth + 1));
287
+ const nextDepth = currentDepth + 1;
288
+ if (TypeValidator.isArray(val)) {
289
+ return sanitizeArray(val, nextDepth);
271
290
  }
272
- const result = {};
273
- for (const key in val) {
274
- result[key] = sanitize(
275
- val[key],
276
- currentDepth + 1
277
- );
278
- }
279
- return result;
291
+ return sanitizeObject(val, nextDepth);
280
292
  };
281
293
  return JSON.stringify(sanitize(value, 0), null, 2);
282
294
  }
283
- _normalizeString(value) {
284
- if (value instanceof String) return value.valueOf();
285
- return value;
286
- }
287
295
  _processArgs(args) {
288
296
  const processedArgs = [];
289
297
  let previousWasObject = false;
290
- for (const rawArg of args) {
291
- const arg = this._normalizeString(rawArg);
298
+ for (const arg of args) {
292
299
  if (TypeValidator.isBrowserColorizedArg(arg)) {
293
300
  processedArgs.push(arg);
294
301
  previousWasObject = false;
@@ -325,8 +332,7 @@ ${arg}`);
325
332
  const cssArgs = [];
326
333
  const otherArgs = [];
327
334
  const paletteHex = this._palette[consoleMethod];
328
- for (const rawArg of args) {
329
- const arg = this._normalizeString(rawArg);
335
+ for (const arg of args) {
330
336
  if (TypeValidator.isBrowserColorizedArg(arg)) {
331
337
  formatParts.push(`%c${arg.text}`);
332
338
  cssArgs.push(`color:${arg.hex}`);
@@ -371,31 +377,21 @@ ${arg}`);
371
377
  }
372
378
  }
373
379
  _applyNodeColors(consoleMethod, args) {
374
- const coloredArgs = [...args];
375
- const firstStringIndex = coloredArgs.findIndex(
376
- (arg) => typeof arg === "string"
377
- );
378
- if (firstStringIndex === -1) {
379
- return coloredArgs;
380
- }
381
- const first = coloredArgs[firstStringIndex];
382
- if (this._isAnsiColoredString(first)) {
383
- return coloredArgs;
384
- }
385
- const hex = this._palette[consoleMethod];
386
- const ansiPrefix = this._toAnsiPrefix(hex);
387
- if (!ansiPrefix) {
388
- return coloredArgs;
389
- }
390
- coloredArgs[firstStringIndex] = `${ansiPrefix}${String(first)}\x1B[0m`;
391
- return coloredArgs;
380
+ const paletteHex = this._palette[consoleMethod];
381
+ const paletteAnsiPrefix = this._toAnsiPrefix(paletteHex);
382
+ if (!paletteAnsiPrefix) return args;
383
+ return args.map((arg) => {
384
+ if (!TypeValidator.isString(arg) || TypeValidator.isAnsiColoredString(arg))
385
+ return arg;
386
+ return `${paletteAnsiPrefix}${String(arg)}\x1B[0m`;
387
+ });
392
388
  }
393
389
  _output(consoleMethod, args) {
394
390
  if (consoleMethod === "trace") this._printCleanTrace(args);
395
391
  else console[consoleMethod](...args);
396
392
  }
397
393
  _out(level, args) {
398
- const consoleMethod = isConsoleMethod(level) ? level : "log";
394
+ const consoleMethod = TypeValidator.isConsoleMethod(level) ? level : "log";
399
395
  const processedArgs = this._processArgs(args);
400
396
  if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
401
397
  this._output(consoleMethod, processedArgs);
package/package.json CHANGED
@@ -1,25 +1,33 @@
1
1
  {
2
2
  "name": "colorino",
3
- "version": "0.13.0",
3
+ "version": "0.13.2",
4
4
  "description": "A super simple colorized logger that gets the most out of your terminal",
5
- "type": "module",
6
- "license": "MIT",
7
- "author": "simwai",
8
5
  "keywords": [
6
+ "ansi",
9
7
  "color",
8
+ "console",
10
9
  "logger",
11
10
  "terminal",
12
- "ansi",
13
- "console"
11
+ "chalk",
12
+ "kuler"
14
13
  ],
15
14
  "homepage": "https://github.com/simwai/colorino",
15
+ "bugs": {
16
+ "url": "https://github.com/simwai/colorino/issues"
17
+ },
18
+ "license": "MIT",
19
+ "author": "simwai",
16
20
  "repository": {
17
21
  "type": "git",
18
22
  "url": "git+https://github.com/simwai/colorino.git"
19
23
  },
20
- "bugs": {
21
- "url": "https://github.com/simwai/colorino/issues"
22
- },
24
+ "files": [
25
+ "dist",
26
+ "LICENSE.md",
27
+ "package.json",
28
+ "README.md"
29
+ ],
30
+ "type": "module",
23
31
  "main": "./dist/node.cjs",
24
32
  "module": "./dist/browser.mjs",
25
33
  "types": "./dist/browser.d.ts",
@@ -35,12 +43,9 @@
35
43
  "require": "./dist/browser.cjs"
36
44
  }
37
45
  },
38
- "files": [
39
- "dist",
40
- "README.md",
41
- "package.json",
42
- "LICENSE.md"
43
- ],
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
44
49
  "scripts": {
45
50
  "bundle:browser": "node --loader ts-node/esm node_modules/rollup/dist/bin/rollup -c rollup.browser.config.ts",
46
51
  "build": "unbuild && npm run bundle:browser",
@@ -76,7 +81,7 @@
76
81
  "lint-staged": "^15.2.0",
77
82
  "md-toc-cli": "^3.1.1",
78
83
  "node-pty": "^1.1.0",
79
- "oxfmt": "^0.9.0",
84
+ "oxfmt": "^0.23.0",
80
85
  "oxlint": "^0.2.0",
81
86
  "playwright": "^1.57.0",
82
87
  "rollup": "^4.54.0",
@@ -96,8 +101,5 @@
96
101
  "engines": {
97
102
  "node": ">=17.0.0",
98
103
  "npm": ">=8.0.0"
99
- },
100
- "publishConfig": {
101
- "access": "public"
102
104
  }
103
105
  }