@logtape/pretty 1.0.0-dev.231
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/LICENSE +20 -0
- package/README.md +236 -0
- package/deno.json +35 -0
- package/dist/_virtual/rolldown_runtime.cjs +30 -0
- package/dist/formatter.cjs +412 -0
- package/dist/formatter.d.cts +488 -0
- package/dist/formatter.d.cts.map +1 -0
- package/dist/formatter.d.ts +488 -0
- package/dist/formatter.d.ts.map +1 -0
- package/dist/formatter.js +411 -0
- package/dist/formatter.js.map +1 -0
- package/dist/mod.cjs +4 -0
- package/dist/mod.d.cts +2 -0
- package/dist/mod.d.ts +2 -0
- package/dist/mod.js +3 -0
- package/dist/terminal.cjs +66 -0
- package/dist/terminal.js +66 -0
- package/dist/terminal.js.map +1 -0
- package/dist/truncate.cjs +57 -0
- package/dist/truncate.d.cts +47 -0
- package/dist/truncate.d.cts.map +1 -0
- package/dist/truncate.d.ts +47 -0
- package/dist/truncate.d.ts.map +1 -0
- package/dist/truncate.js +57 -0
- package/dist/truncate.js.map +1 -0
- package/dist/wcwidth.cjs +86 -0
- package/dist/wcwidth.js +85 -0
- package/dist/wcwidth.js.map +1 -0
- package/dist/wordwrap.cjs +98 -0
- package/dist/wordwrap.js +99 -0
- package/dist/wordwrap.js.map +1 -0
- package/formatter.test.ts +782 -0
- package/formatter.ts +1037 -0
- package/mod.ts +17 -0
- package/package.json +66 -0
- package/terminal.test.ts +67 -0
- package/terminal.ts +94 -0
- package/truncate.test.ts +104 -0
- package/truncate.ts +90 -0
- package/tsdown.config.ts +11 -0
- package/wcwidth.test.ts +60 -0
- package/wcwidth.ts +383 -0
- package/wordwrap.test.ts +110 -0
- package/wordwrap.ts +161 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
|
|
2
|
+
const require_terminal = require('./terminal.cjs');
|
|
3
|
+
const require_truncate = require('./truncate.cjs');
|
|
4
|
+
const require_wcwidth = require('./wcwidth.cjs');
|
|
5
|
+
const require_wordwrap = require('./wordwrap.cjs');
|
|
6
|
+
const node_util = require_rolldown_runtime.__toESM(require("node:util"));
|
|
7
|
+
|
|
8
|
+
//#region formatter.ts
|
|
9
|
+
/**
|
|
10
|
+
* ANSI escape codes for styling
|
|
11
|
+
*/
|
|
12
|
+
const RESET = "\x1B[0m";
|
|
13
|
+
const DIM = "\x1B[2m";
|
|
14
|
+
const defaultColors = {
|
|
15
|
+
trace: "rgb(167,139,250)",
|
|
16
|
+
debug: "rgb(96,165,250)",
|
|
17
|
+
info: "rgb(52,211,153)",
|
|
18
|
+
warning: "rgb(251,191,36)",
|
|
19
|
+
error: "rgb(248,113,113)",
|
|
20
|
+
fatal: "rgb(220,38,38)",
|
|
21
|
+
category: "rgb(100,116,139)",
|
|
22
|
+
message: "rgb(148,163,184)",
|
|
23
|
+
timestamp: "rgb(100,116,139)"
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* ANSI style codes
|
|
27
|
+
*/
|
|
28
|
+
const styles = {
|
|
29
|
+
reset: RESET,
|
|
30
|
+
bold: "\x1B[1m",
|
|
31
|
+
dim: DIM,
|
|
32
|
+
italic: "\x1B[3m",
|
|
33
|
+
underline: "\x1B[4m",
|
|
34
|
+
strikethrough: "\x1B[9m"
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Standard ANSI colors (16-color)
|
|
38
|
+
*/
|
|
39
|
+
const ansiColors = {
|
|
40
|
+
black: "\x1B[30m",
|
|
41
|
+
red: "\x1B[31m",
|
|
42
|
+
green: "\x1B[32m",
|
|
43
|
+
yellow: "\x1B[33m",
|
|
44
|
+
blue: "\x1B[34m",
|
|
45
|
+
magenta: "\x1B[35m",
|
|
46
|
+
cyan: "\x1B[36m",
|
|
47
|
+
white: "\x1B[37m"
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Helper function to convert color to ANSI escape code
|
|
51
|
+
*/
|
|
52
|
+
function colorToAnsi(color) {
|
|
53
|
+
if (color === null) return "";
|
|
54
|
+
if (color in ansiColors) return ansiColors[color];
|
|
55
|
+
const rgbMatch = color.match(/^rgb\((\d+),(\d+),(\d+)\)$/);
|
|
56
|
+
if (rgbMatch) {
|
|
57
|
+
const [, r, g, b] = rgbMatch;
|
|
58
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
59
|
+
}
|
|
60
|
+
const hexMatch = color.match(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/);
|
|
61
|
+
if (hexMatch) {
|
|
62
|
+
let hex = hexMatch[1];
|
|
63
|
+
if (hex.length === 3) hex = hex.split("").map((c) => c + c).join("");
|
|
64
|
+
const r = parseInt(hex.substr(0, 2), 16);
|
|
65
|
+
const g = parseInt(hex.substr(2, 2), 16);
|
|
66
|
+
const b = parseInt(hex.substr(4, 2), 16);
|
|
67
|
+
return `\x1b[38;2;${r};${g};${b}m`;
|
|
68
|
+
}
|
|
69
|
+
return "";
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Helper function to convert style to ANSI escape code
|
|
73
|
+
*/
|
|
74
|
+
function styleToAnsi(style) {
|
|
75
|
+
if (style === null) return "";
|
|
76
|
+
if (Array.isArray(style)) return style.map((s) => styles[s] || "").join("");
|
|
77
|
+
return styles[style] || "";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Converts a category color map to internal patterns and sorts them by specificity.
|
|
81
|
+
* More specific (longer) prefixes come first for proper matching precedence.
|
|
82
|
+
*/
|
|
83
|
+
function prepareCategoryPatterns(categoryColorMap) {
|
|
84
|
+
const patterns = [];
|
|
85
|
+
for (const [prefix, color] of categoryColorMap) patterns.push({
|
|
86
|
+
prefix,
|
|
87
|
+
color
|
|
88
|
+
});
|
|
89
|
+
return patterns.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Matches a category against category color patterns.
|
|
93
|
+
* Returns the color of the first matching pattern, or null if no match.
|
|
94
|
+
*/
|
|
95
|
+
function matchCategoryColor(category, patterns) {
|
|
96
|
+
for (const pattern of patterns) if (categoryMatches(category, pattern.prefix)) return pattern.color;
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Checks if a category matches a prefix pattern.
|
|
101
|
+
* A category matches if it starts with all segments of the prefix.
|
|
102
|
+
*/
|
|
103
|
+
function categoryMatches(category, prefix) {
|
|
104
|
+
if (prefix.length > category.length) return false;
|
|
105
|
+
for (let i = 0; i < prefix.length; i++) if (category[i] !== prefix[i]) return false;
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Default icons for each log level
|
|
110
|
+
*/
|
|
111
|
+
const defaultIcons = {
|
|
112
|
+
trace: "🔍",
|
|
113
|
+
debug: "🐛",
|
|
114
|
+
info: "✨",
|
|
115
|
+
warning: "⚡",
|
|
116
|
+
error: "❌",
|
|
117
|
+
fatal: "💀"
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* Normalize icon spacing to ensure consistent column alignment.
|
|
121
|
+
*
|
|
122
|
+
* All icons will be padded with spaces to match the width of the widest icon,
|
|
123
|
+
* ensuring consistent prefix alignment across all log levels.
|
|
124
|
+
*
|
|
125
|
+
* @param iconMap The icon mapping to normalize
|
|
126
|
+
* @returns A new icon map with consistent spacing
|
|
127
|
+
*/
|
|
128
|
+
function normalizeIconSpacing(iconMap) {
|
|
129
|
+
const maxWidth = Math.max(...Object.values(iconMap).map((icon) => require_wcwidth.getDisplayWidth(icon)));
|
|
130
|
+
const normalizedMap = {};
|
|
131
|
+
for (const [level, icon] of Object.entries(iconMap)) {
|
|
132
|
+
const currentWidth = require_wcwidth.getDisplayWidth(icon);
|
|
133
|
+
const spacesToAdd = maxWidth - currentWidth;
|
|
134
|
+
normalizedMap[level] = icon + " ".repeat(spacesToAdd);
|
|
135
|
+
}
|
|
136
|
+
return normalizedMap;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Platform-specific inspect function. Uses Node.js `util.inspect()` which
|
|
140
|
+
* is available in both Deno and Node.js environments. For browser environments,
|
|
141
|
+
* it falls back to {@link JSON.stringify}.
|
|
142
|
+
*
|
|
143
|
+
* @param value The value to inspect.
|
|
144
|
+
* @param options The options for inspecting the value.
|
|
145
|
+
* @returns The string representation of the value.
|
|
146
|
+
*/
|
|
147
|
+
const inspect = typeof document !== "undefined" || typeof navigator !== "undefined" && navigator.product === "ReactNative" ? (v) => JSON.stringify(v) : (v, opts) => (0, node_util.inspect)(v, {
|
|
148
|
+
maxArrayLength: 10,
|
|
149
|
+
maxStringLength: 80,
|
|
150
|
+
compact: true,
|
|
151
|
+
...opts
|
|
152
|
+
});
|
|
153
|
+
/**
|
|
154
|
+
* Creates a beautiful console formatter optimized for local development.
|
|
155
|
+
*
|
|
156
|
+
* This formatter provides a Signale-inspired visual design with colorful icons,
|
|
157
|
+
* smart category truncation, dimmed styling, and perfect column alignment.
|
|
158
|
+
* It's specifically designed for development environments that support true colors
|
|
159
|
+
* and Unicode characters.
|
|
160
|
+
*
|
|
161
|
+
* The formatter features:
|
|
162
|
+
* - Emoji icons for each log level (🔍 trace, 🐛 debug, ✨ info, etc.)
|
|
163
|
+
* - True color support with rich color schemes
|
|
164
|
+
* - Intelligent category truncation for long hierarchical categories
|
|
165
|
+
* - Optional timestamp display with multiple formats
|
|
166
|
+
* - Configurable alignment and styling options
|
|
167
|
+
* - Enhanced value rendering with syntax highlighting
|
|
168
|
+
*
|
|
169
|
+
* @param options Configuration options for customizing the formatter behavior.
|
|
170
|
+
* @returns A text formatter function that can be used with LogTape sinks.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```typescript
|
|
174
|
+
* import { configure } from "@logtape/logtape";
|
|
175
|
+
* import { getConsoleSink } from "@logtape/logtape";
|
|
176
|
+
* import { getPrettyFormatter } from "@logtape/pretty";
|
|
177
|
+
*
|
|
178
|
+
* await configure({
|
|
179
|
+
* sinks: {
|
|
180
|
+
* console: getConsoleSink({
|
|
181
|
+
* formatter: getPrettyFormatter({
|
|
182
|
+
* timestamp: "time",
|
|
183
|
+
* categoryWidth: 25,
|
|
184
|
+
* icons: {
|
|
185
|
+
* info: "📘",
|
|
186
|
+
* error: "🔥"
|
|
187
|
+
* }
|
|
188
|
+
* })
|
|
189
|
+
* })
|
|
190
|
+
* }
|
|
191
|
+
* });
|
|
192
|
+
* ```
|
|
193
|
+
*
|
|
194
|
+
* @since 1.0.0
|
|
195
|
+
*/
|
|
196
|
+
function getPrettyFormatter(options = {}) {
|
|
197
|
+
const { timestamp = "none", timestampColor = "rgb(100,116,139)", timestampStyle = "dim", level: levelFormat = "full", levelColors = {}, levelStyle = "underline", icons = true, categorySeparator = "·", categoryColor = "rgb(100,116,139)", categoryColorMap = /* @__PURE__ */ new Map(), categoryStyle = ["dim", "italic"], categoryWidth = 20, categoryTruncate = "middle", messageColor = "rgb(148,163,184)", messageStyle = "dim", colors: useColors = true, align = true, inspectOptions = {}, wordWrap = false } = options;
|
|
198
|
+
const baseIconMap = icons === false ? {
|
|
199
|
+
trace: "",
|
|
200
|
+
debug: "",
|
|
201
|
+
info: "",
|
|
202
|
+
warning: "",
|
|
203
|
+
error: "",
|
|
204
|
+
fatal: ""
|
|
205
|
+
} : icons === true ? defaultIcons : {
|
|
206
|
+
...defaultIcons,
|
|
207
|
+
...icons
|
|
208
|
+
};
|
|
209
|
+
const iconMap = normalizeIconSpacing(baseIconMap);
|
|
210
|
+
const resolvedLevelColors = {
|
|
211
|
+
trace: defaultColors.trace,
|
|
212
|
+
debug: defaultColors.debug,
|
|
213
|
+
info: defaultColors.info,
|
|
214
|
+
warning: defaultColors.warning,
|
|
215
|
+
error: defaultColors.error,
|
|
216
|
+
fatal: defaultColors.fatal,
|
|
217
|
+
...levelColors
|
|
218
|
+
};
|
|
219
|
+
const formatLevel = (level) => {
|
|
220
|
+
if (typeof levelFormat === "function") return levelFormat(level);
|
|
221
|
+
switch (levelFormat) {
|
|
222
|
+
case "ABBR": return {
|
|
223
|
+
trace: "TRC",
|
|
224
|
+
debug: "DBG",
|
|
225
|
+
info: "INF",
|
|
226
|
+
warning: "WRN",
|
|
227
|
+
error: "ERR",
|
|
228
|
+
fatal: "FTL"
|
|
229
|
+
}[level];
|
|
230
|
+
case "FULL": return level.toUpperCase();
|
|
231
|
+
case "L": return {
|
|
232
|
+
trace: "T",
|
|
233
|
+
debug: "D",
|
|
234
|
+
info: "I",
|
|
235
|
+
warning: "W",
|
|
236
|
+
error: "E",
|
|
237
|
+
fatal: "F"
|
|
238
|
+
}[level];
|
|
239
|
+
case "abbr": return {
|
|
240
|
+
trace: "trc",
|
|
241
|
+
debug: "dbg",
|
|
242
|
+
info: "inf",
|
|
243
|
+
warning: "wrn",
|
|
244
|
+
error: "err",
|
|
245
|
+
fatal: "ftl"
|
|
246
|
+
}[level];
|
|
247
|
+
case "full": return level;
|
|
248
|
+
case "l": return {
|
|
249
|
+
trace: "t",
|
|
250
|
+
debug: "d",
|
|
251
|
+
info: "i",
|
|
252
|
+
warning: "w",
|
|
253
|
+
error: "e",
|
|
254
|
+
fatal: "f"
|
|
255
|
+
}[level];
|
|
256
|
+
default: return level;
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
let timestampFn = null;
|
|
260
|
+
if (timestamp === "none" || timestamp === "disabled") timestampFn = null;
|
|
261
|
+
else if (timestamp === "date-time-timezone") timestampFn = (ts) => {
|
|
262
|
+
const date = new Date(ts);
|
|
263
|
+
return date.toISOString().replace("T", " ").replace("Z", " +00:00");
|
|
264
|
+
};
|
|
265
|
+
else if (timestamp === "date-time-tz") timestampFn = (ts) => {
|
|
266
|
+
const date = new Date(ts);
|
|
267
|
+
return date.toISOString().replace("T", " ").replace("Z", " +00");
|
|
268
|
+
};
|
|
269
|
+
else if (timestamp === "date-time") timestampFn = (ts) => {
|
|
270
|
+
const date = new Date(ts);
|
|
271
|
+
return date.toISOString().replace("T", " ").replace("Z", "");
|
|
272
|
+
};
|
|
273
|
+
else if (timestamp === "time-timezone") timestampFn = (ts) => {
|
|
274
|
+
const date = new Date(ts);
|
|
275
|
+
return date.toISOString().replace(/.*T/, "").replace("Z", " +00:00");
|
|
276
|
+
};
|
|
277
|
+
else if (timestamp === "time-tz") timestampFn = (ts) => {
|
|
278
|
+
const date = new Date(ts);
|
|
279
|
+
return date.toISOString().replace(/.*T/, "").replace("Z", " +00");
|
|
280
|
+
};
|
|
281
|
+
else if (timestamp === "time") timestampFn = (ts) => {
|
|
282
|
+
const date = new Date(ts);
|
|
283
|
+
return date.toISOString().replace(/.*T/, "").replace("Z", "");
|
|
284
|
+
};
|
|
285
|
+
else if (timestamp === "date") timestampFn = (ts) => {
|
|
286
|
+
const date = new Date(ts);
|
|
287
|
+
return date.toISOString().replace(/T.*/, "");
|
|
288
|
+
};
|
|
289
|
+
else if (timestamp === "rfc3339") timestampFn = (ts) => {
|
|
290
|
+
const date = new Date(ts);
|
|
291
|
+
return date.toISOString();
|
|
292
|
+
};
|
|
293
|
+
else if (typeof timestamp === "function") timestampFn = timestamp;
|
|
294
|
+
const wordWrapEnabled = wordWrap !== false;
|
|
295
|
+
let wordWrapWidth;
|
|
296
|
+
if (typeof wordWrap === "number") wordWrapWidth = wordWrap;
|
|
297
|
+
else if (wordWrap === true) wordWrapWidth = require_terminal.getOptimalWordWrapWidth(80);
|
|
298
|
+
else wordWrapWidth = 80;
|
|
299
|
+
const categoryPatterns = prepareCategoryPatterns(categoryColorMap);
|
|
300
|
+
const allLevels = [
|
|
301
|
+
"trace",
|
|
302
|
+
"debug",
|
|
303
|
+
"info",
|
|
304
|
+
"warning",
|
|
305
|
+
"error",
|
|
306
|
+
"fatal"
|
|
307
|
+
];
|
|
308
|
+
const levelWidth = Math.max(...allLevels.map((l) => formatLevel(l).length));
|
|
309
|
+
return (record) => {
|
|
310
|
+
const icon = iconMap[record.level] || "";
|
|
311
|
+
const level = formatLevel(record.level);
|
|
312
|
+
const categoryStr = require_truncate.truncateCategory(record.category, typeof categoryWidth === "number" ? categoryWidth : 30, categorySeparator, categoryTruncate);
|
|
313
|
+
let message = "";
|
|
314
|
+
const messageColorCode = useColors ? colorToAnsi(messageColor) : "";
|
|
315
|
+
const messageStyleCode = useColors ? styleToAnsi(messageStyle) : "";
|
|
316
|
+
const messagePrefix = useColors ? `${messageStyleCode}${messageColorCode}` : "";
|
|
317
|
+
for (let i = 0; i < record.message.length; i++) if (i % 2 === 0) message += record.message[i];
|
|
318
|
+
else {
|
|
319
|
+
const value = record.message[i];
|
|
320
|
+
const inspected = inspect(value, {
|
|
321
|
+
colors: useColors,
|
|
322
|
+
...inspectOptions
|
|
323
|
+
});
|
|
324
|
+
if (inspected.includes("\n")) {
|
|
325
|
+
const lines = inspected.split("\n");
|
|
326
|
+
const formattedLines = lines.map((line, index) => {
|
|
327
|
+
if (index === 0) if (useColors && (messageColorCode || messageStyleCode)) return `${RESET}${line}${messagePrefix}`;
|
|
328
|
+
else return line;
|
|
329
|
+
else if (useColors && (messageColorCode || messageStyleCode)) return `${line}${messagePrefix}`;
|
|
330
|
+
else return line;
|
|
331
|
+
});
|
|
332
|
+
message += formattedLines.join("\n");
|
|
333
|
+
} else if (useColors && (messageColorCode || messageStyleCode)) message += `${RESET}${inspected}${messagePrefix}`;
|
|
334
|
+
else message += inspected;
|
|
335
|
+
}
|
|
336
|
+
const finalCategoryColor = useColors ? matchCategoryColor(record.category, categoryPatterns) || categoryColor : null;
|
|
337
|
+
const formattedIcon = icon;
|
|
338
|
+
let formattedLevel = level;
|
|
339
|
+
let formattedCategory = categoryStr;
|
|
340
|
+
let formattedMessage = message;
|
|
341
|
+
let formattedTimestamp = "";
|
|
342
|
+
if (useColors) {
|
|
343
|
+
const levelColorCode = colorToAnsi(resolvedLevelColors[record.level]);
|
|
344
|
+
const levelStyleCode = styleToAnsi(levelStyle);
|
|
345
|
+
formattedLevel = `${levelStyleCode}${levelColorCode}${level}${RESET}`;
|
|
346
|
+
const categoryColorCode = colorToAnsi(finalCategoryColor);
|
|
347
|
+
const categoryStyleCode = styleToAnsi(categoryStyle);
|
|
348
|
+
formattedCategory = `${categoryStyleCode}${categoryColorCode}${categoryStr}${RESET}`;
|
|
349
|
+
formattedMessage = `${messagePrefix}${message}${RESET}`;
|
|
350
|
+
}
|
|
351
|
+
if (timestampFn) {
|
|
352
|
+
const ts = timestampFn(record.timestamp);
|
|
353
|
+
if (ts !== null) if (useColors) {
|
|
354
|
+
const timestampColorCode = colorToAnsi(timestampColor);
|
|
355
|
+
const timestampStyleCode = styleToAnsi(timestampStyle);
|
|
356
|
+
formattedTimestamp = `${timestampStyleCode}${timestampColorCode}${ts}${RESET} `;
|
|
357
|
+
} else formattedTimestamp = `${ts} `;
|
|
358
|
+
}
|
|
359
|
+
if (align) {
|
|
360
|
+
const levelColorLength = useColors ? colorToAnsi(resolvedLevelColors[record.level]).length + styleToAnsi(levelStyle).length + RESET.length : 0;
|
|
361
|
+
const categoryColorLength = useColors ? colorToAnsi(finalCategoryColor).length + styleToAnsi(categoryStyle).length + RESET.length : 0;
|
|
362
|
+
const paddedLevel = formattedLevel.padEnd(levelWidth + levelColorLength);
|
|
363
|
+
const paddedCategory = formattedCategory.padEnd((typeof categoryWidth === "number" ? categoryWidth : 30) + categoryColorLength);
|
|
364
|
+
let result = `${formattedTimestamp}${formattedIcon} ${paddedLevel} ${paddedCategory} ${formattedMessage}`;
|
|
365
|
+
if (wordWrapEnabled || message.includes("\n")) result = require_wordwrap.wrapText(result, wordWrapEnabled ? wordWrapWidth : Infinity, message);
|
|
366
|
+
return result + "\n";
|
|
367
|
+
} else {
|
|
368
|
+
let result = `${formattedTimestamp}${formattedIcon} ${formattedLevel} ${formattedCategory} ${formattedMessage}`;
|
|
369
|
+
if (wordWrapEnabled || message.includes("\n")) result = require_wordwrap.wrapText(result, wordWrapEnabled ? wordWrapWidth : Infinity, message);
|
|
370
|
+
return result + "\n";
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* A pre-configured beautiful console formatter for local development.
|
|
376
|
+
*
|
|
377
|
+
* This is a ready-to-use instance of the pretty formatter with sensible defaults
|
|
378
|
+
* for most development scenarios. It provides immediate visual enhancement to
|
|
379
|
+
* your logs without requiring any configuration.
|
|
380
|
+
*
|
|
381
|
+
* Features enabled by default:
|
|
382
|
+
* - Emoji icons for all log levels
|
|
383
|
+
* - True color support with rich color schemes
|
|
384
|
+
* - Dimmed text styling for better readability
|
|
385
|
+
* - Smart category truncation (20 characters max)
|
|
386
|
+
* - Perfect column alignment
|
|
387
|
+
* - No timestamp display (cleaner for development)
|
|
388
|
+
*
|
|
389
|
+
* For custom configuration, use {@link getPrettyFormatter} instead.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* import { configure } from "@logtape/logtape";
|
|
394
|
+
* import { getConsoleSink } from "@logtape/logtape";
|
|
395
|
+
* import { prettyFormatter } from "@logtape/pretty";
|
|
396
|
+
*
|
|
397
|
+
* await configure({
|
|
398
|
+
* sinks: {
|
|
399
|
+
* console: getConsoleSink({
|
|
400
|
+
* formatter: prettyFormatter
|
|
401
|
+
* })
|
|
402
|
+
* }
|
|
403
|
+
* });
|
|
404
|
+
* ```
|
|
405
|
+
*
|
|
406
|
+
* @since 1.0.0
|
|
407
|
+
*/
|
|
408
|
+
const prettyFormatter = getPrettyFormatter();
|
|
409
|
+
|
|
410
|
+
//#endregion
|
|
411
|
+
exports.getPrettyFormatter = getPrettyFormatter;
|
|
412
|
+
exports.prettyFormatter = prettyFormatter;
|