colorino 0.13.2 → 0.14.0

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
@@ -12,6 +12,8 @@ Colorino automatically adapts its palette to your terminal or browser DevTools t
12
12
  - [Features](#2)
13
13
  - [Installation](#3)
14
14
  - [Browser via CDN (unpkg)](#4)
15
+ - [ESM (Recommended)](#4-1)
16
+ - [UMD (Classic `<script>`)](#4-2)
15
17
  - [Usage](#5)
16
18
  - [Quick Start](#5-1)
17
19
  - [Creating a Custom Logger](#5-2)
@@ -59,14 +61,14 @@ npm install colorino
59
61
 
60
62
  You can use Colorino directly in the browser without any build step.
61
63
 
62
- **ESM (recommended):**
64
+ ### <a id="4-1"></a>ESM (Recommended)
63
65
 
64
66
  ```html
65
67
  <!DOCTYPE html>
66
68
  <html>
67
69
  <head>
68
70
  <script type="module">
69
- import { colorino } from 'https://unpkg.com/colorino/dist/browser.bundle.mjs'
71
+ import { colorino } from 'https://unpkg.com/colorino/dist/cdn.min.mjs'
70
72
 
71
73
  colorino.info('Hello from the browser!')
72
74
  colorino.error('Something went wrong')
@@ -76,22 +78,37 @@ You can use Colorino directly in the browser without any build step.
76
78
  </html>
77
79
  ```
78
80
 
79
- CommonJS-style bundle:
81
+ For debugging (non‑minified):
80
82
 
81
- ```HTML
83
+ ```html
84
+ <script type="module">
85
+ import { colorino } from 'https://unpkg.com/colorino/dist/cdn.mjs'
86
+ </script>
87
+ ```
88
+
89
+ ### <a id="4-2"></a>UMD (Classic `<script>`)
90
+
91
+ ```html
82
92
  <!DOCTYPE html>
83
93
  <html>
84
94
  <head>
85
- <script src="https://unpkg.com/colorino/dist/browser.bundle.cjs"></script>
95
+ <script src="https://unpkg.com/colorino/dist/cdn.min.js"></script>
86
96
  <script>
87
97
  // `colorino` is exposed as a global
88
- colorino.info('Hello from the CJS bundle!');
98
+ colorino.info('Hello from the UMD bundle!')
99
+ colorino.error('Something went wrong')
89
100
  </script>
90
101
  </head>
91
102
  <body></body>
92
103
  </html>
93
104
  ```
94
105
 
106
+ For debugging (non‑minified):
107
+
108
+ ```html
109
+ <script src="https://unpkg.com/colorino/dist/cdn.js"></script>
110
+ ```
111
+
95
112
  ## <a id="5"></a>Usage
96
113
 
97
114
  ### <a id="5-1"></a>Quick Start
@@ -379,4 +396,4 @@ logger.error('Failed to load user', { id: 456 })
379
396
 
380
397
  ## <a id="10"></a>License
381
398
 
382
- [MIT](LICENSE.md)
399
+ [MIT](LICENSE.md)
@@ -1,8 +1,29 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.FdIbpxRG.mjs';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.FdIbpxRG.mjs';
1
+ type ConsoleMethod = 'log' | 'info' | 'warn' | 'error' | 'trace' | 'debug';
2
+ type LogLevel = ConsoleMethod & string;
3
+ type Palette = Record<LogLevel, string>;
4
+ type TerminalTheme = 'dark' | 'light' | 'unknown';
5
+ type ThemeName = 'catppuccin-mocha' | 'catppuccin-latte' | 'dracula' | 'github-light';
6
+ interface ColorinoOptions {
7
+ disableWarnings?: boolean;
8
+ theme?: TerminalTheme | ThemeName | 'auto';
9
+ disableOscProbe?: boolean;
10
+ maxDepth?: number;
11
+ }
12
+ interface Colorino {
13
+ log(...args: unknown[]): void;
14
+ info(...args: unknown[]): void;
15
+ warn(...args: unknown[]): void;
16
+ error(...args: unknown[]): void;
17
+ debug(...args: unknown[]): void;
18
+ trace(...args: unknown[]): void;
19
+ colorize(text: string, hex: string): void;
20
+ }
21
+
22
+ declare const themePalettes: Record<ThemeName, Palette>;
3
23
 
4
24
  declare function createColorino(userPalette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
25
 
6
26
  declare const colorino: Colorino;
7
27
 
8
- export { Colorino, ColorinoOptions, Palette, colorino, createColorino };
28
+ export { colorino, createColorino, themePalettes };
29
+ export type { Colorino, ColorinoOptions, LogLevel, Palette, ThemeName };
package/dist/browser.d.ts CHANGED
@@ -1,8 +1,29 @@
1
- import { P as Palette, C as ColorinoOptions, a as Colorino } from './shared/colorino.FdIbpxRG.js';
2
- export { L as LogLevel, T as ThemeName, t as themePalettes } from './shared/colorino.FdIbpxRG.js';
1
+ type ConsoleMethod = 'log' | 'info' | 'warn' | 'error' | 'trace' | 'debug';
2
+ type LogLevel = ConsoleMethod & string;
3
+ type Palette = Record<LogLevel, string>;
4
+ type TerminalTheme = 'dark' | 'light' | 'unknown';
5
+ type ThemeName = 'catppuccin-mocha' | 'catppuccin-latte' | 'dracula' | 'github-light';
6
+ interface ColorinoOptions {
7
+ disableWarnings?: boolean;
8
+ theme?: TerminalTheme | ThemeName | 'auto';
9
+ disableOscProbe?: boolean;
10
+ maxDepth?: number;
11
+ }
12
+ interface Colorino {
13
+ log(...args: unknown[]): void;
14
+ info(...args: unknown[]): void;
15
+ warn(...args: unknown[]): void;
16
+ error(...args: unknown[]): void;
17
+ debug(...args: unknown[]): void;
18
+ trace(...args: unknown[]): void;
19
+ colorize(text: string, hex: string): void;
20
+ }
21
+
22
+ declare const themePalettes: Record<ThemeName, Palette>;
3
23
 
4
24
  declare function createColorino(userPalette?: Partial<Palette>, options?: ColorinoOptions): Colorino;
5
25
 
6
26
  declare const colorino: Colorino;
7
27
 
8
- export { Colorino, ColorinoOptions, Palette, colorino, createColorino };
28
+ export { colorino, createColorino, themePalettes };
29
+ export type { Colorino, ColorinoOptions, LogLevel, Palette, ThemeName };
package/dist/browser.mjs CHANGED
@@ -1,4 +1,232 @@
1
- import { C as ColorLevel, t as themePalettes, M as MyColorino, I as InputValidator, d as determineBaseTheme } from './shared/colorino.vAejLjBp.mjs';
1
+ import { err, ok } from 'neverthrow';
2
+
3
+ const ColorinoBrowserColorized = Symbol("colorino.browserColorized");
4
+ const ColorinoBrowserObject = Symbol("colorino.browserObject");
5
+
6
+ var ColorLevel = /* @__PURE__ */ ((ColorLevel2) => {
7
+ ColorLevel2[ColorLevel2["NO_COLOR"] = 0] = "NO_COLOR";
8
+ ColorLevel2[ColorLevel2["ANSI"] = 1] = "ANSI";
9
+ ColorLevel2[ColorLevel2["ANSI256"] = 2] = "ANSI256";
10
+ ColorLevel2[ColorLevel2["TRUECOLOR"] = 3] = "TRUECOLOR";
11
+ return ColorLevel2;
12
+ })(ColorLevel || {});
13
+
14
+ class TypeValidator {
15
+ static isNull(value) {
16
+ return value === null;
17
+ }
18
+ static isUndefined(value) {
19
+ return value === void 0;
20
+ }
21
+ static isNullOrUndefined(value) {
22
+ return value == null;
23
+ }
24
+ static isObject(value) {
25
+ return typeof value === "object" && value !== null;
26
+ }
27
+ static isString(value) {
28
+ return typeof value === "string" || value instanceof String;
29
+ }
30
+ static isArray(value) {
31
+ return Array.isArray(value);
32
+ }
33
+ static isError(value) {
34
+ return value instanceof Error;
35
+ }
36
+ static isBrowserColorizedArg(value) {
37
+ return TypeValidator.isObject(value) && ColorinoBrowserColorized in value;
38
+ }
39
+ static isBrowserObjectArg(value) {
40
+ return TypeValidator.isObject(value) && ColorinoBrowserObject in value;
41
+ }
42
+ static isAnsiColoredString(value) {
43
+ return TypeValidator.isString(value) && /\x1b\[[0-9;]*m/.test(value.toString());
44
+ }
45
+ static isFormattableObject(value) {
46
+ return TypeValidator.isObject(value) && !TypeValidator.isError(value) && !TypeValidator.isBrowserColorizedArg(value) && !TypeValidator.isString(value);
47
+ }
48
+ static isConsoleMethod(level) {
49
+ return ["log", "info", "warn", "error", "trace", "debug"].includes(level);
50
+ }
51
+ }
52
+
53
+ class AbstractColorino {
54
+ constructor(initialPalette, _userPalette, _validator, colorLevel, _options = {}) {
55
+ this._userPalette = _userPalette;
56
+ this._validator = _validator;
57
+ this._options = _options;
58
+ this._palette = initialPalette;
59
+ const validatePaletteResult = this._validator.validatePalette(this._palette);
60
+ if (validatePaletteResult.isErr()) throw validatePaletteResult.error;
61
+ this._colorLevel = colorLevel;
62
+ }
63
+ _alreadyWarned = false;
64
+ _colorLevel;
65
+ _palette;
66
+ log(...args) {
67
+ this._out("log", args);
68
+ }
69
+ info(...args) {
70
+ this._out("info", args);
71
+ }
72
+ warn(...args) {
73
+ this._out("warn", args);
74
+ }
75
+ error(...args) {
76
+ this._out("error", args);
77
+ }
78
+ trace(...args) {
79
+ this._out("trace", args);
80
+ }
81
+ debug(...args) {
82
+ this._out("debug", args);
83
+ }
84
+ colorize(text, hex) {
85
+ if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
86
+ return text;
87
+ }
88
+ if (this.isBrowser()) {
89
+ return {
90
+ [ColorinoBrowserColorized]: true,
91
+ text,
92
+ hex
93
+ };
94
+ }
95
+ const ansiPrefix = this._toAnsiPrefix(hex);
96
+ if (!ansiPrefix) {
97
+ return text;
98
+ }
99
+ return `${ansiPrefix}${text}\x1B[0m`;
100
+ }
101
+ _out(level, args) {
102
+ const consoleMethod = TypeValidator.isConsoleMethod(level) ? level : "log";
103
+ const processedArgs = this.processArgs(args);
104
+ if (this._colorLevel === ColorLevel.NO_COLOR || this._colorLevel === "UnknownEnv") {
105
+ this.output(consoleMethod, processedArgs);
106
+ return;
107
+ }
108
+ const coloredArgs = this.applyColors(consoleMethod, processedArgs);
109
+ this.output(consoleMethod, coloredArgs);
110
+ }
111
+ _toAnsiPrefix(_hex) {
112
+ return "";
113
+ }
114
+ _formatValue(value, maxDepth = this._options.maxDepth ?? 5) {
115
+ const seen = /* @__PURE__ */ new WeakSet();
116
+ const sanitizeArray = (items, depth) => {
117
+ return items.map((item) => sanitize(item, depth));
118
+ };
119
+ const sanitizeObject = (obj, depth) => {
120
+ const result = {};
121
+ for (const key in obj) {
122
+ result[key] = sanitize(obj[key], depth);
123
+ }
124
+ return result;
125
+ };
126
+ const sanitize = (val, currentDepth) => {
127
+ if (TypeValidator.isNullOrUndefined(val) || !TypeValidator.isObject(val)) {
128
+ return val;
129
+ }
130
+ if (seen.has(val)) return "[Circular]";
131
+ seen.add(val);
132
+ if (currentDepth >= maxDepth) return "[Object]";
133
+ const nextDepth = currentDepth + 1;
134
+ if (TypeValidator.isArray(val)) {
135
+ return sanitizeArray(val, nextDepth);
136
+ }
137
+ return sanitizeObject(val, nextDepth);
138
+ };
139
+ return JSON.stringify(sanitize(value, 0), null, 2);
140
+ }
141
+ _filterStack(stack) {
142
+ return stack.split("\n").filter((line) => !line.match(/.*colorino.*/gi)).join("\n");
143
+ }
144
+ _cleanErrorStack(error) {
145
+ if (!error.stack) return error;
146
+ const cleanStack = this._filterStack(error.stack);
147
+ const cloned = Object.create(Object.getPrototypeOf(error));
148
+ Object.assign(cloned, error);
149
+ cloned.stack = cleanStack;
150
+ return cloned;
151
+ }
152
+ _printCleanTrace(args) {
153
+ const error = new Error();
154
+ if (error.stack) {
155
+ const cleanStack = this._filterStack(error.stack);
156
+ console.log(...args, `
157
+ ${cleanStack}`);
158
+ } else {
159
+ console.log(...args);
160
+ }
161
+ }
162
+ }
163
+
164
+ class ColorinoBrowser extends AbstractColorino {
165
+ constructor(initialPalette, userPalette, validator, colorLevel, options = {}) {
166
+ super(initialPalette, userPalette, validator, colorLevel, options);
167
+ }
168
+ applyColors(consoleMethod, args) {
169
+ const formatParts = [];
170
+ const cssArgs = [];
171
+ const otherArgs = [];
172
+ const paletteHex = this._palette[consoleMethod];
173
+ for (const arg of args) {
174
+ if (TypeValidator.isBrowserColorizedArg(arg)) {
175
+ formatParts.push(`%c${arg.text}`);
176
+ cssArgs.push(`color:${arg.hex}`);
177
+ continue;
178
+ }
179
+ if (TypeValidator.isBrowserObjectArg(arg)) {
180
+ formatParts.push("%o");
181
+ otherArgs.push(arg.value);
182
+ continue;
183
+ }
184
+ if (TypeValidator.isString(arg)) {
185
+ formatParts.push(`%c${arg}`);
186
+ cssArgs.push(`color:${paletteHex}`);
187
+ continue;
188
+ }
189
+ formatParts.push("%o");
190
+ otherArgs.push(arg);
191
+ }
192
+ if (formatParts.length === 0) return args;
193
+ return [formatParts.join(""), ...cssArgs, ...otherArgs];
194
+ }
195
+ output(consoleMethod, args) {
196
+ console[consoleMethod](...args);
197
+ }
198
+ processArgs(args) {
199
+ const processedArgs = [];
200
+ let previousWasObject = false;
201
+ for (const arg of args) {
202
+ if (TypeValidator.isBrowserColorizedArg(arg)) {
203
+ processedArgs.push(arg);
204
+ previousWasObject = false;
205
+ continue;
206
+ }
207
+ if (TypeValidator.isFormattableObject(arg)) {
208
+ processedArgs.push({
209
+ [ColorinoBrowserObject]: true,
210
+ value: arg
211
+ });
212
+ previousWasObject = true;
213
+ } else if (TypeValidator.isError(arg)) {
214
+ processedArgs.push("\n", this._cleanErrorStack(arg));
215
+ previousWasObject = true;
216
+ } else {
217
+ processedArgs.push(
218
+ TypeValidator.isString(arg) && previousWasObject ? `
219
+ ${arg}` : arg
220
+ );
221
+ previousWasObject = false;
222
+ }
223
+ }
224
+ return processedArgs;
225
+ }
226
+ isBrowser() {
227
+ return true;
228
+ }
229
+ }
2
230
 
3
231
  class BrowserColorSupportDetector {
4
232
  constructor(_window, _navigator, _overrideTheme) {
@@ -10,13 +238,15 @@ class BrowserColorSupportDetector {
10
238
  return !!this._window && !!this._navigator?.userAgent;
11
239
  }
12
240
  getColorLevel() {
13
- if (!this.isBrowserEnv()) {
14
- return ColorLevel.NO_COLOR;
241
+ const isTruecolor = window.matchMedia("(color-gamut: p3)").matches;
242
+ if (isTruecolor) {
243
+ return ColorLevel.TRUECOLOR;
15
244
  }
16
- const userAgent = this._navigator.userAgent.toLowerCase();
17
- if (userAgent.includes("chrome")) return ColorLevel.ANSI256;
18
- if (userAgent.includes("firefox")) return ColorLevel.ANSI256;
19
- return ColorLevel.ANSI256;
245
+ const isAnsi256 = window.matchMedia("(monochrome: 0)").matches;
246
+ if (isAnsi256) {
247
+ return ColorLevel.ANSI256;
248
+ }
249
+ return ColorLevel.ANSI;
20
250
  }
21
251
  getTheme() {
22
252
  if (this._overrideTheme) {
@@ -25,16 +255,132 @@ class BrowserColorSupportDetector {
25
255
  if (!this.isBrowserEnv() || typeof this._window.matchMedia !== "function") {
26
256
  return "unknown";
27
257
  }
28
- if (this._window.matchMedia("(prefers-color-scheme: dark)").matches) {
258
+ const isDarkTheme = this._window.matchMedia(
259
+ "(prefers-color-scheme: dark)"
260
+ ).matches;
261
+ if (isDarkTheme) {
29
262
  return "dark";
30
263
  }
31
- if (this._window.matchMedia("(prefers-color-scheme: light)").matches) {
264
+ const isLightTheme = "(prefers-color-scheme: light)";
265
+ if (this._window.matchMedia(isLightTheme).matches) {
32
266
  return "light";
33
267
  }
34
268
  return "unknown";
35
269
  }
36
270
  }
37
271
 
272
+ class InputValidationError extends Error {
273
+ constructor(message) {
274
+ super(message);
275
+ this.name = "InputValidationError";
276
+ Object.setPrototypeOf(this, InputValidationError.prototype);
277
+ }
278
+ }
279
+
280
+ class InputValidator {
281
+ validateHex(hex) {
282
+ const trimmedHex = hex.trim();
283
+ const isHexValid = /^#[0-9A-F]{6}$/i.test(trimmedHex);
284
+ if (!isHexValid) {
285
+ return err(new InputValidationError(`Invalid hex color: '${hex}'`));
286
+ }
287
+ return ok(true);
288
+ }
289
+ validatePalette(palette) {
290
+ for (const level in palette) {
291
+ const hex = palette[level];
292
+ const result = this.validateHex(hex);
293
+ if (result.isErr()) {
294
+ return err(result.error);
295
+ }
296
+ }
297
+ return ok(true);
298
+ }
299
+ }
300
+
301
+ const catppuccinMochaPalette = {
302
+ log: "#cdd6f4",
303
+ // Text
304
+ info: "#89b4fa",
305
+ // Blue
306
+ warn: "#f9e2af",
307
+ // Yellow
308
+ error: "#f38ba8",
309
+ // Red
310
+ debug: "#a6adc8",
311
+ // Subtext0
312
+ trace: "#9399b2"
313
+ // Subtext1
314
+ };
315
+ const catppuccinLattePalette = {
316
+ log: "#4c4f69",
317
+ // Text
318
+ info: "#1e66f5",
319
+ // Blue
320
+ warn: "#df8e1d",
321
+ // Yellow
322
+ error: "#d20f39",
323
+ // Red
324
+ debug: "#7c7f93",
325
+ // Subtext0
326
+ trace: "#8c8fa1"
327
+ // Subtext1
328
+ };
329
+ const draculaPalette = {
330
+ log: "#f8f8f2",
331
+ // Foreground
332
+ info: "#8be9fd",
333
+ // Cyan
334
+ warn: "#f1fa8c",
335
+ // Yellow
336
+ error: "#ff5555",
337
+ // Red
338
+ debug: "#bd93f9",
339
+ // Purple
340
+ trace: "#6272a4"
341
+ // Comment
342
+ };
343
+ const githubLightPalette = {
344
+ log: "#24292e",
345
+ // Text
346
+ info: "#0366d6",
347
+ // Blue
348
+ warn: "#f9a002",
349
+ // Yellow
350
+ error: "#d73a49",
351
+ // Red
352
+ debug: "#586069",
353
+ // Gray
354
+ trace: "#6a737d"
355
+ // Gray-light
356
+ };
357
+
358
+ const themePalettes = {
359
+ "catppuccin-mocha": catppuccinMochaPalette,
360
+ "catppuccin-latte": catppuccinLattePalette,
361
+ dracula: draculaPalette,
362
+ "github-light": githubLightPalette
363
+ };
364
+ const defaultDarkTheme = "dracula";
365
+ const defaultLightTheme = "github-light";
366
+ function isThemeName(theme) {
367
+ return theme in themePalettes;
368
+ }
369
+
370
+ function determineBaseTheme(themeOpt, detectedBrowserTheme) {
371
+ let baseThemeName;
372
+ if (isThemeName(themeOpt)) {
373
+ baseThemeName = themeOpt;
374
+ } else if (themeOpt === "light") {
375
+ baseThemeName = defaultLightTheme;
376
+ } else if (themeOpt === "dark") {
377
+ baseThemeName = defaultDarkTheme;
378
+ } else {
379
+ baseThemeName = detectedBrowserTheme === "light" ? defaultLightTheme : defaultDarkTheme;
380
+ }
381
+ return baseThemeName;
382
+ }
383
+
38
384
  function createColorino(userPalette = {}, options = {}) {
39
385
  const validator = new InputValidator();
40
386
  let detectorThemeOverride;
@@ -48,18 +394,15 @@ function createColorino(userPalette = {}, options = {}) {
48
394
  );
49
395
  const detectedBrowserTheme = browserDetector.getTheme();
50
396
  const themeOpt = options.theme ?? "auto";
51
- const baseThemeName = determineBaseTheme(
52
- themeOpt,
53
- detectedBrowserTheme
54
- );
397
+ const baseThemeName = determineBaseTheme(themeOpt, detectedBrowserTheme);
55
398
  const basePalette = themePalettes[baseThemeName];
56
399
  const finalPalette = { ...basePalette, ...userPalette };
57
- return new MyColorino(
400
+ const colorLevel = browserDetector.isBrowserEnv() ? browserDetector.getColorLevel() ?? "UnknownEnv" : "UnknownEnv";
401
+ return new ColorinoBrowser(
58
402
  finalPalette,
59
403
  userPalette,
60
404
  validator,
61
- browserDetector,
62
- void 0,
405
+ colorLevel,
63
406
  options
64
407
  );
65
408
  }