bare-console 6.1.0 → 6.2.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 +86 -0
- package/index.d.ts +1 -0
- package/index.js +8 -0
- package/lib/table.js +165 -0
- package/package.json +10 -4
package/README.md
CHANGED
|
@@ -23,6 +23,92 @@ console.timeEnd()
|
|
|
23
23
|
console.trace('Show me')
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
+
To install `console` as a global, require the `bare-console/global` subpath:
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
require('bare-console/global')
|
|
30
|
+
|
|
31
|
+
console.log('Hello')
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## API
|
|
35
|
+
|
|
36
|
+
#### `const console = new Console([log])`
|
|
37
|
+
|
|
38
|
+
Construct a new `Console`. By default, output is written through `bare-logger` (<https://github.com/holepunchto/bare-logger>), or `bare-system-logger` (<https://github.com/holepunchto/bare-system-logger>) on Android.
|
|
39
|
+
|
|
40
|
+
Pass a custom `log` object to redirect output:
|
|
41
|
+
|
|
42
|
+
```js
|
|
43
|
+
const Console = require('bare-console')
|
|
44
|
+
const FileLog = require('bare-file-logger')
|
|
45
|
+
|
|
46
|
+
const console = new Console(new FileLog('my-logs.txt'))
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
The `log` object implements the methods used by the console operations being called:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
log = {
|
|
53
|
+
debug(...data),
|
|
54
|
+
info(...data),
|
|
55
|
+
warn(...data),
|
|
56
|
+
error(...data),
|
|
57
|
+
clear(),
|
|
58
|
+
format(...data)
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
A minimal backend only needs the subset it intends to support; for example, `info` is sufficient for `console.log()`.
|
|
63
|
+
|
|
64
|
+
#### `console.log(...data)`
|
|
65
|
+
|
|
66
|
+
#### `console.info(...data)`
|
|
67
|
+
|
|
68
|
+
#### `console.debug(...data)`
|
|
69
|
+
|
|
70
|
+
#### `console.warn(...data)`
|
|
71
|
+
|
|
72
|
+
#### `console.error(...data)`
|
|
73
|
+
|
|
74
|
+
Forward `data` to the corresponding method on the backend. `console.log()` is an alias for `console.info()`.
|
|
75
|
+
|
|
76
|
+
#### `console.clear()`
|
|
77
|
+
|
|
78
|
+
Forward to `log.clear()`.
|
|
79
|
+
|
|
80
|
+
#### `console.time([label])`
|
|
81
|
+
|
|
82
|
+
Start a timer identified by `label` (default `'default'`). Warns if a timer with the same label is already running.
|
|
83
|
+
|
|
84
|
+
#### `console.timeLog([label[, ...data]])`
|
|
85
|
+
|
|
86
|
+
Log the elapsed time for the timer identified by `label` (default `'default'`), along with any additional `data`. Output uses milliseconds for short durations and seconds beyond one second.
|
|
87
|
+
|
|
88
|
+
#### `console.timeEnd([label])`
|
|
89
|
+
|
|
90
|
+
Log the elapsed time and remove the timer identified by `label` (default `'default'`).
|
|
91
|
+
|
|
92
|
+
#### `console.count([label])`
|
|
93
|
+
|
|
94
|
+
Increment and log the counter identified by `label` (default `'default'`).
|
|
95
|
+
|
|
96
|
+
#### `console.countReset([label])`
|
|
97
|
+
|
|
98
|
+
Remove the counter identified by `label` (default `'default'`).
|
|
99
|
+
|
|
100
|
+
#### `console.trace(...data)`
|
|
101
|
+
|
|
102
|
+
Log a stack trace prefixed with the formatted `data`.
|
|
103
|
+
|
|
104
|
+
#### `console.assert(condition, ...data)`
|
|
105
|
+
|
|
106
|
+
If `condition` is falsy, log `data` prefixed with `'Assertion failed'`. Otherwise do nothing.
|
|
107
|
+
|
|
108
|
+
#### `console.table(tabularData[, properties])`
|
|
109
|
+
|
|
110
|
+
Render `tabularData` as a table. Arrays and plain objects use an `(index)` column; `Map` and `Set` use an `(iteration index)` column with `key` and `values` (or `values` only) headers. Pass `properties` to restrict which object keys are shown as columns; the argument is ignored for `Map` and `Set`. Values that aren't tabular (primitives, `null`, functions) fall back to `console.log(tabularData)`.
|
|
111
|
+
|
|
26
112
|
## License
|
|
27
113
|
|
|
28
114
|
Apache-2.0
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const Log = require('bare-logger')
|
|
2
2
|
const SystemLog = require('bare-system-logger')
|
|
3
3
|
const hrtime = require('bare-hrtime')
|
|
4
|
+
const formatTable = require('./lib/table')
|
|
4
5
|
|
|
5
6
|
module.exports = exports = class Console {
|
|
6
7
|
constructor(log = defaultLog()) {
|
|
@@ -107,6 +108,13 @@ module.exports = exports = class Console {
|
|
|
107
108
|
|
|
108
109
|
this.error(...data)
|
|
109
110
|
}
|
|
111
|
+
|
|
112
|
+
// https://console.spec.whatwg.org/#table
|
|
113
|
+
this.table = function table(tabularData, properties) {
|
|
114
|
+
const formatted = formatTable(tabularData, properties, (value) => log.format('%o', value))
|
|
115
|
+
|
|
116
|
+
this.log(formatted !== null ? formatted : tabularData)
|
|
117
|
+
}
|
|
110
118
|
}
|
|
111
119
|
|
|
112
120
|
// For Node.js compatibility
|
package/lib/table.js
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
const type = require('bare-type')
|
|
2
|
+
|
|
3
|
+
module.exports = function formatTable(tabularData, properties, format) {
|
|
4
|
+
if (properties !== undefined && !Array.isArray(properties)) {
|
|
5
|
+
throw new TypeError("The 'properties' argument must be an array")
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
if (tabularData === null || typeof tabularData !== 'object') return null
|
|
9
|
+
|
|
10
|
+
const formatCell = (value) => format(value).replace(/\r\n|\r|\n/g, '\\n')
|
|
11
|
+
|
|
12
|
+
const t = type(tabularData)
|
|
13
|
+
|
|
14
|
+
if (t.isMap()) return renderMap(tabularData, formatCell)
|
|
15
|
+
if (t.isSet()) return renderSet(tabularData, formatCell)
|
|
16
|
+
|
|
17
|
+
const indices = Object.keys(tabularData)
|
|
18
|
+
|
|
19
|
+
if (indices.length === 0) return render(['(index)'], [])
|
|
20
|
+
|
|
21
|
+
const columns = properties !== undefined ? [...properties] : []
|
|
22
|
+
let hasValues = false
|
|
23
|
+
|
|
24
|
+
for (const index of indices) {
|
|
25
|
+
const value = tabularData[index]
|
|
26
|
+
|
|
27
|
+
if (value === null || typeof value !== 'object') {
|
|
28
|
+
hasValues = true
|
|
29
|
+
continue
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (properties === undefined) {
|
|
33
|
+
for (const key of Object.keys(value)) {
|
|
34
|
+
if (!columns.includes(key)) columns.push(key)
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const header = ['(index)', ...columns]
|
|
40
|
+
if (hasValues) header.push('values')
|
|
41
|
+
|
|
42
|
+
const rows = indices.map((index) => {
|
|
43
|
+
const value = tabularData[index]
|
|
44
|
+
const row = new Array(header.length).fill('')
|
|
45
|
+
|
|
46
|
+
row[0] = index
|
|
47
|
+
|
|
48
|
+
if (value !== null && typeof value === 'object') {
|
|
49
|
+
for (let i = 0; i < columns.length; i++) {
|
|
50
|
+
if (Object.hasOwn(value, columns[i])) {
|
|
51
|
+
row[i + 1] = formatCell(value[columns[i]])
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
} else if (hasValues) {
|
|
55
|
+
row[header.length - 1] = formatCell(value)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return row
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
return render(header, rows)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function renderMap(map, formatCell) {
|
|
65
|
+
const header = ['(iteration index)', 'key', 'values']
|
|
66
|
+
const rows = []
|
|
67
|
+
|
|
68
|
+
let i = 0
|
|
69
|
+
for (const [key, value] of map) {
|
|
70
|
+
rows.push([String(i++), formatCell(key), formatCell(value)])
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return render(header, rows)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function renderSet(set, formatCell) {
|
|
77
|
+
const header = ['(iteration index)', 'values']
|
|
78
|
+
const rows = []
|
|
79
|
+
|
|
80
|
+
let i = 0
|
|
81
|
+
for (const value of set) {
|
|
82
|
+
rows.push([String(i++), formatCell(value)])
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return render(header, rows)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function render(header, rows) {
|
|
89
|
+
const widths = header.map((h, i) => {
|
|
90
|
+
let max = stringWidth(h)
|
|
91
|
+
for (const r of rows) max = Math.max(max, stringWidth(r[i]))
|
|
92
|
+
return max
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const border = (l, m, r) => l + widths.map((w) => '─'.repeat(w + 2)).join(m) + r
|
|
96
|
+
|
|
97
|
+
const row = (cells) =>
|
|
98
|
+
'│' + cells.map((c, i) => ` ${c}${' '.repeat(widths[i] - stringWidth(c))} `).join('│') + '│'
|
|
99
|
+
|
|
100
|
+
return [
|
|
101
|
+
border('┌', '┬', '┐'),
|
|
102
|
+
row(header),
|
|
103
|
+
border('├', '┼', '┤'),
|
|
104
|
+
...rows.map(row),
|
|
105
|
+
border('└', '┴', '┘')
|
|
106
|
+
].join('\n')
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const ansi = /\x1b\[[\d;?]*[a-zA-Z]/g
|
|
110
|
+
|
|
111
|
+
function stringWidth(str) {
|
|
112
|
+
str = str.replace(ansi, '')
|
|
113
|
+
|
|
114
|
+
let width = 0
|
|
115
|
+
|
|
116
|
+
for (const char of str) {
|
|
117
|
+
const code = char.codePointAt(0)
|
|
118
|
+
|
|
119
|
+
if (isFullWidthCodePoint(code)) width += 2
|
|
120
|
+
else if (!isZeroWidthCodePoint(code)) width += 1
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return width
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function isFullWidthCodePoint(code) {
|
|
127
|
+
return (
|
|
128
|
+
code >= 0x1100 &&
|
|
129
|
+
(code <= 0x115f ||
|
|
130
|
+
code === 0x2329 ||
|
|
131
|
+
code === 0x232a ||
|
|
132
|
+
(code >= 0x2e80 && code <= 0x3247 && code !== 0x303f) ||
|
|
133
|
+
(code >= 0x3250 && code <= 0x4dbf) ||
|
|
134
|
+
(code >= 0x4e00 && code <= 0xa4c6) ||
|
|
135
|
+
(code >= 0xa960 && code <= 0xa97c) ||
|
|
136
|
+
(code >= 0xac00 && code <= 0xd7a3) ||
|
|
137
|
+
(code >= 0xf900 && code <= 0xfaff) ||
|
|
138
|
+
(code >= 0xfe10 && code <= 0xfe19) ||
|
|
139
|
+
(code >= 0xfe30 && code <= 0xfe6b) ||
|
|
140
|
+
(code >= 0xff01 && code <= 0xff60) ||
|
|
141
|
+
(code >= 0xffe0 && code <= 0xffe6) ||
|
|
142
|
+
(code >= 0x1b000 && code <= 0x1b001) ||
|
|
143
|
+
(code >= 0x1f200 && code <= 0x1f251) ||
|
|
144
|
+
(code >= 0x1f300 && code <= 0x1f64f) ||
|
|
145
|
+
(code >= 0x1f680 && code <= 0x1f6ff) ||
|
|
146
|
+
(code >= 0x1f900 && code <= 0x1f9ff) ||
|
|
147
|
+
(code >= 0x1fa70 && code <= 0x1faff) ||
|
|
148
|
+
(code >= 0x20000 && code <= 0x3fffd))
|
|
149
|
+
)
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function isZeroWidthCodePoint(code) {
|
|
153
|
+
return (
|
|
154
|
+
code <= 0x1f ||
|
|
155
|
+
(code >= 0x7f && code <= 0x9f) ||
|
|
156
|
+
(code >= 0x300 && code <= 0x36f) ||
|
|
157
|
+
(code >= 0x200b && code <= 0x200f) ||
|
|
158
|
+
(code >= 0x20d0 && code <= 0x20ff) ||
|
|
159
|
+
(code >= 0xfe00 && code <= 0xfe0f) ||
|
|
160
|
+
(code >= 0xfe20 && code <= 0xfe2f) ||
|
|
161
|
+
code === 0x200d ||
|
|
162
|
+
(code >= 0xfff9 && code <= 0xfffb) ||
|
|
163
|
+
(code >= 0xe0100 && code <= 0xe01ef)
|
|
164
|
+
)
|
|
165
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bare-console",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"description": "WHATWG debugging console for JavaScript",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./package": "./package.json",
|
|
@@ -17,10 +17,13 @@
|
|
|
17
17
|
"index.js",
|
|
18
18
|
"index.d.ts",
|
|
19
19
|
"global.js",
|
|
20
|
-
"global.d.ts"
|
|
20
|
+
"global.d.ts",
|
|
21
|
+
"lib"
|
|
21
22
|
],
|
|
22
23
|
"scripts": {
|
|
23
|
-
"
|
|
24
|
+
"format": "prettier --write . && lunte --fix",
|
|
25
|
+
"lint": "prettier --check . && lunte",
|
|
26
|
+
"test": "brittle-bare --coverage test.js"
|
|
24
27
|
},
|
|
25
28
|
"repository": {
|
|
26
29
|
"type": "git",
|
|
@@ -33,12 +36,15 @@
|
|
|
33
36
|
},
|
|
34
37
|
"homepage": "https://github.com/holepunchto/bare-console#readme",
|
|
35
38
|
"dependencies": {
|
|
39
|
+
"bare-format": "^1.0.2",
|
|
36
40
|
"bare-hrtime": "^2.0.0",
|
|
37
41
|
"bare-logger": "^2.0.0",
|
|
38
|
-
"bare-system-logger": "^1.0.2"
|
|
42
|
+
"bare-system-logger": "^1.0.2",
|
|
43
|
+
"bare-type": "^1.1.0"
|
|
39
44
|
},
|
|
40
45
|
"devDependencies": {
|
|
41
46
|
"brittle": "^3.1.1",
|
|
47
|
+
"lunte": "^1.8.0",
|
|
42
48
|
"prettier": "^3.3.3",
|
|
43
49
|
"prettier-config-holepunch": "^2.0.0"
|
|
44
50
|
}
|