ast-monkey-traverse examples

Table of Contents

Quick Take

import { strict as assert } from "assert";
import { traverse } from "ast-monkey-traverse";

const paths = [];
const source = {
  a: {
    foo: {
      bar: [
        {
          foo: "c",
        },
      ],
      d: {
        e: {
          foo: "f",
        },
      },
    },
  },
};

traverse(source, (key, val, innerObj) => {
  // if currently an object is traversed, you get both "key" and "val"
  // if it's array, only "key" is present, "val" is undefined
  const current = val !== undefined ? val : key;
  if (
    // it's object (not array)
    val !== undefined &&
    // and has the key we need
    key === "foo"
  ) {
    // push the path to array in the outer scope
    paths.push(innerObj.path);
  }
  return current;
});

// notice object-path notation "a.foo.bar.0.foo" - array segments use dots too:
assert.deepEqual(paths, [
  "a.foo",
  "a.foo.bar.0.foo",
  "a.foo.d.e.foo",
]);

Compatible With object-path

import { strict as assert } from "assert";
import op from "object-path";
import { traverse } from "ast-monkey-traverse";

const input = { a: "1", b: [{ c: "2" }] };
Object.freeze(input); // let's freeze it, just for fun
const result1 = [];

// the full traversal would look like this:
traverse(input, (key1, val1, innerObj) => {
  const current = val1 !== undefined ? val1 : key1;
  result1.push(innerObj.path);
  return current;
});

// notice the object-path notation is "b.0.c" not "b[0].c"
assert.deepEqual(result1, ["a", "b", "b.0", "b.0.c"]);

// each reported path is fully compatible with `object-path` get() method
assert.deepEqual(op.get(input, "a"), "1");
assert.deepEqual(op.get(input, "b"), [{ c: "2" }]);
assert.deepEqual(op.get(input, "b.0"), { c: "2" });
assert.deepEqual(op.get(input, "b.0.c"), "2");

Stop

import { strict as assert } from "assert";
import { traverse } from "ast-monkey-traverse";

const input = { a: "1", b: { c: "2" } };
const result1 = [];

// the full traversal would look like this:
traverse(input, (key1, val1, innerObj) => {
  const current = val1 !== undefined ? val1 : key1;
  result1.push(innerObj.path);
  return current;
});
assert.deepEqual(result1, ["a", "b", "b.c"]);

// now let's stop the traversal at path "b" (that's real
// path, how object-path would reference it)
const result2 = [];
traverse(input, (key1, val1, innerObj, stop) => {
  const current = val1 !== undefined ? val1 : key1;
  result2.push(innerObj.path);
  if (innerObj.path === "b") {
    stop.now = true; // <---------------- !!!!!!!!!!
  }
  return current;
});
assert.deepEqual(result2, ["a", "b"]);