Jxpath instead of treewalker


NOTE (added): I am new to parsing but I see that “esquery” kindof does the same thing, but I will let this post stand anyway, in the hope someone will find it usefull.

I am using acorn to change the code transpiled by “ts” (typescript compiler) before it is emitted as a file to disk.

While writing typescript i have to fully specify the import url (as per standard ES2020) must have a file extension and directory imports dont work in ESM)



import isBrowser from './isBrowser.js'

ESM TARGET (after transpilation by ts)

import isBrowser from './isBrowser.js'

COMMONJS TARGET (after transpilation by ts)

> const isBrowser = require('./isBrowser.js') // <--- typescript cannot remove the ".js" I am doing this with acorn

basicly the ast require snippet looks like so (acorn parsed)

> Node {
>             type: 'CallExpression',
>             start: 10,
>             end: 33,
>             callee: Node { type: 'Identifier', start: 10, end: 17, name: 'require' },
>             arguments: [
>               Node {
>                 type: 'Literal',
>                 start: 18,
>                 end: 32,
>                 value: 'something.js',
>                 raw: "'something.js'"
>               }
>             ],
>             optional: false
>      }

I want to share a tool I wrote while back to “walk” through general JS object hierarchies, it works a bit like JXPATH for XML but instead for JS objects

so to find all require statements , all i need to do is this

// other import statements
import jxpath from 3@mangos/jxpath"

// parsing source with acorn

const astTree = parse(
  contents, // contents is the source data
      ecmaVersion: 'latest',
      sourceType: 'module',
      ranges: true,
      locations: false

 const data = jxpath(

// returned "data" is an iterator, 

// Use jxpath Query magic (breaking down the query expression steps from left to right)

//  /**/                             = recursive descent
//  /**/[type=CallExpression/           = having property type=CallExpression
//  /**/[type=CallExpression/callee/[type=Identifier]/   = having childobject with poperty  "type" equal to "Identifier"   
//  /**/[type=CallExpression/callee/[type=Identifier]/../   = select its parent selector
// /**/[type=CallExpression/callee/[type=Identifier]/../arguments/   = find sibling property "arguments"
// '/**/[type=CallExpression]/callee/[type=Identifier]/[name=require]/../arguments/[type=Literal]/[value=/\.js$/]/    = having property "type" with value "Literal" and property "value" with value ending in ".js"