@glion/util-visit 0.27.0 → 0.28.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/README.md CHANGED
@@ -4,7 +4,7 @@ Visitor for traversing HL7v2 AST trees with ancestor context.
4
4
 
5
5
  ## What it does
6
6
 
7
- Walks an HL7v2 AST from any starting node — Root, Group, Segment, Field, Component, or Subcomponent — calling a visitor function for each matching node with the node and its ancestors, from the node the walk starts at to the node's parent. Supports filtering by type string, property object, or predicate, and exposes `SKIP`/`EXIT` control actions. Delegates traversal to `unist-util-visit-parents`, with types from `@glion/ast`.
7
+ Walks an HL7v2 AST from any starting node — Root, Group, Segment, Field, Component, or Subcomponent — calling a visitor function for each matching node with the node and its ancestors, from the node the walk starts at to the node's parent. Supports filtering by type string, property object, or predicate, and exposes `SKIP`/`EXIT` control actions. Visits in the same order, and reads a visitor's result the same way, as `unist-util-visit-parents`, with types from `@glion/ast`.
8
8
 
9
9
  ## Install
10
10
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /**
2
- * HL7v2 AST visitor over `unist-util-visit-parents`, typed for `@glion/ast`.
2
+ * HL7v2 AST visitor, typed for `@glion/ast`, with the semantics of
3
+ * `unist-util-visit-parents`.
3
4
  *
4
5
  * @module
5
6
  */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGxC,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAG7C,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEtD,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxD,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;AAC3D,wBAAgB,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,CAAC,EAC9C,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC,GAC/C,IAAI,CAAC;AACR,wBAAgB,KAAK,CAAC,CAAC,SAAS,KAAK,EACnC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EACb,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,IAAI,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAIxC,OAAO,KAAK,EAAa,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxD,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEtD,YAAY,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAGxD,wBAAgB,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;AAC3D,wBAAgB,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,CAAC,EAC9C,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,IAAI,CAAA;CAAE,CAAC,CAAC,GAC/C,IAAI,CAAC;AACR,wBAAgB,KAAK,CAAC,CAAC,SAAS,KAAK,EACnC,IAAI,EAAE,KAAK,EACX,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EACb,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAClB,IAAI,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { EXIT, SKIP, visitParents } from "unist-util-visit-parents";
1
+ import { EXIT, EXIT as EXIT$1, SKIP, SKIP as SKIP$1 } from "unist-util-visit-parents";
2
2
  //#region src/utils.ts
3
3
  /**
4
4
  * The predicate a `visit` test describes.
@@ -46,17 +46,35 @@ function createTest(test) {
46
46
  //#endregion
47
47
  //#region src/index.ts
48
48
  /**
49
- * Visit nodes in an HL7 AST tree.
49
+ * Visits `tree` and every node below it, depth-first and in document order,
50
+ * calling `visitor` with each node that passes `test` and that node's
51
+ * ancestors.
50
52
  *
51
- * @param tree - The tree to traverse (can be any node type, not just Root)
52
- * @param test - Optional test to filter nodes (type string, partial match, or
53
- * Test function)
54
- * @param visitor - Function called for each matching node
53
+ * `test` is a node type (`"segment"`), an object whose own properties a node
54
+ * must equal (`{ name: "PID" }`), or a function of `(node, ancestors)`. With no
55
+ * test, every node passes. A function passed as the second argument is always
56
+ * the visitor; a test function needs the three-argument form.
55
57
  *
56
- * **Important**: If you pass a function as the second argument, it is always
57
- * treated as a Visitor, never as a Test. To use a Test function, you MUST
58
- * provide both the test and visitor parameters: `visit(tree, testFn,
59
- * visitorFn)`.
58
+ * The visitor's result decides what the walk does next:
59
+ *
60
+ * - Nothing: enter the node's children, then go on.
61
+ * - `SKIP`: do not enter the node's children.
62
+ * - `EXIT`: stop the whole walk.
63
+ * - A number: go on at that index among the node's siblings, after the visitor
64
+ * removed or inserted siblings. `[action, index]` combines both.
65
+ *
66
+ * `ancestors` runs from `tree` to the node's parent. Siblings share one array:
67
+ * a visitor MUST NOT change it, and MAY keep it, since a later visit never
68
+ * changes it either.
69
+ *
70
+ * With a type test, the walk does not enter a node that cannot contain that
71
+ * type in an HL7v2 tree (Root → Group → Segment → Field → FieldRepetition →
72
+ * Component → Subcomponent): `visit(tree, "segment", …)` never enters a
73
+ * segment. Nodes of a type `@glion/ast` does not define are always entered.
74
+ *
75
+ * @param tree - The node the walk starts at, of any type.
76
+ * @param test - Which nodes the visitor is called with.
77
+ * @param visitor - Called with each node that passes `test`.
60
78
  */
61
79
  function visit(tree, arg2, arg3) {
62
80
  let test = null;
@@ -66,12 +84,52 @@ function visit(tree, arg2, arg3) {
66
84
  test = arg2;
67
85
  visitor = arg3;
68
86
  }
69
- const predicate = createTest(test);
70
- visitParents(tree, (node, ancestors) => {
71
- if (!predicate(node, ancestors)) return;
72
- return visitor(node, ancestors);
87
+ walk(tree, [], {
88
+ predicate: createTest(test),
89
+ unmatchableBelow: UNMATCHABLE_BELOW.get(test),
90
+ visitor
73
91
  });
74
92
  }
93
+ /**
94
+ * The depth of each `@glion/ast` node type in an HL7v2 tree. A group may hold
95
+ * groups, so it is the one type found below its own depth.
96
+ */
97
+ const DEPTH = new Map([
98
+ ["root", 0],
99
+ ["group", 1],
100
+ ["segment", 2],
101
+ ["field", 3],
102
+ ["field-repetition", 4],
103
+ ["component", 5],
104
+ ["subcomponent", 6]
105
+ ]);
106
+ /**
107
+ * For each node type, the node types whose children cannot include a node of
108
+ * that type. Any other test, such as an object or a function, finds nothing.
109
+ */
110
+ const UNMATCHABLE_BELOW = new Map([...DEPTH].map(([type, depth]) => [type, new Set([...DEPTH].filter(([parent, parentDepth]) => parentDepth >= depth && !(parent === "group" && type === "group")).map(([parent]) => parent))]));
111
+ /**
112
+ * Visits `node`, then its children in order, and returns the visitor's result
113
+ * for `node`, or the first EXIT a descendant's visitor returns.
114
+ *
115
+ * Reads `children` after the visitor runs, and again after each child, so a
116
+ * visitor may change its own children or its parent's.
117
+ */
118
+ function walk(node, ancestors, context) {
119
+ const result = context.predicate(node, ancestors) ? context.visitor(node, ancestors) : void 0;
120
+ const action = Array.isArray(result) ? result[0] : result;
121
+ if (action === EXIT$1 || action === SKIP$1 || !("children" in node) || context.unmatchableBelow?.has(node.type)) return result;
122
+ const childAncestors = [...ancestors, node];
123
+ let index = 0;
124
+ while (index < node.children.length) {
125
+ const child = node.children[index];
126
+ const childResult = walk(child, childAncestors, context);
127
+ if ((Array.isArray(childResult) ? childResult[0] : childResult) === EXIT$1) return childResult;
128
+ const next = Array.isArray(childResult) ? childResult[1] : childResult;
129
+ index = typeof next === "number" ? next : index + 1;
130
+ }
131
+ return result;
132
+ }
75
133
  //#endregion
76
134
  export { EXIT, SKIP, visit };
77
135
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Nodes } from \"@glion/ast\";\n\nimport type { Predicate, Test } from \"./types\";\n\n/**\n * The predicate a `visit` test describes.\n *\n * - `null` matches every node.\n * - A string matches nodes whose `type` equals it.\n * - A function is the predicate.\n * - An object matches nodes whose own property equals (`===`) each of its values.\n * A property the node does not own reads as `undefined`, so an `undefined`\n * value matches an absent property, and a key that names an inherited member\n * (`constructor`, `toString`, an own `__proto__`) matches no node. The\n * object's entries are read once, when the predicate is created.\n *\n * @example\n * ```typescript\n * const msh = s(\"MSH\", f(\"|\"));\n *\n * createTest(null)(msh, []); // true\n * createTest(\"segment\")(msh, []); // true\n * createTest(\"field\")(msh, []); // false\n *\n * createTest({ type: \"segment\", name: \"MSH\" })(msh, []); // true\n * createTest({ name: \"PID\" })(msh, []); // false\n *\n * // `undefined` matches a property the node does not have\n * createTest({ name: undefined })(f(\"|\"), []); // true\n *\n * // An inherited member is never matched\n * createTest({ constructor: Object })(msh, []); // false\n *\n * // A function receives the ancestors as well\n * const inGroup = createTest((_node, ancestors) => ancestors.length > 1);\n * ```;\n *\n * @param test - `null`, a node type, a property object, or a predicate.\n * @returns The predicate.\n */\nexport function createTest(test: Test<Nodes>): Predicate {\n if (test === null) {\n return () => true;\n }\n if (typeof test === \"string\") {\n return (node) => node.type === test;\n }\n if (typeof test === \"function\") {\n // Used as is: `visit` calls it with `(node, ancestors)`, so it may match on\n // a node's position in the tree as well as on the node itself.\n return test;\n }\n\n // Read once here rather than per visited node: a visit calls the predicate\n // for every node, and a test object changed during the visit does not change\n // which nodes match.\n const entries = Object.entries(test);\n\n return (node) =>\n entries.every(\n ([key, value]) =>\n // `Object.hasOwn` limits the match to the node's own properties. Without\n // it, `node[key]` also finds inherited members, so `{ constructor: x }`\n // or `{ toString: x }` would be compared against `Object.prototype`.\n // `Reflect.get(node, key)` is `node[key]`; it compiles for an arbitrary\n // string key, which `Nodes` (no index signature) does not allow.\n (Object.hasOwn(node, key) ? Reflect.get(node, key) : undefined) ===\n value\n );\n}\n","/**\n * HL7v2 AST visitor over `unist-util-visit-parents`, typed for `@glion/ast`.\n *\n * @module\n */\n\nimport type { Nodes } from \"@glion/ast\";\nimport { visitParents } from \"unist-util-visit-parents\";\n\nimport type { Test, Visitor } from \"./types\";\nimport { createTest } from \"./utils\";\n\nexport type { VisitorResult } from \"unist-util-visit-parents\";\n\nexport { EXIT, SKIP } from \"unist-util-visit-parents\";\n\nexport type { Predicate, Test, Visitor } from \"./types\";\n\n// Overload signatures\nexport function visit(tree: Nodes, visitor: Visitor): void;\nexport function visit<Type extends Nodes[\"type\"]>(\n tree: Nodes,\n test: Type,\n visitor: Visitor<Extract<Nodes, { type: Type }>>\n): void;\nexport function visit<T extends Nodes>(\n tree: Nodes,\n test: Test<T>,\n visitor: Visitor<T>\n): void;\n\n/**\n * Visit nodes in an HL7 AST tree.\n *\n * @param tree - The tree to traverse (can be any node type, not just Root)\n * @param test - Optional test to filter nodes (type string, partial match, or\n * Test function)\n * @param visitor - Function called for each matching node\n *\n * **Important**: If you pass a function as the second argument, it is always\n * treated as a Visitor, never as a Test. To use a Test function, you MUST\n * provide both the test and visitor parameters: `visit(tree, testFn,\n * visitorFn)`.\n */\nexport function visit<T extends Nodes>(\n tree: Nodes,\n arg2: Visitor<T> | Test<T>,\n arg3?: Visitor<T>\n): void {\n let test: Test<T> = null;\n let visitor: Visitor<T>;\n\n if (arg3 === undefined) {\n visitor = arg2 as Visitor<T>;\n } else {\n test = arg2 as Test<T>;\n visitor = arg3;\n }\n\n const predicate = createTest(test as Test<Nodes>);\n\n // The caller's test runs in the visitor, not as visit-parents' test: it may\n // read `ancestors`, which visit-parents gives only to the visitor.\n visitParents(tree, (node, ancestors) => {\n if (!predicate(node, ancestors)) {\n // Returning nothing means \"continue\": visit-parents still walks into\n // this node's children, so `visit(tree, \"field\", …)` reaches the fields\n // of segments it does not match.\n return;\n }\n\n // visit-parents reads the visitor's return value to decide what to visit\n // next (CONTINUE, SKIP, EXIT, an index, or both), so the caller's result\n // is passed through unchanged.\n return visitor(node as T, ancestors);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,WAAW,MAA8B;AACvD,KAAI,SAAS,KACX,cAAa;AAEf,KAAI,OAAO,SAAS,SAClB,SAAQ,SAAS,KAAK,SAAS;AAEjC,KAAI,OAAO,SAAS,WAGlB,QAAO;CAMT,MAAM,UAAU,OAAO,QAAQ,KAAK;AAEpC,SAAQ,SACN,QAAQ,OACL,CAAC,KAAK,YAMJ,OAAO,OAAO,MAAM,IAAI,GAAG,QAAQ,IAAI,MAAM,IAAI,GAAG,KAAA,OACrD,MACH;;;;;;;;;;;;;;;;;ACxBL,SAAgB,MACd,MACA,MACA,MACM;CACN,IAAI,OAAgB;CACpB,IAAI;AAEJ,KAAI,SAAS,KAAA,EACX,WAAU;MACL;AACL,SAAO;AACP,YAAU;;CAGZ,MAAM,YAAY,WAAW,KAAoB;AAIjD,cAAa,OAAO,MAAM,cAAc;AACtC,MAAI,CAAC,UAAU,MAAM,UAAU,CAI7B;AAMF,SAAO,QAAQ,MAAW,UAAU;GACpC"}
1
+ {"version":3,"file":"index.js","names":["EXIT","SKIP"],"sources":["../src/utils.ts","../src/index.ts"],"sourcesContent":["import type { Nodes } from \"@glion/ast\";\n\nimport type { Predicate, Test } from \"./types\";\n\n/**\n * The predicate a `visit` test describes.\n *\n * - `null` matches every node.\n * - A string matches nodes whose `type` equals it.\n * - A function is the predicate.\n * - An object matches nodes whose own property equals (`===`) each of its values.\n * A property the node does not own reads as `undefined`, so an `undefined`\n * value matches an absent property, and a key that names an inherited member\n * (`constructor`, `toString`, an own `__proto__`) matches no node. The\n * object's entries are read once, when the predicate is created.\n *\n * @example\n * ```typescript\n * const msh = s(\"MSH\", f(\"|\"));\n *\n * createTest(null)(msh, []); // true\n * createTest(\"segment\")(msh, []); // true\n * createTest(\"field\")(msh, []); // false\n *\n * createTest({ type: \"segment\", name: \"MSH\" })(msh, []); // true\n * createTest({ name: \"PID\" })(msh, []); // false\n *\n * // `undefined` matches a property the node does not have\n * createTest({ name: undefined })(f(\"|\"), []); // true\n *\n * // An inherited member is never matched\n * createTest({ constructor: Object })(msh, []); // false\n *\n * // A function receives the ancestors as well\n * const inGroup = createTest((_node, ancestors) => ancestors.length > 1);\n * ```;\n *\n * @param test - `null`, a node type, a property object, or a predicate.\n * @returns The predicate.\n */\nexport function createTest(test: Test<Nodes>): Predicate {\n if (test === null) {\n return () => true;\n }\n if (typeof test === \"string\") {\n return (node) => node.type === test;\n }\n if (typeof test === \"function\") {\n // Used as is: `visit` calls it with `(node, ancestors)`, so it may match on\n // a node's position in the tree as well as on the node itself.\n return test;\n }\n\n // Read once here rather than per visited node: a visit calls the predicate\n // for every node, and a test object changed during the visit does not change\n // which nodes match.\n const entries = Object.entries(test);\n\n return (node) =>\n entries.every(\n ([key, value]) =>\n // `Object.hasOwn` limits the match to the node's own properties. Without\n // it, `node[key]` also finds inherited members, so `{ constructor: x }`\n // or `{ toString: x }` would be compared against `Object.prototype`.\n // `Reflect.get(node, key)` is `node[key]`; it compiles for an arbitrary\n // string key, which `Nodes` (no index signature) does not allow.\n (Object.hasOwn(node, key) ? Reflect.get(node, key) : undefined) ===\n value\n );\n}\n","/**\n * HL7v2 AST visitor, typed for `@glion/ast`, with the semantics of\n * `unist-util-visit-parents`.\n *\n * @module\n */\n\nimport type { Nodes } from \"@glion/ast\";\nimport { EXIT, SKIP } from \"unist-util-visit-parents\";\nimport type { VisitorResult } from \"unist-util-visit-parents\";\n\nimport type { Predicate, Test, Visitor } from \"./types\";\nimport { createTest } from \"./utils\";\n\nexport type { VisitorResult } from \"unist-util-visit-parents\";\n\nexport { EXIT, SKIP } from \"unist-util-visit-parents\";\n\nexport type { Predicate, Test, Visitor } from \"./types\";\n\n// Overload signatures\nexport function visit(tree: Nodes, visitor: Visitor): void;\nexport function visit<Type extends Nodes[\"type\"]>(\n tree: Nodes,\n test: Type,\n visitor: Visitor<Extract<Nodes, { type: Type }>>\n): void;\nexport function visit<T extends Nodes>(\n tree: Nodes,\n test: Test<T>,\n visitor: Visitor<T>\n): void;\n\n/**\n * Visits `tree` and every node below it, depth-first and in document order,\n * calling `visitor` with each node that passes `test` and that node's\n * ancestors.\n *\n * `test` is a node type (`\"segment\"`), an object whose own properties a node\n * must equal (`{ name: \"PID\" }`), or a function of `(node, ancestors)`. With no\n * test, every node passes. A function passed as the second argument is always\n * the visitor; a test function needs the three-argument form.\n *\n * The visitor's result decides what the walk does next:\n *\n * - Nothing: enter the node's children, then go on.\n * - `SKIP`: do not enter the node's children.\n * - `EXIT`: stop the whole walk.\n * - A number: go on at that index among the node's siblings, after the visitor\n * removed or inserted siblings. `[action, index]` combines both.\n *\n * `ancestors` runs from `tree` to the node's parent. Siblings share one array:\n * a visitor MUST NOT change it, and MAY keep it, since a later visit never\n * changes it either.\n *\n * With a type test, the walk does not enter a node that cannot contain that\n * type in an HL7v2 tree (Root → Group → Segment → Field → FieldRepetition →\n * Component → Subcomponent): `visit(tree, \"segment\", …)` never enters a\n * segment. Nodes of a type `@glion/ast` does not define are always entered.\n *\n * @param tree - The node the walk starts at, of any type.\n * @param test - Which nodes the visitor is called with.\n * @param visitor - Called with each node that passes `test`.\n */\nexport function visit<T extends Nodes>(\n tree: Nodes,\n arg2: Visitor<T> | Test<T>,\n arg3?: Visitor<T>\n): void {\n let test: Test<T> = null;\n let visitor: Visitor<T>;\n\n if (arg3 === undefined) {\n visitor = arg2 as Visitor<T>;\n } else {\n test = arg2 as Test<T>;\n visitor = arg3;\n }\n\n walk(tree, [], {\n predicate: createTest(test as Test<Nodes>),\n unmatchableBelow: UNMATCHABLE_BELOW.get(test),\n visitor: visitor as Visitor<Nodes>,\n });\n}\n\n/** What one `visit` call holds fixed for every node it walks. */\ninterface Walk {\n predicate: Predicate;\n /** Node types whose children cannot pass the test. */\n unmatchableBelow: ReadonlySet<string> | undefined;\n visitor: Visitor<Nodes>;\n}\n\n/**\n * The depth of each `@glion/ast` node type in an HL7v2 tree. A group may hold\n * groups, so it is the one type found below its own depth.\n */\nconst DEPTH: ReadonlyMap<string, number> = new Map([\n [\"root\", 0],\n [\"group\", 1],\n [\"segment\", 2],\n [\"field\", 3],\n [\"field-repetition\", 4],\n [\"component\", 5],\n [\"subcomponent\", 6],\n]);\n\n/**\n * For each node type, the node types whose children cannot include a node of\n * that type. Any other test, such as an object or a function, finds nothing.\n */\nconst UNMATCHABLE_BELOW: ReadonlyMap<unknown, ReadonlySet<string>> = new Map(\n [...DEPTH].map(([type, depth]) => [\n type,\n new Set(\n [...DEPTH]\n .filter(\n ([parent, parentDepth]) =>\n parentDepth >= depth && !(parent === \"group\" && type === \"group\")\n )\n .map(([parent]) => parent)\n ),\n ])\n);\n\n/**\n * Visits `node`, then its children in order, and returns the visitor's result\n * for `node`, or the first EXIT a descendant's visitor returns.\n *\n * Reads `children` after the visitor runs, and again after each child, so a\n * visitor may change its own children or its parent's.\n */\nfunction walk(node: Nodes, ancestors: Nodes[], context: Walk): VisitorResult {\n const result = context.predicate(node, ancestors)\n ? context.visitor(node, ancestors)\n : undefined;\n const action = Array.isArray(result) ? result[0] : result;\n\n if (\n action === EXIT ||\n action === SKIP ||\n !(\"children\" in node) ||\n context.unmatchableBelow?.has(node.type)\n ) {\n return result;\n }\n\n // One array for all of this node's children: the visitor's contract forbids\n // changing it, so siblings can share it.\n const childAncestors = [...ancestors, node];\n let index = 0;\n\n while (index < node.children.length) {\n const child = node.children[index] as Nodes;\n const childResult = walk(child, childAncestors, context);\n const childAction = Array.isArray(childResult)\n ? childResult[0]\n : childResult;\n\n if (childAction === EXIT) {\n return childResult;\n }\n\n // A child's visitor that returns an index (alone or as `[action, index]`)\n // names the sibling to visit next; otherwise the walk moves one along.\n const next = Array.isArray(childResult) ? childResult[1] : childResult;\n index = typeof next === \"number\" ? next : index + 1;\n }\n\n return result;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwCA,SAAgB,WAAW,MAA8B;AACvD,KAAI,SAAS,KACX,cAAa;AAEf,KAAI,OAAO,SAAS,SAClB,SAAQ,SAAS,KAAK,SAAS;AAEjC,KAAI,OAAO,SAAS,WAGlB,QAAO;CAMT,MAAM,UAAU,OAAO,QAAQ,KAAK;AAEpC,SAAQ,SACN,QAAQ,OACL,CAAC,KAAK,YAMJ,OAAO,OAAO,MAAM,IAAI,GAAG,QAAQ,IAAI,MAAM,IAAI,GAAG,KAAA,OACrD,MACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACJL,SAAgB,MACd,MACA,MACA,MACM;CACN,IAAI,OAAgB;CACpB,IAAI;AAEJ,KAAI,SAAS,KAAA,EACX,WAAU;MACL;AACL,SAAO;AACP,YAAU;;AAGZ,MAAK,MAAM,EAAE,EAAE;EACb,WAAW,WAAW,KAAoB;EAC1C,kBAAkB,kBAAkB,IAAI,KAAK;EACpC;EACV,CAAC;;;;;;AAeJ,MAAM,QAAqC,IAAI,IAAI;CACjD,CAAC,QAAQ,EAAE;CACX,CAAC,SAAS,EAAE;CACZ,CAAC,WAAW,EAAE;CACd,CAAC,SAAS,EAAE;CACZ,CAAC,oBAAoB,EAAE;CACvB,CAAC,aAAa,EAAE;CAChB,CAAC,gBAAgB,EAAE;CACpB,CAAC;;;;;AAMF,MAAM,oBAA+D,IAAI,IACvE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,WAAW,CAChC,MACA,IAAI,IACF,CAAC,GAAG,MAAM,CACP,QACE,CAAC,QAAQ,iBACR,eAAe,SAAS,EAAE,WAAW,WAAW,SAAS,SAC5D,CACA,KAAK,CAAC,YAAY,OAAO,CAC7B,CACF,CAAC,CACH;;;;;;;;AASD,SAAS,KAAK,MAAa,WAAoB,SAA8B;CAC3E,MAAM,SAAS,QAAQ,UAAU,MAAM,UAAU,GAC7C,QAAQ,QAAQ,MAAM,UAAU,GAChC,KAAA;CACJ,MAAM,SAAS,MAAM,QAAQ,OAAO,GAAG,OAAO,KAAK;AAEnD,KACE,WAAWA,UACX,WAAWC,UACX,EAAE,cAAc,SAChB,QAAQ,kBAAkB,IAAI,KAAK,KAAK,CAExC,QAAO;CAKT,MAAM,iBAAiB,CAAC,GAAG,WAAW,KAAK;CAC3C,IAAI,QAAQ;AAEZ,QAAO,QAAQ,KAAK,SAAS,QAAQ;EACnC,MAAM,QAAQ,KAAK,SAAS;EAC5B,MAAM,cAAc,KAAK,OAAO,gBAAgB,QAAQ;AAKxD,OAJoB,MAAM,QAAQ,YAAY,GAC1C,YAAY,KACZ,iBAEgBD,OAClB,QAAO;EAKT,MAAM,OAAO,MAAM,QAAQ,YAAY,GAAG,YAAY,KAAK;AAC3D,UAAQ,OAAO,SAAS,WAAW,OAAO,QAAQ;;AAGpD,QAAO"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glion/util-visit",
3
- "version": "0.27.0",
3
+ "version": "0.28.0",
4
4
  "description": "An AST visitor for HL7v2 messages",
5
5
  "keywords": [
6
6
  "health",
@@ -45,10 +45,10 @@
45
45
  "tsdown": "0.21.10",
46
46
  "typescript": "6.0.3",
47
47
  "vitest": "4.1.11",
48
- "@glion/ast": "0.27.0",
49
- "@glion/builder": "0.27.0",
48
+ "@glion/ast": "0.28.0",
50
49
  "@glion/check-readme": "0.18.0",
51
- "@glion/parser": "0.27.0",
50
+ "@glion/builder": "0.28.0",
51
+ "@glion/parser": "0.28.0",
52
52
  "@glion/testing": "0.18.0",
53
53
  "@glion/tsconfig": "0.18.0"
54
54
  },