-
Notifications
You must be signed in to change notification settings - Fork 95
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; }" | ||
|
Member
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 use single quotes or double quotes, but not both. |
||
|
|
||
| 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 | ||
|
Member
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. Combinators |
||
|
|
||
| - 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) | ||
|
Member
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. I'm not sure how this is related. Instead, one should see the estree specification.
Member
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. You might also want to point them to the CSS documentation because these combinators are both syntactically and semantically identical. |
||
|
|
||
| `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` | ||
|
Member
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. No, a |
||
|
|
||
| Valid: `if (2 === 2)` | ||
|
Member
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. | ||
|
Member
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. A binary expression nested arbitrarily deeply within an |
||
|
|
||
| `VariableDeclaration ~ IfStatement` | ||
|
|
||
| `var` declaration with sibling `if` statement | ||
|
Member
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.
|
||
|
|
||
| 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 | ||
|
Member
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. This link should be updated to estree. |
||
|
|
||
| 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)` | ||
|
Member
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.
any |
||
|
|
||
| `!* > [name="foo"]` all nodes but those where the immediate child is a node namded `foo` | ||
|
Member
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. namded -> named |
||
|
|
||
| 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` | ||
|
Member
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. I don't think this is a productive example. What is it trying to show off?
Author
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 do whatever it takes to add sufficient docs for how to use the API. I tried my best using the tests cases for inspiration. |
||
| - `!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", | ||
|
Member
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 <jrfeenst+esquery@gmail.com>", | ||
| "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.