@protoqol/vivid-log 2.0.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/lib/ansi.ts ADDED
@@ -0,0 +1,47 @@
1
+ export const ANSI = {
2
+ reset : "\x1b[0m",
3
+ bold : "\x1b[1m",
4
+ italic : "\x1b[3m",
5
+ underline: "\x1b[4m",
6
+ inverse : "\x1b[7m",
7
+ black : "\x1b[30m",
8
+ red : "\x1b[31m",
9
+ green : "\x1b[32m",
10
+ yellow : "\x1b[33m",
11
+ blue : "\x1b[34m",
12
+ magenta : "\x1b[35m",
13
+ cyan : "\x1b[36m",
14
+ white : "\x1b[37m",
15
+ bgBlack : "\x1b[40m",
16
+ bgRed : "\x1b[41m",
17
+ bgGreen : "\x1b[42m",
18
+ bgYellow : "\x1b[43m",
19
+ bgBlue : "\x1b[44m",
20
+ bgMagenta: "\x1b[45m",
21
+ bgCyan : "\x1b[46m",
22
+ bgWhite : "\x1b[47m",
23
+ };
24
+
25
+ export const hexToAnsi = (hex: string): string => {
26
+ hex = hex.replace(/^#/, "");
27
+ if (hex.length === 3) {
28
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
29
+ }
30
+ const r = parseInt(hex.substring(0, 2), 16);
31
+ const g = parseInt(hex.substring(2, 4), 16);
32
+ const b = parseInt(hex.substring(4, 6), 16);
33
+
34
+ return `\x1b[38;2;${r};${g};${b}m`;
35
+ };
36
+
37
+ export const hexToAnsiBg = (hex: string): string => {
38
+ hex = hex.replace(/^#/, "");
39
+ if (hex.length === 3) {
40
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
41
+ }
42
+ const r = parseInt(hex.substring(0, 2), 16);
43
+ const g = parseInt(hex.substring(2, 4), 16);
44
+ const b = parseInt(hex.substring(4, 6), 16);
45
+
46
+ return `\x1b[48;2;${r};${g};${b}m`;
47
+ };
@@ -0,0 +1,68 @@
1
+ export interface StatusConfig {
2
+ lightColor: string;
3
+
4
+ darkColor: string;
5
+
6
+ code: string;
7
+ }
8
+
9
+ export interface VividLogConfig {
10
+ autoGroup: boolean;
11
+
12
+ timeNotation: string;
13
+
14
+ iUseLightTheme: boolean;
15
+
16
+ customStyle: string;
17
+
18
+ fontSize: string;
19
+
20
+ newLine: boolean;
21
+
22
+ status: {
23
+ [key: string]: StatusConfig;
24
+ };
25
+ }
26
+
27
+ const config: VividLogConfig = {
28
+ autoGroup : true,
29
+ timeNotation : "h:m:s",
30
+ iUseLightTheme: false,
31
+ customStyle : "",
32
+ fontSize : "12px",
33
+ newLine : typeof navigator !== "undefined" ? navigator.userAgent.includes("Firefox") : false,
34
+ status : {
35
+ error : {
36
+ lightColor: "#da3030",
37
+ darkColor : "#872323",
38
+ code : "ERROR",
39
+ },
40
+ success: {
41
+ lightColor: "#00b808",
42
+ darkColor : "#21872a",
43
+ code : "SUCCESS",
44
+ },
45
+ warning: {
46
+ lightColor: "#da993e",
47
+ darkColor : "#875a2a",
48
+ code : "WARNING",
49
+ },
50
+ info : {
51
+ lightColor: "#b0b52c",
52
+ darkColor : "#788738",
53
+ code : "INFO",
54
+ },
55
+ debug : {
56
+ lightColor: "#da43be",
57
+ darkColor : "#872773",
58
+ code : "DEBUG",
59
+ },
60
+ log : {
61
+ lightColor: "#65b0b9",
62
+ darkColor : "#4f7e87",
63
+ code : "LOG",
64
+ },
65
+ },
66
+ };
67
+
68
+ export default config;
package/lib/enums.ts ADDED
@@ -0,0 +1,35 @@
1
+ export enum LogSize {
2
+ SMALL_LOGGABLE = 0,
3
+ BIG_LOGGABLE = 1,
4
+ }
5
+
6
+ export interface LogTypeInfo {
7
+ i: number;
8
+
9
+ val: string;
10
+ }
11
+
12
+ export const DEBUG: LogTypeInfo = {
13
+ i : 2,
14
+ val: "debug",
15
+ };
16
+
17
+ export const ERROR: LogTypeInfo = {
18
+ i : 3,
19
+ val: "error",
20
+ };
21
+
22
+ export const INFO: LogTypeInfo = {
23
+ i : 4,
24
+ val: "info",
25
+ };
26
+
27
+ export const LOG: LogTypeInfo = {
28
+ i : 5,
29
+ val: "log",
30
+ };
31
+
32
+ export const WARNING: LogTypeInfo = {
33
+ i : 6,
34
+ val: "warning",
35
+ };
package/lib/methods.ts ADDED
@@ -0,0 +1,32 @@
1
+ export class Methods {
2
+ static takeOver(turnOn: boolean): boolean {
3
+ if (turnOn) {
4
+ if (typeof window !== "undefined") {
5
+ window.onerror = (_message, _source, _lineno, _colno, error) => {
6
+ if (error) {
7
+ window.vividLog?.err(error.stack);
8
+ return true;
9
+ }
10
+
11
+ return false;
12
+ };
13
+ } else if (typeof process !== "undefined") {
14
+ process.on("uncaughtException", (error) => {
15
+ const vividLog = (global as any).vividLog;
16
+ if (vividLog) {
17
+ vividLog.err(error.stack);
18
+ } else {
19
+ console.error(error);
20
+ }
21
+ });
22
+ }
23
+ return true;
24
+ }
25
+
26
+ const vividLog = (typeof window !== "undefined") ? window.vividLog : (global as any).vividLog;
27
+
28
+ vividLog?.style("font-style: italic;").say("f v.takeOver() was called but was not turned on. Do so by using v.takeOver(true)", "VividLog", "#E3342F");
29
+
30
+ return false;
31
+ }
32
+ }
package/lib/utils.ts ADDED
@@ -0,0 +1,271 @@
1
+ import {LogSize} from "./enums";
2
+ import config from "./config/config";
3
+ import {ANSI, hexToAnsi, hexToAnsiBg} from "./ansi";
4
+
5
+ declare global {
6
+ interface Window {
7
+ vividLog: any;
8
+ }
9
+
10
+ const vividLog: any;
11
+ }
12
+
13
+ const isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined";
14
+
15
+ export class Utils {
16
+ static evaluate(loggable: any, type: string): boolean {
17
+ if (this.checkTypeLog(loggable) === LogSize.SMALL_LOGGABLE) {
18
+ return this.fire(this.logBuilder(loggable, type), this.styleBuilder(type));
19
+ }
20
+
21
+ if (this.checkTypeLog(loggable) === LogSize.BIG_LOGGABLE) {
22
+ const style = this.styleBuilder(type);
23
+
24
+ if (isBrowser) {
25
+ console.log(
26
+ this.logBuilder(loggable, type, true),
27
+ style.status,
28
+ style.time,
29
+ style.type,
30
+ );
31
+ console.log(loggable);
32
+ console.log(
33
+ "%c ",
34
+ "padding: 0 5px;font-weight: bolder; border-top: 2px solid " + (window.vividLog?.config?.status[type]?.lightColor || "#000") + ";",
35
+ );
36
+ } else {
37
+ console.log(this.logBuilder(loggable, type, true));
38
+ console.log(loggable);
39
+ const color = (global as any).vividLog?.config?.status[type]?.lightColor || config.status[type]?.lightColor || "#000";
40
+ console.log(hexToAnsi(color) + "-------------------------" + ANSI.reset);
41
+ }
42
+ }
43
+
44
+ return false;
45
+ }
46
+
47
+ static getType(loggable: any): string | false {
48
+ let len: number;
49
+
50
+ if (loggable instanceof Error) {
51
+ return "error";
52
+ }
53
+
54
+ switch (typeof loggable) {
55
+ case "string":
56
+ len = loggable.length || 0;
57
+ return `string[${len}]`;
58
+ case "boolean":
59
+ return "boolean";
60
+ case "number":
61
+ len = String(loggable).length;
62
+ return `integer[${len}]`;
63
+ case "object":
64
+ if (loggable === null) {
65
+ return "null";
66
+ }
67
+ if (Array.isArray(loggable)) {
68
+ len = loggable.length;
69
+ return `array[${len}]`;
70
+ }
71
+ len = Object.keys(loggable).length;
72
+ return `object[${len}]`;
73
+ case "bigint":
74
+ len = String(loggable).length;
75
+ return `big integer[${len}]`;
76
+ case "function":
77
+ return "function";
78
+ case "symbol":
79
+ return "symbol";
80
+ case "undefined":
81
+ return "undefined";
82
+ default:
83
+ return false;
84
+ }
85
+ }
86
+
87
+ static isTypeOfLoggable(variable: string): boolean {
88
+ return ["log", "debug", "error", "info", "success", "warning"].includes(variable);
89
+ }
90
+
91
+ static createTime(format: string): string | false {
92
+ const time = this.timeObj(format);
93
+ let returnTime = "";
94
+ const formats = time.format;
95
+
96
+ for (let iteration = 0; iteration < formats.length; iteration++) {
97
+ switch (formats[iteration]) {
98
+ case "h":
99
+ returnTime += time.h;
100
+ break;
101
+ case "m":
102
+ returnTime += time.m;
103
+ break;
104
+ case "s":
105
+ returnTime += time.s;
106
+ break;
107
+ case "ms":
108
+ returnTime += time.ms;
109
+ break;
110
+ }
111
+ if (iteration !== (formats.length - 1)) {
112
+ returnTime += ":";
113
+ }
114
+ }
115
+
116
+ return returnTime.length >= 1 ? returnTime : false;
117
+ }
118
+
119
+ static timeObj(format: string) {
120
+ const date = new Date();
121
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
122
+
123
+ return {
124
+ format: format.split(":") || cfg.timeNotation.split(":"),
125
+ h : String(date.getHours()).padStart(2, "0"),
126
+ m : String(date.getMinutes()).padStart(2, "0"),
127
+ s : String(date.getSeconds()).padStart(2, "0"),
128
+ ms : String(date.getMilliseconds()).padStart(2, "0"),
129
+ };
130
+ }
131
+
132
+ static checkTypeLog(loggable: any): LogSize {
133
+ return (typeof loggable === "string" || typeof loggable === "number" || typeof loggable === "undefined")
134
+ ? LogSize.SMALL_LOGGABLE
135
+ : LogSize.BIG_LOGGABLE;
136
+ }
137
+
138
+ static makeStyleCompatible(css: string): string {
139
+ return css;
140
+ }
141
+
142
+ static styleBuilder(type: string, color?: string) {
143
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
144
+ const lightTheme = cfg.iUseLightTheme ? "color: white;" : "";
145
+ const customStyle = cfg.customStyle;
146
+ const fontSize = `font-size: ${cfg.fontSize};`;
147
+
148
+ const typeOrColorLight = this.isTypeOfLoggable(type) ? cfg.status[type].lightColor : color;
149
+ const typeOrColorDark = this.isTypeOfLoggable(type) ? cfg.status[type].darkColor : color;
150
+
151
+ const style = {
152
+ default : "color: #F1F5F8;" + fontSize,
153
+ labelDefault : `border-radius: 5px; padding: 5px; background: ${typeOrColorLight};`,
154
+ timeDefault : "",
155
+ logNameDefault : "font-weight: bold;",
156
+ typeNameDefault: `background: ${typeOrColorDark};`,
157
+ varDefault : "margin-top: 10px; margin-bottom: 5px;" + lightTheme,
158
+ custom : this.makeStyleCompatible(customStyle),
159
+ };
160
+
161
+ return {
162
+ status: style.default + style.labelDefault + style.logNameDefault,
163
+ time : style.default + style.labelDefault + style.timeDefault,
164
+ type : style.default + style.labelDefault + style.typeNameDefault,
165
+ var : style.default + style.varDefault + style.custom,
166
+ };
167
+ }
168
+
169
+ static logBuilder(loggable: any, typeOrLabel: string, onlyHeader: boolean = false): string {
170
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
171
+ const label = this.isTypeOfLoggable(typeOrLabel) ? cfg.status[typeOrLabel].code : typeOrLabel;
172
+
173
+ if (!isBrowser) {
174
+ const time = this.createTime(cfg.timeNotation);
175
+ const type = this.getType(loggable);
176
+ const statusColor = this.isTypeOfLoggable(typeOrLabel) ? cfg.status[typeOrLabel].lightColor : (typeOrLabel === "LABEL" ? "#800080" : "#A52A2A");
177
+ const typeColor = this.isTypeOfLoggable(typeOrLabel) ? cfg.status[typeOrLabel].darkColor : (typeOrLabel === "LABEL" ? "#800080" : "#A52A2A");
178
+
179
+ const labelStyled = hexToAnsiBg(statusColor) + ANSI.white + ANSI.bold + ` ${label} ` + ANSI.reset;
180
+ const timeStyled = hexToAnsiBg("#444") + ANSI.white + ` ${time} ` + ANSI.reset;
181
+ const typeStyled = hexToAnsiBg(typeColor) + ANSI.white + ` ${type} ` + ANSI.reset;
182
+
183
+ if (!onlyHeader) {
184
+ return `${labelStyled}${timeStyled}${typeStyled}${cfg.newLine ? " " : "\n"} ${loggable}`;
185
+ }
186
+
187
+ return `${labelStyled}${timeStyled}${typeStyled}`;
188
+ }
189
+
190
+ if (!onlyHeader) {
191
+ return "%c" + label +
192
+ "%c" + this.createTime(cfg.timeNotation) +
193
+ "%c" + this.getType(loggable) + (cfg.newLine ? " " : "\n") +
194
+ "%c " + loggable;
195
+ }
196
+
197
+ const typeCode = cfg.status[typeOrLabel]?.code || typeOrLabel;
198
+
199
+ return "%c" + typeCode +
200
+ "%c" + this.createTime(cfg.timeNotation) +
201
+ "%c" + this.getType(loggable);
202
+ }
203
+
204
+ static resetConfs(): boolean {
205
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
206
+ cfg.customStyle = "";
207
+ cfg.autoGroup = false;
208
+ return cfg.customStyle === "" && cfg.autoGroup === false;
209
+ }
210
+
211
+ static fire(loggable: string, style: any): boolean {
212
+ if (this.resetConfs()) {
213
+ if (isBrowser) {
214
+ console.log(loggable, style.status, style.time, style.type, style.var);
215
+ } else {
216
+ console.log(loggable);
217
+ }
218
+
219
+ return true;
220
+ }
221
+
222
+ return false;
223
+ }
224
+
225
+ static fireLabel(label: string, type: string = "LABEL"): void {
226
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
227
+
228
+ if (isBrowser) {
229
+ const compiled = `%c${label}%c${this.createTime(cfg.timeNotation)}%c${type}`;
230
+ const style = this.styleBuilder("purple", "purple");
231
+ style.var = "";
232
+ this.fire(compiled, style);
233
+ } else {
234
+ const compiled = this.logBuilder(null, label, true);
235
+ this.fire(compiled, {});
236
+ }
237
+ }
238
+
239
+ static loggable(args: IArguments | any[], type: string): boolean {
240
+ if (args.length > 1) {
241
+ return this.iterateLoggables(args, type);
242
+ }
243
+
244
+ return this.evaluate(args[0], type);
245
+ }
246
+
247
+ static iterateLoggables(args: IArguments | any[], type: string): boolean {
248
+ const cfg = (isBrowser ? window.vividLog?.config : (global as any).vividLog?.config) || config;
249
+
250
+ if (cfg.autoGroup) {
251
+ this.fireLabel(type.toUpperCase(), `Group[${args.length}]`);
252
+ if (isBrowser && console.groupCollapsed) {
253
+ console.groupCollapsed(type.toUpperCase());
254
+ }
255
+ }
256
+
257
+ for (let i = 0; i < args.length; i++) {
258
+ this.evaluate(args[i], "log");
259
+ }
260
+
261
+ if (cfg.autoGroup) {
262
+ if (isBrowser && console.groupEnd) {
263
+ console.groupEnd();
264
+ }
265
+ }
266
+
267
+ cfg.autoGroup = false;
268
+
269
+ return true;
270
+ }
271
+ }
@@ -0,0 +1,134 @@
1
+ import {Utils} from "./utils";
2
+ import {Methods} from "./methods";
3
+ import config, {VividLogConfig} from "./config/config";
4
+ import {LogSize} from "./enums";
5
+
6
+ export class VividLog {
7
+ public config: VividLogConfig = config;
8
+
9
+ constructor() {
10
+ if (typeof window !== "undefined") {
11
+ (window as any).vividLog = this;
12
+ } else if (typeof global !== "undefined") {
13
+ (global as any).vividLog = this;
14
+ }
15
+ }
16
+
17
+ /**
18
+ * Take over default error log
19
+ */
20
+ public takeOver(activate: boolean = false): void {
21
+ Methods.takeOver(activate);
22
+ }
23
+
24
+ /**
25
+ * Chain before log to group the all logs
26
+ */
27
+ public group(grouped: boolean = true): this {
28
+ this.config.autoGroup = grouped;
29
+ return this;
30
+ }
31
+
32
+ /**
33
+ * Chain before log to give message a custom style
34
+ */
35
+ public style(customStyle: string = ""): this {
36
+ this.config.customStyle = customStyle;
37
+ return this;
38
+ }
39
+
40
+ /**
41
+ * Only log a label
42
+ */
43
+ public fireLabel(label: string): this {
44
+ Utils.fireLabel(label);
45
+ return this;
46
+ }
47
+
48
+ /**
49
+ * Normal priority log
50
+ */
51
+ public log(...args: any[]): this {
52
+ Utils.loggable(args, "log");
53
+ return this;
54
+ }
55
+
56
+ /**
57
+ * Debug priority log
58
+ */
59
+ public debug(...args: any[]): this {
60
+ Utils.loggable(args, "debug");
61
+ return this;
62
+ }
63
+
64
+ /**
65
+ * Error priority log
66
+ */
67
+ public err(...args: any[]): this {
68
+ Utils.loggable(args, "error");
69
+ return this;
70
+ }
71
+
72
+ /**
73
+ * Warning priority log
74
+ */
75
+ public warn(...args: any[]): this {
76
+ Utils.loggable(args, "warning");
77
+ return this;
78
+ }
79
+
80
+ /**
81
+ * Success priority log
82
+ */
83
+ public done(...args: any[]): this {
84
+ Utils.loggable(args, "success");
85
+ return this;
86
+ }
87
+
88
+ /**
89
+ * Information priority log
90
+ */
91
+ public info(...args: any[]): this {
92
+ Utils.loggable(args, "info");
93
+ return this;
94
+ }
95
+
96
+ /**
97
+ * Custom logging utility
98
+ */
99
+ public say(loggable: any, label?: string, color?: string): boolean | void {
100
+ const type = Utils.checkTypeLog(loggable);
101
+
102
+ if (type === LogSize.SMALL_LOGGABLE) {
103
+ return Utils.fire(
104
+ Utils.logBuilder(loggable, label || (typeof document !== "undefined" ? document.title : (typeof process !== "undefined" ? "node" : "vividLog"))),
105
+ Utils.styleBuilder(color || "brown", color || "brown"),
106
+ );
107
+ }
108
+
109
+ if (type === LogSize.BIG_LOGGABLE) {
110
+ const style = Utils.styleBuilder("log"); // Default to log style if big
111
+ console.log(
112
+ Utils.logBuilder(loggable, "log", true),
113
+ style.status,
114
+ style.time,
115
+ style.type,
116
+ );
117
+ console.log(loggable);
118
+ console.log(
119
+ "%c ",
120
+ "padding: 0 5px;font-weight: bolder; border-top: 2px solid " + this.config.status["log"].lightColor + ";",
121
+ );
122
+ return true;
123
+ }
124
+ }
125
+ }
126
+
127
+ const vividLogInstance = new VividLog();
128
+ export default vividLogInstance;
129
+
130
+ if (typeof window !== "undefined") {
131
+ (window as any).vividLog = vividLogInstance;
132
+ } else if (typeof global !== "undefined") {
133
+ (global as any).vividLog = vividLogInstance;
134
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name" : "@protoqol/vivid-log",
3
+ "version" : "2.0.0",
4
+ "description" : "Console Logs, reimagined for JavaScript & TypeScript",
5
+ "main" : "dist/vividLog.js",
6
+ "author" : {
7
+ "name" : "Protoqol",
8
+ "email": "open-source@protoqol.nl",
9
+ "url" : "https://protoqol.nl"
10
+ },
11
+ "repository" : {
12
+ "type": "git",
13
+ "url" : "https://github.com/Protoqol/vivid-log"
14
+ },
15
+ "scripts" : {
16
+ "test" : "mocha -r ts-node/register test/**/*.ts",
17
+ "build": "tsc && webpack --mode production",
18
+ "watch": "tsc -w"
19
+ },
20
+ "keywords" : [
21
+ "logging",
22
+ "debug",
23
+ "javascript",
24
+ "ecmascript",
25
+ "protoqol"
26
+ ],
27
+ "license" : "MIT",
28
+ "bugs" : {
29
+ "url": "https://github.com/Protoqol/vivid-log/issues"
30
+ },
31
+ "homepage" : "https://github.com/Protoqol/vivid-log#readme",
32
+ "devDependencies": {
33
+ "@types/mocha": "^10.0.10",
34
+ "@types/node" : "^22.13.4",
35
+ "mocha" : "^11.7.5",
36
+ "ts-loader" : "^9.5.4",
37
+ "ts-node" : "^10.9.2",
38
+ "typescript" : "^5.9.3",
39
+ "webpack" : "^5.0.0",
40
+ "webpack-cli" : "^4.0.0"
41
+ }
42
+ }