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

ast-query

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ast-query - npm Package Compare versions

Comparing version 0.1.0-pre.2 to 0.2.0

lib/factory/value.js

20

Gruntfile.js

@@ -1,3 +0,3 @@

/*jshint strict:false */
module.exports = function( grunt ) {
module.exports = function (grunt) {
'use strict';

@@ -8,5 +8,5 @@ grunt.initConfig({

options: {
jshintrc : ".jshintrc"
jshintrc : '.jshintrc'
},
all: [ "lib/**/*.js", "test/**/*.js" ]
all: [ 'lib/**/*.js', 'test/**/*.js', 'gruntfile.js' ]
},

@@ -16,6 +16,6 @@

options: {
ui: "bdd",
reporter: "spec"
ui: 'bdd',
reporter: 'spec'
},
all: "test/specs/**/*.js"
all: 'test/**/*.js'
}

@@ -25,8 +25,8 @@

grunt.loadNpmTasks("grunt-contrib-jshint");
grunt.loadNpmTasks("grunt-simple-mocha");
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-simple-mocha');
grunt.loadNpmTasks('grunt-release');
grunt.registerTask("default", [ "jshint", "simplemocha" ]);
grunt.registerTask('default', [ 'jshint', 'simplemocha' ]);
};

@@ -1,69 +0,81 @@

var falafel = require("falafel");
var helpers = require("./helpers");
var types = require("./types");
var esprima = require('esprima');
var escodegen = require('escodegen');
var traverse = require('traverse');
var utils = require('./util/utils');
var Variable = require('./nodes/variable');
var CallExpression = require('./nodes/CallExpression');
var AssignmentExpression = require('./nodes/AssignmentExpression');
var Body = require('./nodes/Body');
module.exports = Tree;
function Tree(source) {
this.tree = esprima.parse(source);
this.body = new Body(this.tree.body);
}
/**
* Queriable AST Tree constructor
* @param {String} src Source code string
* Return the regenerated code string
* @return {String} outputted code
*/
function Tree( src ) {
this.src = src;
this.tokens = [];
}
Tree.prototype.toString = function () {
// Filter the three to remove temporary placeholders
var tree = traverse(this.tree).map(function (node) {
if (node && node.TEMP === true) {
this.remove();
}
});
return escodegen.generate(tree);
};
/**
* Get the compiled source string
* @return {String} source code
* Find variables declaration
* @param {String} name Name of the declared variable
* @return {Variable}
*/
Tree.prototype.toString = function() {
return this._process().src;
Tree.prototype.var = function (name) {
var nodes = traverse(this.tree).nodes().filter(function (node) {
if (node && node.type === 'VariableDeclarator' && node.id.name === name) {
return true;
}
});
return new Variable(nodes);
};
/**
* Compile the source by passing control to registered tokens
* @return {Self} Tree
* Select function/method calls
* @param {String} name Name of the called function (`foo`, `foo.bar`)
* @return {CallExpression}
*/
Tree.prototype._process = function() {
var self = this;
var output = falafel( this.src, helpers.unbox(this.tokens, "use"));
this.src = output.toString();
this.tokens.length = 0;
return this;
};
Tree.prototype.callExpression = function (name) {
var nodes = traverse(this.tree).nodes().filter(function (node) {
if (!node || node.type !== 'CallExpression') return false;
// Simple function call
if (node.callee.type === 'Identifier' && node.callee.name === name) return true;
// ---
// Token types
// Method call
if (utils.matchMemberExpression(name, node.callee)) return true;
});
return new CallExpression(nodes);
};
/**
* Add a variable token to the queue
* @param {string} name Variable name
* @return {Var token} Selected variable token
* Select an AssignmentExpression node
* @param {String} assignedTo Name of assignement left handside
* @return {AssignmentExpression} Matched node
*/
Tree.prototype.var = function( name ) {
var token = new types.Var(name);
this.tokens.push( token );
return token;
};
Tree.prototype.assignment = function (assignedTo) {
var nodes = traverse(this.tree).nodes().filter(function (node) {
if (!node || node.type !== 'AssignmentExpression') return false;
/**
* Add an object token to the queue
* @return {Var token} Selected variable token
*/
Tree.prototype.object = function() {
var token = new types.Object();
this.tokens.push( token );
return token;
// Simple assignement
if (node.left.type === 'Identifier' && node.left.name === assignedTo) return true;
// Assignement to an object key
if (utils.matchMemberExpression(assignedTo, node.left)) return true;
});
return new AssignmentExpression(nodes);
};
/**
* Add an array token to the queue
* @return {Var token} Selected variable token
*/
Tree.prototype.array = function() {
var token = new types.Array();
this.tokens.push( token );
return token;
module.exports = function (source) {
return new Tree(source);
};
{
"name": "ast-query",
"version": "0.1.0-pre.2",
"version": "0.2.0",
"description": "Declarative JavaScript AST modification façade",

@@ -8,3 +8,9 @@ "main": "lib/tree.js",

"license": "MIT",
"keywords": [ "AST", "source", "traversal", "syntax", "tree" ],
"keywords": [
"AST",
"source",
"traversal",
"syntax",
"tree"
],
"scripts": {

@@ -18,6 +24,9 @@ "test": "grunt"

"dependencies": {
"falafel": "~0.3.1"
"esprima": "~1.0.4",
"escodegen": "~1.2.0",
"lodash": "~2.4.1",
"traverse": "~0.6.6",
"class-extend": "~0.1.1"
},
"devDependencies": {
"chai": "~1.7.2",
"grunt": "~0.4.1",

@@ -24,0 +33,0 @@ "grunt-cli": "~0.1.9",

AST Query
================
Tentative to a simple JavaScript AST modification library.
This project is a tentative to create a simple JavaScript AST modification library.
If you've ever worked with AST trying to edit source code, you've probably had a hard time
as the syntax is somehow terse and you need to loop and use conditionnals a lot. AST Query
try to hide this complexity behind a declarative façade.
If you've ever worked with AST trying to edit source code, you'll know it is a bad time. AST syntax is terse and forces you to loop a three and use conditionals structure a lot. AST Query hide this complexity behind a declarative façade.
Making this choice, AST Query does not try to cover a full AST API, but instead answer
common needs.
Making the simplicity choice means AST Query won't try to cover the full AST API. Rather we strive to answer commons needs.

@@ -19,12 +16,13 @@

First, you always need to create a `Tree` which you'll edit
First, you need to pass a program code into AST query:
``` javascript
var Tree = require("ast-query");
var tree = new Tree("var a = 'foo'");
var program = require("ast-query");
var tree = program("var a = 'foo'");
```
To get the source code back after modifying the AST, call the `toString` method on the
tree.
This function returns a wrapped AST tree you can query and modify.
Once you've modified the AST, get the source code back by calling the `toString` method on the tree.
``` javascript

@@ -38,120 +36,143 @@ // ...

Reminder you're editing source code. As so, you'll need to add extra quotes when outputting
strings (e.g.: `"'foo'"`).
Remember that you are editing source code. This mean you provide raw source code strings. This mean you need to double wrap strings (e.g.: `"'foo'"`). If that's not done, AST-query assume you're referencing a variable called `foo`.
Also, note that AST Query isn't checking you output valid code; neither does it check for
whitespace consistency. You may want to pass each transformed sources in a beautifier if
this is important.
API
================
Tree
Program
----------------
### `new Tree( sourceCode )`
- **sourceCode**
- type: String
- The source code to edit.
### `var tree = program( sourceCode )`
- **sourceCode** (String) - The source code to edit.
Returns an AST tree you can then query as explained below:
### `tree.var( name )`
- **name**
- type: String
- The variable name
- Returns: A `variable` token. [See object methods](#variable-token)
- **name** (String) - The variable name
### `tree.object()`
- Returns: An `object` literal token. [See object methods](#object-literal-token)
Find and returns a [`Variable` node](#variable-node).
Given this code
Variable token
``` js
var bar = 23;
```
You'd call `tree.var('bar')` to get the Variable node.
### `tree.callExpression( name )`
- **name** (String) - The name of the function or method being called.
Find a function or method call and return a [`CallExpression` node](#callexpression-node)
Given this code
```js
grunt.initConfig({});
```
You'd call `tree.callExpression('grunt.initConfig')` to get the CallExpression node.
### `tree.assignment( assignedTo )`
- **assignedTo** (String) - The name (name or object) a value is assigned to
Find and return an [`AssignementExpression` node](#AssignementExpression-node).
You'd call `tree.assignment('module.exports')` to query the code below:
```js
module.exports = function () {
// code
};
```
### `tree.body`
Property representing the program body in a [`Body` node](#body-node).
Variable node
-----------------
### `.value( value )`
- **value**
- type: String|function
- A string containing the new variable value or a function taking the current value as
a parameter and returning the new variable value
- **value** (String) _optionnal_ - A string containing the new variable value.
It returns the current or new value wrapped in AST query interface.
### `.rename( name )`
- **name**
- type: String
- Change the variable name
- **name** (String) - Change the variable name
### `.replaceWith( value )`
- **value**
- type: String
- Replace the current variable declaration string with a new one. Note this method only
replace the string between the var declarations tokens, e.g. `var <value goes here>;`
CallExpression node
--------------------
### `.insertAfter( value )`
- **value**
- type: String
- Insert a string after the variable declaration code blocks. If there's multiple
declaration inside the code block, the string will be inserted after everyone.
### `.filter( iterator )`
- **iterator** (Function) - Function receiving each node as arguments and returning true to keep the current node in the returned set.
### `.insertBefore( value )`
- **value**
- type: String
- Insert a string before the `var` keyword
Return a new CallExpression nodes collection with nodes passing the iterator test.
### `.delete()`
- Delete the variable declaration. If the declaration block contain a single variable,
it'll delete it all, otherwise, it'll only delete the relevant section
### `.arguments`
A property pointing to an [`ArrayExpression` node] referencing the called function arguments.
Object literal token
AssignementExpression node
--------------------
### `.assignedTo( name )`
- **name**
- type: String
- Only select object assigned to a `var`.
### `.value( value )`
### `.passedTo( name )`
- **name**
- type: String
- Only select object passed as argument to a `function` or a `method`
- Known issue: Currently only work with objects nested two levels down. (PR welcomed)
Replace the assignement value with a new value or return the current value wrapped in an AST query interface.
Example:
```javascript
var tree = new Tree("grunt.init({ key: 'value' })");
tree.object().passedTo("grunt.init").key("key").value("'foo'");
console.log( tree.toString() );
```
Literal node
--------------------
### `.key( name )`
- **name**
- type: String
- A key name to select
- Returns: A `Property` token. [See object methods](#property-token)
A Literal node represent a raw JavaScript value as a String, a Number or a Boolean.
### `.value( value )`
Property token
------------------
Get or update the value.
### `.value( value )`
- **value**
- type: String|function
- A string containing the new property value or a function taking the current value as
a parameter and returning the new property value
FunctionExpression node
-------------------
### `.rename( name )`
- **name**
- type: String
- Change the variable property key
Node representing a function declaration (e.g. `function () {}`).
### `.delete()`
- Delete the property from the object.
### `.body`
Property pointing to a [`Body` node](#body-node) representing the function expression body.
ObjectExpression node
-------------------
### `.key( name )`
- **name**
- type: String
- If the property value is an object, key name to select (if value is not an object, this
condition is just ignored).
- Returns: A `Property` token.
- **name** (String) - Key name
Get a key value object or create a blank placeholder
### `value( value )`
Replace current node with a new value. Returns the new value wrapped.
ArrayExpression node
-------------------
### `.push( value )`
- **value** (String) - value to push in the array
### `.unshift( value )`
- **value** (String) - value to unshift in the array
### `.at( index )`
- **index** (Number) - Index of the value to fetch
Returns a value wrapped in an AST query interface.
Body node
-------------------
### `.prepend( code )`
Preprend the given code lines in the body. If a `"use strict";` statement is present, it always stay first.
### `.append( code )`
Append the given code lines in the body.
Contributing

@@ -158,0 +179,0 @@ =====================

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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