Skip to content

Commit 1a2f84b

Browse files
committed
Refactor to move implementation to lib/
1 parent d1d6df9 commit 1a2f84b

File tree

5 files changed

+312
-310
lines changed

5 files changed

+312
-310
lines changed

index.js

+2-304
Original file line numberDiff line numberDiff line change
@@ -1,310 +1,8 @@
11
/**
2-
* @typedef {import('unist').Node} Node
3-
* @typedef {import('unist').Position} Position
4-
* @typedef {import('unist').Point} Point
5-
*
6-
* @typedef Options
7-
* @property {boolean} [showPositions=true]
2+
* @typedef {import('./lib/index.js')} Options
83
*
94
* @typedef {Options} InspectOptions
105
* Deprecated, use `Options`.
116
*/
127

13-
import {color} from './color.js'
14-
15-
/* c8 ignore next */
16-
export const inspect = color ? inspectColor : inspectNoColor
17-
18-
const own = {}.hasOwnProperty
19-
20-
const bold = ansiColor(1, 22)
21-
const dim = ansiColor(2, 22)
22-
const yellow = ansiColor(33, 39)
23-
const green = ansiColor(32, 39)
24-
25-
// ANSI color regex.
26-
/* eslint-disable no-control-regex */
27-
const colorExpression =
28-
/(?:(?:\u001B\[)|\u009B)(?:\d{1,3})?(?:(?:;\d{0,3})*)?[A-M|f-m]|\u001B[A-M]/g
29-
/* eslint-enable no-control-regex */
30-
31-
/**
32-
* Inspects a node, without using color.
33-
*
34-
* @param {unknown} node
35-
* @param {Options} [options]
36-
* @returns {string}
37-
*/
38-
export function inspectNoColor(node, options) {
39-
return inspectColor(node, options).replace(colorExpression, '')
40-
}
41-
42-
/**
43-
* Inspects a node, using color.
44-
*
45-
* @param {unknown} tree
46-
* @param {Options} [options]
47-
* @returns {string}
48-
*/
49-
export function inspectColor(tree, options = {}) {
50-
const positions =
51-
options.showPositions === null || options.showPositions === undefined
52-
? true
53-
: options.showPositions
54-
55-
return inspectValue(tree)
56-
57-
/**
58-
* @param {unknown} node
59-
* @returns {string}
60-
*/
61-
function inspectValue(node) {
62-
if (node && typeof node === 'object' && 'length' in node) {
63-
// @ts-expect-error looks like a list of nodes.
64-
return inspectNodes(node)
65-
}
66-
67-
// @ts-expect-error looks like a single node.
68-
if (node && node.type) {
69-
// @ts-expect-error looks like a single node.
70-
return inspectTree(node)
71-
}
72-
73-
return inspectNonTree(node)
74-
}
75-
76-
/**
77-
* @param {unknown} value
78-
* @returns {string}
79-
*/
80-
function inspectNonTree(value) {
81-
return JSON.stringify(value)
82-
}
83-
84-
/**
85-
* @param {Array<Node>} nodes
86-
* @returns {string}
87-
*/
88-
function inspectNodes(nodes) {
89-
const size = String(nodes.length - 1).length
90-
/** @type {Array<string>} */
91-
const result = []
92-
let index = -1
93-
94-
while (++index < nodes.length) {
95-
result.push(
96-
dim(
97-
(index < nodes.length - 1 ? '├' : '└') +
98-
'─' +
99-
String(index).padEnd(size)
100-
) +
101-
' ' +
102-
indent(
103-
inspectValue(nodes[index]),
104-
(index < nodes.length - 1 ? dim('│') : ' ') + ' '.repeat(size + 2),
105-
true
106-
)
107-
)
108-
}
109-
110-
return result.join('\n')
111-
}
112-
113-
/**
114-
* @param {Record<string, unknown>} object
115-
* @returns {string}
116-
*/
117-
// eslint-disable-next-line complexity
118-
function inspectFields(object) {
119-
/** @type {Array<string>} */
120-
const result = []
121-
/** @type {string} */
122-
let key
123-
124-
for (key in object) {
125-
/* c8 ignore next 1 */
126-
if (!own.call(object, key)) continue
127-
128-
const value = object[key]
129-
/** @type {string} */
130-
let formatted
131-
132-
if (
133-
value === undefined ||
134-
// Standard keys defined by unist that we format differently.
135-
// <https://github.com/syntax-tree/unist>
136-
key === 'type' ||
137-
key === 'value' ||
138-
key === 'children' ||
139-
key === 'position' ||
140-
// Ignore `name` (from xast) and `tagName` (from `hast`) when string.
141-
(typeof value === 'string' && (key === 'name' || key === 'tagName'))
142-
) {
143-
continue
144-
}
145-
146-
// A single node.
147-
if (
148-
value &&
149-
typeof value === 'object' &&
150-
// @ts-expect-error looks like a node.
151-
value.type &&
152-
key !== 'data' &&
153-
key !== 'attributes' &&
154-
key !== 'properties'
155-
) {
156-
// @ts-expect-error looks like a node.
157-
formatted = inspectTree(value)
158-
}
159-
// A list of nodes.
160-
else if (
161-
value &&
162-
Array.isArray(value) &&
163-
// Looks like a node.
164-
// type-coverage:ignore-next-line
165-
value[0] &&
166-
// Looks like a node.
167-
// type-coverage:ignore-next-line
168-
value[0].type
169-
) {
170-
formatted = '\n' + inspectNodes(value)
171-
} else {
172-
formatted = inspectNonTree(value)
173-
}
174-
175-
result.push(
176-
key + dim(':') + (/\s/.test(formatted.charAt(0)) ? '' : ' ') + formatted
177-
)
178-
}
179-
180-
return indent(
181-
result.join('\n'),
182-
// @ts-expect-error looks like a parent node.
183-
(object.children && object.children.length > 0 ? dim('│') : ' ') + ' '
184-
)
185-
}
186-
187-
/**
188-
* @param {Node} node
189-
* @returns {string}
190-
*/
191-
function inspectTree(node) {
192-
const result = [formatNode(node)]
193-
// @ts-expect-error: looks like a record.
194-
const fields = inspectFields(node)
195-
// @ts-expect-error looks like a parent.
196-
const content = inspectNodes(node.children || [])
197-
if (fields) result.push(fields)
198-
if (content) result.push(content)
199-
return result.join('\n')
200-
}
201-
202-
/**
203-
* Colored node formatter.
204-
*
205-
* @param {Node} node
206-
* @returns {string}
207-
*/
208-
function formatNode(node) {
209-
const result = [bold(node.type)]
210-
/** @type {string|undefined} */
211-
// @ts-expect-error: might be available.
212-
const kind = node.tagName || node.name
213-
const position = positions ? stringifyPosition(node.position) : ''
214-
215-
if (typeof kind === 'string') {
216-
result.push('<', kind, '>')
217-
}
218-
219-
// @ts-expect-error: looks like a parent.
220-
if (node.children) {
221-
// @ts-expect-error looks like a parent.
222-
result.push(dim('['), yellow(node.children.length), dim(']'))
223-
// @ts-expect-error: looks like a literal.
224-
} else if (typeof node.value === 'string') {
225-
// @ts-expect-error: looks like a literal.
226-
result.push(' ', green(inspectNonTree(node.value)))
227-
}
228-
229-
if (position) {
230-
result.push(' ', dim('('), position, dim(')'))
231-
}
232-
233-
return result.join('')
234-
}
235-
}
236-
237-
/**
238-
* @param {string} value
239-
* @param {string} indentation
240-
* @param {boolean} [ignoreFirst=false]
241-
* @returns {string}
242-
*/
243-
function indent(value, indentation, ignoreFirst) {
244-
const lines = value.split('\n')
245-
let index = ignoreFirst ? 0 : -1
246-
247-
if (!value) return value
248-
249-
while (++index < lines.length) {
250-
lines[index] = indentation + lines[index]
251-
}
252-
253-
return lines.join('\n')
254-
}
255-
256-
/**
257-
* @param {Position|undefined} [value]
258-
* @returns {string}
259-
*/
260-
function stringifyPosition(value) {
261-
/** @type {Position} */
262-
// @ts-expect-error: fine.
263-
const position = value || {}
264-
/** @type {Array<string>} */
265-
const result = []
266-
/** @type {Array<string>} */
267-
const positions = []
268-
/** @type {Array<string>} */
269-
const offsets = []
270-
271-
point(position.start)
272-
point(position.end)
273-
274-
if (positions.length > 0) result.push(positions.join('-'))
275-
if (offsets.length > 0) result.push(offsets.join('-'))
276-
277-
return result.join(', ')
278-
279-
/**
280-
* @param {Point} value
281-
*/
282-
function point(value) {
283-
if (value) {
284-
positions.push((value.line || 1) + ':' + (value.column || 1))
285-
286-
if ('offset' in value) {
287-
offsets.push(String(value.offset || 0))
288-
}
289-
}
290-
}
291-
}
292-
293-
/**
294-
* Factory to wrap values in ANSI colours.
295-
*
296-
* @param {number} open
297-
* @param {number} close
298-
* @returns {function(string): string}
299-
*/
300-
function ansiColor(open, close) {
301-
return color
302-
303-
/**
304-
* @param {string} value
305-
* @returns {string}
306-
*/
307-
function color(value) {
308-
return '\u001B[' + open + 'm' + value + '\u001B[' + close + 'm'
309-
}
310-
}
8+
export {inspect, inspectColor, inspectNoColor} from './lib/index.js'
File renamed without changes.

color.js renamed to lib/color.js

File renamed without changes.

0 commit comments

Comments
 (0)