@speclynx/apidom-traverse 4.10.1 → 4.12.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/CHANGELOG.md +14 -0
- package/dist/apidom-traverse.browser.js +40 -8
- package/dist/apidom-traverse.browser.min.js +1 -1
- package/package.json +8 -8
- package/src/Path.cjs +11 -1
- package/src/Path.mjs +8 -0
- package/src/index.cjs +117 -21
- package/src/operations/filter.cjs +3 -1
- package/src/operations/find-at-offset.cjs +3 -1
- package/src/operations/find.cjs +3 -1
- package/src/operations/for-each.cjs +3 -1
- package/src/operations/parents.cjs +3 -1
- package/src/operations/reject.cjs +3 -1
- package/src/operations/some.cjs +3 -1
- package/src/traversal.cjs +32 -8
- package/src/traversal.mjs +29 -7
- package/src/visitors.cjs +6 -2
- package/src/visitors.mjs +3 -1
- package/types/apidom-traverse.d.ts +30 -9
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,20 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [4.12.0](https://github.com/speclynx/apidom/compare/v4.11.1...v4.12.0) (2026-06-23)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @speclynx/apidom-traverse
|
|
9
|
+
|
|
10
|
+
## [4.11.1](https://github.com/speclynx/apidom/compare/v4.11.0...v4.11.1) (2026-06-10)
|
|
11
|
+
|
|
12
|
+
**Note:** Version bump only for package @speclynx/apidom-traverse
|
|
13
|
+
|
|
14
|
+
# [4.11.0](https://github.com/speclynx/apidom/compare/v4.10.1...v4.11.0) (2026-06-10)
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
- **traverse:** skipVisited 'enter-only' mode and path.revisited ([#333](https://github.com/speclynx/apidom/issues/333)) ([fe944df](https://github.com/speclynx/apidom/commit/fe944df0eaab437a65d5761e6a3e14d490d2d3d6))
|
|
19
|
+
|
|
6
20
|
## [4.10.1](https://github.com/speclynx/apidom/compare/v4.10.0...v4.10.1) (2026-05-20)
|
|
7
21
|
|
|
8
22
|
**Note:** Version bump only for package @speclynx/apidom-traverse
|
|
@@ -76,6 +76,14 @@ class Path {
|
|
|
76
76
|
*/
|
|
77
77
|
inList;
|
|
78
78
|
|
|
79
|
+
/**
|
|
80
|
+
* True when this node is a non-descending revisit of an already-visited node
|
|
81
|
+
* (only under skipVisited: 'enter-only'). Children are not traversed.
|
|
82
|
+
* Set on both the enter and the matching leave phase, so it is meaningful
|
|
83
|
+
* in either phase.
|
|
84
|
+
*/
|
|
85
|
+
revisited = false;
|
|
86
|
+
|
|
79
87
|
/**
|
|
80
88
|
* Internal state for traversal control.
|
|
81
89
|
*/
|
|
@@ -609,6 +617,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
609
617
|
|
|
610
618
|
|
|
611
619
|
|
|
620
|
+
/**
|
|
621
|
+
* Controls handling of already-visited nodes during traversal.
|
|
622
|
+
* @public
|
|
623
|
+
*/
|
|
624
|
+
|
|
612
625
|
/**
|
|
613
626
|
* Options for the traverse function.
|
|
614
627
|
* @public
|
|
@@ -618,6 +631,11 @@ __webpack_require__.r(__webpack_exports__);
|
|
|
618
631
|
// Internal types for generator
|
|
619
632
|
// =============================================================================
|
|
620
633
|
|
|
634
|
+
const normalizeSkipVisited = v => {
|
|
635
|
+
if (v === true) return 'skip';
|
|
636
|
+
if (v === false || v === undefined) return 'never';
|
|
637
|
+
return v;
|
|
638
|
+
};
|
|
621
639
|
// =============================================================================
|
|
622
640
|
// Core generator
|
|
623
641
|
// =============================================================================
|
|
@@ -635,7 +653,7 @@ function* traverseGenerator(root, visitor, options) {
|
|
|
635
653
|
mutationFn
|
|
636
654
|
} = options;
|
|
637
655
|
const keyMapIsFunction = typeof keyMap === 'function';
|
|
638
|
-
const visitedNodes = skipVisited ? new WeakSet() : null;
|
|
656
|
+
const visitedNodes = skipVisited !== 'never' ? new WeakSet() : null;
|
|
639
657
|
let stack;
|
|
640
658
|
let inArray = Array.isArray(root);
|
|
641
659
|
let keys = [root];
|
|
@@ -650,6 +668,7 @@ function* traverseGenerator(root, visitor, options) {
|
|
|
650
668
|
index += 1;
|
|
651
669
|
const isLeaving = index === keys.length;
|
|
652
670
|
let key;
|
|
671
|
+
let revisitNoDescend = false;
|
|
653
672
|
const isEdited = isLeaving && edits.length !== 0;
|
|
654
673
|
if (isLeaving) {
|
|
655
674
|
key = ancestors.length === 0 ? undefined : currentPath?.key;
|
|
@@ -691,6 +710,7 @@ function* traverseGenerator(root, visitor, options) {
|
|
|
691
710
|
edits = stack.edits;
|
|
692
711
|
const parentInArray = stack.inArray;
|
|
693
712
|
parentPath = stack.parentPath;
|
|
713
|
+
revisitNoDescend = stack.revisitNoDescend;
|
|
694
714
|
stack = stack.prev;
|
|
695
715
|
|
|
696
716
|
// Push the edited node to parent's edits for propagation up the tree
|
|
@@ -722,15 +742,22 @@ function* traverseGenerator(root, visitor, options) {
|
|
|
722
742
|
}
|
|
723
743
|
|
|
724
744
|
// Skip already-visited nodes (handles DAG structures from cloneShallow)
|
|
725
|
-
if (skipVisited && !isLeaving) {
|
|
745
|
+
if (skipVisited !== 'never' && !isLeaving) {
|
|
726
746
|
if (visitedNodes.has(node)) {
|
|
727
|
-
|
|
747
|
+
if (skipVisited === 'enter-only') {
|
|
748
|
+
// fire enter/leave for this occurrence, but don't re-descend
|
|
749
|
+
revisitNoDescend = true;
|
|
750
|
+
} else {
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
} else {
|
|
754
|
+
visitedNodes.add(node);
|
|
728
755
|
}
|
|
729
|
-
visitedNodes.add(node);
|
|
730
756
|
}
|
|
731
757
|
|
|
732
758
|
// Always create Path for the current node (needed for parentPath chain)
|
|
733
759
|
currentPath = new _Path_ts__WEBPACK_IMPORTED_MODULE_2__.Path(node, parent, parentPath, key, inArray);
|
|
760
|
+
currentPath.revisited = revisitNoDescend;
|
|
734
761
|
const visitFn = (0,_visitors_ts__WEBPACK_IMPORTED_MODULE_3__.getVisitFn)(visitor, nodeTypeGetter(node), isLeaving);
|
|
735
762
|
if (visitFn) {
|
|
736
763
|
// Assign state to visitor
|
|
@@ -794,10 +821,13 @@ function* traverseGenerator(root, visitor, options) {
|
|
|
794
821
|
keys,
|
|
795
822
|
edits,
|
|
796
823
|
parentPath,
|
|
824
|
+
revisitNoDescend,
|
|
797
825
|
prev: stack
|
|
798
826
|
};
|
|
799
827
|
inArray = Array.isArray(node);
|
|
800
|
-
if (
|
|
828
|
+
if (revisitNoDescend) {
|
|
829
|
+
keys = [];
|
|
830
|
+
} else if (inArray) {
|
|
801
831
|
keys = node;
|
|
802
832
|
} else if (keyMapIsFunction) {
|
|
803
833
|
keys = keyMap(node);
|
|
@@ -872,7 +902,7 @@ const traverse = (root, visitor, options = {}) => {
|
|
|
872
902
|
nodePredicate: options.nodePredicate ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.isNode,
|
|
873
903
|
nodeCloneFn: options.nodeCloneFn ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.cloneNode,
|
|
874
904
|
detectCycles: options.detectCycles ?? true,
|
|
875
|
-
skipVisited: options.skipVisited
|
|
905
|
+
skipVisited: normalizeSkipVisited(options.skipVisited),
|
|
876
906
|
mutable: options.mutable ?? false,
|
|
877
907
|
mutationFn: options.mutationFn ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.mutateNode
|
|
878
908
|
};
|
|
@@ -904,7 +934,7 @@ const traverseAsync = async (root, visitor, options = {}) => {
|
|
|
904
934
|
nodePredicate: options.nodePredicate ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.isNode,
|
|
905
935
|
nodeCloneFn: options.nodeCloneFn ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.cloneNode,
|
|
906
936
|
detectCycles: options.detectCycles ?? true,
|
|
907
|
-
skipVisited: options.skipVisited
|
|
937
|
+
skipVisited: normalizeSkipVisited(options.skipVisited),
|
|
908
938
|
mutable: options.mutable ?? false,
|
|
909
939
|
mutationFn: options.mutationFn ?? _visitors_ts__WEBPACK_IMPORTED_MODULE_3__.mutateNode
|
|
910
940
|
};
|
|
@@ -1374,7 +1404,9 @@ mergeVisitors[Symbol.for('nodejs.util.promisify.custom')] = mergeVisitorsAsync;
|
|
|
1374
1404
|
* @internal
|
|
1375
1405
|
*/
|
|
1376
1406
|
function createPathProxy(originalPath, currentNode) {
|
|
1377
|
-
|
|
1407
|
+
const proxy = new _Path_ts__WEBPACK_IMPORTED_MODULE_4__.Path(currentNode, originalPath.parent, originalPath.parentPath, originalPath.key, originalPath.inList);
|
|
1408
|
+
proxy.revisited = originalPath.revisited;
|
|
1409
|
+
return proxy;
|
|
1378
1410
|
}
|
|
1379
1411
|
|
|
1380
1412
|
/***/ },
|