@speclynx/apidom-traverse 1.12.2
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/LICENSES/AFL-3.0.txt +182 -0
- package/LICENSES/Apache-2.0.txt +202 -0
- package/LICENSES/BSD-3-Clause.txt +26 -0
- package/LICENSES/MIT.txt +9 -0
- package/NOTICE +74 -0
- package/README.md +238 -0
- package/dist/apidom-traverse.browser.js +6900 -0
- package/dist/apidom-traverse.browser.min.js +1 -0
- package/package.json +59 -0
- package/src/Path.cjs +276 -0
- package/src/Path.mjs +271 -0
- package/src/index.cjs +43 -0
- package/src/index.mjs +19 -0
- package/src/operations/filter.cjs +21 -0
- package/src/operations/filter.mjs +17 -0
- package/src/operations/find-at-offset.cjs +45 -0
- package/src/operations/find-at-offset.mjs +40 -0
- package/src/operations/find.cjs +22 -0
- package/src/operations/find.mjs +18 -0
- package/src/operations/for-each.cjs +37 -0
- package/src/operations/for-each.mjs +31 -0
- package/src/operations/parents.cjs +21 -0
- package/src/operations/parents.mjs +17 -0
- package/src/operations/reject.cjs +14 -0
- package/src/operations/reject.mjs +9 -0
- package/src/operations/some.cjs +14 -0
- package/src/operations/some.mjs +9 -0
- package/src/traversal.cjs +313 -0
- package/src/traversal.mjs +305 -0
- package/src/visitors.cjs +420 -0
- package/src/visitors.mjs +407 -0
- package/types/apidom-traverse.d.ts +403 -0
package/README.md
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# @speclynx/apidom-traverse
|
|
2
|
+
|
|
3
|
+
`@speclynx/apidom-traverse` provides traversal utilities for ApiDOM structures.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
You can install this package via [npm CLI](https://docs.npmjs.com/cli) by running the following command:
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
$ npm install @speclynx/apidom-traverse
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### traverse
|
|
16
|
+
|
|
17
|
+
The core traversal function that walks an ApiDOM tree using visitors.
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
import { ObjectElement } from '@speclynx/apidom-datamodel';
|
|
21
|
+
import { traverse } from '@speclynx/apidom-traverse';
|
|
22
|
+
|
|
23
|
+
const element = new ObjectElement({ a: 'b' });
|
|
24
|
+
|
|
25
|
+
traverse(element, {
|
|
26
|
+
enter(path) {
|
|
27
|
+
console.log('entering:', path.node.element);
|
|
28
|
+
},
|
|
29
|
+
leave(path) {
|
|
30
|
+
console.log('leaving:', path.node.element);
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### traverseAsync
|
|
36
|
+
|
|
37
|
+
Async version of traverse that supports async visitors.
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
import { ObjectElement } from '@speclynx/apidom-datamodel';
|
|
41
|
+
import { traverseAsync } from '@speclynx/apidom-traverse';
|
|
42
|
+
|
|
43
|
+
const element = new ObjectElement({ a: 'b' });
|
|
44
|
+
|
|
45
|
+
await traverseAsync(element, {
|
|
46
|
+
async enter(path) {
|
|
47
|
+
await someAsyncOperation(path.node);
|
|
48
|
+
},
|
|
49
|
+
});
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Operations
|
|
55
|
+
|
|
56
|
+
Higher-level functions built on top of `traverse` for common use cases.
|
|
57
|
+
All operations use **data-first** signatures: the element comes before the predicate/options.
|
|
58
|
+
|
|
59
|
+
### filter
|
|
60
|
+
|
|
61
|
+
Finds all elements matching the predicate.
|
|
62
|
+
|
|
63
|
+
```js
|
|
64
|
+
import { ObjectElement, isNumberElement } from '@speclynx/apidom-datamodel';
|
|
65
|
+
import { filter } from '@speclynx/apidom-traverse';
|
|
66
|
+
|
|
67
|
+
const element = new ObjectElement({ a: 'b', c: 2 });
|
|
68
|
+
|
|
69
|
+
filter(element, isNumberElement); // => [NumberElement<2>]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### find
|
|
73
|
+
|
|
74
|
+
Find first element that satisfies the provided predicate.
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
import { ObjectElement, isNumberElement } from '@speclynx/apidom-datamodel';
|
|
78
|
+
import { find } from '@speclynx/apidom-traverse';
|
|
79
|
+
|
|
80
|
+
const element = new ObjectElement({ a: 'b', c: 2 });
|
|
81
|
+
|
|
82
|
+
find(element, isNumberElement); // => NumberElement<2>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### findAtOffset
|
|
86
|
+
|
|
87
|
+
ApiDOM nodes can be associated with source maps. This function finds the most inner node at the given offset.
|
|
88
|
+
If includeRightBound is set, also finds nodes that end at the given offset.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
import { findAtOffset } from '@speclynx/apidom-traverse';
|
|
92
|
+
|
|
93
|
+
findAtOffset(elementWithSourceMaps, 3); // => returns most inner node at offset 3
|
|
94
|
+
findAtOffset(elementWithSourceMaps, { offset: 3, includeRightBound: true });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### reject
|
|
98
|
+
|
|
99
|
+
Complement of [filter](#filter). Finds all elements NOT matching the predicate.
|
|
100
|
+
|
|
101
|
+
```js
|
|
102
|
+
import { ArrayElement, isNumberElement } from '@speclynx/apidom-datamodel';
|
|
103
|
+
import { reject } from '@speclynx/apidom-traverse';
|
|
104
|
+
|
|
105
|
+
const element = new ArrayElement([1, 'a']);
|
|
106
|
+
|
|
107
|
+
reject(element, isNumberElement); // => [ArrayElement, StringElement<'a'>]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### some
|
|
111
|
+
|
|
112
|
+
Tests whether at least one element passes the predicate.
|
|
113
|
+
|
|
114
|
+
```js
|
|
115
|
+
import { ArrayElement, isNumberElement } from '@speclynx/apidom-datamodel';
|
|
116
|
+
import { some } from '@speclynx/apidom-traverse';
|
|
117
|
+
|
|
118
|
+
const element = new ArrayElement([1, 'a']);
|
|
119
|
+
|
|
120
|
+
some(element, isNumberElement); // => true
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### forEach
|
|
124
|
+
|
|
125
|
+
Executes the callback on this element and all descendants.
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
import { ArrayElement } from '@speclynx/apidom-datamodel';
|
|
129
|
+
import { forEach } from '@speclynx/apidom-traverse';
|
|
130
|
+
|
|
131
|
+
const element = new ArrayElement([1, 'a']);
|
|
132
|
+
|
|
133
|
+
forEach(element, console.dir); // => prints ArrayElement, NumberElement, StringElement in this order
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The execution of the callback can be controlled further by providing a predicate.
|
|
137
|
+
|
|
138
|
+
```js
|
|
139
|
+
import { ArrayElement, isNumberElement } from '@speclynx/apidom-datamodel';
|
|
140
|
+
import { forEach } from '@speclynx/apidom-traverse';
|
|
141
|
+
|
|
142
|
+
const element = new ArrayElement([1, 'a']);
|
|
143
|
+
|
|
144
|
+
forEach(element, { callback: console.dir, predicate: isNumberElement }); // => prints NumberElement<1>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### parents
|
|
148
|
+
|
|
149
|
+
Computes upwards edges from every child to its parent.
|
|
150
|
+
|
|
151
|
+
#### ObjectElement example
|
|
152
|
+
|
|
153
|
+
```js
|
|
154
|
+
import { ObjectElement } from '@speclynx/apidom-datamodel';
|
|
155
|
+
import { parents } from '@speclynx/apidom-traverse';
|
|
156
|
+
|
|
157
|
+
const element = new ObjectElement({ key: 'value' });
|
|
158
|
+
const memberElement = element.getMember('key');
|
|
159
|
+
const { key: keyElement, value: valueElement } = memberElement;
|
|
160
|
+
|
|
161
|
+
const parentEdges = parents(element); // => WeakMap<ChildElement, ParentElement>
|
|
162
|
+
|
|
163
|
+
parentEdges.get(memberElement) === element; // => true
|
|
164
|
+
parentEdges.get(keyElement) === memberElement; // => true
|
|
165
|
+
parentEdges.get(valueElement) === memberElement; // => true
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### ArrayElement example
|
|
169
|
+
|
|
170
|
+
```js
|
|
171
|
+
import { ArrayElement, StringElement } from '@speclynx/apidom-datamodel';
|
|
172
|
+
import { parents } from '@speclynx/apidom-traverse';
|
|
173
|
+
|
|
174
|
+
const itemElement1 = new StringElement('item1');
|
|
175
|
+
const itemElement2 = new StringElement('item2');
|
|
176
|
+
const element = new ArrayElement([itemElement1, itemElement2]);
|
|
177
|
+
|
|
178
|
+
const parentEdges = parents(element); // => WeakMap<ChildElement, ParentElement>
|
|
179
|
+
|
|
180
|
+
parentEdges.get(itemElement1) === element; // => true
|
|
181
|
+
parentEdges.get(itemElement2) === element; // => true
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Path
|
|
187
|
+
|
|
188
|
+
The `Path` object is passed to visitor functions and provides context about the current node.
|
|
189
|
+
|
|
190
|
+
### Properties
|
|
191
|
+
|
|
192
|
+
- `node` - The current element being visited
|
|
193
|
+
- `parent` - The parent container (array or element)
|
|
194
|
+
- `parentPath` - The Path of the parent element
|
|
195
|
+
- `key` - The key or index in the parent
|
|
196
|
+
- `index` - Numeric index if inside an array (undefined otherwise)
|
|
197
|
+
- `inList` - Whether the node is inside an array
|
|
198
|
+
|
|
199
|
+
### Methods
|
|
200
|
+
|
|
201
|
+
- `skip()` - Skip visiting children of this node
|
|
202
|
+
- `stop()` - Stop all traversal
|
|
203
|
+
- `replaceWith(node)` - Replace the current node
|
|
204
|
+
- `remove()` - Remove the current node (in mutable mode)
|
|
205
|
+
- `isRoot()` - Check if this is the root node
|
|
206
|
+
- `getAncestry()` - Get all ancestor paths
|
|
207
|
+
- `getAncestorNodes()` - Get all ancestor nodes
|
|
208
|
+
- `getPathKeys()` - Get the path from root to current node
|
|
209
|
+
- `findParent(predicate)` - Find first parent matching predicate
|
|
210
|
+
- `find(predicate)` - Find self or parent matching predicate
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Visitor Utilities
|
|
215
|
+
|
|
216
|
+
### getNodeType
|
|
217
|
+
|
|
218
|
+
Returns the element type name for use in visitors.
|
|
219
|
+
|
|
220
|
+
```js
|
|
221
|
+
import { StringElement } from '@speclynx/apidom-datamodel';
|
|
222
|
+
import { getNodeType } from '@speclynx/apidom-traverse';
|
|
223
|
+
|
|
224
|
+
getNodeType(new StringElement('hello')); // => 'StringElement'
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### mergeVisitors
|
|
228
|
+
|
|
229
|
+
Merges multiple visitors into a single visitor.
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
import { mergeVisitors } from '@speclynx/apidom-traverse';
|
|
233
|
+
|
|
234
|
+
const visitor1 = { StringElement(path) { /* ... */ } };
|
|
235
|
+
const visitor2 = { NumberElement(path) { /* ... */ } };
|
|
236
|
+
|
|
237
|
+
const merged = mergeVisitors([visitor1, visitor2]);
|
|
238
|
+
```
|