Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

abstract-syntax-tree

Package Overview
Dependencies
Maintainers
3
Versions
67
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

abstract-syntax-tree - npm Package Compare versions

Comparing version 1.1.2 to 2.0.0

src/append.js

10

CHANGELOG.md
# abstract-syntax-tree changelog
## 2.0.0
* add: static methods: find, each, first, last, count, has, remove, equal and traverse
* add: getters -> type, body, source and map
* edit: replace method now accepts options object instead of a callback
* edit: removed the `is` method, please use static `equal` method instead
* edit: ast property has been replaced with _tree
* remove: `minify` and `beautify` methods
* remove: `toSource`, `toSourceMap` and `toString` methods
## 1.1.2

@@ -4,0 +14,0 @@

238

index.js

@@ -1,207 +0,171 @@

const cherow = require('cherow')
const esquery = require('esquery')
const astring = require('astring')
const estraverse = require('estraverse')
const template = require('estemplate')
const comparify = require('comparify')
const toAST = require('to-ast')
const prettier = require('prettier')
const sourcemap = require('source-map')
const find = require('./src/find')
const each = require('./src/each')
const first = require('./src/first')
const last = require('./src/last')
const count = require('./src/count')
const equal = require('./src/equal')
const has = require('./src/has')
const remove = require('./src/remove')
const prepend = require('./src/prepend')
const append = require('./src/append')
const replace = require('./src/replace')
const walk = require('./src/walk')
const traverse = require('./src/traverse')
const generate = require('./src/generate')
const parse = require('./src/parse')
const template = require('./src/template')
const sourcemap = require('./src/sourcemap')
const mark = require('./src/mark')
class AbstractSyntaxTree {
constructor (source, options) {
options = options || {}
if (typeof source === 'string') {
this.source = source
this.ast = this.constructor.parse(source, {
loc: true,
jsx: options.jsx
})
} else {
this.ast = source
}
static find (tree, selector) {
return find(tree, selector)
}
query (node, selector) {
return esquery(node, selector)
static each (tree, selector, callback) {
return each(tree, selector, callback)
}
find (selector, options) {
return this.query(this.ast, selector, options)
static first (tree, selector) {
return first(tree, selector)
}
each (selector, callback) {
return this.find(selector).forEach(callback)
static last (tree, selector) {
return last(tree, selector)
}
first (selector) {
return this.find(selector)[0]
static count (tree, selector) {
return count(tree, selector)
}
last (selector) {
var nodes = this.find(selector)
return nodes[nodes.length - 1]
static has (tree, selector) {
return has(tree, selector)
}
count (selector) {
return this.find(selector).length
static remove (tree, target, options) {
return remove(tree, target, options)
}
has (selector) {
return this.count(selector) > 0
static prepend (tree, node) {
return prepend(tree, node)
}
is (node, expected) {
return comparify(node, expected)
static append (tree, node) {
return append(tree, node)
}
remove (target, options) {
options = options || {}
if (typeof target === 'string') {
return this.removeBySelector(target, options)
}
this.removeByNode(target, options)
static equal (node1, node2) {
return equal(node1, node2)
}
removeBySelector (target, options) {
var nodes = this.find(target)
// this could be improved by traversing once and
// comparing the current node to the found nodes
// one by one while making the array of nodes smaller too
nodes.forEach(node => this.removeByNode(node, options))
static generate (tree, options) {
return generate(tree, options)
}
removeByNode (node, options) {
var count = 0
estraverse.replace(this.ast, {
enter: function (current, parent) {
if (options.first && count === 1) {
return this.break()
}
if (comparify(current, node)) {
count += 1
return this.remove()
}
},
leave: function (current, parent) {
if (current.expression === null ||
(current.type === 'VariableDeclaration' && current.declarations.length === 0)) {
return this.remove()
}
}
})
static parse (source, options) {
return parse(source, options)
}
walk (callback) {
return estraverse.traverse(this.ast, { enter: callback })
static walk (tree, callback) {
return walk(tree, callback)
}
traverse (options) {
return estraverse.traverse(this.ast, options)
static traverse (tree, callback) {
return traverse(tree, callback)
}
replace (options) {
return replace(this.ast, options)
static replace (tree, callback) {
return replace(tree, callback)
}
prepend (node) {
this.ast.body.unshift(node)
static template (source, options) {
return template(source, options)
}
append (node) {
this.ast.body.push(node)
constructor (source, options = {}) {
if (typeof source === 'string') {
this._tree = typeof source === 'string' ? parse(source, { loc: true, ...options }) : source
} else {
this._tree = source
}
}
body () {
return this.ast.body
get type () {
return this._tree.type
}
wrap (callback) {
this.ast.body = callback(this.ast.body)
get body () {
return this._tree.body
}
unwrap () {
let block = this.first('BlockStatement')
this.ast.body = block.body
get source () {
return generate(this._tree)
}
template (source, options) {
options = options || {}
if (typeof source === 'string') {
return template(source, options).body
}
return toAST(source, options)
get map () {
return sourcemap(this._tree).map
}
beautify (source, options) {
if (typeof options === 'boolean') { options = {} }
options = { parser: 'babylon', ...options }
return prettier.format(source, options)
set body (body) {
this._tree.body = body
}
mark () {
let cid = 1
this.walk(node => {
node.cid = cid
cid += 1
})
find (selector) {
return find(this._tree, selector)
}
minify (ast) {
return ast
each (selector, callback) {
return each(this._tree, selector, callback)
}
toSource (options) {
options = options || {}
first (selector) {
return first(this._tree, selector)
}
if (options.minify) {
this.ast = this.minify(this.ast)
}
last (selector) {
return last(this._tree, selector)
}
var source = this.constructor.generate(this.ast)
count (selector) {
return count(this._tree, selector)
}
if (options.beautify) {
source = this.beautify(source, options.beautify)
}
has (selector) {
return has(this._tree, selector)
}
var map
if (options.sourceMap) {
map = this.toSourceMap(options)
}
remove (target, options) {
return remove(this._tree, target, options)
}
this.source = source
walk (callback) {
return walk(this._tree, callback)
}
if (map) { return { map, source } }
return source
traverse (options) {
return traverse(this._tree, options)
}
toSourceMap (options) {
const map = new sourcemap.SourceMapGenerator({
file: options.sourceFile || 'UNKNOWN'
})
this.constructor.generate(this.ast, {
sourceMap: map
})
return map.toString()
replace (options) {
return replace(this._tree, options)
}
toString (options) {
return this.toSource(options)
prepend (node) {
return prepend(this._tree, node)
}
static generate (tree, options) {
return astring.generate(tree, options)
append (node) {
return append(this._tree, node)
}
static parse (source, options) {
return cherow.parseModule(source, options)
wrap (callback) {
this._tree.body = callback(this._tree.body)
}
static walk (node, callback) {
return estraverse.traverse(node, { enter: callback })
unwrap () {
this._tree.body = first(this._tree, 'BlockStatement').body
}
static replace (node, callback) {
return replace(node, { enter: callback })
mark () {
return mark(this._tree)
}

@@ -208,0 +172,0 @@ }

{
"name": "abstract-syntax-tree",
"version": "1.1.2",
"description": "abstract syntax tree class for js",
"version": "2.0.0",
"description": "abstract syntax tree",
"main": "index.js",
"scripts": {
"test": "node test/basic.js && node test/examples.js && node test/jsx.js && node test/static.js",
"test": "ava 'test/*.js'",
"lint": "standard",
"benchmark": "node test/benchmark.js",
"memory": "node test/memory.js"
"benchmark": "ava 'test/benchmarks/*.js'",
"coverage": "nyc npm test"
},

@@ -20,5 +20,5 @@ "engines": {

"keywords": [
"ast",
"abstract syntax tree",
"javascript",
"abstract syntax tree"
"ast"
],

@@ -36,4 +36,6 @@ "author": "Emil Ajdyna <emil@ajdyna.com>",

"devDependencies": {
"ava": "^1.0.1",
"benchmark": "^2.1.4",
"standard": "^11.0.1"
"nyc": "^13.1.0",
"standard": "^12.0.1"
},

@@ -48,5 +50,4 @@ "dependencies": {

"source-map": "^0.7.2",
"prettier": "^1.15.1",
"to-ast": "^1.0.0"
}
}
# abstract-syntax-tree
![npm](https://img.shields.io/npm/v/abstract-syntax-tree.svg) [![Build Status](https://travis-ci.org/buxlabs/abstract-syntax-tree.svg?branch=master)](https://travis-ci.org/buxlabs/ast)
![npm](https://img.shields.io/npm/v/abstract-syntax-tree.svg) ![build](https://img.shields.io/codeship/c6391230-e90c-0136-c202-269c372fd6f7/master.svg)
## What is an abstract syntax tree?

@@ -42,15 +43,2 @@

## What are abstract syntax trees used for?
They're used e.g. for code's:
- highligthing
- linting
- refactoring
- transformations
- analysis
- minification
- obfuscation
- generation
- source maps
## Installation

@@ -60,135 +48,180 @@

## Key Features
## How does it work?
- source to ast conversion
- ast to source generation
- ast traversal
- ast manipulation
The library exposes a set of utility methods that can be useful for analysis or transformation of abstract syntax trees. It supports functional and object-oriented programming style.
## Methods
## Examples
### find
```js
const { parse, find } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(find(tree, 'Literal')) // [ { type: 'Literal', value: 42 } ]
```
Find all nodes of given type.
```js
const AbstractSyntaxTree = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = new AbstractSyntaxTree(source)
console.log(tree.find('Literal')) // [ { type: 'Literal', value: 42 } ]
```
## API
### Static Methods
#### parse
```javascript
const source = 'const a = "x";'
const ast = new AbstractSyntaxTree(source)
ast.find('VariableDeclaration')
const { parse } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(tree) // { type: 'Program', body: [ ... ] }
```
### each
#### generate
Iterate over all nodes of given type.
```javascript
const source = 'const a = "x";'
const ast = new AbstractSyntaxTree(source)
ast.each('VariableDeclaration', node => {})
const { parse, generate } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(generate(tree)) // 'const answer = 42;'
```
### has
#### walk
Check if ast contains a node of given type.
```javascript
const source = 'const a = "x";'
const ast = new AbstractSyntaxTree(source)
ast.has('VariableDeclaration')
const { parse, walk } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
walk(tree, (node, parent) => {
console.log(node)
console.log(parent)
})
```
### count
#### find
Count ast nodes of given type.
```javascript
const source = 'const a = "x"; const b = "y";'
const ast = new AbstractSyntaxTree(source)
ast.count('VariableDeclaration')
const { parse, find } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
const nodes = find(tree, 'VariableDeclaration')
console.log(nodes)
```
### first
#### traverse
First first node of given type.
```javascript
const source = 'var a = "x";'
const ast = new AbstractSyntaxTree(source)
ast.first('VariableDeclaration')
const { parse, traverse } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
traverse(tree, {
enter (node) {},
leave (node) {}
})
```
### last
#### replace
Find last node of given type.
```javascript
const source = 'const a = "x";'
const ast = new AbstractSyntaxTree(source)
ast.last('VariableDeclaration')
const { parse, replace } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
replace(tree, {
enter (node) {
if (node.type === 'VariableDeclaration') {
node.kind = 'let'
}
return node
}
})
```
### remove
#### remove
Remove all nodes that match the criteria.
```javascript
const { parse, remove, generate } = require('abstract-syntax-tree')
const source = '"use strict"; const b = 4;'
const ast = new AbstractSyntaxTree(source)
ast.remove({ type: 'Literal', value: 'use strict' })
const ast = parse(source)
remove(tree, { type: 'Literal', value: 'use strict' })
console.log(generate(tree)) // 'const b = 4;'
```
#### each
```javascript
const source = 'function hello () { const foo = "bar"; return "world"; }'
const ast = new AbstractSyntaxTree(source)
ast.remove('BlockStatement > VariableDeclaration')
const { parse, each } = require('abstract-syntax-tree')
const source = 'const foo = 1; const bar = 2;'
const tree = parse(source)
each(tree, 'VariableDeclaration', node => {
console.log(node)
})
```
### walk
#### first
Walks over all nodes
```javascript
const { parse, first } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(first(tree, 'VariableDeclaration')) // { type: 'VariableDeclaration', ... }
```
#### last
```javascript
const source = 'const a = 1'
const ast = new AbstractSyntaxTree(source)
ast.walk((node, parent) => {})
const { parse, last } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(last(tree, 'VariableDeclaration')) // { type: 'VariableDeclaration', ... }
```
### traverse
#### has
Walks over all nodes
```javascript
const { parse, has } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(has(tree, 'VariableDeclaration')) // true
```
#### count
```javascript
const source = 'const a = 1'
const ast = new AbstractSyntaxTree(source)
ast.walk({
enter (node) {},
leave (node) {}
})
const { parse, count } = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = parse(source)
console.log(count(tree, 'VariableDeclaration')) // 1
```
### replace
#### equal
Replace all nodes that match the criteria.
```javascript
const { equal } = require('abstract-syntax-tree')
console.log(equal({ type: 'Literal', value: 42 }, { type: 'Literal', value: 42 })) // true
console.log(equal({ type: 'Literal', value: 41 }, { type: 'Literal', value: 42 })) // false
````
#### template
```javascript
const source = 'const a = 1'
const ast = new AbstractSyntaxTree(source)
ast.replace({
enter (node) {
if (node.type === 'VariableDeclaration') {
node.kind = 'let'
}
return node
}
})
const { template } = require('abstract-syntax-tree')
const literal = template(42)
const nodes = template('const foo = <%= bar %>;', { bar: { type: 'Literal', value: 1 } })
```
### prepend
### Instance Methods
Almost all of the static methods (excluding parse, generate, template and equal) have their instance equivalents. There are few extra instance methods:
#### prepend
Prepend a node to the body.
```javascript
const AbstractSyntaxTree = require('abstract-syntax-tree')
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
ast.prepend({
const tree = new AbstractSyntaxTree(source)
tree.prepend({
type: 'ExpressionStatement',

@@ -202,3 +235,3 @@ expression: {

### append
#### append

@@ -208,5 +241,6 @@ Append a node to the body.

```javascript
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
ast.append({
const AbstractSyntaxTree = require('abstract-syntax-tree')
const source = 'const answer = 42'
const tree = new AbstractSyntaxTree(source)
tree.append({
type: 'ExpressionStatement',

@@ -220,10 +254,23 @@ expression: {

### wrap
#### mark
Add cid to all nodes
```javascript
const AbstractSyntaxTree = require('abstract-syntax-tree')
const tree = new AbstractSyntaxTree('const a = 1')
tree.mark()
console.log(tree.first('Program').cid) // 1
console.log(tree.first('VariableDeclaration').cid) // 2
```
#### wrap
Wrap body with given node.
```javascript
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
ast.wrap(body => {
const AbstractSyntaxTree = require('abstract-syntax-tree')
const source = 'const a = 1'
const tree = new AbstractSyntaxTree(source)
tree.wrap(body => {
return [

@@ -249,59 +296,24 @@ {

### unwrap
#### unwrap
Change the code to the first BlockStatement body
```javascript
const AbstractSyntaxTree = require('abstract-syntax-tree')
const source = '(function () { console.log(1); }())'
const ast = new AbstractSyntaxTree(source)
ast.unwrap()
ast.toSource()
const tree = new AbstractSyntaxTree(source)
tree.unwrap()
console.log(tree.source) // 'console.log(1);'
```
### template
### Getters
Create ast partials from templates
#### type
```javascript
const source = 'console.log(1);'
const ast = new AbstractSyntaxTree(source)
ast.template('const foo = <%= bar %>;' { bar: { type: 'Literal', value: 1 } })
```
#### body
### mark
#### source
Add cid to all nodes
#### map
```javascript
const ast = new AbstractSyntaxTree('const a = 1;')
ast.mark()
assert(ast.first('Program').cid === 1)
assert(ast.first('VariableDeclaration').cid === 2)
```
### Setters
### toSource
Convert the ast to string.
```javascript
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
const source = ast.toSource()
```
```javascript
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
const { source, map } = ast.toSource({ sourceMap: true })
```
### toSourceMap
Generates a source map.
```javascript
const source = 'const a = 1;'
const ast = new AbstractSyntaxTree(source)
const map = ast.toSourceMap()
```
#### body

@@ -18,4 +18,4 @@ const estraverse = require('estraverse')

module.exports = function replace (ast, options) {
return estraverse.replace(ast, {
module.exports = function replace (tree, options) {
return estraverse.replace(tree, {
enter (node, parent) {

@@ -34,2 +34,2 @@ if (options.enter) {

})
}
}

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc