Installation
Quick Take
Examples
Purpose
Traverse, read and edit a parsed JSON-like data structure.
API — traverse()
The main function traverse()
is imported like this:
It’s a function which takes two input arguments, 1. a data structure and 2. a callback function:
where the callback has the following API:
The callback API is similar to Array.forEach()
:
import { traverse } from "ast-monkey-traverse";
let ast = [{ a: "b", c: "d" }];
ast = traverse(ast, (key, val, innerObj, stop) => {
let current = val !== undefined ? val : key;
// if you are traversing and "stumbled" upon an object, it will have both "key" and "val"
// if you are traversing and "stumbled" upon an array, it will have only "key"
// you can detect either using the principle above.
// you can also now change "current" - what you return will be overwritten.
// return `NaN` to give instruction to delete currently traversed piece of AST.
//
return current; // #1 <------ it's obligatory to return it, unless you want to assign it to "undefined"
});
It’s very important to return the value of the callback function (point marked #1
above) because otherwise whatever you return will be written over the current AST piece being iterated.
If you want to delete, return NaN
.
API — version
You can import version
:
innerObj
in the callback
When you call traverse()
like this:
input = traverse(input, (key, val, innerObj, stop) => {
...
})
you get four variables:
key
val
innerObj
stop
— setstop.now = true;
to stop the traversal
If traverse()
is currently traversing a plain object, going each key/value pair, key
will be the object’s current key and val
will be the value.
If traverse()
is currently traversing an array, going through all elements, a key
will be the current element and val
will be null
.
innerObj object’s key | Type | Description |
---|---|---|
depth Type: Integer number | ||
depth | Integer number | Zero is root, topmost level. Every level deeper increments depth by 1 . |
path Type: String | ||
path | String | The path to the current value. The path uses object-path notation. |
topmostKey Type: String | ||
topmostKey | String | When you are very deep, this is the topmost parent’s key. |
parent Type: Type of the parent of current element being traversed | ||
parent | Type of the parent of current element being traversed | A whole parent (array or a plain object) which contains the current element. Its purpose is to allow you to query the siblings of the current element. |
parentType Type: String | ||
parentType | String | Either array if parent is array or object if parent is a plain object (not the “object” type, which includes functions, arrays etc.). |
Stopping
Here’s how to stop the traversal. Let’s gather all the traversed paths first. By the way, paths are marked in object-path
notation (arrays use dots too, a.1.b
instead of a[1].b
).
import { traverse } from "ast-monkey-traverse";
const input = { a: "1", b: { c: "2" } };
const gathered = [];
traverse(input, (key1, val1, innerObj) => {
const current = val1 !== undefined ? val1 : key1;
gathered.push(innerObj.path);
return current;
});
console.log(gathered);
// => ["a", "b", "b.c"]
All paths were gathered: ["a", "b", "b.c"]
.
Let’s force the program to stop at the path “b”:
import { traverse } from "ast-monkey-traverse";
const input = { a: "1", b: { c: "2" } };
const gathered = [];
traverse(input, (key1, val1, innerObj, stop) => {
const current = val1 !== undefined ? val1 : key1;
gathered.push(innerObj.path);
if (innerObj.path === "b") {
stop.now = true; // <---------------- !!!!!!!!!!
}
return current;
});
console.log(gathered);
// => ["a", "b"]
Notice how there were no more gathered paths after “b”, only ["a", "b"]
.
Compared to ast-monkey-traverse-with-lookahead
ast-monkey-traverse
can amend AST (it matters what you return within a callback)
ast-monkey-traverse-with-lookahead
is read-only, it can’t amend AST it reads
ast-monkey-traverse
does not “see” future nodes, it just reports what it has just traversed
ast-monkey-traverse-with-lookahead
can report as many nodes “from the future”, upon request
Personally, in the context of linting, parsing and other tooling, we’re going to use ast-monkey-traverse-with-lookahead
because we don’t need to mutate the AST, yet we need to “see” what’s next in order to patch AST tree errors.