Skip to content

Commit 81bbaf0

Browse files
authored
Change to better show non-unist fields
Closes GH-11. Closes GH-14. Previously, all fields that were not specified by unist, but for example defined in another spec such as hast, were show rather verbosely on one line. This especially became unreadable when those fields were populated with a single node, or a list of nodes. This change makes fields more readable, by displaying them on their own line, and supports nodes or list of nodes as the values of those fields. It also streamlines the indentation a bit: previously, 3 spaces were used: now, either 2 or 4 spaces. Finally, there is now a number before each child, which shows its index. Reviewed-by: Christian Murphy <[email protected]>
1 parent b7ab151 commit 81bbaf0

File tree

4 files changed

+347
-187
lines changed

4 files changed

+347
-187
lines changed

index.js

+85-46
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict'
22

3-
var isEmpty = require('is-empty')
43
var color = require('./color')
54

65
module.exports = color ? inspect : /* istanbul ignore next */ noColor
@@ -10,6 +9,7 @@ noColor.color = inspect
109
inspect.noColor = noColor
1110
noColor.noColor = noColor
1211

12+
var bold = ansiColor(1, 22)
1313
var dim = ansiColor(2, 22)
1414
var yellow = ansiColor(33, 39)
1515
var green = ansiColor(32, 39)
@@ -21,7 +21,10 @@ var colorExpression = /(?:(?:\u001B\[)|\u009B)(?:\d{1,3})?(?:(?:;\d{0,3})*)?[A-M
2121
// we format differently.
2222
// We don’t ignore `data` though.
2323
// Also includes `name` (from xast) and `tagName` (from `hast`).
24-
var ignore = ['type', 'value', 'children', 'position', 'name', 'tagName']
24+
var ignore = ['type', 'value', 'children', 'position']
25+
var ignoreString = ['name', 'tagName']
26+
27+
var dataOnly = ['data', 'attributes', 'properties']
2528

2629
// Inspects a node, without using color.
2730
function noColor(node) {
@@ -37,103 +40,139 @@ function inspect(node, options) {
3740
showPositions = true
3841
}
3942

40-
return inspectValue(node, '')
43+
return inspectValue(node)
4144

42-
function inspectValue(node, pad) {
45+
function inspectValue(node) {
4346
if (node && Boolean(node.length) && typeof node === 'object') {
44-
return inspectAll(node, pad)
47+
return inspectNodes(node)
4548
}
4649

4750
if (node && node.type) {
48-
return inspectTree(node, pad)
51+
return inspectTree(node)
4952
}
5053

51-
return inspectNonTree(node, pad)
54+
return inspectNonTree(node)
5255
}
5356

54-
function inspectNonTree(value, pad) {
55-
return formatNesting(pad) + String(value)
57+
function inspectNonTree(value) {
58+
return JSON.stringify(value)
5659
}
5760

58-
function inspectAll(nodes, pad) {
61+
function inspectNodes(nodes) {
5962
var length = nodes.length
6063
var index = -1
6164
var result = []
6265
var node
6366
var tail
67+
var value
6468

6569
while (++index < length) {
6670
node = nodes[index]
6771
tail = index === length - 1
6872

73+
value =
74+
dim((tail ? '└' : '├') + '─' + index) +
75+
' ' +
76+
indent(inspectValue(node), (tail ? ' ' : dim('│')) + ' ', true)
77+
78+
result.push(value)
79+
}
80+
81+
return result.join('\n')
82+
}
83+
84+
function inspectFields(object) {
85+
var nonEmpty = object.children && object.children.length
86+
var result = []
87+
var key
88+
var value
89+
var formatted
90+
91+
for (key in object) {
92+
value = object[key]
93+
94+
if (
95+
value === undefined ||
96+
ignore.indexOf(key) !== -1 ||
97+
(ignoreString.indexOf(key) !== -1 && typeof value === 'string')
98+
) {
99+
continue
100+
}
101+
102+
if (
103+
value &&
104+
typeof value === 'object' &&
105+
typeof value.type === 'string' &&
106+
dataOnly.indexOf(key) === -1
107+
) {
108+
formatted = inspectTree(value)
109+
} else if (
110+
Array.isArray(value) &&
111+
value[0] &&
112+
typeof value[0] === 'object' &&
113+
typeof value[0].type === 'string'
114+
) {
115+
formatted = '\n' + inspectNodes(value)
116+
} else {
117+
formatted = inspectNonTree(value)
118+
}
119+
69120
result.push(
70-
formatNesting(pad + (tail ? '└' : '├') + '─ '),
71-
inspectValue(node, pad + (tail ? ' ' : '│') + ' '),
72-
tail ? '' : '\n'
121+
key + dim(':') + (/\s/.test(formatted.charAt(0)) ? '' : ' ') + formatted
73122
)
74123
}
75124

76-
return result.join('')
125+
return indent(result.join('\n'), (nonEmpty ? dim('│') : ' ') + ' ')
77126
}
78127

79128
function inspectTree(node, pad) {
80-
var result = formatNode(node, pad)
81-
var content = inspectAll(node.children || [], pad)
82-
return content ? result + '\n' + content : result
83-
}
84-
85-
// Colored nesting formatter.
86-
function formatNesting(value) {
87-
return value ? dim(value) : ''
129+
var result = [formatNode(node, pad)]
130+
var fields = inspectFields(node)
131+
var content = inspectNodes(node.children || [])
132+
if (fields) result.push(fields)
133+
if (content) result.push(content)
134+
return result.join('\n')
88135
}
89136

90137
// Colored node formatter.
91138
function formatNode(node) {
92-
var result = [node.type]
139+
var result = [bold(node.type)]
93140
var kind = node.tagName || node.name
94141
var position = node.position || {}
95142
var location = showPositions
96143
? stringifyPosition(position.start, position.end)
97144
: ''
98-
var attributes = []
99-
var key
100-
var value
101145

102-
if (kind) {
146+
if (typeof kind === 'string') {
103147
result.push('<', kind, '>')
104148
}
105149

106150
if (node.children) {
107151
result.push(dim('['), yellow(node.children.length), dim(']'))
108152
} else if (typeof node.value === 'string') {
109-
result.push(dim(': '), green(JSON.stringify(node.value)))
153+
result.push(' ', green(inspectNonTree(node.value, '')))
110154
}
111155

112156
if (location) {
113-
result.push(' (', location, ')')
157+
result.push(' ', dim('('), location, dim(')'))
114158
}
115159

116-
for (key in node) {
117-
value = node[key]
118-
119-
if (
120-
ignore.indexOf(key) !== -1 ||
121-
value === null ||
122-
value === undefined ||
123-
(typeof value === 'object' && isEmpty(value))
124-
) {
125-
continue
126-
}
160+
return result.join('')
161+
}
162+
}
127163

128-
attributes.push('[' + key + '=' + JSON.stringify(value) + ']')
129-
}
164+
function indent(value, indentation, ignoreFirst) {
165+
var lines = value.split('\n')
166+
var index = ignoreFirst ? 0 : -1
167+
var length = lines.length
130168

131-
if (attributes.length !== 0) {
132-
result = result.concat(' ', attributes)
133-
}
169+
if (value === '') return ''
134170

135-
return result.join('')
171+
while (++index < length) {
172+
lines[index] = indentation + lines[index]
136173
}
174+
175+
return lines.join('\n')
137176
}
138177

139178
// Compile a position.

package.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,13 @@
3636
"./color.js": "./color-browser.js"
3737
},
3838
"types": "types/index.d.ts",
39-
"dependencies": {
40-
"is-empty": "^1.0.0"
41-
},
39+
"dependencies": {},
4240
"devDependencies": {
4341
"@types/unist": "^2.0.3",
4442
"browserify": "^16.0.0",
4543
"chalk": "^4.0.0",
4644
"dtslint": "^3.0.0",
45+
"hastscript": "^5.0.0",
4746
"nyc": "^15.0.0",
4847
"prettier": "^2.0.0",
4948
"remark-cli": "^8.0.0",
@@ -52,6 +51,8 @@
5251
"strip-ansi": "^6.0.0",
5352
"tape": "^5.0.0",
5453
"tinyify": "^2.0.0",
54+
"unist-builder": "^2.0.0",
55+
"xastscript": "^1.0.0",
5556
"xast-util-from-xml": "^1.0.0",
5657
"xo": "^0.29.0"
5758
},

readme.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ Yields:
4040

4141
```text
4242
root[2]
43-
├─ literal: "1"
44-
└─ parent[3]
45-
├─ void [id="a"]
46-
├─ literal: "2"
47-
└─ node[0] [id="b"]
43+
├─0 literal "1"
44+
└─1 parent[3]
45+
├─0 void
46+
│ id: "a"
47+
├─1 literal "2"
48+
└─2 node[0]
49+
id: "b"
4850
```
4951

5052
## API

0 commit comments

Comments
 (0)