Skip to content

Commit fc266f3

Browse files
committed
Add positional information, escape characters
* Add the nodes positional information to the representation; * Stringify values using `JSON.stringify` to escape all JSON escapables (`\"`, `\\`, '\/', '\b', '\f', '\n', '\r', '\t'). Closes GH-1. Thanks to @muraken720 for the initial work.
1 parent ac359de commit fc266f3

File tree

5 files changed

+266
-76
lines changed

5 files changed

+266
-76
lines changed

index.js

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,69 @@ function formatNesting(value) {
8484
return dim(value);
8585
}
8686

87+
/**
88+
* Compile a single position.
89+
*
90+
* @param {Object?} pos - Single position.
91+
* @return {Array.<string>?} - Compiled position.
92+
*/
93+
function compile(pos) {
94+
var values = [];
95+
96+
if (!pos) {
97+
return null;
98+
}
99+
100+
values = [
101+
[pos.line || 1, pos.column || 1].join(':')
102+
];
103+
104+
if ('offset' in pos) {
105+
values.push(String(pos.offset || 0));
106+
}
107+
108+
return values;
109+
}
110+
111+
/**
112+
* Compile a location.
113+
*
114+
* @param {Object?} start - Start position.
115+
* @param {Object?} end - End position.
116+
* @return {string} - Stringified position.
117+
*/
118+
function stringify(start, end) {
119+
var values = [];
120+
var positions = [];
121+
var offsets = [];
122+
123+
/** Add a position. */
124+
function add(position) {
125+
var tuple = compile(position);
126+
127+
if (tuple) {
128+
positions.push(tuple[0]);
129+
130+
if (tuple[1]) {
131+
offsets.push(tuple[1]);
132+
}
133+
}
134+
}
135+
136+
add(start);
137+
add(end)
138+
139+
if (positions.length) {
140+
values.push(positions.join('-'));
141+
}
142+
143+
if (offsets.length) {
144+
values.push(offsets.join('-'));
145+
}
146+
147+
return values.join(', ');
148+
}
149+
87150
/**
88151
* Colored node formatter.
89152
*
@@ -92,11 +155,17 @@ function formatNesting(value) {
92155
*/
93156
function formatNode(node) {
94157
var log = node.type;
158+
var location = node.position || {};
159+
var position = stringify(location.start, location.end);
95160

96161
if (node.children && node.children.length) {
97162
log += dim('[') + yellow(node.children.length) + dim(']');
98163
} else {
99-
log += dim(': \'') + green(node.value) + dim('\'');
164+
log += dim(': ') + green(JSON.stringify(node.value));
165+
}
166+
167+
if (position) {
168+
log += ' (' + position + ')';
100169
}
101170

102171
if (!isEmpty(node.data)) {

readme.md

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,36 +39,35 @@ and for AMD, CommonJS, and globals ([uncompressed](unist-util-inspect.js) and
3939
var retext = require('retext');
4040
var inspect = require('unist-util-inspect');
4141

42-
retext().use(function (cst) {
43-
console.log(inspect(cst));
42+
retext().use(function () {
43+
return function (cst) {
44+
console.log(inspect(cst));
45+
}
4446
}).process('Some simple text.');
4547
```
4648

4749
Yields:
4850

4951
```text
50-
RootNode[1]
51-
└─ ParagraphNode[1]
52-
└─ SentenceNode[6]
53-
├─ WordNode[1]
54-
│ └─ TextNode: 'Some'
55-
├─ WhiteSpaceNode[1]
56-
│ └─ TextNode: ' '
57-
├─ WordNode[1]
58-
│ └─ TextNode: 'simple'
59-
├─ WhiteSpaceNode[1]
60-
│ └─ TextNode: ' '
61-
├─ WordNode[1]
62-
│ └─ TextNode: 'text'
63-
└─ PunctuationNode[1]
64-
└─ TextNode: '.'
52+
RootNode[1] (1:1-1:18, 0-17)
53+
└─ ParagraphNode[1] (1:1-1:18, 0-17)
54+
└─ SentenceNode[6] (1:1-1:18, 0-17)
55+
├─ WordNode[1] (1:1-1:5, 0-4)
56+
│ └─ TextNode: "Some" (1:1-1:5, 0-4)
57+
├─ WhiteSpaceNode: " " (1:5-1:6, 4-5)
58+
├─ WordNode[1] (1:6-1:12, 5-11)
59+
│ └─ TextNode: "simple" (1:6-1:12, 5-11)
60+
├─ WhiteSpaceNode: " " (1:12-1:13, 11-12)
61+
├─ WordNode[1] (1:13-1:17, 12-16)
62+
│ └─ TextNode: "text" (1:13-1:17, 12-16)
63+
└─ PunctuationNode: "." (1:17-1:18, 16-17)
6564
```
6665

6766
## API
6867

6968
### inspect([node](https://github.com/wooorm/unist#unist-nodes))
7069

71-
By default, color support is enabled on node and disabled anywhere else.
70+
By default, color support is enabled on node and turned off anywhere else.
7271
See below on how to change that.
7372

7473
**Parameters**

test.js

Lines changed: 108 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -65,28 +65,28 @@ describe('inspect()', function () {
6565
equal(
6666
strip(inspect(tree)),
6767
[
68-
'RootNode[1]',
69-
'└─ ParagraphNode[3]',
70-
' ├─ SentenceNode[6]',
71-
' │ ├─ WordNode[1]',
72-
' │ │ └─ TextNode: \'Some\'',
73-
' │ ├─ WhiteSpaceNode: \' \'',
74-
' │ ├─ WordNode[1]',
75-
' │ │ └─ TextNode: \'simple\'',
76-
' │ ├─ WhiteSpaceNode: \' \'',
77-
' │ ├─ WordNode[1]',
78-
' │ │ └─ TextNode: \'text\'',
79-
' │ └─ PunctuationNode: \'.\'',
80-
' ├─ WhiteSpaceNode: \' \'',
81-
' └─ SentenceNode[6]',
82-
' ├─ WordNode[1]',
83-
' │ └─ TextNode: \'Other\'',
84-
' ├─ WhiteSpaceNode: \' \'',
85-
' ├─ PunctuationNode: \'“\'',
86-
' ├─ WordNode[1]',
87-
' │ └─ TextNode: \'sentence\'',
88-
' ├─ PunctuationNode: \'”\'',
89-
' └─ PunctuationNode: \'.\''
68+
'RootNode[1] (1:1-1:36, 0-35)',
69+
'└─ ParagraphNode[3] (1:1-1:36, 0-35)',
70+
' ├─ SentenceNode[6] (1:1-1:18, 0-17)',
71+
' │ ├─ WordNode[1] (1:1-1:5, 0-4)',
72+
' │ │ └─ TextNode: "Some" (1:1-1:5, 0-4)',
73+
' │ ├─ WhiteSpaceNode: " " (1:5-1:6, 4-5)',
74+
' │ ├─ WordNode[1] (1:6-1:12, 5-11)',
75+
' │ │ └─ TextNode: "simple" (1:6-1:12, 5-11)',
76+
' │ ├─ WhiteSpaceNode: " " (1:12-1:13, 11-12)',
77+
' │ ├─ WordNode[1] (1:13-1:17, 12-16)',
78+
' │ │ └─ TextNode: "text" (1:13-1:17, 12-16)',
79+
' │ └─ PunctuationNode: "." (1:17-1:18, 16-17)',
80+
' ├─ WhiteSpaceNode: " " (1:18-1:19, 17-18)',
81+
' └─ SentenceNode[6] (1:19-1:36, 18-35)',
82+
' ├─ WordNode[1] (1:19-1:24, 18-23)',
83+
' │ └─ TextNode: "Other" (1:19-1:24, 18-23)',
84+
' ├─ WhiteSpaceNode: " " (1:24-1:25, 23-24)',
85+
' ├─ PunctuationNode: "“" (1:25-1:26, 24-25)',
86+
' ├─ WordNode[1] (1:26-1:34, 25-33)',
87+
' │ └─ TextNode: "sentence" (1:26-1:34, 25-33)',
88+
' ├─ PunctuationNode: "”" (1:34-1:35, 33-34)',
89+
' └─ PunctuationNode: "." (1:35-1:36, 34-35)'
9090
].join('\n')
9191
);
9292
});
@@ -95,16 +95,16 @@ describe('inspect()', function () {
9595
equal(
9696
strip(inspect(tree.children[0].children[0])),
9797
[
98-
'SentenceNode[6]',
99-
'├─ WordNode[1]',
100-
'│ └─ TextNode: \'Some\'',
101-
'├─ WhiteSpaceNode: \' \'',
102-
'├─ WordNode[1]',
103-
'│ └─ TextNode: \'simple\'',
104-
'├─ WhiteSpaceNode: \' \'',
105-
'├─ WordNode[1]',
106-
'│ └─ TextNode: \'text\'',
107-
'└─ PunctuationNode: \'.\''
98+
'SentenceNode[6] (1:1-1:18, 0-17)',
99+
'├─ WordNode[1] (1:1-1:5, 0-4)',
100+
'│ └─ TextNode: "Some" (1:1-1:5, 0-4)',
101+
'├─ WhiteSpaceNode: " " (1:5-1:6, 4-5)',
102+
'├─ WordNode[1] (1:6-1:12, 5-11)',
103+
'│ └─ TextNode: "simple" (1:6-1:12, 5-11)',
104+
'├─ WhiteSpaceNode: " " (1:12-1:13, 11-12)',
105+
'├─ WordNode[1] (1:13-1:17, 12-16)',
106+
'│ └─ TextNode: "text" (1:13-1:17, 12-16)',
107+
'└─ PunctuationNode: "." (1:17-1:18, 16-17)'
108108
].join('\n')
109109
);
110110
});
@@ -123,9 +123,9 @@ describe('inspect()', function () {
123123
}]
124124
}
125125
])), [
126-
'SymbolNode: \'$\'',
126+
'SymbolNode: "$"',
127127
'WordNode[1]',
128-
'└─ text: \'5,00\''
128+
'└─ text: "5,00"'
129129
].join('\n'));
130130
});
131131

@@ -143,7 +143,50 @@ describe('inspect()', function () {
143143
'data': {
144144
'test': true
145145
}
146-
})), 'SymbolNode: \'$\' [data={"test":true}]');
146+
})), 'SymbolNode: "$" [data={"test":true}]');
147+
});
148+
149+
it('should work without `offset` in `position`', function () {
150+
equal(strip(inspect({
151+
'type': 'foo',
152+
'value': 'foo\nbaar',
153+
'position': {
154+
'start': {
155+
'line': 1,
156+
'column': 1
157+
},
158+
'end': {
159+
'line': 2,
160+
'column': 5
161+
}
162+
}
163+
})), 'foo: "foo\\nbaar" (1:1-2:5)');
164+
});
165+
166+
it('should work without `line` and `column` in `position`', function () {
167+
equal(strip(inspect({
168+
'type': 'foo',
169+
'value': 'foo\nbaar',
170+
'position': {
171+
'start': {},
172+
'end': {}
173+
}
174+
})), 'foo: "foo\\nbaar" (1:1-1:1)');
175+
});
176+
177+
it('should work with just `offset` in `position`', function () {
178+
equal(strip(inspect({
179+
'type': 'foo',
180+
'value': 'foo\nbaar',
181+
'position': {
182+
'start': {
183+
'offset': 1
184+
},
185+
'end': {
186+
'offset': 8
187+
}
188+
}
189+
})), 'foo: "foo\\nbaar" (1:1-1:1, 1-8)');
147190
});
148191
});
149192

@@ -152,16 +195,16 @@ describe('inspect.noColor()', function () {
152195
var sentence = retext().parse(paragraph).children[0].children[0];
153196

154197
equal(inspect.noColor(sentence), [
155-
'SentenceNode[6]',
156-
'├─ WordNode[1]',
157-
'│ └─ TextNode: \'Some\'',
158-
'├─ WhiteSpaceNode: \' \'',
159-
'├─ WordNode[1]',
160-
'│ └─ TextNode: \'simple\'',
161-
'├─ WhiteSpaceNode: \' \'',
162-
'├─ WordNode[1]',
163-
'│ └─ TextNode: \'text\'',
164-
'└─ PunctuationNode: \'.\''
198+
'SentenceNode[6] (1:1-1:18, 0-17)',
199+
'├─ WordNode[1] (1:1-1:5, 0-4)',
200+
'│ └─ TextNode: "Some" (1:1-1:5, 0-4)',
201+
'├─ WhiteSpaceNode: " " (1:5-1:6, 4-5)',
202+
'├─ WordNode[1] (1:6-1:12, 5-11)',
203+
'│ └─ TextNode: "simple" (1:6-1:12, 5-11)',
204+
'├─ WhiteSpaceNode: " " (1:12-1:13, 11-12)',
205+
'├─ WordNode[1] (1:13-1:17, 12-16)',
206+
'│ └─ TextNode: "text" (1:13-1:17, 12-16)',
207+
'└─ PunctuationNode: "." (1:17-1:18, 16-17)'
165208
].join('\n'));
166209
});
167210
});
@@ -172,25 +215,35 @@ describe('inspect.color()', function () {
172215

173216
equal(inspect.color(sentence), [
174217
'SentenceNode' +
175-
chalk.dim('[') + chalk.yellow('6') + chalk.dim(']'),
218+
chalk.dim('[') + chalk.yellow('6') + chalk.dim(']') +
219+
' (1:1-1:18, 0-17)',
176220
chalk.dim('├─ ') + 'WordNode' +
177-
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']'),
221+
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']') +
222+
' (1:1-1:5, 0-4)',
178223
chalk.dim('│ └─ ') + 'TextNode' +
179-
chalk.dim(': \'') + chalk.green('Some') + chalk.dim('\''),
224+
chalk.dim(': ') + chalk.green('"Some"') +
225+
' (1:1-1:5, 0-4)',
180226
chalk.dim('├─ ') + 'WhiteSpaceNode' +
181-
chalk.dim(': \'') + chalk.green(' ') + chalk.dim('\''),
227+
chalk.dim(': ') + chalk.green('" "') +
228+
' (1:5-1:6, 4-5)',
182229
chalk.dim('├─ ') + 'WordNode' +
183-
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']'),
230+
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']') +
231+
' (1:6-1:12, 5-11)',
184232
chalk.dim('│ └─ ') + 'TextNode' +
185-
chalk.dim(': \'') + chalk.green('simple') + chalk.dim('\''),
233+
chalk.dim(': ') + chalk.green('"simple"') +
234+
' (1:6-1:12, 5-11)',
186235
chalk.dim('├─ ') + 'WhiteSpaceNode' +
187-
chalk.dim(': \'') + chalk.green(' ') + chalk.dim('\''),
236+
chalk.dim(': ') + chalk.green('" "') +
237+
' (1:12-1:13, 11-12)',
188238
chalk.dim('├─ ') + 'WordNode' +
189-
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']'),
239+
chalk.dim('[') + chalk.yellow('1') + chalk.dim(']') +
240+
' (1:13-1:17, 12-16)',
190241
chalk.dim('│ └─ ') + 'TextNode' +
191-
chalk.dim(': \'') + chalk.green('text') + chalk.dim('\''),
242+
chalk.dim(': ') + chalk.green('"text"') +
243+
' (1:13-1:17, 12-16)',
192244
chalk.dim('└─ ') + 'PunctuationNode' +
193-
chalk.dim(': \'') + chalk.green('.') + chalk.dim('\'')
245+
chalk.dim(': ') + chalk.green('"."') +
246+
' (1:17-1:18, 16-17)'
194247
].join('\n'));
195248
});
196249
});

0 commit comments

Comments
 (0)