-
Notifications
You must be signed in to change notification settings - Fork 94
Update deps and adds some useful API documentation #49
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
011b931
7d05c2c
3959378
e1da92d
c29c622
ee41f84
457fa59
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,256 @@ | ||
## API and usage | ||
|
||
*Install (via npm for Node.js)* | ||
|
||
`npm i esquery --save` | ||
|
||
*Quick start* | ||
|
||
```js | ||
const esquery = require('esquery'); | ||
|
||
const conditional = "if (x === 1) { foo(); } else { x = 2; }" | ||
|
||
|
||
var matches = esquery(conditional, "[name='x']") | ||
console.log(matches); | ||
``` | ||
|
||
The following examples are taken from the test cases in `/tests` folder. | ||
|
||
### Attribute query | ||
|
||
*for loop* | ||
|
||
`for (i = 0; i < foo.length; i++) { foo[i](); }` | ||
|
||
- `[operator="="]` - matches `i = 0` | ||
- `[object.name="foo"]` - object named `foo` ie. `foo.length` | ||
- `[name=/i|foo/]` - where name of node matches `i` or `foo` | ||
|
||
*simple function* | ||
|
||
```js | ||
function foo(x, y) { | ||
var z = x + y; | ||
z++; | ||
return z; | ||
} | ||
``` | ||
|
||
- `[kind="var"]` - a `var` | ||
- `[id.name="foo"]` - `foo` declaration, fx a function or variable | ||
- `[left]` - left expression, such as `var z` | ||
- `FunctionDeclaration[params.0.name=x]` - where first argument of function is named `x` | ||
|
||
*simple program* | ||
|
||
```js | ||
var x = 1; | ||
var y = 'y'; | ||
x = x * 2; | ||
if (y) { y += 'z'; } | ||
``` | ||
|
||
- `[body]` - full body, such as function/scope body | ||
- `[body.length<2]` - body has less than 2 nodes | ||
- `[body.length>1]` - body has more than 1 node | ||
- `[body.length<=2]` - body has 2 or less nodes | ||
- `[body.length>=1]` - body has 1 or more nodes | ||
- `[name=/[asdfy]/]` - name matches the characters `asdfy` | ||
|
||
*conditional* | ||
|
||
```js | ||
if (x === 1) { foo(); } else { x = 2; } | ||
if (x == 'test' && true || x) { y = -1; } else if (false) { y = 1; } | ||
``` | ||
|
||
- `[name="x"]` - node named `x` | ||
- `[name!="x"]` - node not named `x` | ||
- `[name=/x|foo/]` - node matches `x` or `foo` | ||
- `[name!=/x|y/]` - node does not match `x` or `y` | ||
- `[callee.name="foo"]` - Where `callee` is named `foo` (ie. function call) | ||
- `[operator]` - That is any type of operator (such as `==`, `||` etc) | ||
- `[prefix=true]` - node that has `prefix` set to true, such as `++c` | ||
- `[test=type(object)]` - where subject of condition is an object, such as `x` in `|| x` | ||
- `[value=type(boolean)]` - where value is a boolean, such | ||
as `&& true` | ||
|
||
Example: `prefix` | ||
|
||
AST node representing unary operators such as `++`, `~`, `typeof` and `delete`" | ||
|
||
`++c` has `prefix: true` and `c++` has `prefix: false` | ||
|
||
```js | ||
interface UnaryExpression <: Expression { | ||
type: "UnaryExpression"; | ||
operator: UnaryOperator; | ||
prefix: boolean; | ||
argument: Expression; | ||
} | ||
``` | ||
|
||
### Classes | ||
|
||
`:statement` - a statement | ||
`:expression` - an expression | ||
`:function` - a function | ||
`:declaration` - a declaration | ||
`:pattern` - a pattern | ||
|
||
Examples: | ||
|
||
`[name="x"]:function` - function named `x` | ||
`[name="foo"]:declaration` - declaration named `foo` | ||
|
||
## Complex | ||
|
||
|
||
- descendant selector (` ` space) | ||
- child selector (`>`) | ||
- adjacent sibling selector (`+`) | ||
- general sibling selector (`~`) | ||
|
||
Please see [javascript: expressions-vs-statements](http://www.2ality.com/2012/09/expressions-vs-statements.html) | ||
|
||
|
||
`IfStatement > BinaryExpression` - `if` statement followed by a [binary expression](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators) fx `3+4` or `x*y` | ||
|
||
|
||
Valid: `if (2 === 2)` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These examples are not valid JavaScript. You can make it valid by adding a semicolon. |
||
|
||
`IfStatement > BinaryExpression > Identifier` | ||
|
||
Valid: `if (x === 2)` | ||
|
||
`IfStatement BinaryExpression` | ||
|
||
An `if` statement with any binary expression below it. | ||
|
||
|
||
`VariableDeclaration ~ IfStatement` | ||
|
||
`var` declaration with sibling `if` statement | ||
|
||
|
||
Valid: siblings of same body | ||
```js | ||
var x = 1; | ||
if (x === 2) | ||
``` | ||
|
||
`VariableDeclaration + ExpressionStatement` | ||
|
||
Valid: variable declaration followed by next sibling which is an expression statement (see [javascript statements and declarations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements)) | ||
|
||
```js | ||
var y = 'y'; | ||
x = x * 2; | ||
``` | ||
|
||
### Compound | ||
|
||
`[left.name="x"][right.value=1]` - where the left side is a node name `x` and the right has the value `1` | ||
|
||
Valid: `x = 1` | ||
|
||
`[left.name="x"]:matches(*)` any type of node where the left side is named `x` | ||
|
||
### Descendant | ||
|
||
`Program IfStatement` - Any program with an `if` statement | ||
|
||
`Identifier[name=x]` - identified named `x` such as `const x`. Identifiers are used to name variables and functions and to provide labels for certain loops... | ||
|
||
`Identifier [name=x]` - any identifier with named `x`, such as `const x` | ||
|
||
`BinaryExpression [name=x]` a binary expression where one side is named `x`, such as `x !== 3` | ||
|
||
`AssignmentExpression [name=x]` an assignment where one side is named `x`, such as `x = 2` or `y = x` | ||
|
||
### Fields | ||
|
||
You can also query on the [Mozilla Parser API](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Parser_API) fields directly | ||
|
||
|
||
Example: | ||
|
||
```js | ||
interface IfStatement <: Statement { | ||
type: "IfStatement"; | ||
test: Expression; | ||
consequent: Statement; | ||
alternate: Statement | null; | ||
} | ||
``` | ||
|
||
`.test` - node (object) that has a `test` field set | ||
`.declarations.init` - node that has `.declarations.init` set | ||
|
||
`init` means initialised, such as `var x = 1`, where `x` is initialised to value `1` | ||
|
||
```js | ||
interface VariableDeclaration <: Declaration { | ||
type: "VariableDeclaration"; | ||
declarations: [ VariableDeclarator ]; | ||
kind: "var" | "let" | "const"; | ||
} | ||
|
||
interface VariableDeclarator <: Node { | ||
type: "VariableDeclarator"; | ||
id: Pattern; | ||
init: Expression | null; | ||
} | ||
``` | ||
|
||
### :has | ||
|
||
`ExpressionStatement:has([name="foo"][type="Identifier"])` | ||
|
||
Valid: `const foo = 2` | ||
|
||
### Matches | ||
|
||
`,` means OR (ie. any of) | ||
|
||
- `:matches(IfStatement)` | ||
- `:matches(BinaryExpression, MemberExpression)` | ||
- `:matches([name="foo"], ReturnStatement)` | ||
- `:matches(AssignmentExpression, BinaryExpression)` | ||
- `AssignmentExpression, BinaryExpression, NonExistant` | ||
|
||
### Not | ||
|
||
- `:not(Literal)` not a literal | ||
- `:not([name="x"])` not a node named `x` | ||
- `:not(*)` - not anything! | ||
- `:not(Identifier, IfStatement)` | ||
- `:not([value=1])` not a node set to value of `1` | ||
|
||
### Pseudo child | ||
|
||
`:first-child` - first child node | ||
`:last-child` - last child node | ||
`:nth-child(2)` - 2nd child | ||
`:nth-last-child(2)` - 2nd last child | ||
|
||
### Subject | ||
|
||
`!IfStatement Identifier` - any not an If statement with an Identifier under, such as `const x = 3` but not `if (x == 2)` | ||
|
||
|
||
`!* > [name="foo"]` all nodes but those where the immediate child is a node namded `foo` | ||
|
||
|
||
More examples: | ||
|
||
- `![test] [name="y"]` | ||
- `![generator=type(boolean)] > BlockStatement` | ||
- `![operator=/=+/] > [name="x"]` | ||
- `!:matches(*) > [name="foo"]` | ||
- `!:not(BlockStatement) > [name="foo"]` | ||
- `![left.name="x"][right.value=1]` | ||
- `* !AssignmentExpression` | ||
|
||
- `!VariableDeclaration ~ IfStatement` | ||
- `!VariableDeclaration + !ExpressionStatement` | ||
|
||
### Types | ||
|
||
- `LogicalExpression` | ||
- `ForStatement` | ||
- `FunctionDeclaration` | ||
- `ReturnStatement` | ||
- `AssignmentExpression` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
{ | ||
"name": "esquery", | ||
"preferGlobal": false, | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't bump the version. We'll bump it appropriately during a release. |
||
"author": "Joel Feenstra <[email protected]>", | ||
"description": "A query library for ECMAScript AST using a CSS selector like query language.", | ||
"main": "esquery.js", | ||
|
@@ -25,16 +25,16 @@ | |
"query" | ||
], | ||
"devDependencies": { | ||
"jstestr": ">=0.4", | ||
"pegjs": "~0.7.0", | ||
"commonjs-everywhere": "~0.9.4", | ||
"esprima": "~1.1.1" | ||
"commonjs-everywhere": "~0.9.7", | ||
"esprima": "^3.1.0", | ||
"jstestr": "^0.4.2", | ||
"pegjs": "^0.10.0" | ||
}, | ||
"license": "BSD", | ||
"engines": { | ||
"node": ">=0.6" | ||
"node": ">=5.0.0" | ||
}, | ||
"dependencies": { | ||
"estraverse": "^4.0.0" | ||
"estraverse": "^4.2.0" | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I strongly prefer installation documentation to use
npm install ...
. There's no reason to use shorthand in documentation.