@innei/pretty-logger-core 0.3.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/consola/consola.ts +409 -0
- package/consola/constants.ts +109 -0
- package/consola/core.ts +2 -0
- package/consola/index.ts +50 -0
- package/consola/reporters/basic.ts +74 -0
- package/consola/reporters/browser.ts +70 -0
- package/consola/reporters/fancy.ts +152 -0
- package/consola/reporters/file.ts +126 -0
- package/consola/reporters/index.ts +6 -0
- package/consola/reporters/logger.ts +31 -0
- package/consola/reporters/subscriber.ts +30 -0
- package/consola/shared.ts +6 -0
- package/consola/types.ts +60 -0
- package/consola/utils/box.ts +320 -0
- package/consola/utils/color.ts +132 -0
- package/consola/utils/error.ts +12 -0
- package/consola/utils/log.ts +22 -0
- package/consola/utils/stream.ts +9 -0
- package/consola/utils/string.ts +64 -0
- package/consola/utils/tester.ts +16 -0
- package/consola/utils.ts +9 -0
- package/consola.instance.ts +36 -0
- package/dist/index.d.mts +190 -0
- package/dist/index.d.ts +190 -0
- package/dist/index.js +1105 -0
- package/dist/index.mjs +1054 -0
- package/index.ts +3 -0
- package/package.json +23 -0
- package/tool.util.ts +29 -0
- package/tsup.config.ts +9 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { getColor } from './color'
|
|
2
|
+
import { stripAnsi } from './string'
|
|
3
|
+
|
|
4
|
+
export type BoxBorderStyle = {
|
|
5
|
+
/**
|
|
6
|
+
* Top left corner
|
|
7
|
+
* @example `┌`
|
|
8
|
+
* @example `╔`
|
|
9
|
+
* @example `╓`
|
|
10
|
+
*/
|
|
11
|
+
tl: string
|
|
12
|
+
/**
|
|
13
|
+
* Top right corner
|
|
14
|
+
* @example `┐`
|
|
15
|
+
* @example `╗`
|
|
16
|
+
* @example `╖`
|
|
17
|
+
*/
|
|
18
|
+
tr: string
|
|
19
|
+
/**
|
|
20
|
+
* Bottom left corner
|
|
21
|
+
* @example `└`
|
|
22
|
+
* @example `╚`
|
|
23
|
+
* @example `╙`
|
|
24
|
+
*/
|
|
25
|
+
bl: string
|
|
26
|
+
/**
|
|
27
|
+
* Bottom right corner
|
|
28
|
+
* @example `┘`
|
|
29
|
+
* @example `╝`
|
|
30
|
+
* @example `╜`
|
|
31
|
+
*/
|
|
32
|
+
br: string
|
|
33
|
+
/**
|
|
34
|
+
* Horizontal line
|
|
35
|
+
* @example `─`
|
|
36
|
+
* @example `═`
|
|
37
|
+
* @example `─`
|
|
38
|
+
*/
|
|
39
|
+
h: string
|
|
40
|
+
/**
|
|
41
|
+
* Vertical line
|
|
42
|
+
* @example `│`
|
|
43
|
+
* @example `║`
|
|
44
|
+
* @example `║`
|
|
45
|
+
*/
|
|
46
|
+
v: string
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const boxStylePresets: Record<string, BoxBorderStyle> = {
|
|
50
|
+
solid: {
|
|
51
|
+
tl: '┌',
|
|
52
|
+
tr: '┐',
|
|
53
|
+
bl: '└',
|
|
54
|
+
br: '┘',
|
|
55
|
+
h: '─',
|
|
56
|
+
v: '│',
|
|
57
|
+
},
|
|
58
|
+
double: {
|
|
59
|
+
tl: '╔',
|
|
60
|
+
tr: '╗',
|
|
61
|
+
bl: '╚',
|
|
62
|
+
br: '╝',
|
|
63
|
+
h: '═',
|
|
64
|
+
v: '║',
|
|
65
|
+
},
|
|
66
|
+
doubleSingle: {
|
|
67
|
+
tl: '╓',
|
|
68
|
+
tr: '╖',
|
|
69
|
+
bl: '╙',
|
|
70
|
+
br: '╜',
|
|
71
|
+
h: '─',
|
|
72
|
+
v: '║',
|
|
73
|
+
},
|
|
74
|
+
doubleSingleRounded: {
|
|
75
|
+
tl: '╭',
|
|
76
|
+
tr: '╮',
|
|
77
|
+
bl: '╰',
|
|
78
|
+
br: '╯',
|
|
79
|
+
h: '─',
|
|
80
|
+
v: '║',
|
|
81
|
+
},
|
|
82
|
+
singleThick: {
|
|
83
|
+
tl: '┏',
|
|
84
|
+
tr: '┓',
|
|
85
|
+
bl: '┗',
|
|
86
|
+
br: '┛',
|
|
87
|
+
h: '━',
|
|
88
|
+
v: '┃',
|
|
89
|
+
},
|
|
90
|
+
singleDouble: {
|
|
91
|
+
tl: '╒',
|
|
92
|
+
tr: '╕',
|
|
93
|
+
bl: '╘',
|
|
94
|
+
br: '╛',
|
|
95
|
+
h: '═',
|
|
96
|
+
v: '│',
|
|
97
|
+
},
|
|
98
|
+
singleDoubleRounded: {
|
|
99
|
+
tl: '╭',
|
|
100
|
+
tr: '╮',
|
|
101
|
+
bl: '╰',
|
|
102
|
+
br: '╯',
|
|
103
|
+
h: '═',
|
|
104
|
+
v: '│',
|
|
105
|
+
},
|
|
106
|
+
rounded: {
|
|
107
|
+
tl: '╭',
|
|
108
|
+
tr: '╮',
|
|
109
|
+
bl: '╰',
|
|
110
|
+
br: '╯',
|
|
111
|
+
h: '─',
|
|
112
|
+
v: '│',
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export type BoxStyle = {
|
|
117
|
+
/**
|
|
118
|
+
* The border color
|
|
119
|
+
* @default 'white'
|
|
120
|
+
*/
|
|
121
|
+
borderColor:
|
|
122
|
+
| 'black'
|
|
123
|
+
| 'red'
|
|
124
|
+
| 'green'
|
|
125
|
+
| 'yellow'
|
|
126
|
+
| 'blue'
|
|
127
|
+
| 'magenta'
|
|
128
|
+
| 'cyan'
|
|
129
|
+
| 'white'
|
|
130
|
+
| 'gray'
|
|
131
|
+
| 'blackBright'
|
|
132
|
+
| 'redBright'
|
|
133
|
+
| 'greenBright'
|
|
134
|
+
| 'yellowBright'
|
|
135
|
+
| 'blueBright'
|
|
136
|
+
| 'magentaBright'
|
|
137
|
+
| 'cyanBright'
|
|
138
|
+
| 'whiteBright'
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* The border style
|
|
142
|
+
* @default 'solid'
|
|
143
|
+
* @example 'single-double-rounded'
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* {
|
|
147
|
+
* tl: '┌',
|
|
148
|
+
* tr: '┐',
|
|
149
|
+
* bl: '└',
|
|
150
|
+
* br: '┘',
|
|
151
|
+
* h: '─',
|
|
152
|
+
* v: '│',
|
|
153
|
+
* }
|
|
154
|
+
* ```
|
|
155
|
+
*/
|
|
156
|
+
borderStyle: BoxBorderStyle | keyof typeof boxStylePresets
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The vertical alignment of the text
|
|
160
|
+
* @default 'center'
|
|
161
|
+
*/
|
|
162
|
+
valign: 'top' | 'center' | 'bottom'
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The padding of the box
|
|
166
|
+
* @default 2
|
|
167
|
+
*/
|
|
168
|
+
padding: number
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* The left margin of the box
|
|
172
|
+
* @default 1
|
|
173
|
+
*/
|
|
174
|
+
marginLeft: number
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The top margin of the box
|
|
178
|
+
* @default 1
|
|
179
|
+
*/
|
|
180
|
+
marginTop: number
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* The top margin of the box
|
|
184
|
+
* @default 1
|
|
185
|
+
*/
|
|
186
|
+
marginBottom: number
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The border options of the box
|
|
191
|
+
*/
|
|
192
|
+
export type BoxOpts = {
|
|
193
|
+
/**
|
|
194
|
+
* Title that will be displayed on top of the box
|
|
195
|
+
* @example 'Hello World'
|
|
196
|
+
* @example 'Hello {name}'
|
|
197
|
+
*/
|
|
198
|
+
title?: string
|
|
199
|
+
|
|
200
|
+
style?: Partial<BoxStyle>
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const defaultStyle: BoxStyle = {
|
|
204
|
+
borderColor: 'white',
|
|
205
|
+
borderStyle: 'rounded',
|
|
206
|
+
valign: 'center',
|
|
207
|
+
padding: 2,
|
|
208
|
+
marginLeft: 1,
|
|
209
|
+
marginTop: 1,
|
|
210
|
+
marginBottom: 1,
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export function box(text: string, _opts: BoxOpts = {}) {
|
|
214
|
+
const opts = {
|
|
215
|
+
..._opts,
|
|
216
|
+
style: {
|
|
217
|
+
...defaultStyle,
|
|
218
|
+
..._opts.style,
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Split the text into lines
|
|
223
|
+
const textLines = text.split('\n')
|
|
224
|
+
|
|
225
|
+
// Create the box
|
|
226
|
+
const boxLines = []
|
|
227
|
+
|
|
228
|
+
// Get the characters for the box and colorize
|
|
229
|
+
const _color = getColor(opts.style.borderColor)
|
|
230
|
+
const borderStyle = {
|
|
231
|
+
...(typeof opts.style.borderStyle === 'string'
|
|
232
|
+
? boxStylePresets[
|
|
233
|
+
opts.style.borderStyle as keyof typeof boxStylePresets
|
|
234
|
+
] || boxStylePresets.solid
|
|
235
|
+
: opts.style.borderStyle),
|
|
236
|
+
}
|
|
237
|
+
if (_color) {
|
|
238
|
+
for (const key in borderStyle) {
|
|
239
|
+
borderStyle[key as keyof typeof borderStyle] = _color(
|
|
240
|
+
borderStyle[key as keyof typeof borderStyle],
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Calculate the width and height of the box
|
|
246
|
+
const paddingOffset =
|
|
247
|
+
opts.style.padding % 2 === 0 ? opts.style.padding : opts.style.padding + 1
|
|
248
|
+
const height = textLines.length + paddingOffset
|
|
249
|
+
const width =
|
|
250
|
+
Math.max(...textLines.map((line) => line.length)) + paddingOffset
|
|
251
|
+
const widthOffset = width + paddingOffset
|
|
252
|
+
|
|
253
|
+
const leftSpace =
|
|
254
|
+
opts.style.marginLeft > 0 ? ' '.repeat(opts.style.marginLeft) : ''
|
|
255
|
+
|
|
256
|
+
// Top line
|
|
257
|
+
if (opts.style.marginTop > 0) {
|
|
258
|
+
boxLines.push(''.repeat(opts.style.marginTop))
|
|
259
|
+
}
|
|
260
|
+
// Include the title if it exists with borders
|
|
261
|
+
if (opts.title) {
|
|
262
|
+
const left = borderStyle.h.repeat(
|
|
263
|
+
Math.floor((width - stripAnsi(opts.title).length) / 2),
|
|
264
|
+
)
|
|
265
|
+
const right = borderStyle.h.repeat(
|
|
266
|
+
width -
|
|
267
|
+
stripAnsi(opts.title).length -
|
|
268
|
+
stripAnsi(left).length +
|
|
269
|
+
paddingOffset,
|
|
270
|
+
)
|
|
271
|
+
boxLines.push(
|
|
272
|
+
`${leftSpace}${borderStyle.tl}${left}${opts.title}${right}${borderStyle.tr}`,
|
|
273
|
+
)
|
|
274
|
+
} else {
|
|
275
|
+
boxLines.push(
|
|
276
|
+
`${leftSpace}${borderStyle.tl}${borderStyle.h.repeat(widthOffset)}${
|
|
277
|
+
borderStyle.tr
|
|
278
|
+
}`,
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Middle lines
|
|
283
|
+
const valignOffset =
|
|
284
|
+
opts.style.valign === 'center'
|
|
285
|
+
? Math.floor((height - textLines.length) / 2)
|
|
286
|
+
: opts.style.valign === 'top'
|
|
287
|
+
? height - textLines.length - paddingOffset
|
|
288
|
+
: height - textLines.length
|
|
289
|
+
|
|
290
|
+
for (let i = 0; i < height; i++) {
|
|
291
|
+
if (i < valignOffset || i >= valignOffset + textLines.length) {
|
|
292
|
+
// Empty line
|
|
293
|
+
boxLines.push(
|
|
294
|
+
`${leftSpace}${borderStyle.v}${' '.repeat(widthOffset)}${
|
|
295
|
+
borderStyle.v
|
|
296
|
+
}`,
|
|
297
|
+
)
|
|
298
|
+
} else {
|
|
299
|
+
// Text line
|
|
300
|
+
const line = textLines[i - valignOffset]
|
|
301
|
+
const left = ' '.repeat(paddingOffset)
|
|
302
|
+
const right = ' '.repeat(width - stripAnsi(line).length)
|
|
303
|
+
boxLines.push(
|
|
304
|
+
`${leftSpace}${borderStyle.v}${left}${line}${right}${borderStyle.v}`,
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Bottom line
|
|
310
|
+
boxLines.push(
|
|
311
|
+
`${leftSpace}${borderStyle.bl}${borderStyle.h.repeat(widthOffset)}${
|
|
312
|
+
borderStyle.br
|
|
313
|
+
}`,
|
|
314
|
+
)
|
|
315
|
+
if (opts.style.marginBottom > 0) {
|
|
316
|
+
boxLines.push(''.repeat(opts.style.marginBottom))
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
return boxLines.join('\n')
|
|
320
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Based on https://github.com/jorgebucaran/colorette
|
|
3
|
+
* Read LICENSE file for more information
|
|
4
|
+
* https://github.com/jorgebucaran/colorette/blob/20fc196d07d0f87c61e0256eadd7831c79b24108/index.js
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as tty from 'node:tty'
|
|
8
|
+
|
|
9
|
+
// TODO: Migrate to std-env
|
|
10
|
+
const {
|
|
11
|
+
env = {},
|
|
12
|
+
argv = [],
|
|
13
|
+
platform = '',
|
|
14
|
+
} = typeof process === 'undefined' ? {} : process
|
|
15
|
+
const isDisabled = 'NO_COLOR' in env || argv.includes('--no-color')
|
|
16
|
+
const isForced = 'FORCE_COLOR' in env || argv.includes('--color')
|
|
17
|
+
const isWindows = platform === 'win32'
|
|
18
|
+
const isDumbTerminal = env.TERM === 'dumb'
|
|
19
|
+
const isCompatibleTerminal =
|
|
20
|
+
tty && tty.isatty && tty.isatty(1) && env.TERM && !isDumbTerminal
|
|
21
|
+
const isCI =
|
|
22
|
+
'CI' in env &&
|
|
23
|
+
('GITHUB_ACTIONS' in env || 'GITLAB_CI' in env || 'CIRCLECI' in env)
|
|
24
|
+
const isColorSupported =
|
|
25
|
+
!isDisabled &&
|
|
26
|
+
(isForced || (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI)
|
|
27
|
+
|
|
28
|
+
function replaceClose(
|
|
29
|
+
index: number,
|
|
30
|
+
string: string,
|
|
31
|
+
close: string,
|
|
32
|
+
replace: string,
|
|
33
|
+
head = string.slice(0, Math.max(0, index)) + replace,
|
|
34
|
+
tail = string.slice(Math.max(0, index + close.length)),
|
|
35
|
+
next = tail.indexOf(close),
|
|
36
|
+
): string {
|
|
37
|
+
return head + (next < 0 ? tail : replaceClose(next, tail, close, replace))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function clearBleed(
|
|
41
|
+
index: number,
|
|
42
|
+
string: string,
|
|
43
|
+
open: string,
|
|
44
|
+
close: string,
|
|
45
|
+
replace: string,
|
|
46
|
+
) {
|
|
47
|
+
return index < 0
|
|
48
|
+
? open + string + close
|
|
49
|
+
: open + replaceClose(index, string, close, replace) + close
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function filterEmpty(
|
|
53
|
+
open: string,
|
|
54
|
+
close: string,
|
|
55
|
+
replace = open,
|
|
56
|
+
at = open.length + 1,
|
|
57
|
+
) {
|
|
58
|
+
return (string: string) =>
|
|
59
|
+
string || !(string === '' || string === undefined)
|
|
60
|
+
? clearBleed(`${string}`.indexOf(close, at), string, open, close, replace)
|
|
61
|
+
: ''
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function init(open: number, close: number, replace?: string) {
|
|
65
|
+
return filterEmpty(`\u001B[${open}m`, `\u001B[${close}m`, replace)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const colorDefs = {
|
|
69
|
+
reset: init(0, 0),
|
|
70
|
+
bold: init(1, 22, '\u001B[22m\u001B[1m'),
|
|
71
|
+
dim: init(2, 22, '\u001B[22m\u001B[2m'),
|
|
72
|
+
italic: init(3, 23),
|
|
73
|
+
underline: init(4, 24),
|
|
74
|
+
inverse: init(7, 27),
|
|
75
|
+
hidden: init(8, 28),
|
|
76
|
+
strikethrough: init(9, 29),
|
|
77
|
+
black: init(30, 39),
|
|
78
|
+
red: init(31, 39),
|
|
79
|
+
green: init(32, 39),
|
|
80
|
+
yellow: init(33, 39),
|
|
81
|
+
blue: init(34, 39),
|
|
82
|
+
magenta: init(35, 39),
|
|
83
|
+
cyan: init(36, 39),
|
|
84
|
+
white: init(37, 39),
|
|
85
|
+
gray: init(90, 39),
|
|
86
|
+
bgBlack: init(40, 49),
|
|
87
|
+
bgRed: init(41, 49),
|
|
88
|
+
bgGreen: init(42, 49),
|
|
89
|
+
bgYellow: init(43, 49),
|
|
90
|
+
bgBlue: init(44, 49),
|
|
91
|
+
bgMagenta: init(45, 49),
|
|
92
|
+
bgCyan: init(46, 49),
|
|
93
|
+
bgWhite: init(47, 49),
|
|
94
|
+
blackBright: init(90, 39),
|
|
95
|
+
redBright: init(91, 39),
|
|
96
|
+
greenBright: init(92, 39),
|
|
97
|
+
yellowBright: init(93, 39),
|
|
98
|
+
blueBright: init(94, 39),
|
|
99
|
+
magentaBright: init(95, 39),
|
|
100
|
+
cyanBright: init(96, 39),
|
|
101
|
+
whiteBright: init(97, 39),
|
|
102
|
+
bgBlackBright: init(100, 49),
|
|
103
|
+
bgRedBright: init(101, 49),
|
|
104
|
+
bgGreenBright: init(102, 49),
|
|
105
|
+
bgYellowBright: init(103, 49),
|
|
106
|
+
bgBlueBright: init(104, 49),
|
|
107
|
+
bgMagentaBright: init(105, 49),
|
|
108
|
+
bgCyanBright: init(106, 49),
|
|
109
|
+
bgWhiteBright: init(107, 49),
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type ColorName = keyof typeof colorDefs
|
|
113
|
+
export type ColorFunction = (text: string | number) => string
|
|
114
|
+
|
|
115
|
+
function createColors(useColor = isColorSupported) {
|
|
116
|
+
return useColor
|
|
117
|
+
? colorDefs
|
|
118
|
+
: Object.fromEntries(Object.keys(colorDefs).map((key) => [key, String]))
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export const colors = createColors() as Record<ColorName, ColorFunction>
|
|
122
|
+
|
|
123
|
+
export function getColor(
|
|
124
|
+
color: ColorName,
|
|
125
|
+
fallback: ColorName = 'reset',
|
|
126
|
+
): ColorFunction {
|
|
127
|
+
return colors[color] || colors[fallback]
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function colorize(color: ColorName, text: string | number): string {
|
|
131
|
+
return getColor(color)(text)
|
|
132
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function isPlainObject(obj: any) {
|
|
2
|
+
return Object.prototype.toString.call(obj) === '[object Object]'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isLogObj(arg: any) {
|
|
6
|
+
// Should be plain object
|
|
7
|
+
if (!isPlainObject(arg)) {
|
|
8
|
+
return false
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Should contains either 'message' or 'args' field
|
|
12
|
+
if (!arg.message && !arg.args) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Handle non-standard error objects
|
|
17
|
+
if (arg.stack) {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return true
|
|
22
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
const ansiRegex = [
|
|
2
|
+
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
|
3
|
+
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))',
|
|
4
|
+
].join('|')
|
|
5
|
+
|
|
6
|
+
export function stripAnsi(text: string) {
|
|
7
|
+
return text.replace(new RegExp(ansiRegex, 'g'), '')
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function centerAlign(str: string, len: number, space = ' ') {
|
|
11
|
+
const free = len - str.length
|
|
12
|
+
if (free <= 0) {
|
|
13
|
+
return str
|
|
14
|
+
}
|
|
15
|
+
const freeLeft = Math.floor(free / 2)
|
|
16
|
+
let _str = ''
|
|
17
|
+
for (let i = 0; i < len; i++) {
|
|
18
|
+
_str +=
|
|
19
|
+
i < freeLeft || i >= freeLeft + str.length ? space : str[i - freeLeft]
|
|
20
|
+
}
|
|
21
|
+
return _str
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function rightAlign(str: string, len: number, space = ' ') {
|
|
25
|
+
const free = len - str.length
|
|
26
|
+
if (free <= 0) {
|
|
27
|
+
return str
|
|
28
|
+
}
|
|
29
|
+
let _str = ''
|
|
30
|
+
for (let i = 0; i < len; i++) {
|
|
31
|
+
_str += i < free ? space : str[i - free]
|
|
32
|
+
}
|
|
33
|
+
return _str
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function leftAlign(str: string, len: number, space = ' ') {
|
|
37
|
+
let _str = ''
|
|
38
|
+
for (let i = 0; i < len; i++) {
|
|
39
|
+
_str += i < str.length ? str[i] : space
|
|
40
|
+
}
|
|
41
|
+
return _str
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function align(
|
|
45
|
+
alignment: 'left' | 'right' | 'center',
|
|
46
|
+
str: string,
|
|
47
|
+
len: number,
|
|
48
|
+
space = ' ',
|
|
49
|
+
) {
|
|
50
|
+
switch (alignment) {
|
|
51
|
+
case 'left': {
|
|
52
|
+
return leftAlign(str, len, space)
|
|
53
|
+
}
|
|
54
|
+
case 'right': {
|
|
55
|
+
return rightAlign(str, len, space)
|
|
56
|
+
}
|
|
57
|
+
case 'center': {
|
|
58
|
+
return centerAlign(str, len, space)
|
|
59
|
+
}
|
|
60
|
+
default: {
|
|
61
|
+
return str
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export function isUnicodeSupported() {
|
|
2
|
+
if (process.platform !== 'win32') {
|
|
3
|
+
return process.env.TERM !== 'linux' // Linux console (kernel)
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
return (
|
|
7
|
+
Boolean(process.env.WT_SESSION) || // Windows Terminal
|
|
8
|
+
Boolean(process.env.TERMINUS_SUBLIME) || // Terminus (<0.2.27)
|
|
9
|
+
process.env.ConEmuTask === '{cmd::Cmder}' || // ConEmu and cmder
|
|
10
|
+
process.env.TERM_PROGRAM === 'Terminus-Sublime' ||
|
|
11
|
+
process.env.TERM_PROGRAM === 'vscode' ||
|
|
12
|
+
process.env.TERM === 'xterm-256color' ||
|
|
13
|
+
process.env.TERM === 'alacritty' ||
|
|
14
|
+
process.env.TERMINAL_EMULATOR === 'JetBrains-JediTerm'
|
|
15
|
+
)
|
|
16
|
+
}
|
package/consola/utils.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { isDevelopment } from 'std-env'
|
|
2
|
+
import type { ConsolaOptions, ConsolaReporter } from './consola'
|
|
3
|
+
import type { FileReporterConfig } from './consola/reporters/file'
|
|
4
|
+
|
|
5
|
+
import { createConsola, LogLevels } from './consola'
|
|
6
|
+
import { FancyReporter } from './consola/reporters/fancy'
|
|
7
|
+
import { FileReporter } from './consola/reporters/file'
|
|
8
|
+
import {
|
|
9
|
+
SubscriberReporter,
|
|
10
|
+
wrapperSubscribers,
|
|
11
|
+
} from './consola/reporters/subscriber'
|
|
12
|
+
|
|
13
|
+
export interface LoggerConsolaOptions extends Partial<ConsolaOptions> {
|
|
14
|
+
writeToFile?: FileReporterConfig
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const createLoggerConsola = (options?: LoggerConsolaOptions) => {
|
|
18
|
+
const reporters: ConsolaReporter[] = [
|
|
19
|
+
new FancyReporter(),
|
|
20
|
+
new SubscriberReporter(),
|
|
21
|
+
]
|
|
22
|
+
if (options?.writeToFile) {
|
|
23
|
+
reporters.push(new FileReporter(options.writeToFile))
|
|
24
|
+
}
|
|
25
|
+
const consola = createConsola({
|
|
26
|
+
formatOptions: {
|
|
27
|
+
date: true,
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
reporters,
|
|
31
|
+
level: isDevelopment ? LogLevels.trace : LogLevels.info,
|
|
32
|
+
...options,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
return wrapperSubscribers(consola)
|
|
36
|
+
}
|