Initial commit
This commit is contained in:
+33
@@ -0,0 +1,33 @@
|
||||
Copyright (c) 2016, Daniel Wirtz All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of its author, nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
---
|
||||
|
||||
Code generated by the command line utilities is owned by the owner
|
||||
of the input file used when generating it. This code is not
|
||||
standalone and requires a support library to be linked with it. This
|
||||
support library is itself covered by the above license.
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
protobufjs-cli
|
||||
==============
|
||||
[](https://www.npmjs.com/package/protobufjs-cli)
|
||||
|
||||
Command line interface (CLI) for [protobuf.js](https://github.com/dcodeIO/protobuf.js). Translates between file formats and generates static code as well as TypeScript definitions.
|
||||
|
||||
* [CLI Documentation](https://github.com/dcodeIO/protobuf.js#command-line)
|
||||
|
||||
**Note** that moving the CLI to its own package is a work in progress. At the moment, it's still part of the main package.
|
||||
* [pbjs for JavaScript](#pbjs-for-javascript)
|
||||
* [pbts for TypeScript](#pbts-for-typescript)
|
||||
* [Reflection vs. static code](#reflection-vs-static-code)
|
||||
* [Command line API](#command-line-api)<br />
|
||||
|
||||
### pbjs for JavaScript
|
||||
|
||||
```
|
||||
Translates between file formats and generates static code.
|
||||
|
||||
-t, --target Specifies the target format. Also accepts a path to require a custom target.
|
||||
|
||||
json JSON representation
|
||||
json-module JSON representation as a module
|
||||
proto2 Protocol Buffers, Version 2
|
||||
proto3 Protocol Buffers, Version 3
|
||||
static Static code without reflection (non-functional on its own)
|
||||
static-module Static code without reflection as a module
|
||||
|
||||
-p, --path Adds a directory to the include path.
|
||||
|
||||
-o, --out Saves to a file instead of writing to stdout.
|
||||
|
||||
--sparse Exports only those types referenced from a main file (experimental).
|
||||
|
||||
Module targets only:
|
||||
|
||||
-w, --wrap Specifies the wrapper to use. Also accepts a path to require a custom wrapper.
|
||||
|
||||
default Default wrapper supporting both CommonJS and AMD
|
||||
commonjs CommonJS wrapper
|
||||
amd AMD wrapper
|
||||
es6 ES6 wrapper (implies --es6)
|
||||
closure A closure adding to protobuf.roots where protobuf is a global
|
||||
|
||||
-r, --root Specifies an alternative protobuf.roots name.
|
||||
|
||||
-l, --lint Linter configuration. Defaults to protobuf.js-compatible rules:
|
||||
|
||||
eslint-disable block-scoped-var, no-redeclare, no-control-regex, no-prototype-builtins
|
||||
|
||||
--es6 Enables ES6 syntax (const/let instead of var)
|
||||
|
||||
Proto sources only:
|
||||
|
||||
--keep-case Keeps field casing instead of converting to camel case.
|
||||
|
||||
Static targets only:
|
||||
|
||||
--no-create Does not generate create functions used for reflection compatibility.
|
||||
--no-encode Does not generate encode functions.
|
||||
--no-decode Does not generate decode functions.
|
||||
--no-verify Does not generate verify functions.
|
||||
--no-convert Does not generate convert functions like from/toObject
|
||||
--no-delimited Does not generate delimited encode/decode functions.
|
||||
--no-beautify Does not beautify generated code.
|
||||
--no-comments Does not output any JSDoc comments.
|
||||
--no-service Does not output service classes.
|
||||
|
||||
--force-long Enforces the use of 'Long' for s-/u-/int64 and s-/fixed64 fields.
|
||||
--force-number Enforces the use of 'number' for s-/u-/int64 and s-/fixed64 fields.
|
||||
--force-message Enforces the use of message instances instead of plain objects.
|
||||
|
||||
usage: pbjs [options] file1.proto file2.json ... (or pipe) other | pbjs [options] -
|
||||
```
|
||||
|
||||
For production environments it is recommended to bundle all your .proto files to a single .json file, which minimizes the number of network requests and avoids any parser overhead (hint: works with just the **light** library):
|
||||
|
||||
```
|
||||
$> pbjs -t json file1.proto file2.proto > bundle.json
|
||||
```
|
||||
|
||||
Now, either include this file in your final bundle:
|
||||
|
||||
```js
|
||||
var root = protobuf.Root.fromJSON(require("./bundle.json"));
|
||||
```
|
||||
|
||||
or load it the usual way:
|
||||
|
||||
```js
|
||||
protobuf.load("bundle.json", function(err, root) {
|
||||
...
|
||||
});
|
||||
```
|
||||
|
||||
Generated static code, on the other hand, works with just the **minimal** library. For example
|
||||
|
||||
```
|
||||
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
|
||||
```
|
||||
|
||||
will generate static code for definitions within `file1.proto` and `file2.proto` to a CommonJS module `compiled.js`.
|
||||
|
||||
**ProTip!** Documenting your .proto files with `/** ... */`-blocks or (trailing) `/// ...` lines translates to generated static code.
|
||||
|
||||
|
||||
### pbts for TypeScript
|
||||
|
||||
```
|
||||
Generates TypeScript definitions from annotated JavaScript files.
|
||||
|
||||
-o, --out Saves to a file instead of writing to stdout.
|
||||
|
||||
-g, --global Name of the global object in browser environments, if any.
|
||||
|
||||
--no-comments Does not output any JSDoc comments.
|
||||
|
||||
Internal flags:
|
||||
|
||||
-n, --name Wraps everything in a module of the specified name.
|
||||
|
||||
-m, --main Whether building the main library without any imports.
|
||||
|
||||
usage: pbts [options] file1.js file2.js ... (or) other | pbts [options] -
|
||||
```
|
||||
|
||||
Picking up on the example above, the following not only generates static code to a CommonJS module `compiled.js` but also its respective TypeScript definitions to `compiled.d.ts`:
|
||||
|
||||
```
|
||||
$> pbjs -t static-module -w commonjs -o compiled.js file1.proto file2.proto
|
||||
$> pbts -o compiled.d.ts compiled.js
|
||||
```
|
||||
|
||||
Additionally, TypeScript definitions of static modules are compatible with their reflection-based counterparts (i.e. as exported by JSON modules), as long as the following conditions are met:
|
||||
|
||||
1. Instead of using `new SomeMessage(...)`, always use `SomeMessage.create(...)` because reflection objects do not provide a constructor.
|
||||
2. Types, services and enums must start with an uppercase letter to become available as properties of the reflected types as well (i.e. to be able to use `MyMessage.MyEnum` instead of `root.lookup("MyMessage.MyEnum")`).
|
||||
|
||||
For example, the following generates a JSON module `bundle.js` and a `bundle.d.ts`, but no static code:
|
||||
|
||||
```
|
||||
$> pbjs -t json-module -w commonjs -o bundle.js file1.proto file2.proto
|
||||
$> pbjs -t static-module file1.proto file2.proto | pbts -o bundle.d.ts -
|
||||
```
|
||||
|
||||
### Reflection vs. static code
|
||||
|
||||
While using .proto files directly requires the full library respectively pure reflection/JSON the light library, pretty much all code but the relatively short descriptors is shared.
|
||||
|
||||
Static code, on the other hand, requires just the minimal library, but generates additional source code without any reflection features. This also implies that there is a break-even point where statically generated code becomes larger than descriptor-based code once the amount of code generated exceeds the size of the full respectively light library.
|
||||
|
||||
There is no significant difference performance-wise as the code generated statically is pretty much the same as generated at runtime and both are largely interchangeable as seen in the previous section.
|
||||
|
||||
| Source | Library | Advantages | Tradeoffs
|
||||
|--------|---------|------------|-----------
|
||||
| .proto | full | Easily editable<br />Interoperability with other libraries<br />No compile step | Some parsing and possibly network overhead
|
||||
| JSON | light | Easily editable<br />No parsing overhead<br />Single bundle (no network overhead) | protobuf.js specific<br />Has a compile step
|
||||
| static | minimal | Works where `eval` access is restricted<br />Fully documented<br />Small footprint for small protos | Can be hard to edit<br />No reflection<br />Has a compile step
|
||||
|
||||
### Command line API
|
||||
|
||||
Both utilities can be used programmatically by providing command line arguments and a callback to their respective `main` functions:
|
||||
|
||||
```js
|
||||
var pbjs = require("protobufjs-cli/pbjs"); // or require("protobufjs-cli").pbjs / .pbts
|
||||
|
||||
pbjs.main([ "--target", "json-module", "path/to/myproto.proto" ], function(err, output) {
|
||||
if (err)
|
||||
throw err;
|
||||
// do something with output
|
||||
});
|
||||
```
|
||||
|
||||
**License:** [BSD 3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
var path = require("path"),
|
||||
cli = require(path.join(__dirname, "..", "pbjs.js"));
|
||||
var ret = cli.main(process.argv.slice(2));
|
||||
if (typeof ret === 'number')
|
||||
process.exit(ret);
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
var path = require("path"),
|
||||
cli = require(path.join(__dirname, "..", "pbts.js"));
|
||||
var ret = cli.main(process.argv.slice(2));
|
||||
if (typeof ret === 'number')
|
||||
process.exit(ret);
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import * as pbjs from "./pbjs.js";
|
||||
import * as pbts from "./pbts.js";
|
||||
export { pbjs, pbts };
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
exports.pbjs = require("./pbjs");
|
||||
exports.pbts = require("./pbts");
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"tags": {
|
||||
"allowUnknownTags": false
|
||||
},
|
||||
"plugins": [
|
||||
"./tsd-jsdoc/plugin"
|
||||
],
|
||||
"opts": {
|
||||
"encoding" : "utf8",
|
||||
"recurse" : true,
|
||||
"lenient" : true,
|
||||
"template" : "./tsd-jsdoc",
|
||||
|
||||
"private" : false,
|
||||
"comments" : true,
|
||||
"destination" : false
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2016 Chad Engler
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
protobuf.js fork of tsd-jsdoc
|
||||
=============================
|
||||
|
||||
This is a modified version of [tsd-jsdoc](https://github.com/englercj/tsd-jsdoc) v1.0.1 for use with protobuf.js, parked here so we can process issues and pull requests. The ultimate goal is to switch back to the a recent version of tsd-jsdoc once it meets our needs.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
* **module: `string`**<br />
|
||||
Wraps everything in a module of the specified name.
|
||||
|
||||
* **private: `boolean`**<br />
|
||||
Includes private members when set to `true`.
|
||||
|
||||
* **comments: `boolean`**<br />
|
||||
Skips comments when explicitly set to `false`.
|
||||
|
||||
* **destination: `string|boolean`**<br />
|
||||
Saves to the specified destination file or to console when set to `false`.
|
||||
|
||||
Setting options on the command line
|
||||
-----------------------------------
|
||||
Providing `-q, --query <queryString>` on the command line will set respectively override existing options. Example: `-q module=protobufjs`
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
exports.defineTags = function(dictionary) {
|
||||
|
||||
dictionary.defineTag("template", {
|
||||
mustHaveValue: true,
|
||||
canHaveType: false,
|
||||
canHaveName: false,
|
||||
onTagged: function(doclet, tag) {
|
||||
(doclet.templates || (doclet.templates = [])).push(tag.text);
|
||||
}
|
||||
});
|
||||
|
||||
dictionary.defineTag("tstype", {
|
||||
mustHaveValue: true,
|
||||
canHaveType: false,
|
||||
canHaveName: false,
|
||||
onTagged: function(doclet, tag) {
|
||||
doclet.tsType = tag.text;
|
||||
}
|
||||
});
|
||||
};
|
||||
+705
@@ -0,0 +1,705 @@
|
||||
"use strict";
|
||||
|
||||
var fs = require("fs");
|
||||
|
||||
// output stream
|
||||
var out = null;
|
||||
|
||||
// documentation data
|
||||
var data = null;
|
||||
|
||||
// already handled objects, by name
|
||||
var seen = {};
|
||||
|
||||
// indentation level
|
||||
var indent = 0;
|
||||
|
||||
// whether indent has been written for the current line yet
|
||||
var indentWritten = false;
|
||||
|
||||
// provided options
|
||||
var options = {};
|
||||
|
||||
// queued interfaces
|
||||
var queuedInterfaces = [];
|
||||
|
||||
// whether writing the first line
|
||||
var firstLine = true;
|
||||
|
||||
// JSDoc hook
|
||||
exports.publish = function publish(taffy, opts) {
|
||||
options = opts || {};
|
||||
|
||||
// query overrides options
|
||||
if (options.query)
|
||||
Object.keys(options.query).forEach(function(key) {
|
||||
if (key !== "query")
|
||||
switch (options[key] = options.query[key]) {
|
||||
case "true":
|
||||
options[key] = true;
|
||||
break;
|
||||
case "false":
|
||||
options[key] = false;
|
||||
break;
|
||||
case "null":
|
||||
options[key] = null;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// remove undocumented
|
||||
taffy({ undocumented: true }).remove();
|
||||
taffy({ ignore: true }).remove();
|
||||
taffy({ inherited: true }).remove();
|
||||
|
||||
// remove private
|
||||
if (!options.private)
|
||||
taffy({ access: "private" }).remove();
|
||||
|
||||
// setup output
|
||||
out = options.destination
|
||||
? fs.createWriteStream(options.destination)
|
||||
: process.stdout;
|
||||
|
||||
try {
|
||||
// setup environment
|
||||
data = taffy().get();
|
||||
indent = 0;
|
||||
indentWritten = false;
|
||||
firstLine = true;
|
||||
|
||||
// wrap everything in a module if configured
|
||||
if (options.module) {
|
||||
writeln("export = ", options.module, ";");
|
||||
writeln();
|
||||
writeln("declare namespace ", options.module, " {");
|
||||
writeln();
|
||||
++indent;
|
||||
}
|
||||
|
||||
// handle all
|
||||
getChildrenOf(undefined).forEach(function(child) {
|
||||
handleElement(child, null);
|
||||
});
|
||||
|
||||
// process queued
|
||||
while (queuedInterfaces.length) {
|
||||
var element = queuedInterfaces.shift();
|
||||
begin(element);
|
||||
writeInterface(element);
|
||||
writeln(";");
|
||||
}
|
||||
|
||||
// end wrap
|
||||
if (options.module) {
|
||||
--indent;
|
||||
writeln("}");
|
||||
}
|
||||
|
||||
// close file output
|
||||
if (out !== process.stdout)
|
||||
out.end();
|
||||
|
||||
} finally {
|
||||
// gc environment objects
|
||||
out = data = null;
|
||||
seen = options = {};
|
||||
queuedInterfaces = [];
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Utility
|
||||
//
|
||||
|
||||
// writes one or multiple strings
|
||||
function write() {
|
||||
var s = Array.prototype.slice.call(arguments).join("");
|
||||
if (!indentWritten) {
|
||||
for (var i = 0; i < indent; ++i)
|
||||
s = " " + s;
|
||||
indentWritten = true;
|
||||
}
|
||||
out.write(s);
|
||||
firstLine = false;
|
||||
}
|
||||
|
||||
// writes zero or multiple strings, followed by a new line
|
||||
function writeln() {
|
||||
var s = Array.prototype.slice.call(arguments).join("");
|
||||
if (s.length)
|
||||
write(s, "\n");
|
||||
else if (!firstLine)
|
||||
out.write("\n");
|
||||
indentWritten = false;
|
||||
}
|
||||
|
||||
var keepTags = [
|
||||
"param",
|
||||
"returns",
|
||||
"throws",
|
||||
"see"
|
||||
];
|
||||
|
||||
// parses a comment into text and tags
|
||||
function parseComment(comment) {
|
||||
var lines = comment.replace(/^ *\/\*\* *|^ *\*\/| *\*\/ *$|^ *\* */mg, "").trim().split(/\r?\n|\r/g); // property.description has just "\r" ?!
|
||||
var desc;
|
||||
var text = [];
|
||||
var tags = null;
|
||||
for (var i = 0; i < lines.length; ++i) {
|
||||
var match = /^@(\w+)\b/.exec(lines[i]);
|
||||
if (match) {
|
||||
if (!tags) {
|
||||
tags = [];
|
||||
desc = text;
|
||||
}
|
||||
text = [];
|
||||
tags.push({ name: match[1], text: text });
|
||||
lines[i] = lines[i].substring(match[1].length + 1).trim();
|
||||
}
|
||||
if (lines[i].length || text.length)
|
||||
text.push(lines[i]);
|
||||
}
|
||||
return {
|
||||
text: desc || text,
|
||||
tags: tags || []
|
||||
};
|
||||
}
|
||||
|
||||
// writes a comment
|
||||
function writeComment(comment, otherwiseNewline) {
|
||||
if (!comment || options.comments === false) {
|
||||
if (otherwiseNewline)
|
||||
writeln();
|
||||
return;
|
||||
}
|
||||
if (typeof comment !== "object")
|
||||
comment = parseComment(comment);
|
||||
comment.tags = comment.tags.filter(function(tag) {
|
||||
return keepTags.indexOf(tag.name) > -1 && (tag.name !== "returns" || tag.text[0] !== "{undefined}");
|
||||
});
|
||||
writeln();
|
||||
if (!comment.tags.length && comment.text.length < 2) {
|
||||
writeln("/** " + comment.text[0] + " */");
|
||||
return;
|
||||
}
|
||||
writeln("/**");
|
||||
comment.text.forEach(function(line) {
|
||||
if (line.length)
|
||||
writeln(" * ", line);
|
||||
else
|
||||
writeln(" *");
|
||||
});
|
||||
comment.tags.forEach(function(tag) {
|
||||
var started = false;
|
||||
if (tag.text.length) {
|
||||
tag.text.forEach(function(line, i) {
|
||||
if (i > 0)
|
||||
write(" * ");
|
||||
else if (tag.name !== "throws")
|
||||
line = line.replace(/^\{[^\s]*} ?/, "");
|
||||
if (!line.length)
|
||||
return;
|
||||
if (!started) {
|
||||
write(" * @", tag.name, " ");
|
||||
started = true;
|
||||
}
|
||||
writeln(line);
|
||||
});
|
||||
}
|
||||
});
|
||||
writeln(" */");
|
||||
}
|
||||
|
||||
// recursively replaces all occurencies of re's match
|
||||
function replaceRecursive(name, re, fn) {
|
||||
var found;
|
||||
|
||||
function replacer() {
|
||||
found = true;
|
||||
return fn.apply(null, arguments);
|
||||
}
|
||||
|
||||
do {
|
||||
found = false;
|
||||
name = name.replace(re, replacer);
|
||||
} while (found);
|
||||
return name;
|
||||
}
|
||||
|
||||
// tests if an element is considered to be a class or class-like
|
||||
function isClassLike(element) {
|
||||
return isClass(element) || isInterface(element);
|
||||
}
|
||||
|
||||
// tests if an element is considered to be a class
|
||||
function isClass(element) {
|
||||
return element && element.kind === "class";
|
||||
}
|
||||
|
||||
// tests if an element is considered to be an interface
|
||||
function isInterface(element) {
|
||||
return element && (element.kind === "interface" || element.kind === "mixin");
|
||||
}
|
||||
|
||||
// tests if an element is considered to be a namespace
|
||||
function isNamespace(element) {
|
||||
return element && (element.kind === "namespace" || element.kind === "module");
|
||||
}
|
||||
|
||||
// gets all children of the specified parent
|
||||
function getChildrenOf(parent) {
|
||||
var memberof = parent ? parent.longname : undefined;
|
||||
return data.filter(function(element) {
|
||||
return element.memberof === memberof;
|
||||
});
|
||||
}
|
||||
|
||||
// gets the literal type of an element
|
||||
function getTypeOf(element) {
|
||||
if (element.tsType)
|
||||
return element.tsType.replace(/\r?\n|\r/g, "\n");
|
||||
var name = "any";
|
||||
var type = element.type;
|
||||
if (type && type.names && type.names.length) {
|
||||
if (type.names.length === 1)
|
||||
name = element.type.names[0].trim();
|
||||
else
|
||||
name = "(" + element.type.names.join("|") + ")";
|
||||
} else
|
||||
return name;
|
||||
|
||||
// Replace catchalls with any
|
||||
name = name.replace(/\*|\bmixed\b/g, "any");
|
||||
|
||||
// Ensure upper case Object for map expressions below
|
||||
name = name.replace(/\bobject\b/g, "Object");
|
||||
|
||||
// Correct Something.<Something> to Something<Something>
|
||||
name = replaceRecursive(name, /\b(?!Object|Array)([\w$]+)\.<([^>]*)>/gi, function($0, $1, $2) {
|
||||
return $1 + "<" + $2 + ">";
|
||||
});
|
||||
|
||||
// Replace Array.<string> with string[]
|
||||
name = replaceRecursive(name, /\bArray\.?<([^>]*)>/gi, function($0, $1) {
|
||||
return $1 + "[]";
|
||||
});
|
||||
|
||||
// Replace Object.<string,number> with { [k: string]: number }
|
||||
name = replaceRecursive(name, /\bObject\.?<([^,]*), *([^>]*)>/gi, function($0, $1, $2) {
|
||||
return "{ [k: " + $1 + "]: " + $2 + " }";
|
||||
});
|
||||
|
||||
// Replace functions (there are no signatures) with Function
|
||||
name = name.replace(/\bfunction(?:\(\))?\b/g, "Function");
|
||||
|
||||
// Convert plain Object back to just object
|
||||
name = name.replace(/\b(Object\b(?!\.))/g, function($0, $1) {
|
||||
return $1.toLowerCase();
|
||||
});
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
// begins writing the definition of the specified element
|
||||
function begin(element, is_interface) {
|
||||
if (!seen[element.longname]) {
|
||||
if (isClass(element)) {
|
||||
var comment = parseComment(element.comment);
|
||||
var classdesc = comment.tags.find(function(tag) { return tag.name === "classdesc"; });
|
||||
if (classdesc) {
|
||||
comment.text = classdesc.text;
|
||||
comment.tags = [];
|
||||
}
|
||||
writeComment(comment, true);
|
||||
} else
|
||||
writeComment(element.comment, is_interface || isClassLike(element) || isNamespace(element) || element.isEnum || element.scope === "global");
|
||||
seen[element.longname] = element;
|
||||
} else
|
||||
writeln();
|
||||
// ????: something changed in JSDoc 3.6.0? so that @exports + @enum does
|
||||
// no longer yield a 'global' scope, but is some sort of unscoped module
|
||||
// element now. The additional condition added below works around this.
|
||||
if ((element.scope === "global" || element.isEnum && element.scope === undefined) && !options.module)
|
||||
write("export ");
|
||||
}
|
||||
|
||||
// writes the function signature describing element
|
||||
function writeFunctionSignature(element, isConstructor, isTypeDef) {
|
||||
write("(");
|
||||
|
||||
var params = {};
|
||||
|
||||
// this type
|
||||
if (element.this)
|
||||
params["this"] = {
|
||||
type: element.this.replace(/^{|}$/g, ""),
|
||||
optional: false
|
||||
};
|
||||
|
||||
// parameter types
|
||||
if (element.params)
|
||||
element.params.forEach(function(param) {
|
||||
var path = param.name.split(/\./g);
|
||||
if (path.length === 1)
|
||||
params[param.name] = {
|
||||
type: getTypeOf(param),
|
||||
variable: param.variable === true,
|
||||
optional: param.optional === true,
|
||||
defaultValue: param.defaultvalue // Not used yet (TODO)
|
||||
};
|
||||
else // Property syntax (TODO)
|
||||
params[path[0]].type = "{ [k: string]: any }";
|
||||
});
|
||||
|
||||
var paramNames = Object.keys(params);
|
||||
paramNames.forEach(function(name, i) {
|
||||
var param = params[name];
|
||||
var type = param.type;
|
||||
if (param.variable) {
|
||||
name = "..." + name;
|
||||
type = param.type.charAt(0) === "(" ? "any[]" : param.type + "[]";
|
||||
}
|
||||
write(name, !param.variable && param.optional ? "?: " : ": ", type);
|
||||
if (i < paramNames.length - 1)
|
||||
write(", ");
|
||||
});
|
||||
|
||||
write(")");
|
||||
|
||||
// return type
|
||||
if (!isConstructor) {
|
||||
write(isTypeDef ? " => " : ": ");
|
||||
var typeName;
|
||||
if (element.returns && element.returns.length && (typeName = getTypeOf(element.returns[0])) !== "undefined")
|
||||
write(typeName);
|
||||
else
|
||||
write("void");
|
||||
}
|
||||
}
|
||||
|
||||
// writes (a typedef as) an interface
|
||||
function writeInterface(element) {
|
||||
write("interface ", element.name);
|
||||
writeInterfaceBody(element);
|
||||
writeln();
|
||||
}
|
||||
|
||||
function writeInterfaceBody(element) {
|
||||
writeln("{");
|
||||
++indent;
|
||||
if (element.tsType)
|
||||
writeln(element.tsType.replace(/\r?\n|\r/g, "\n"));
|
||||
else if (element.properties && element.properties.length)
|
||||
element.properties.forEach(writeProperty);
|
||||
--indent;
|
||||
write("}");
|
||||
}
|
||||
|
||||
function writeProperty(property, declare) {
|
||||
writeComment(property.description);
|
||||
if (declare)
|
||||
write("let ");
|
||||
write(property.name);
|
||||
if (property.optional)
|
||||
write("?");
|
||||
writeln(": ", getTypeOf(property), ";");
|
||||
}
|
||||
|
||||
//
|
||||
// Handlers
|
||||
//
|
||||
|
||||
// handles a single element of any understood type
|
||||
function handleElement(element, parent) {
|
||||
if (element.scope === "inner")
|
||||
return false;
|
||||
|
||||
if (element.optional !== true && element.type && element.type.names && element.type.names.length) {
|
||||
for (var i = 0; i < element.type.names.length; i++) {
|
||||
if (element.type.names[i].toLowerCase() === "undefined") {
|
||||
// This element is actually optional. Set optional to true and
|
||||
// remove the 'undefined' type
|
||||
element.optional = true;
|
||||
element.type.names.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (seen[element.longname])
|
||||
return true;
|
||||
if (isClassLike(element))
|
||||
handleClass(element, parent);
|
||||
else switch (element.kind) {
|
||||
case "module":
|
||||
if (element.isEnum) {
|
||||
handleEnum(element, parent);
|
||||
break;
|
||||
}
|
||||
// eslint-disable-line no-fallthrough
|
||||
case "namespace":
|
||||
handleNamespace(element, parent);
|
||||
break;
|
||||
case "constant":
|
||||
case "member":
|
||||
handleMember(element, parent);
|
||||
break;
|
||||
case "function":
|
||||
handleFunction(element, parent);
|
||||
break;
|
||||
case "typedef":
|
||||
handleTypeDef(element, parent);
|
||||
break;
|
||||
case "package":
|
||||
break;
|
||||
}
|
||||
seen[element.longname] = element;
|
||||
return true;
|
||||
}
|
||||
|
||||
// handles (just) a namespace
|
||||
function handleNamespace(element/*, parent*/) {
|
||||
var children = getChildrenOf(element);
|
||||
if (!children.length)
|
||||
return;
|
||||
var first = true;
|
||||
if (element.properties)
|
||||
element.properties.forEach(function(property) {
|
||||
if (!/^[$\w]+$/.test(property.name)) // incompatible in namespace
|
||||
return;
|
||||
if (first) {
|
||||
begin(element);
|
||||
writeln("namespace ", element.name, " {");
|
||||
++indent;
|
||||
first = false;
|
||||
}
|
||||
writeProperty(property, true);
|
||||
});
|
||||
children.forEach(function(child) {
|
||||
if (child.scope === "inner" || seen[child.longname])
|
||||
return;
|
||||
if (first) {
|
||||
begin(element);
|
||||
writeln("namespace ", element.name, " {");
|
||||
++indent;
|
||||
first = false;
|
||||
}
|
||||
handleElement(child, element);
|
||||
});
|
||||
if (!first) {
|
||||
--indent;
|
||||
writeln("}");
|
||||
}
|
||||
}
|
||||
|
||||
// a filter function to remove any module references
|
||||
function notAModuleReference(ref) {
|
||||
return ref.indexOf("module:") === -1;
|
||||
}
|
||||
|
||||
// handles a class or class-like
|
||||
function handleClass(element, parent) {
|
||||
var is_interface = isInterface(element);
|
||||
begin(element, is_interface);
|
||||
if (is_interface)
|
||||
write("interface ");
|
||||
else {
|
||||
if (element.virtual)
|
||||
write("abstract ");
|
||||
write("class ");
|
||||
}
|
||||
write(element.name);
|
||||
if (element.templates && element.templates.length)
|
||||
write("<", element.templates.join(", "), ">");
|
||||
write(" ");
|
||||
|
||||
// extended classes
|
||||
if (element.augments) {
|
||||
var augments = element.augments.filter(notAModuleReference);
|
||||
if (augments.length)
|
||||
write("extends ", augments[0], " ");
|
||||
}
|
||||
|
||||
// implemented interfaces
|
||||
var impls = [];
|
||||
if (element.implements)
|
||||
Array.prototype.push.apply(impls, element.implements);
|
||||
if (element.mixes)
|
||||
Array.prototype.push.apply(impls, element.mixes);
|
||||
impls = impls.filter(notAModuleReference);
|
||||
if (impls.length)
|
||||
write("implements ", impls.join(", "), " ");
|
||||
|
||||
writeln("{");
|
||||
++indent;
|
||||
|
||||
if (element.tsType)
|
||||
writeln(element.tsType.replace(/\r?\n|\r/g, "\n"));
|
||||
|
||||
// constructor
|
||||
if (!is_interface && !element.virtual)
|
||||
handleFunction(element, parent, true);
|
||||
|
||||
// properties
|
||||
if (is_interface && element.properties)
|
||||
element.properties.forEach(function(property) {
|
||||
writeProperty(property);
|
||||
});
|
||||
|
||||
// class-compatible members
|
||||
var incompatible = [];
|
||||
getChildrenOf(element).forEach(function(child) {
|
||||
if (isClassLike(child) || child.kind === "module" || child.kind === "typedef" || child.isEnum) {
|
||||
incompatible.push(child);
|
||||
return;
|
||||
}
|
||||
handleElement(child, element);
|
||||
});
|
||||
|
||||
--indent;
|
||||
writeln("}");
|
||||
|
||||
// class-incompatible members
|
||||
if (incompatible.length) {
|
||||
writeln();
|
||||
if (element.scope === "global" && !options.module)
|
||||
write("export ");
|
||||
writeln("namespace ", element.name, " {");
|
||||
++indent;
|
||||
incompatible.forEach(function(child) {
|
||||
handleElement(child, element);
|
||||
});
|
||||
--indent;
|
||||
writeln("}");
|
||||
}
|
||||
}
|
||||
|
||||
// handles an enum
|
||||
function handleEnum(element) {
|
||||
begin(element);
|
||||
|
||||
var stringEnum = false;
|
||||
element.properties.forEach(function(property) {
|
||||
if (isNaN(property.defaultvalue)) {
|
||||
stringEnum = true;
|
||||
}
|
||||
});
|
||||
if (stringEnum) {
|
||||
writeln("type ", element.name, " =");
|
||||
++indent;
|
||||
element.properties.forEach(function(property, i) {
|
||||
write(i === 0 ? "" : "| ", JSON.stringify(property.defaultvalue));
|
||||
});
|
||||
--indent;
|
||||
writeln(";");
|
||||
} else {
|
||||
writeln("enum ", element.name, " {");
|
||||
++indent;
|
||||
element.properties.forEach(function(property, i) {
|
||||
write(property.name);
|
||||
if (property.defaultvalue !== undefined)
|
||||
write(" = ", JSON.stringify(property.defaultvalue));
|
||||
if (i < element.properties.length - 1)
|
||||
writeln(",");
|
||||
else
|
||||
writeln();
|
||||
});
|
||||
--indent;
|
||||
writeln("}");
|
||||
}
|
||||
}
|
||||
|
||||
// handles a namespace or class member
|
||||
function handleMember(element, parent) {
|
||||
if (element.isEnum) {
|
||||
handleEnum(element);
|
||||
return;
|
||||
}
|
||||
begin(element);
|
||||
|
||||
var inClass = isClassLike(parent);
|
||||
if (inClass) {
|
||||
write(element.access || "public", " ");
|
||||
if (element.scope === "static")
|
||||
write("static ");
|
||||
if (element.readonly)
|
||||
write("readonly ");
|
||||
} else
|
||||
write(element.kind === "constant" ? "const " : "let ");
|
||||
|
||||
write(element.name);
|
||||
if (element.optional)
|
||||
write("?");
|
||||
write(": ");
|
||||
|
||||
if (element.type && element.type.names && /^Object\b/i.test(element.type.names[0]) && element.properties) {
|
||||
writeln("{");
|
||||
++indent;
|
||||
element.properties.forEach(function(property, i) {
|
||||
writeln(JSON.stringify(property.name), ": ", getTypeOf(property), i < element.properties.length - 1 ? "," : "");
|
||||
});
|
||||
--indent;
|
||||
writeln("};");
|
||||
} else
|
||||
writeln(getTypeOf(element), ";");
|
||||
}
|
||||
|
||||
// handles a function or method
|
||||
function handleFunction(element, parent, isConstructor) {
|
||||
var insideClass = true;
|
||||
if (isConstructor) {
|
||||
writeComment(element.comment);
|
||||
write("constructor");
|
||||
} else {
|
||||
begin(element);
|
||||
insideClass = isClassLike(parent);
|
||||
if (insideClass) {
|
||||
write(element.access || "public", " ");
|
||||
if (element.scope === "static")
|
||||
write("static ");
|
||||
} else
|
||||
write("function ");
|
||||
write(element.name);
|
||||
if (element.templates && element.templates.length)
|
||||
write("<", element.templates.join(", "), ">");
|
||||
}
|
||||
writeFunctionSignature(element, isConstructor, false);
|
||||
writeln(";");
|
||||
if (!insideClass)
|
||||
handleNamespace(element);
|
||||
}
|
||||
|
||||
// handles a type definition (not a real type)
|
||||
function handleTypeDef(element, parent) {
|
||||
if (isInterface(element)) {
|
||||
if (isClassLike(parent))
|
||||
queuedInterfaces.push(element);
|
||||
else {
|
||||
begin(element);
|
||||
writeInterface(element);
|
||||
}
|
||||
} else {
|
||||
writeComment(element.comment, true);
|
||||
write("type ", element.name);
|
||||
if (element.templates && element.templates.length)
|
||||
write("<", element.templates.join(", "), ">");
|
||||
write(" = ");
|
||||
if (element.tsType)
|
||||
write(element.tsType.replace(/\r?\n|\r/g, "\n"));
|
||||
else {
|
||||
var type = getTypeOf(element);
|
||||
if (element.type && element.type.names.length === 1 && element.type.names[0] === "function")
|
||||
writeFunctionSignature(element, false, true);
|
||||
else if (type === "object") {
|
||||
if (element.properties && element.properties.length)
|
||||
writeInterfaceBody(element);
|
||||
else
|
||||
write("{}");
|
||||
} else
|
||||
write(type);
|
||||
}
|
||||
writeln(";");
|
||||
}
|
||||
}
|
||||
+256
@@ -0,0 +1,256 @@
|
||||
{
|
||||
"name": "cli",
|
||||
"version": "6.9.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"node_modules/acorn": {
|
||||
"version": "7.4.1",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-jsx": {
|
||||
"version": "5.3.1",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/deep-is": {
|
||||
"version": "0.1.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/escodegen": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.0.0.tgz",
|
||||
"integrity": "sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw==",
|
||||
"dependencies": {
|
||||
"esprima": "^4.0.1",
|
||||
"estraverse": "^5.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"optionator": "^0.8.1"
|
||||
},
|
||||
"bin": {
|
||||
"escodegen": "bin/escodegen.js",
|
||||
"esgenerate": "bin/esgenerate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"source-map": "~0.6.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-visitor-keys": {
|
||||
"version": "1.3.0",
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/espree": {
|
||||
"version": "7.3.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^7.4.0",
|
||||
"acorn-jsx": "^5.3.1",
|
||||
"eslint-visitor-keys": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esprima": {
|
||||
"version": "4.0.1",
|
||||
"license": "BSD-2-Clause",
|
||||
"bin": {
|
||||
"esparse": "bin/esparse.js",
|
||||
"esvalidate": "bin/esvalidate.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/estraverse": {
|
||||
"version": "5.2.0",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esutils": {
|
||||
"version": "2.0.3",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-levenshtein": {
|
||||
"version": "2.0.6",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.1.6",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.4",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/levn": {
|
||||
"version": "0.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.0.4",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"node_modules/optionator": {
|
||||
"version": "0.8.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deep-is": "~0.1.3",
|
||||
"fast-levenshtein": "~2.0.6",
|
||||
"levn": "~0.3.0",
|
||||
"prelude-ls": "~1.1.2",
|
||||
"type-check": "~0.3.2",
|
||||
"word-wrap": "~1.2.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/prelude-ls": {
|
||||
"version": "1.1.2",
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "3.0.2",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^7.1.3"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "bin.js"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tmp": {
|
||||
"version": "0.2.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"rimraf": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.3.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"prelude-ls": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/word-wrap": {
|
||||
"version": "1.2.3",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/wrappy": {
|
||||
"version": "1.0.2",
|
||||
"license": "ISC"
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2012-2017 by Ingvar Stepanyan
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
# Acorn-JSX
|
||||
|
||||
[](https://travis-ci.org/acornjs/acorn-jsx)
|
||||
[](https://www.npmjs.org/package/acorn-jsx)
|
||||
|
||||
This is plugin for [Acorn](http://marijnhaverbeke.nl/acorn/) - a tiny, fast JavaScript parser, written completely in JavaScript.
|
||||
|
||||
It was created as an experimental alternative, faster [React.js JSX](http://facebook.github.io/react/docs/jsx-in-depth.html) parser. Later, it replaced the [official parser](https://github.com/facebookarchive/esprima) and these days is used by many prominent development tools.
|
||||
|
||||
## Transpiler
|
||||
|
||||
Please note that this tool only parses source code to JSX AST, which is useful for various language tools and services. If you want to transpile your code to regular ES5-compliant JavaScript with source map, check out [Babel](https://babeljs.io/) and [Buble](https://buble.surge.sh/) transpilers which use `acorn-jsx` under the hood.
|
||||
|
||||
## Usage
|
||||
|
||||
Requiring this module provides you with an Acorn plugin that you can use like this:
|
||||
|
||||
```javascript
|
||||
var acorn = require("acorn");
|
||||
var jsx = require("acorn-jsx");
|
||||
acorn.Parser.extend(jsx()).parse("my(<jsx/>, 'code');");
|
||||
```
|
||||
|
||||
Note that official spec doesn't support mix of XML namespaces and object-style access in tag names (#27) like in `<namespace:Object.Property />`, so it was deprecated in `acorn-jsx@3.0`. If you still want to opt-in to support of such constructions, you can pass the following option:
|
||||
|
||||
```javascript
|
||||
acorn.Parser.extend(jsx({ allowNamespacedObjects: true }))
|
||||
```
|
||||
|
||||
Also, since most apps use pure React transformer, a new option was introduced that allows to prohibit namespaces completely:
|
||||
|
||||
```javascript
|
||||
acorn.Parser.extend(jsx({ allowNamespaces: false }))
|
||||
```
|
||||
|
||||
Note that by default `allowNamespaces` is enabled for spec compliancy.
|
||||
|
||||
## License
|
||||
|
||||
This plugin is issued under the [MIT license](./LICENSE).
|
||||
+488
@@ -0,0 +1,488 @@
|
||||
'use strict';
|
||||
|
||||
const XHTMLEntities = require('./xhtml');
|
||||
|
||||
const hexNumber = /^[\da-fA-F]+$/;
|
||||
const decimalNumber = /^\d+$/;
|
||||
|
||||
// The map to `acorn-jsx` tokens from `acorn` namespace objects.
|
||||
const acornJsxMap = new WeakMap();
|
||||
|
||||
// Get the original tokens for the given `acorn` namespace object.
|
||||
function getJsxTokens(acorn) {
|
||||
acorn = acorn.Parser.acorn || acorn;
|
||||
let acornJsx = acornJsxMap.get(acorn);
|
||||
if (!acornJsx) {
|
||||
const tt = acorn.tokTypes;
|
||||
const TokContext = acorn.TokContext;
|
||||
const TokenType = acorn.TokenType;
|
||||
const tc_oTag = new TokContext('<tag', false);
|
||||
const tc_cTag = new TokContext('</tag', false);
|
||||
const tc_expr = new TokContext('<tag>...</tag>', true, true);
|
||||
const tokContexts = {
|
||||
tc_oTag: tc_oTag,
|
||||
tc_cTag: tc_cTag,
|
||||
tc_expr: tc_expr
|
||||
};
|
||||
const tokTypes = {
|
||||
jsxName: new TokenType('jsxName'),
|
||||
jsxText: new TokenType('jsxText', {beforeExpr: true}),
|
||||
jsxTagStart: new TokenType('jsxTagStart', {startsExpr: true}),
|
||||
jsxTagEnd: new TokenType('jsxTagEnd')
|
||||
};
|
||||
|
||||
tokTypes.jsxTagStart.updateContext = function() {
|
||||
this.context.push(tc_expr); // treat as beginning of JSX expression
|
||||
this.context.push(tc_oTag); // start opening tag context
|
||||
this.exprAllowed = false;
|
||||
};
|
||||
tokTypes.jsxTagEnd.updateContext = function(prevType) {
|
||||
let out = this.context.pop();
|
||||
if (out === tc_oTag && prevType === tt.slash || out === tc_cTag) {
|
||||
this.context.pop();
|
||||
this.exprAllowed = this.curContext() === tc_expr;
|
||||
} else {
|
||||
this.exprAllowed = true;
|
||||
}
|
||||
};
|
||||
|
||||
acornJsx = { tokContexts: tokContexts, tokTypes: tokTypes };
|
||||
acornJsxMap.set(acorn, acornJsx);
|
||||
}
|
||||
|
||||
return acornJsx;
|
||||
}
|
||||
|
||||
// Transforms JSX element name to string.
|
||||
|
||||
function getQualifiedJSXName(object) {
|
||||
if (!object)
|
||||
return object;
|
||||
|
||||
if (object.type === 'JSXIdentifier')
|
||||
return object.name;
|
||||
|
||||
if (object.type === 'JSXNamespacedName')
|
||||
return object.namespace.name + ':' + object.name.name;
|
||||
|
||||
if (object.type === 'JSXMemberExpression')
|
||||
return getQualifiedJSXName(object.object) + '.' +
|
||||
getQualifiedJSXName(object.property);
|
||||
}
|
||||
|
||||
module.exports = function(options) {
|
||||
options = options || {};
|
||||
return function(Parser) {
|
||||
return plugin({
|
||||
allowNamespaces: options.allowNamespaces !== false,
|
||||
allowNamespacedObjects: !!options.allowNamespacedObjects
|
||||
}, Parser);
|
||||
};
|
||||
};
|
||||
|
||||
// This is `tokTypes` of the peer dep.
|
||||
// This can be different instances from the actual `tokTypes` this plugin uses.
|
||||
Object.defineProperty(module.exports, "tokTypes", {
|
||||
get: function get_tokTypes() {
|
||||
return getJsxTokens(require("acorn")).tokTypes;
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
function plugin(options, Parser) {
|
||||
const acorn = Parser.acorn || require("acorn");
|
||||
const acornJsx = getJsxTokens(acorn);
|
||||
const tt = acorn.tokTypes;
|
||||
const tok = acornJsx.tokTypes;
|
||||
const tokContexts = acorn.tokContexts;
|
||||
const tc_oTag = acornJsx.tokContexts.tc_oTag;
|
||||
const tc_cTag = acornJsx.tokContexts.tc_cTag;
|
||||
const tc_expr = acornJsx.tokContexts.tc_expr;
|
||||
const isNewLine = acorn.isNewLine;
|
||||
const isIdentifierStart = acorn.isIdentifierStart;
|
||||
const isIdentifierChar = acorn.isIdentifierChar;
|
||||
|
||||
return class extends Parser {
|
||||
// Expose actual `tokTypes` and `tokContexts` to other plugins.
|
||||
static get acornJsx() {
|
||||
return acornJsx;
|
||||
}
|
||||
|
||||
// Reads inline JSX contents token.
|
||||
jsx_readToken() {
|
||||
let out = '', chunkStart = this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated JSX contents');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
|
||||
switch (ch) {
|
||||
case 60: // '<'
|
||||
case 123: // '{'
|
||||
if (this.pos === this.start) {
|
||||
if (ch === 60 && this.exprAllowed) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return this.getTokenFromCode(ch);
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
return this.finishToken(tok.jsxText, out);
|
||||
|
||||
case 38: // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
break;
|
||||
|
||||
case 62: // '>'
|
||||
case 125: // '}'
|
||||
this.raise(
|
||||
this.pos,
|
||||
"Unexpected token `" + this.input[this.pos] + "`. Did you mean `" +
|
||||
(ch === 62 ? ">" : "}") + "` or " + "`{\"" + this.input[this.pos] + "\"}" + "`?"
|
||||
);
|
||||
|
||||
default:
|
||||
if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(true);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jsx_readNewLine(normalizeCRLF) {
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
let out;
|
||||
++this.pos;
|
||||
if (ch === 13 && this.input.charCodeAt(this.pos) === 10) {
|
||||
++this.pos;
|
||||
out = normalizeCRLF ? '\n' : '\r\n';
|
||||
} else {
|
||||
out = String.fromCharCode(ch);
|
||||
}
|
||||
if (this.options.locations) {
|
||||
++this.curLine;
|
||||
this.lineStart = this.pos;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
jsx_readString(quote) {
|
||||
let out = '', chunkStart = ++this.pos;
|
||||
for (;;) {
|
||||
if (this.pos >= this.input.length)
|
||||
this.raise(this.start, 'Unterminated string constant');
|
||||
let ch = this.input.charCodeAt(this.pos);
|
||||
if (ch === quote) break;
|
||||
if (ch === 38) { // '&'
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readEntity();
|
||||
chunkStart = this.pos;
|
||||
} else if (isNewLine(ch)) {
|
||||
out += this.input.slice(chunkStart, this.pos);
|
||||
out += this.jsx_readNewLine(false);
|
||||
chunkStart = this.pos;
|
||||
} else {
|
||||
++this.pos;
|
||||
}
|
||||
}
|
||||
out += this.input.slice(chunkStart, this.pos++);
|
||||
return this.finishToken(tt.string, out);
|
||||
}
|
||||
|
||||
jsx_readEntity() {
|
||||
let str = '', count = 0, entity;
|
||||
let ch = this.input[this.pos];
|
||||
if (ch !== '&')
|
||||
this.raise(this.pos, 'Entity must start with an ampersand');
|
||||
let startPos = ++this.pos;
|
||||
while (this.pos < this.input.length && count++ < 10) {
|
||||
ch = this.input[this.pos++];
|
||||
if (ch === ';') {
|
||||
if (str[0] === '#') {
|
||||
if (str[1] === 'x') {
|
||||
str = str.substr(2);
|
||||
if (hexNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 16));
|
||||
} else {
|
||||
str = str.substr(1);
|
||||
if (decimalNumber.test(str))
|
||||
entity = String.fromCharCode(parseInt(str, 10));
|
||||
}
|
||||
} else {
|
||||
entity = XHTMLEntities[str];
|
||||
}
|
||||
break;
|
||||
}
|
||||
str += ch;
|
||||
}
|
||||
if (!entity) {
|
||||
this.pos = startPos;
|
||||
return '&';
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
// Read a JSX identifier (valid tag or attribute name).
|
||||
//
|
||||
// Optimized version since JSX identifiers can't contain
|
||||
// escape characters and so can be read as single slice.
|
||||
// Also assumes that first character was already checked
|
||||
// by isIdentifierStart in readToken.
|
||||
|
||||
jsx_readWord() {
|
||||
let ch, start = this.pos;
|
||||
do {
|
||||
ch = this.input.charCodeAt(++this.pos);
|
||||
} while (isIdentifierChar(ch) || ch === 45); // '-'
|
||||
return this.finishToken(tok.jsxName, this.input.slice(start, this.pos));
|
||||
}
|
||||
|
||||
// Parse next token as JSX identifier
|
||||
|
||||
jsx_parseIdentifier() {
|
||||
let node = this.startNode();
|
||||
if (this.type === tok.jsxName)
|
||||
node.name = this.value;
|
||||
else if (this.type.keyword)
|
||||
node.name = this.type.keyword;
|
||||
else
|
||||
this.unexpected();
|
||||
this.next();
|
||||
return this.finishNode(node, 'JSXIdentifier');
|
||||
}
|
||||
|
||||
// Parse namespaced identifier.
|
||||
|
||||
jsx_parseNamespacedName() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let name = this.jsx_parseIdentifier();
|
||||
if (!options.allowNamespaces || !this.eat(tt.colon)) return name;
|
||||
var node = this.startNodeAt(startPos, startLoc);
|
||||
node.namespace = name;
|
||||
node.name = this.jsx_parseIdentifier();
|
||||
return this.finishNode(node, 'JSXNamespacedName');
|
||||
}
|
||||
|
||||
// Parses element name in any form - namespaced, member
|
||||
// or single identifier.
|
||||
|
||||
jsx_parseElementName() {
|
||||
if (this.type === tok.jsxTagEnd) return '';
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
let node = this.jsx_parseNamespacedName();
|
||||
if (this.type === tt.dot && node.type === 'JSXNamespacedName' && !options.allowNamespacedObjects) {
|
||||
this.unexpected();
|
||||
}
|
||||
while (this.eat(tt.dot)) {
|
||||
let newNode = this.startNodeAt(startPos, startLoc);
|
||||
newNode.object = node;
|
||||
newNode.property = this.jsx_parseIdentifier();
|
||||
node = this.finishNode(newNode, 'JSXMemberExpression');
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses any type of JSX attribute value.
|
||||
|
||||
jsx_parseAttributeValue() {
|
||||
switch (this.type) {
|
||||
case tt.braceL:
|
||||
let node = this.jsx_parseExpressionContainer();
|
||||
if (node.expression.type === 'JSXEmptyExpression')
|
||||
this.raise(node.start, 'JSX attributes must only be assigned a non-empty expression');
|
||||
return node;
|
||||
|
||||
case tok.jsxTagStart:
|
||||
case tt.string:
|
||||
return this.parseExprAtom();
|
||||
|
||||
default:
|
||||
this.raise(this.start, 'JSX value should be either an expression or a quoted JSX text');
|
||||
}
|
||||
}
|
||||
|
||||
// JSXEmptyExpression is unique type since it doesn't actually parse anything,
|
||||
// and so it should start at the end of last read token (left brace) and finish
|
||||
// at the beginning of the next one (right brace).
|
||||
|
||||
jsx_parseEmptyExpression() {
|
||||
let node = this.startNodeAt(this.lastTokEnd, this.lastTokEndLoc);
|
||||
return this.finishNodeAt(node, 'JSXEmptyExpression', this.start, this.startLoc);
|
||||
}
|
||||
|
||||
// Parses JSX expression enclosed into curly brackets.
|
||||
|
||||
jsx_parseExpressionContainer() {
|
||||
let node = this.startNode();
|
||||
this.next();
|
||||
node.expression = this.type === tt.braceR
|
||||
? this.jsx_parseEmptyExpression()
|
||||
: this.parseExpression();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXExpressionContainer');
|
||||
}
|
||||
|
||||
// Parses following JSX attribute name-value pair.
|
||||
|
||||
jsx_parseAttribute() {
|
||||
let node = this.startNode();
|
||||
if (this.eat(tt.braceL)) {
|
||||
this.expect(tt.ellipsis);
|
||||
node.argument = this.parseMaybeAssign();
|
||||
this.expect(tt.braceR);
|
||||
return this.finishNode(node, 'JSXSpreadAttribute');
|
||||
}
|
||||
node.name = this.jsx_parseNamespacedName();
|
||||
node.value = this.eat(tt.eq) ? this.jsx_parseAttributeValue() : null;
|
||||
return this.finishNode(node, 'JSXAttribute');
|
||||
}
|
||||
|
||||
// Parses JSX opening tag starting after '<'.
|
||||
|
||||
jsx_parseOpeningElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
node.attributes = [];
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
while (this.type !== tt.slash && this.type !== tok.jsxTagEnd)
|
||||
node.attributes.push(this.jsx_parseAttribute());
|
||||
node.selfClosing = this.eat(tt.slash);
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXOpeningElement' : 'JSXOpeningFragment');
|
||||
}
|
||||
|
||||
// Parses JSX closing tag starting after '</'.
|
||||
|
||||
jsx_parseClosingElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let nodeName = this.jsx_parseElementName();
|
||||
if (nodeName) node.name = nodeName;
|
||||
this.expect(tok.jsxTagEnd);
|
||||
return this.finishNode(node, nodeName ? 'JSXClosingElement' : 'JSXClosingFragment');
|
||||
}
|
||||
|
||||
// Parses entire JSX element, including it's opening tag
|
||||
// (starting after '<'), attributes, contents and closing tag.
|
||||
|
||||
jsx_parseElementAt(startPos, startLoc) {
|
||||
let node = this.startNodeAt(startPos, startLoc);
|
||||
let children = [];
|
||||
let openingElement = this.jsx_parseOpeningElementAt(startPos, startLoc);
|
||||
let closingElement = null;
|
||||
|
||||
if (!openingElement.selfClosing) {
|
||||
contents: for (;;) {
|
||||
switch (this.type) {
|
||||
case tok.jsxTagStart:
|
||||
startPos = this.start; startLoc = this.startLoc;
|
||||
this.next();
|
||||
if (this.eat(tt.slash)) {
|
||||
closingElement = this.jsx_parseClosingElementAt(startPos, startLoc);
|
||||
break contents;
|
||||
}
|
||||
children.push(this.jsx_parseElementAt(startPos, startLoc));
|
||||
break;
|
||||
|
||||
case tok.jsxText:
|
||||
children.push(this.parseExprAtom());
|
||||
break;
|
||||
|
||||
case tt.braceL:
|
||||
children.push(this.jsx_parseExpressionContainer());
|
||||
break;
|
||||
|
||||
default:
|
||||
this.unexpected();
|
||||
}
|
||||
}
|
||||
if (getQualifiedJSXName(closingElement.name) !== getQualifiedJSXName(openingElement.name)) {
|
||||
this.raise(
|
||||
closingElement.start,
|
||||
'Expected corresponding JSX closing tag for <' + getQualifiedJSXName(openingElement.name) + '>');
|
||||
}
|
||||
}
|
||||
let fragmentOrElement = openingElement.name ? 'Element' : 'Fragment';
|
||||
|
||||
node['opening' + fragmentOrElement] = openingElement;
|
||||
node['closing' + fragmentOrElement] = closingElement;
|
||||
node.children = children;
|
||||
if (this.type === tt.relational && this.value === "<") {
|
||||
this.raise(this.start, "Adjacent JSX elements must be wrapped in an enclosing tag");
|
||||
}
|
||||
return this.finishNode(node, 'JSX' + fragmentOrElement);
|
||||
}
|
||||
|
||||
// Parse JSX text
|
||||
|
||||
jsx_parseText() {
|
||||
let node = this.parseLiteral(this.value);
|
||||
node.type = "JSXText";
|
||||
return node;
|
||||
}
|
||||
|
||||
// Parses entire JSX element from current position.
|
||||
|
||||
jsx_parseElement() {
|
||||
let startPos = this.start, startLoc = this.startLoc;
|
||||
this.next();
|
||||
return this.jsx_parseElementAt(startPos, startLoc);
|
||||
}
|
||||
|
||||
parseExprAtom(refShortHandDefaultPos) {
|
||||
if (this.type === tok.jsxText)
|
||||
return this.jsx_parseText();
|
||||
else if (this.type === tok.jsxTagStart)
|
||||
return this.jsx_parseElement();
|
||||
else
|
||||
return super.parseExprAtom(refShortHandDefaultPos);
|
||||
}
|
||||
|
||||
readToken(code) {
|
||||
let context = this.curContext();
|
||||
|
||||
if (context === tc_expr) return this.jsx_readToken();
|
||||
|
||||
if (context === tc_oTag || context === tc_cTag) {
|
||||
if (isIdentifierStart(code)) return this.jsx_readWord();
|
||||
|
||||
if (code == 62) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagEnd);
|
||||
}
|
||||
|
||||
if ((code === 34 || code === 39) && context == tc_oTag)
|
||||
return this.jsx_readString(code);
|
||||
}
|
||||
|
||||
if (code === 60 && this.exprAllowed && this.input.charCodeAt(this.pos + 1) !== 33) {
|
||||
++this.pos;
|
||||
return this.finishToken(tok.jsxTagStart);
|
||||
}
|
||||
return super.readToken(code);
|
||||
}
|
||||
|
||||
updateContext(prevType) {
|
||||
if (this.type == tt.braceL) {
|
||||
var curContext = this.curContext();
|
||||
if (curContext == tc_oTag) this.context.push(tokContexts.b_expr);
|
||||
else if (curContext == tc_expr) this.context.push(tokContexts.b_tmpl);
|
||||
else super.updateContext(prevType);
|
||||
this.exprAllowed = true;
|
||||
} else if (this.type === tt.slash && prevType === tok.jsxTagStart) {
|
||||
this.context.length -= 2; // do not consider JSX expr -> JSX open tag -> ... anymore
|
||||
this.context.push(tc_cTag); // reconsider as closing tag context
|
||||
this.exprAllowed = false;
|
||||
} else {
|
||||
return super.updateContext(prevType);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "acorn-jsx",
|
||||
"description": "Modern, fast React.js JSX parser",
|
||||
"homepage": "https://github.com/acornjs/acorn-jsx",
|
||||
"version": "5.3.1",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"web": "http://rreverser.com/"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/acornjs/acorn-jsx"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "node test/run.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "^8.0.1"
|
||||
}
|
||||
}
|
||||
+255
@@ -0,0 +1,255 @@
|
||||
module.exports = {
|
||||
quot: '\u0022',
|
||||
amp: '&',
|
||||
apos: '\u0027',
|
||||
lt: '<',
|
||||
gt: '>',
|
||||
nbsp: '\u00A0',
|
||||
iexcl: '\u00A1',
|
||||
cent: '\u00A2',
|
||||
pound: '\u00A3',
|
||||
curren: '\u00A4',
|
||||
yen: '\u00A5',
|
||||
brvbar: '\u00A6',
|
||||
sect: '\u00A7',
|
||||
uml: '\u00A8',
|
||||
copy: '\u00A9',
|
||||
ordf: '\u00AA',
|
||||
laquo: '\u00AB',
|
||||
not: '\u00AC',
|
||||
shy: '\u00AD',
|
||||
reg: '\u00AE',
|
||||
macr: '\u00AF',
|
||||
deg: '\u00B0',
|
||||
plusmn: '\u00B1',
|
||||
sup2: '\u00B2',
|
||||
sup3: '\u00B3',
|
||||
acute: '\u00B4',
|
||||
micro: '\u00B5',
|
||||
para: '\u00B6',
|
||||
middot: '\u00B7',
|
||||
cedil: '\u00B8',
|
||||
sup1: '\u00B9',
|
||||
ordm: '\u00BA',
|
||||
raquo: '\u00BB',
|
||||
frac14: '\u00BC',
|
||||
frac12: '\u00BD',
|
||||
frac34: '\u00BE',
|
||||
iquest: '\u00BF',
|
||||
Agrave: '\u00C0',
|
||||
Aacute: '\u00C1',
|
||||
Acirc: '\u00C2',
|
||||
Atilde: '\u00C3',
|
||||
Auml: '\u00C4',
|
||||
Aring: '\u00C5',
|
||||
AElig: '\u00C6',
|
||||
Ccedil: '\u00C7',
|
||||
Egrave: '\u00C8',
|
||||
Eacute: '\u00C9',
|
||||
Ecirc: '\u00CA',
|
||||
Euml: '\u00CB',
|
||||
Igrave: '\u00CC',
|
||||
Iacute: '\u00CD',
|
||||
Icirc: '\u00CE',
|
||||
Iuml: '\u00CF',
|
||||
ETH: '\u00D0',
|
||||
Ntilde: '\u00D1',
|
||||
Ograve: '\u00D2',
|
||||
Oacute: '\u00D3',
|
||||
Ocirc: '\u00D4',
|
||||
Otilde: '\u00D5',
|
||||
Ouml: '\u00D6',
|
||||
times: '\u00D7',
|
||||
Oslash: '\u00D8',
|
||||
Ugrave: '\u00D9',
|
||||
Uacute: '\u00DA',
|
||||
Ucirc: '\u00DB',
|
||||
Uuml: '\u00DC',
|
||||
Yacute: '\u00DD',
|
||||
THORN: '\u00DE',
|
||||
szlig: '\u00DF',
|
||||
agrave: '\u00E0',
|
||||
aacute: '\u00E1',
|
||||
acirc: '\u00E2',
|
||||
atilde: '\u00E3',
|
||||
auml: '\u00E4',
|
||||
aring: '\u00E5',
|
||||
aelig: '\u00E6',
|
||||
ccedil: '\u00E7',
|
||||
egrave: '\u00E8',
|
||||
eacute: '\u00E9',
|
||||
ecirc: '\u00EA',
|
||||
euml: '\u00EB',
|
||||
igrave: '\u00EC',
|
||||
iacute: '\u00ED',
|
||||
icirc: '\u00EE',
|
||||
iuml: '\u00EF',
|
||||
eth: '\u00F0',
|
||||
ntilde: '\u00F1',
|
||||
ograve: '\u00F2',
|
||||
oacute: '\u00F3',
|
||||
ocirc: '\u00F4',
|
||||
otilde: '\u00F5',
|
||||
ouml: '\u00F6',
|
||||
divide: '\u00F7',
|
||||
oslash: '\u00F8',
|
||||
ugrave: '\u00F9',
|
||||
uacute: '\u00FA',
|
||||
ucirc: '\u00FB',
|
||||
uuml: '\u00FC',
|
||||
yacute: '\u00FD',
|
||||
thorn: '\u00FE',
|
||||
yuml: '\u00FF',
|
||||
OElig: '\u0152',
|
||||
oelig: '\u0153',
|
||||
Scaron: '\u0160',
|
||||
scaron: '\u0161',
|
||||
Yuml: '\u0178',
|
||||
fnof: '\u0192',
|
||||
circ: '\u02C6',
|
||||
tilde: '\u02DC',
|
||||
Alpha: '\u0391',
|
||||
Beta: '\u0392',
|
||||
Gamma: '\u0393',
|
||||
Delta: '\u0394',
|
||||
Epsilon: '\u0395',
|
||||
Zeta: '\u0396',
|
||||
Eta: '\u0397',
|
||||
Theta: '\u0398',
|
||||
Iota: '\u0399',
|
||||
Kappa: '\u039A',
|
||||
Lambda: '\u039B',
|
||||
Mu: '\u039C',
|
||||
Nu: '\u039D',
|
||||
Xi: '\u039E',
|
||||
Omicron: '\u039F',
|
||||
Pi: '\u03A0',
|
||||
Rho: '\u03A1',
|
||||
Sigma: '\u03A3',
|
||||
Tau: '\u03A4',
|
||||
Upsilon: '\u03A5',
|
||||
Phi: '\u03A6',
|
||||
Chi: '\u03A7',
|
||||
Psi: '\u03A8',
|
||||
Omega: '\u03A9',
|
||||
alpha: '\u03B1',
|
||||
beta: '\u03B2',
|
||||
gamma: '\u03B3',
|
||||
delta: '\u03B4',
|
||||
epsilon: '\u03B5',
|
||||
zeta: '\u03B6',
|
||||
eta: '\u03B7',
|
||||
theta: '\u03B8',
|
||||
iota: '\u03B9',
|
||||
kappa: '\u03BA',
|
||||
lambda: '\u03BB',
|
||||
mu: '\u03BC',
|
||||
nu: '\u03BD',
|
||||
xi: '\u03BE',
|
||||
omicron: '\u03BF',
|
||||
pi: '\u03C0',
|
||||
rho: '\u03C1',
|
||||
sigmaf: '\u03C2',
|
||||
sigma: '\u03C3',
|
||||
tau: '\u03C4',
|
||||
upsilon: '\u03C5',
|
||||
phi: '\u03C6',
|
||||
chi: '\u03C7',
|
||||
psi: '\u03C8',
|
||||
omega: '\u03C9',
|
||||
thetasym: '\u03D1',
|
||||
upsih: '\u03D2',
|
||||
piv: '\u03D6',
|
||||
ensp: '\u2002',
|
||||
emsp: '\u2003',
|
||||
thinsp: '\u2009',
|
||||
zwnj: '\u200C',
|
||||
zwj: '\u200D',
|
||||
lrm: '\u200E',
|
||||
rlm: '\u200F',
|
||||
ndash: '\u2013',
|
||||
mdash: '\u2014',
|
||||
lsquo: '\u2018',
|
||||
rsquo: '\u2019',
|
||||
sbquo: '\u201A',
|
||||
ldquo: '\u201C',
|
||||
rdquo: '\u201D',
|
||||
bdquo: '\u201E',
|
||||
dagger: '\u2020',
|
||||
Dagger: '\u2021',
|
||||
bull: '\u2022',
|
||||
hellip: '\u2026',
|
||||
permil: '\u2030',
|
||||
prime: '\u2032',
|
||||
Prime: '\u2033',
|
||||
lsaquo: '\u2039',
|
||||
rsaquo: '\u203A',
|
||||
oline: '\u203E',
|
||||
frasl: '\u2044',
|
||||
euro: '\u20AC',
|
||||
image: '\u2111',
|
||||
weierp: '\u2118',
|
||||
real: '\u211C',
|
||||
trade: '\u2122',
|
||||
alefsym: '\u2135',
|
||||
larr: '\u2190',
|
||||
uarr: '\u2191',
|
||||
rarr: '\u2192',
|
||||
darr: '\u2193',
|
||||
harr: '\u2194',
|
||||
crarr: '\u21B5',
|
||||
lArr: '\u21D0',
|
||||
uArr: '\u21D1',
|
||||
rArr: '\u21D2',
|
||||
dArr: '\u21D3',
|
||||
hArr: '\u21D4',
|
||||
forall: '\u2200',
|
||||
part: '\u2202',
|
||||
exist: '\u2203',
|
||||
empty: '\u2205',
|
||||
nabla: '\u2207',
|
||||
isin: '\u2208',
|
||||
notin: '\u2209',
|
||||
ni: '\u220B',
|
||||
prod: '\u220F',
|
||||
sum: '\u2211',
|
||||
minus: '\u2212',
|
||||
lowast: '\u2217',
|
||||
radic: '\u221A',
|
||||
prop: '\u221D',
|
||||
infin: '\u221E',
|
||||
ang: '\u2220',
|
||||
and: '\u2227',
|
||||
or: '\u2228',
|
||||
cap: '\u2229',
|
||||
cup: '\u222A',
|
||||
'int': '\u222B',
|
||||
there4: '\u2234',
|
||||
sim: '\u223C',
|
||||
cong: '\u2245',
|
||||
asymp: '\u2248',
|
||||
ne: '\u2260',
|
||||
equiv: '\u2261',
|
||||
le: '\u2264',
|
||||
ge: '\u2265',
|
||||
sub: '\u2282',
|
||||
sup: '\u2283',
|
||||
nsub: '\u2284',
|
||||
sube: '\u2286',
|
||||
supe: '\u2287',
|
||||
oplus: '\u2295',
|
||||
otimes: '\u2297',
|
||||
perp: '\u22A5',
|
||||
sdot: '\u22C5',
|
||||
lceil: '\u2308',
|
||||
rceil: '\u2309',
|
||||
lfloor: '\u230A',
|
||||
rfloor: '\u230B',
|
||||
lang: '\u2329',
|
||||
rang: '\u232A',
|
||||
loz: '\u25CA',
|
||||
spades: '\u2660',
|
||||
clubs: '\u2663',
|
||||
hearts: '\u2665',
|
||||
diams: '\u2666'
|
||||
};
|
||||
+620
@@ -0,0 +1,620 @@
|
||||
## 7.4.0 (2020-08-03)
|
||||
|
||||
### New features
|
||||
|
||||
Add support for logical assignment operators.
|
||||
|
||||
Add support for numeric separators.
|
||||
|
||||
## 7.3.1 (2020-06-11)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Make the string in the `version` export match the actual library version.
|
||||
|
||||
## 7.3.0 (2020-06-11)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a bug that caused parsing of object patterns with a property named `set` that had a default value to fail.
|
||||
|
||||
### New features
|
||||
|
||||
Add support for optional chaining (`?.`).
|
||||
|
||||
## 7.2.0 (2020-05-09)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix precedence issue in parsing of async arrow functions.
|
||||
|
||||
### New features
|
||||
|
||||
Add support for nullish coalescing.
|
||||
|
||||
Add support for `import.meta`.
|
||||
|
||||
Support `export * as ...` syntax.
|
||||
|
||||
Upgrade to Unicode 13.
|
||||
|
||||
## 6.4.1 (2020-03-09)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
More carefully check for valid UTF16 surrogate pairs in regexp validator.
|
||||
|
||||
## 7.1.1 (2020-03-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Treat `\8` and `\9` as invalid escapes in template strings.
|
||||
|
||||
Allow unicode escapes in property names that are keywords.
|
||||
|
||||
Don't error on an exponential operator expression as argument to `await`.
|
||||
|
||||
More carefully check for valid UTF16 surrogate pairs in regexp validator.
|
||||
|
||||
## 7.1.0 (2019-09-24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disallow trailing object literal commas when ecmaVersion is less than 5.
|
||||
|
||||
### New features
|
||||
|
||||
Add a static `acorn` property to the `Parser` class that contains the entire module interface, to allow plugins to access the instance of the library that they are acting on.
|
||||
|
||||
## 7.0.0 (2019-08-13)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Changes the node format for dynamic imports to use the `ImportExpression` node type, as defined in [ESTree](https://github.com/estree/estree/blob/master/es2020.md#importexpression).
|
||||
|
||||
Makes 10 (ES2019) the default value for the `ecmaVersion` option.
|
||||
|
||||
## 6.3.0 (2019-08-12)
|
||||
|
||||
### New features
|
||||
|
||||
`sourceType: "module"` can now be used even when `ecmaVersion` is less than 6, to parse module-style code that otherwise conforms to an older standard.
|
||||
|
||||
## 6.2.1 (2019-07-21)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug causing Acorn to treat some characters as identifier characters that shouldn't be treated as such.
|
||||
|
||||
Fix issue where setting the `allowReserved` option to `"never"` allowed reserved words in some circumstances.
|
||||
|
||||
## 6.2.0 (2019-07-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Improve valid assignment checking in `for`/`in` and `for`/`of` loops.
|
||||
|
||||
Disallow binding `let` in patterns.
|
||||
|
||||
### New features
|
||||
|
||||
Support bigint syntax with `ecmaVersion` >= 11.
|
||||
|
||||
Support dynamic `import` syntax with `ecmaVersion` >= 11.
|
||||
|
||||
Upgrade to Unicode version 12.
|
||||
|
||||
## 6.1.1 (2019-02-27)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug that caused parsing default exports of with names to fail.
|
||||
|
||||
## 6.1.0 (2019-02-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix scope checking when redefining a `var` as a lexical binding.
|
||||
|
||||
### New features
|
||||
|
||||
Split up `parseSubscripts` to use an internal `parseSubscript` method to make it easier to extend with plugins.
|
||||
|
||||
## 6.0.7 (2019-02-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Check that exported bindings are defined.
|
||||
|
||||
Don't treat `\u180e` as a whitespace character.
|
||||
|
||||
Check for duplicate parameter names in methods.
|
||||
|
||||
Don't allow shorthand properties when they are generators or async methods.
|
||||
|
||||
Forbid binding `await` in async arrow function's parameter list.
|
||||
|
||||
## 6.0.6 (2019-01-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
The content of class declarations and expressions is now always parsed in strict mode.
|
||||
|
||||
Don't allow `let` or `const` to bind the variable name `let`.
|
||||
|
||||
Treat class declarations as lexical.
|
||||
|
||||
Don't allow a generator function declaration as the sole body of an `if` or `else`.
|
||||
|
||||
Ignore `"use strict"` when after an empty statement.
|
||||
|
||||
Allow string line continuations with special line terminator characters.
|
||||
|
||||
Treat `for` bodies as part of the `for` scope when checking for conflicting bindings.
|
||||
|
||||
Fix bug with parsing `yield` in a `for` loop initializer.
|
||||
|
||||
Implement special cases around scope checking for functions.
|
||||
|
||||
## 6.0.5 (2019-01-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix TypeScript type for `Parser.extend` and add `allowAwaitOutsideFunction` to options type.
|
||||
|
||||
Don't treat `let` as a keyword when the next token is `{` on the next line.
|
||||
|
||||
Fix bug that broke checking for parentheses around an object pattern in a destructuring assignment when `preserveParens` was on.
|
||||
|
||||
## 6.0.4 (2018-11-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Further improvements to tokenizing regular expressions in corner cases.
|
||||
|
||||
## 6.0.3 (2018-11-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug in tokenizing an expression-less return followed by a function followed by a regular expression.
|
||||
|
||||
Remove stray symlink in the package tarball.
|
||||
|
||||
## 6.0.2 (2018-09-26)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug where default expressions could fail to parse inside an object destructuring assignment expression.
|
||||
|
||||
## 6.0.1 (2018-09-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix wrong value in `version` export.
|
||||
|
||||
## 6.0.0 (2018-09-14)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Better handle variable-redefinition checks for catch bindings and functions directly under if statements.
|
||||
|
||||
Forbid `new.target` in top-level arrow functions.
|
||||
|
||||
Fix issue with parsing a regexp after `yield` in some contexts.
|
||||
|
||||
### New features
|
||||
|
||||
The package now comes with TypeScript definitions.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default value of the `ecmaVersion` option is now 9 (2018).
|
||||
|
||||
Plugins work differently, and will have to be rewritten to work with this version.
|
||||
|
||||
The loose parser and walker have been moved into separate packages (`acorn-loose` and `acorn-walk`).
|
||||
|
||||
## 5.7.3 (2018-09-10)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix failure to tokenize regexps after expressions like `x.of`.
|
||||
|
||||
Better error message for unterminated template literals.
|
||||
|
||||
## 5.7.2 (2018-08-24)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Properly handle `allowAwaitOutsideFunction` in for statements.
|
||||
|
||||
Treat function declarations at the top level of modules like let bindings.
|
||||
|
||||
Don't allow async function declarations as the only statement under a label.
|
||||
|
||||
## 5.7.0 (2018-06-15)
|
||||
|
||||
### New features
|
||||
|
||||
Upgraded to Unicode 11.
|
||||
|
||||
## 5.6.0 (2018-05-31)
|
||||
|
||||
### New features
|
||||
|
||||
Allow U+2028 and U+2029 in string when ECMAVersion >= 10.
|
||||
|
||||
Allow binding-less catch statements when ECMAVersion >= 10.
|
||||
|
||||
Add `allowAwaitOutsideFunction` option for parsing top-level `await`.
|
||||
|
||||
## 5.5.3 (2018-03-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A _second_ republish of the code in 5.5.1, this time with yarn, to hopefully get valid timestamps.
|
||||
|
||||
## 5.5.2 (2018-03-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A republish of the code in 5.5.1 in an attempt to solve an issue with the file timestamps in the npm package being 0.
|
||||
|
||||
## 5.5.1 (2018-03-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix misleading error message for octal escapes in template strings.
|
||||
|
||||
## 5.5.0 (2018-02-27)
|
||||
|
||||
### New features
|
||||
|
||||
The identifier character categorization is now based on Unicode version 10.
|
||||
|
||||
Acorn will now validate the content of regular expressions, including new ES9 features.
|
||||
|
||||
## 5.4.0 (2018-02-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disallow duplicate or escaped flags on regular expressions.
|
||||
|
||||
Disallow octal escapes in strings in strict mode.
|
||||
|
||||
### New features
|
||||
|
||||
Add support for async iteration.
|
||||
|
||||
Add support for object spread and rest.
|
||||
|
||||
## 5.3.0 (2017-12-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix parsing of floating point literals with leading zeroes in loose mode.
|
||||
|
||||
Allow duplicate property names in object patterns.
|
||||
|
||||
Don't allow static class methods named `prototype`.
|
||||
|
||||
Disallow async functions directly under `if` or `else`.
|
||||
|
||||
Parse right-hand-side of `for`/`of` as an assignment expression.
|
||||
|
||||
Stricter parsing of `for`/`in`.
|
||||
|
||||
Don't allow unicode escapes in contextual keywords.
|
||||
|
||||
### New features
|
||||
|
||||
Parsing class members was factored into smaller methods to allow plugins to hook into it.
|
||||
|
||||
## 5.2.1 (2017-10-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix a token context corruption bug.
|
||||
|
||||
## 5.2.0 (2017-10-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix token context tracking for `class` and `function` in property-name position.
|
||||
|
||||
Make sure `%*` isn't parsed as a valid operator.
|
||||
|
||||
Allow shorthand properties `get` and `set` to be followed by default values.
|
||||
|
||||
Disallow `super` when not in callee or object position.
|
||||
|
||||
### New features
|
||||
|
||||
Support [`directive` property](https://github.com/estree/estree/compare/b3de58c9997504d6fba04b72f76e6dd1619ee4eb...1da8e603237144f44710360f8feb7a9977e905e0) on directive expression statements.
|
||||
|
||||
## 5.1.2 (2017-09-04)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disable parsing of legacy HTML-style comments in modules.
|
||||
|
||||
Fix parsing of async methods whose names are keywords.
|
||||
|
||||
## 5.1.1 (2017-07-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix problem with disambiguating regexp and division after a class.
|
||||
|
||||
## 5.1.0 (2017-07-05)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix tokenizing of regexps in an object-desctructuring `for`/`of` loop and after `yield`.
|
||||
|
||||
Parse zero-prefixed numbers with non-octal digits as decimal.
|
||||
|
||||
Allow object/array patterns in rest parameters.
|
||||
|
||||
Don't error when `yield` is used as a property name.
|
||||
|
||||
Allow `async` as a shorthand object property.
|
||||
|
||||
### New features
|
||||
|
||||
Implement the [template literal revision proposal](https://github.com/tc39/proposal-template-literal-revision) for ES9.
|
||||
|
||||
## 5.0.3 (2017-04-01)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix spurious duplicate variable definition errors for named functions.
|
||||
|
||||
## 5.0.2 (2017-03-30)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
A binary operator after a parenthesized arrow expression is no longer incorrectly treated as an error.
|
||||
|
||||
## 5.0.0 (2017-03-28)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Raise an error for duplicated lexical bindings.
|
||||
|
||||
Fix spurious error when an assignement expression occurred after a spread expression.
|
||||
|
||||
Accept regular expressions after `of` (in `for`/`of`), `yield` (in a generator), and braced arrow functions.
|
||||
|
||||
Allow labels in front or `var` declarations, even in strict mode.
|
||||
|
||||
### Breaking changes
|
||||
|
||||
Parse declarations following `export default` as declaration nodes, not expressions. This means that class and function declarations nodes can now have `null` as their `id`.
|
||||
|
||||
## 4.0.11 (2017-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow all forms of member expressions to be parenthesized as lvalue.
|
||||
|
||||
## 4.0.10 (2017-02-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't expect semicolons after default-exported functions or classes, even when they are expressions.
|
||||
|
||||
Check for use of `'use strict'` directives in non-simple parameter functions, even when already in strict mode.
|
||||
|
||||
## 4.0.9 (2017-02-06)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix incorrect error raised for parenthesized simple assignment targets, so that `(x) = 1` parses again.
|
||||
|
||||
## 4.0.8 (2017-02-03)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Solve spurious parenthesized pattern errors by temporarily erring on the side of accepting programs that our delayed errors don't handle correctly yet.
|
||||
|
||||
## 4.0.7 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Accept invalidly rejected code like `(x).y = 2` again.
|
||||
|
||||
Don't raise an error when a function _inside_ strict code has a non-simple parameter list.
|
||||
|
||||
## 4.0.6 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix exponential behavior (manifesting itself as a complete hang for even relatively small source files) introduced by the new 'use strict' check.
|
||||
|
||||
## 4.0.5 (2017-02-02)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Disallow parenthesized pattern expressions.
|
||||
|
||||
Allow keywords as export names.
|
||||
|
||||
Don't allow the `async` keyword to be parenthesized.
|
||||
|
||||
Properly raise an error when a keyword contains a character escape.
|
||||
|
||||
Allow `"use strict"` to appear after other string literal expressions.
|
||||
|
||||
Disallow labeled declarations.
|
||||
|
||||
## 4.0.4 (2016-12-19)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix crash when `export` was followed by a keyword that can't be
|
||||
exported.
|
||||
|
||||
## 4.0.3 (2016-08-16)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Allow regular function declarations inside single-statement `if` branches in loose mode. Forbid them entirely in strict mode.
|
||||
|
||||
Properly parse properties named `async` in ES2017 mode.
|
||||
|
||||
Fix bug where reserved words were broken in ES2017 mode.
|
||||
|
||||
## 4.0.2 (2016-08-11)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Don't ignore period or 'e' characters after octal numbers.
|
||||
|
||||
Fix broken parsing for call expressions in default parameter values of arrow functions.
|
||||
|
||||
## 4.0.1 (2016-08-08)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix false positives in duplicated export name errors.
|
||||
|
||||
## 4.0.0 (2016-08-07)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default `ecmaVersion` option value is now 7.
|
||||
|
||||
A number of internal method signatures changed, so plugins might need to be updated.
|
||||
|
||||
### Bug fixes
|
||||
|
||||
The parser now raises errors on duplicated export names.
|
||||
|
||||
`arguments` and `eval` can now be used in shorthand properties.
|
||||
|
||||
Duplicate parameter names in non-simple argument lists now always produce an error.
|
||||
|
||||
### New features
|
||||
|
||||
The `ecmaVersion` option now also accepts year-style version numbers
|
||||
(2015, etc).
|
||||
|
||||
Support for `async`/`await` syntax when `ecmaVersion` is >= 8.
|
||||
|
||||
Support for trailing commas in call expressions when `ecmaVersion` is >= 8.
|
||||
|
||||
## 3.3.0 (2016-07-25)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Fix bug in tokenizing of regexp operator after a function declaration.
|
||||
|
||||
Fix parser crash when parsing an array pattern with a hole.
|
||||
|
||||
### New features
|
||||
|
||||
Implement check against complex argument lists in functions that enable strict mode in ES7.
|
||||
|
||||
## 3.2.0 (2016-06-07)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Improve handling of lack of unicode regexp support in host
|
||||
environment.
|
||||
|
||||
Properly reject shorthand properties whose name is a keyword.
|
||||
|
||||
### New features
|
||||
|
||||
Visitors created with `visit.make` now have their base as _prototype_, rather than copying properties into a fresh object.
|
||||
|
||||
## 3.1.0 (2016-04-18)
|
||||
|
||||
### Bug fixes
|
||||
|
||||
Properly tokenize the division operator directly after a function expression.
|
||||
|
||||
Allow trailing comma in destructuring arrays.
|
||||
|
||||
## 3.0.4 (2016-02-25)
|
||||
|
||||
### Fixes
|
||||
|
||||
Allow update expressions as left-hand-side of the ES7 exponential operator.
|
||||
|
||||
## 3.0.2 (2016-02-10)
|
||||
|
||||
### Fixes
|
||||
|
||||
Fix bug that accidentally made `undefined` a reserved word when parsing ES7.
|
||||
|
||||
## 3.0.0 (2016-02-10)
|
||||
|
||||
### Breaking changes
|
||||
|
||||
The default value of the `ecmaVersion` option is now 6 (used to be 5).
|
||||
|
||||
Support for comprehension syntax (which was dropped from the draft spec) has been removed.
|
||||
|
||||
### Fixes
|
||||
|
||||
`let` and `yield` are now “contextual keywords”, meaning you can mostly use them as identifiers in ES5 non-strict code.
|
||||
|
||||
A parenthesized class or function expression after `export default` is now parsed correctly.
|
||||
|
||||
### New features
|
||||
|
||||
When `ecmaVersion` is set to 7, Acorn will parse the exponentiation operator (`**`).
|
||||
|
||||
The identifier character ranges are now based on Unicode 8.0.0.
|
||||
|
||||
Plugins can now override the `raiseRecoverable` method to override the way non-critical errors are handled.
|
||||
|
||||
## 2.7.0 (2016-01-04)
|
||||
|
||||
### Fixes
|
||||
|
||||
Stop allowing rest parameters in setters.
|
||||
|
||||
Disallow `y` rexexp flag in ES5.
|
||||
|
||||
Disallow `\00` and `\000` escapes in strict mode.
|
||||
|
||||
Raise an error when an import name is a reserved word.
|
||||
|
||||
## 2.6.2 (2015-11-10)
|
||||
|
||||
### Fixes
|
||||
|
||||
Don't crash when no options object is passed.
|
||||
|
||||
## 2.6.0 (2015-11-09)
|
||||
|
||||
### Fixes
|
||||
|
||||
Add `await` as a reserved word in module sources.
|
||||
|
||||
Disallow `yield` in a parameter default value for a generator.
|
||||
|
||||
Forbid using a comma after a rest pattern in an array destructuring.
|
||||
|
||||
### New features
|
||||
|
||||
Support parsing stdin in command-line tool.
|
||||
|
||||
## 2.5.0 (2015-10-27)
|
||||
|
||||
### Fixes
|
||||
|
||||
Fix tokenizer support in the command-line tool.
|
||||
|
||||
Stop allowing `new.target` outside of functions.
|
||||
|
||||
Remove legacy `guard` and `guardedHandler` properties from try nodes.
|
||||
|
||||
Stop allowing multiple `__proto__` properties on an object literal in strict mode.
|
||||
|
||||
Don't allow rest parameters to be non-identifier patterns.
|
||||
|
||||
Check for duplicate paramter names in arrow functions.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2012-2018 by various contributors (see AUTHORS)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
# Acorn
|
||||
|
||||
A tiny, fast JavaScript parser written in JavaScript.
|
||||
|
||||
## Community
|
||||
|
||||
Acorn is open source software released under an
|
||||
[MIT license](https://github.com/acornjs/acorn/blob/master/acorn/LICENSE).
|
||||
|
||||
You are welcome to
|
||||
[report bugs](https://github.com/acornjs/acorn/issues) or create pull
|
||||
requests on [github](https://github.com/acornjs/acorn). For questions
|
||||
and discussion, please use the
|
||||
[Tern discussion forum](https://discuss.ternjs.net).
|
||||
|
||||
## Installation
|
||||
|
||||
The easiest way to install acorn is from [`npm`](https://www.npmjs.com/):
|
||||
|
||||
```sh
|
||||
npm install acorn
|
||||
```
|
||||
|
||||
Alternately, you can download the source and build acorn yourself:
|
||||
|
||||
```sh
|
||||
git clone https://github.com/acornjs/acorn.git
|
||||
cd acorn
|
||||
npm install
|
||||
```
|
||||
|
||||
## Interface
|
||||
|
||||
**parse**`(input, options)` is the main interface to the library. The
|
||||
`input` parameter is a string, `options` can be undefined or an object
|
||||
setting some of the options listed below. The return value will be an
|
||||
abstract syntax tree object as specified by the [ESTree
|
||||
spec](https://github.com/estree/estree).
|
||||
|
||||
```javascript
|
||||
let acorn = require("acorn");
|
||||
console.log(acorn.parse("1 + 1"));
|
||||
```
|
||||
|
||||
When encountering a syntax error, the parser will raise a
|
||||
`SyntaxError` object with a meaningful message. The error object will
|
||||
have a `pos` property that indicates the string offset at which the
|
||||
error occurred, and a `loc` object that contains a `{line, column}`
|
||||
object referring to that same position.
|
||||
|
||||
Options can be provided by passing a second argument, which should be
|
||||
an object containing any of these fields:
|
||||
|
||||
- **ecmaVersion**: Indicates the ECMAScript version to parse. Must be
|
||||
either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), 10 (2019) or 11
|
||||
(2020, partial support). This influences support for strict mode,
|
||||
the set of reserved words, and support for new syntax features.
|
||||
Default is 10.
|
||||
|
||||
**NOTE**: Only 'stage 4' (finalized) ECMAScript features are being
|
||||
implemented by Acorn. Other proposed new features can be implemented
|
||||
through plugins.
|
||||
|
||||
- **sourceType**: Indicate the mode the code should be parsed in. Can be
|
||||
either `"script"` or `"module"`. This influences global strict mode
|
||||
and parsing of `import` and `export` declarations.
|
||||
|
||||
**NOTE**: If set to `"module"`, then static `import` / `export` syntax
|
||||
will be valid, even if `ecmaVersion` is less than 6.
|
||||
|
||||
- **onInsertedSemicolon**: If given a callback, that callback will be
|
||||
called whenever a missing semicolon is inserted by the parser. The
|
||||
callback will be given the character offset of the point where the
|
||||
semicolon is inserted as argument, and if `locations` is on, also a
|
||||
`{line, column}` object representing this position.
|
||||
|
||||
- **onTrailingComma**: Like `onInsertedSemicolon`, but for trailing
|
||||
commas.
|
||||
|
||||
- **allowReserved**: If `false`, using a reserved word will generate
|
||||
an error. Defaults to `true` for `ecmaVersion` 3, `false` for higher
|
||||
versions. When given the value `"never"`, reserved words and
|
||||
keywords can also not be used as property names (as in Internet
|
||||
Explorer's old parser).
|
||||
|
||||
- **allowReturnOutsideFunction**: By default, a return statement at
|
||||
the top level raises an error. Set this to `true` to accept such
|
||||
code.
|
||||
|
||||
- **allowImportExportEverywhere**: By default, `import` and `export`
|
||||
declarations can only appear at a program's top level. Setting this
|
||||
option to `true` allows them anywhere where a statement is allowed.
|
||||
|
||||
- **allowAwaitOutsideFunction**: By default, `await` expressions can
|
||||
only appear inside `async` functions. Setting this option to
|
||||
`true` allows to have top-level `await` expressions. They are
|
||||
still not allowed in non-`async` functions, though.
|
||||
|
||||
- **allowHashBang**: When this is enabled (off by default), if the
|
||||
code starts with the characters `#!` (as in a shellscript), the
|
||||
first line will be treated as a comment.
|
||||
|
||||
- **locations**: When `true`, each node has a `loc` object attached
|
||||
with `start` and `end` subobjects, each of which contains the
|
||||
one-based line and zero-based column numbers in `{line, column}`
|
||||
form. Default is `false`.
|
||||
|
||||
- **onToken**: If a function is passed for this option, each found
|
||||
token will be passed in same format as tokens returned from
|
||||
`tokenizer().getToken()`.
|
||||
|
||||
If array is passed, each found token is pushed to it.
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **onComment**: If a function is passed for this option, whenever a
|
||||
comment is encountered the function will be called with the
|
||||
following parameters:
|
||||
|
||||
- `block`: `true` if the comment is a block comment, false if it
|
||||
is a line comment.
|
||||
- `text`: The content of the comment.
|
||||
- `start`: Character offset of the start of the comment.
|
||||
- `end`: Character offset of the end of the comment.
|
||||
|
||||
When the `locations` options is on, the `{line, column}` locations
|
||||
of the comment’s start and end are passed as two additional
|
||||
parameters.
|
||||
|
||||
If array is passed for this option, each found comment is pushed
|
||||
to it as object in Esprima format:
|
||||
|
||||
```javascript
|
||||
{
|
||||
"type": "Line" | "Block",
|
||||
"value": "comment text",
|
||||
"start": Number,
|
||||
"end": Number,
|
||||
// If `locations` option is on:
|
||||
"loc": {
|
||||
"start": {line: Number, column: Number}
|
||||
"end": {line: Number, column: Number}
|
||||
},
|
||||
// If `ranges` option is on:
|
||||
"range": [Number, Number]
|
||||
}
|
||||
```
|
||||
|
||||
Note that you are not allowed to call the parser from the
|
||||
callback—that will corrupt its internal state.
|
||||
|
||||
- **ranges**: Nodes have their start and end characters offsets
|
||||
recorded in `start` and `end` properties (directly on the node,
|
||||
rather than the `loc` object, which holds line/column data. To also
|
||||
add a
|
||||
[semi-standardized](https://bugzilla.mozilla.org/show_bug.cgi?id=745678)
|
||||
`range` property holding a `[start, end]` array with the same
|
||||
numbers, set the `ranges` option to `true`.
|
||||
|
||||
- **program**: It is possible to parse multiple files into a single
|
||||
AST by passing the tree produced by parsing the first file as the
|
||||
`program` option in subsequent parses. This will add the toplevel
|
||||
forms of the parsed file to the "Program" (top) node of an existing
|
||||
parse tree.
|
||||
|
||||
- **sourceFile**: When the `locations` option is `true`, you can pass
|
||||
this option to add a `source` attribute in every node’s `loc`
|
||||
object. Note that the contents of this option are not examined or
|
||||
processed in any way; you are free to use whatever format you
|
||||
choose.
|
||||
|
||||
- **directSourceFile**: Like `sourceFile`, but a `sourceFile` property
|
||||
will be added (regardless of the `location` option) directly to the
|
||||
nodes, rather than the `loc` object.
|
||||
|
||||
- **preserveParens**: If this option is `true`, parenthesized expressions
|
||||
are represented by (non-standard) `ParenthesizedExpression` nodes
|
||||
that have a single `expression` property containing the expression
|
||||
inside parentheses.
|
||||
|
||||
**parseExpressionAt**`(input, offset, options)` will parse a single
|
||||
expression in a string, and return its AST. It will not complain if
|
||||
there is more of the string left after the expression.
|
||||
|
||||
**tokenizer**`(input, options)` returns an object with a `getToken`
|
||||
method that can be called repeatedly to get the next token, a `{start,
|
||||
end, type, value}` object (with added `loc` property when the
|
||||
`locations` option is enabled and `range` property when the `ranges`
|
||||
option is enabled). When the token's type is `tokTypes.eof`, you
|
||||
should stop calling the method, since it will keep returning that same
|
||||
token forever.
|
||||
|
||||
In ES6 environment, returned result can be used as any other
|
||||
protocol-compliant iterable:
|
||||
|
||||
```javascript
|
||||
for (let token of acorn.tokenizer(str)) {
|
||||
// iterate over the tokens
|
||||
}
|
||||
|
||||
// transform code to array of tokens:
|
||||
var tokens = [...acorn.tokenizer(str)];
|
||||
```
|
||||
|
||||
**tokTypes** holds an object mapping names to the token type objects
|
||||
that end up in the `type` properties of tokens.
|
||||
|
||||
**getLineInfo**`(input, offset)` can be used to get a `{line,
|
||||
column}` object for a given program string and offset.
|
||||
|
||||
### The `Parser` class
|
||||
|
||||
Instances of the **`Parser`** class contain all the state and logic
|
||||
that drives a parse. It has static methods `parse`,
|
||||
`parseExpressionAt`, and `tokenizer` that match the top-level
|
||||
functions by the same name.
|
||||
|
||||
When extending the parser with plugins, you need to call these methods
|
||||
on the extended version of the class. To extend a parser with plugins,
|
||||
you can use its static `extend` method.
|
||||
|
||||
```javascript
|
||||
var acorn = require("acorn");
|
||||
var jsx = require("acorn-jsx");
|
||||
var JSXParser = acorn.Parser.extend(jsx());
|
||||
JSXParser.parse("foo(<bar/>)");
|
||||
```
|
||||
|
||||
The `extend` method takes any number of plugin values, and returns a
|
||||
new `Parser` class that includes the extra parser logic provided by
|
||||
the plugins.
|
||||
|
||||
## Command line interface
|
||||
|
||||
The `bin/acorn` utility can be used to parse a file from the command
|
||||
line. It accepts as arguments its input file and the following
|
||||
options:
|
||||
|
||||
- `--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|--ecma10`: Sets the ECMAScript version
|
||||
to parse. Default is version 9.
|
||||
|
||||
- `--module`: Sets the parsing mode to `"module"`. Is set to `"script"` otherwise.
|
||||
|
||||
- `--locations`: Attaches a "loc" object to each node with "start" and
|
||||
"end" subobjects, each of which contains the one-based line and
|
||||
zero-based column numbers in `{line, column}` form.
|
||||
|
||||
- `--allow-hash-bang`: If the code starts with the characters #! (as
|
||||
in a shellscript), the first line will be treated as a comment.
|
||||
|
||||
- `--compact`: No whitespace is used in the AST output.
|
||||
|
||||
- `--silent`: Do not output the AST, just return the exit status.
|
||||
|
||||
- `--help`: Print the usage information and quit.
|
||||
|
||||
The utility spits out the syntax tree as JSON data.
|
||||
|
||||
## Existing plugins
|
||||
|
||||
- [`acorn-jsx`](https://github.com/RReverser/acorn-jsx): Parse [Facebook JSX syntax extensions](https://github.com/facebook/jsx)
|
||||
|
||||
Plugins for ECMAScript proposals:
|
||||
|
||||
- [`acorn-stage3`](https://github.com/acornjs/acorn-stage3): Parse most stage 3 proposals, bundling:
|
||||
- [`acorn-class-fields`](https://github.com/acornjs/acorn-class-fields): Parse [class fields proposal](https://github.com/tc39/proposal-class-fields)
|
||||
- [`acorn-import-meta`](https://github.com/acornjs/acorn-import-meta): Parse [import.meta proposal](https://github.com/tc39/proposal-import-meta)
|
||||
- [`acorn-private-methods`](https://github.com/acornjs/acorn-private-methods): parse [private methods, getters and setters proposal](https://github.com/tc39/proposal-private-methods)n
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
require('../dist/bin.js');
|
||||
+209
@@ -0,0 +1,209 @@
|
||||
export as namespace acorn
|
||||
export = acorn
|
||||
|
||||
declare namespace acorn {
|
||||
function parse(input: string, options?: Options): Node
|
||||
|
||||
function parseExpressionAt(input: string, pos?: number, options?: Options): Node
|
||||
|
||||
function tokenizer(input: string, options?: Options): {
|
||||
getToken(): Token
|
||||
[Symbol.iterator](): Iterator<Token>
|
||||
}
|
||||
|
||||
interface Options {
|
||||
ecmaVersion?: 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 2015 | 2016 | 2017 | 2018 | 2019 | 2020
|
||||
sourceType?: 'script' | 'module'
|
||||
onInsertedSemicolon?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
|
||||
onTrailingComma?: (lastTokEnd: number, lastTokEndLoc?: Position) => void
|
||||
allowReserved?: boolean | 'never'
|
||||
allowReturnOutsideFunction?: boolean
|
||||
allowImportExportEverywhere?: boolean
|
||||
allowAwaitOutsideFunction?: boolean
|
||||
allowHashBang?: boolean
|
||||
locations?: boolean
|
||||
onToken?: ((token: Token) => any) | Token[]
|
||||
onComment?: ((
|
||||
isBlock: boolean, text: string, start: number, end: number, startLoc?: Position,
|
||||
endLoc?: Position
|
||||
) => void) | Comment[]
|
||||
ranges?: boolean
|
||||
program?: Node
|
||||
sourceFile?: string
|
||||
directSourceFile?: string
|
||||
preserveParens?: boolean
|
||||
}
|
||||
|
||||
class Parser {
|
||||
constructor(options: Options, input: string, startPos?: number)
|
||||
parse(this: Parser): Node
|
||||
static parse(this: typeof Parser, input: string, options?: Options): Node
|
||||
static parseExpressionAt(this: typeof Parser, input: string, pos: number, options?: Options): Node
|
||||
static tokenizer(this: typeof Parser, input: string, options?: Options): {
|
||||
getToken(): Token
|
||||
[Symbol.iterator](): Iterator<Token>
|
||||
}
|
||||
static extend(this: typeof Parser, ...plugins: ((BaseParser: typeof Parser) => typeof Parser)[]): typeof Parser
|
||||
}
|
||||
|
||||
interface Position { line: number; column: number; offset: number }
|
||||
|
||||
const defaultOptions: Options
|
||||
|
||||
function getLineInfo(input: string, offset: number): Position
|
||||
|
||||
class SourceLocation {
|
||||
start: Position
|
||||
end: Position
|
||||
source?: string | null
|
||||
constructor(p: Parser, start: Position, end: Position)
|
||||
}
|
||||
|
||||
class Node {
|
||||
type: string
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
sourceFile?: string
|
||||
range?: [number, number]
|
||||
constructor(parser: Parser, pos: number, loc?: SourceLocation)
|
||||
}
|
||||
|
||||
class TokenType {
|
||||
label: string
|
||||
keyword: string
|
||||
beforeExpr: boolean
|
||||
startsExpr: boolean
|
||||
isLoop: boolean
|
||||
isAssign: boolean
|
||||
prefix: boolean
|
||||
postfix: boolean
|
||||
binop: number
|
||||
updateContext?: (prevType: TokenType) => void
|
||||
constructor(label: string, conf?: any)
|
||||
}
|
||||
|
||||
const tokTypes: {
|
||||
num: TokenType
|
||||
regexp: TokenType
|
||||
string: TokenType
|
||||
name: TokenType
|
||||
eof: TokenType
|
||||
bracketL: TokenType
|
||||
bracketR: TokenType
|
||||
braceL: TokenType
|
||||
braceR: TokenType
|
||||
parenL: TokenType
|
||||
parenR: TokenType
|
||||
comma: TokenType
|
||||
semi: TokenType
|
||||
colon: TokenType
|
||||
dot: TokenType
|
||||
question: TokenType
|
||||
arrow: TokenType
|
||||
template: TokenType
|
||||
ellipsis: TokenType
|
||||
backQuote: TokenType
|
||||
dollarBraceL: TokenType
|
||||
eq: TokenType
|
||||
assign: TokenType
|
||||
incDec: TokenType
|
||||
prefix: TokenType
|
||||
logicalOR: TokenType
|
||||
logicalAND: TokenType
|
||||
bitwiseOR: TokenType
|
||||
bitwiseXOR: TokenType
|
||||
bitwiseAND: TokenType
|
||||
equality: TokenType
|
||||
relational: TokenType
|
||||
bitShift: TokenType
|
||||
plusMin: TokenType
|
||||
modulo: TokenType
|
||||
star: TokenType
|
||||
slash: TokenType
|
||||
starstar: TokenType
|
||||
_break: TokenType
|
||||
_case: TokenType
|
||||
_catch: TokenType
|
||||
_continue: TokenType
|
||||
_debugger: TokenType
|
||||
_default: TokenType
|
||||
_do: TokenType
|
||||
_else: TokenType
|
||||
_finally: TokenType
|
||||
_for: TokenType
|
||||
_function: TokenType
|
||||
_if: TokenType
|
||||
_return: TokenType
|
||||
_switch: TokenType
|
||||
_throw: TokenType
|
||||
_try: TokenType
|
||||
_var: TokenType
|
||||
_const: TokenType
|
||||
_while: TokenType
|
||||
_with: TokenType
|
||||
_new: TokenType
|
||||
_this: TokenType
|
||||
_super: TokenType
|
||||
_class: TokenType
|
||||
_extends: TokenType
|
||||
_export: TokenType
|
||||
_import: TokenType
|
||||
_null: TokenType
|
||||
_true: TokenType
|
||||
_false: TokenType
|
||||
_in: TokenType
|
||||
_instanceof: TokenType
|
||||
_typeof: TokenType
|
||||
_void: TokenType
|
||||
_delete: TokenType
|
||||
}
|
||||
|
||||
class TokContext {
|
||||
constructor(token: string, isExpr: boolean, preserveSpace: boolean, override?: (p: Parser) => void)
|
||||
}
|
||||
|
||||
const tokContexts: {
|
||||
b_stat: TokContext
|
||||
b_expr: TokContext
|
||||
b_tmpl: TokContext
|
||||
p_stat: TokContext
|
||||
p_expr: TokContext
|
||||
q_tmpl: TokContext
|
||||
f_expr: TokContext
|
||||
}
|
||||
|
||||
function isIdentifierStart(code: number, astral?: boolean): boolean
|
||||
|
||||
function isIdentifierChar(code: number, astral?: boolean): boolean
|
||||
|
||||
interface AbstractToken {
|
||||
}
|
||||
|
||||
interface Comment extends AbstractToken {
|
||||
type: string
|
||||
value: string
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
range?: [number, number]
|
||||
}
|
||||
|
||||
class Token {
|
||||
type: TokenType
|
||||
value: any
|
||||
start: number
|
||||
end: number
|
||||
loc?: SourceLocation
|
||||
range?: [number, number]
|
||||
constructor(p: Parser)
|
||||
}
|
||||
|
||||
function isNewLine(code: number): boolean
|
||||
|
||||
const lineBreak: RegExp
|
||||
|
||||
const lineBreakG: RegExp
|
||||
|
||||
const version: string
|
||||
}
|
||||
+5186
File diff suppressed because it is too large
Load Diff
+1
File diff suppressed because one or more lines are too long
+5155
File diff suppressed because it is too large
Load Diff
+2
@@ -0,0 +1,2 @@
|
||||
import * as acorn from "./acorn";
|
||||
export = acorn;
|
||||
+1
File diff suppressed because one or more lines are too long
+64
@@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var acorn = require('./acorn.js');
|
||||
|
||||
var infile, forceFile, silent = false, compact = false, tokenize = false;
|
||||
var options = {};
|
||||
|
||||
function help(status) {
|
||||
var print = (status === 0) ? console.log : console.error;
|
||||
print("usage: " + path.basename(process.argv[1]) + " [--ecma3|--ecma5|--ecma6|--ecma7|--ecma8|--ecma9|...|--ecma2015|--ecma2016|--ecma2017|--ecma2018|...]");
|
||||
print(" [--tokenize] [--locations] [---allow-hash-bang] [--compact] [--silent] [--module] [--help] [--] [infile]");
|
||||
process.exit(status);
|
||||
}
|
||||
|
||||
for (var i = 2; i < process.argv.length; ++i) {
|
||||
var arg = process.argv[i];
|
||||
if ((arg === "-" || arg[0] !== "-") && !infile) { infile = arg; }
|
||||
else if (arg === "--" && !infile && i + 2 === process.argv.length) { forceFile = infile = process.argv[++i]; }
|
||||
else if (arg === "--locations") { options.locations = true; }
|
||||
else if (arg === "--allow-hash-bang") { options.allowHashBang = true; }
|
||||
else if (arg === "--silent") { silent = true; }
|
||||
else if (arg === "--compact") { compact = true; }
|
||||
else if (arg === "--help") { help(0); }
|
||||
else if (arg === "--tokenize") { tokenize = true; }
|
||||
else if (arg === "--module") { options.sourceType = "module"; }
|
||||
else {
|
||||
var match = arg.match(/^--ecma(\d+)$/);
|
||||
if (match)
|
||||
{ options.ecmaVersion = +match[1]; }
|
||||
else
|
||||
{ help(1); }
|
||||
}
|
||||
}
|
||||
|
||||
function run(code) {
|
||||
var result;
|
||||
try {
|
||||
if (!tokenize) {
|
||||
result = acorn.parse(code, options);
|
||||
} else {
|
||||
result = [];
|
||||
var tokenizer = acorn.tokenizer(code, options), token;
|
||||
do {
|
||||
token = tokenizer.getToken();
|
||||
result.push(token);
|
||||
} while (token.type !== acorn.tokTypes.eof)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(infile && infile !== "-" ? e.message.replace(/\(\d+:\d+\)$/, function (m) { return m.slice(0, 1) + infile + " " + m.slice(1); }) : e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
if (!silent) { console.log(JSON.stringify(result, null, compact ? null : 2)); }
|
||||
}
|
||||
|
||||
if (forceFile || infile && infile !== "-") {
|
||||
run(fs.readFileSync(infile, "utf8"));
|
||||
} else {
|
||||
var code = "";
|
||||
process.stdin.resume();
|
||||
process.stdin.on("data", function (chunk) { return code += chunk; });
|
||||
process.stdin.on("end", function () { return run(code); });
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"name": "acorn",
|
||||
"description": "ECMAScript parser",
|
||||
"homepage": "https://github.com/acornjs/acorn",
|
||||
"main": "dist/acorn.js",
|
||||
"types": "dist/acorn.d.ts",
|
||||
"module": "dist/acorn.mjs",
|
||||
"version": "7.4.1",
|
||||
"engines": {"node": ">=0.4.0"},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Marijn Haverbeke",
|
||||
"email": "marijnh@gmail.com",
|
||||
"web": "https://marijnhaverbeke.nl"
|
||||
},
|
||||
{
|
||||
"name": "Ingvar Stepanyan",
|
||||
"email": "me@rreverser.com",
|
||||
"web": "https://rreverser.com/"
|
||||
},
|
||||
{
|
||||
"name": "Adrian Heine",
|
||||
"web": "http://adrianheine.de"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/acornjs/acorn.git"
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"prepare": "cd ..; npm run build:main && npm run build:bin"
|
||||
},
|
||||
"bin": {"acorn": "./bin/acorn"}
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
test
|
||||
.gitignore
|
||||
.travis.yml
|
||||
Makefile
|
||||
example.js
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# balanced-match
|
||||
|
||||
Match balanced string pairs, like `{` and `}` or `<b>` and `</b>`. Supports regular expressions as well!
|
||||
|
||||
[](http://travis-ci.org/juliangruber/balanced-match)
|
||||
[](https://www.npmjs.org/package/balanced-match)
|
||||
|
||||
[](https://ci.testling.com/juliangruber/balanced-match)
|
||||
|
||||
## Example
|
||||
|
||||
Get the first matching pair of braces:
|
||||
|
||||
```js
|
||||
var balanced = require('balanced-match');
|
||||
|
||||
console.log(balanced('{', '}', 'pre{in{nested}}post'));
|
||||
console.log(balanced('{', '}', 'pre{first}between{second}post'));
|
||||
console.log(balanced(/\s+\{\s+/, /\s+\}\s+/, 'pre { in{nest} } post'));
|
||||
```
|
||||
|
||||
The matches are:
|
||||
|
||||
```bash
|
||||
$ node example.js
|
||||
{ start: 3, end: 14, pre: 'pre', body: 'in{nested}', post: 'post' }
|
||||
{ start: 3,
|
||||
end: 9,
|
||||
pre: 'pre',
|
||||
body: 'first',
|
||||
post: 'between{second}post' }
|
||||
{ start: 3, end: 17, pre: 'pre', body: 'in{nest}', post: 'post' }
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### var m = balanced(a, b, str)
|
||||
|
||||
For the first non-nested matching pair of `a` and `b` in `str`, return an
|
||||
object with those keys:
|
||||
|
||||
* **start** the index of the first match of `a`
|
||||
* **end** the index of the matching `b`
|
||||
* **pre** the preamble, `a` and `b` not included
|
||||
* **body** the match, `a` and `b` not included
|
||||
* **post** the postscript, `a` and `b` not included
|
||||
|
||||
If there's no match, `undefined` will be returned.
|
||||
|
||||
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `['{', 'a', '']` and `{a}}` will match `['', 'a', '}']`.
|
||||
|
||||
### var r = balanced.range(a, b, str)
|
||||
|
||||
For the first non-nested matching pair of `a` and `b` in `str`, return an
|
||||
array with indexes: `[ <a index>, <b index> ]`.
|
||||
|
||||
If there's no match, `undefined` will be returned.
|
||||
|
||||
If the `str` contains more `a` than `b` / there are unmatched pairs, the first match that was closed will be used. For example, `{{a}` will match `[ 1, 3 ]` and `{a}}` will match `[0, 2]`.
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```bash
|
||||
npm install balanced-match
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
module.exports = balanced;
|
||||
function balanced(a, b, str) {
|
||||
if (a instanceof RegExp) a = maybeMatch(a, str);
|
||||
if (b instanceof RegExp) b = maybeMatch(b, str);
|
||||
|
||||
var r = range(a, b, str);
|
||||
|
||||
return r && {
|
||||
start: r[0],
|
||||
end: r[1],
|
||||
pre: str.slice(0, r[0]),
|
||||
body: str.slice(r[0] + a.length, r[1]),
|
||||
post: str.slice(r[1] + b.length)
|
||||
};
|
||||
}
|
||||
|
||||
function maybeMatch(reg, str) {
|
||||
var m = str.match(reg);
|
||||
return m ? m[0] : null;
|
||||
}
|
||||
|
||||
balanced.range = range;
|
||||
function range(a, b, str) {
|
||||
var begs, beg, left, right, result;
|
||||
var ai = str.indexOf(a);
|
||||
var bi = str.indexOf(b, ai + 1);
|
||||
var i = ai;
|
||||
|
||||
if (ai >= 0 && bi > 0) {
|
||||
begs = [];
|
||||
left = str.length;
|
||||
|
||||
while (i >= 0 && !result) {
|
||||
if (i == ai) {
|
||||
begs.push(i);
|
||||
ai = str.indexOf(a, i + 1);
|
||||
} else if (begs.length == 1) {
|
||||
result = [ begs.pop(), bi ];
|
||||
} else {
|
||||
beg = begs.pop();
|
||||
if (beg < left) {
|
||||
left = beg;
|
||||
right = bi;
|
||||
}
|
||||
|
||||
bi = str.indexOf(b, i + 1);
|
||||
}
|
||||
|
||||
i = ai < bi && ai >= 0 ? ai : bi;
|
||||
}
|
||||
|
||||
if (begs.length) {
|
||||
result = [ left, right ];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"name": "balanced-match",
|
||||
"description": "Match balanced character pairs, like \"{\" and \"}\"",
|
||||
"version": "1.0.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/juliangruber/balanced-match.git"
|
||||
},
|
||||
"homepage": "https://github.com/juliangruber/balanced-match",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "make test",
|
||||
"bench": "make bench"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"matcha": "^0.7.0",
|
||||
"tape": "^4.6.0"
|
||||
},
|
||||
"keywords": [
|
||||
"match",
|
||||
"regexp",
|
||||
"test",
|
||||
"balanced",
|
||||
"parse"
|
||||
],
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/20..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/25..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
# brace-expansion
|
||||
|
||||
[Brace expansion](https://www.gnu.org/software/bash/manual/html_node/Brace-Expansion.html),
|
||||
as known from sh/bash, in JavaScript.
|
||||
|
||||
[](http://travis-ci.org/juliangruber/brace-expansion)
|
||||
[](https://www.npmjs.org/package/brace-expansion)
|
||||
[](https://greenkeeper.io/)
|
||||
|
||||
[](https://ci.testling.com/juliangruber/brace-expansion)
|
||||
|
||||
## Example
|
||||
|
||||
```js
|
||||
var expand = require('brace-expansion');
|
||||
|
||||
expand('file-{a,b,c}.jpg')
|
||||
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
|
||||
|
||||
expand('-v{,,}')
|
||||
// => ['-v', '-v', '-v']
|
||||
|
||||
expand('file{0..2}.jpg')
|
||||
// => ['file0.jpg', 'file1.jpg', 'file2.jpg']
|
||||
|
||||
expand('file-{a..c}.jpg')
|
||||
// => ['file-a.jpg', 'file-b.jpg', 'file-c.jpg']
|
||||
|
||||
expand('file{2..0}.jpg')
|
||||
// => ['file2.jpg', 'file1.jpg', 'file0.jpg']
|
||||
|
||||
expand('file{0..4..2}.jpg')
|
||||
// => ['file0.jpg', 'file2.jpg', 'file4.jpg']
|
||||
|
||||
expand('file-{a..e..2}.jpg')
|
||||
// => ['file-a.jpg', 'file-c.jpg', 'file-e.jpg']
|
||||
|
||||
expand('file{00..10..5}.jpg')
|
||||
// => ['file00.jpg', 'file05.jpg', 'file10.jpg']
|
||||
|
||||
expand('{{A..C},{a..c}}')
|
||||
// => ['A', 'B', 'C', 'a', 'b', 'c']
|
||||
|
||||
expand('ppp{,config,oe{,conf}}')
|
||||
// => ['ppp', 'pppconfig', 'pppoe', 'pppoeconf']
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var expand = require('brace-expansion');
|
||||
```
|
||||
|
||||
### var expanded = expand(str)
|
||||
|
||||
Return an array of all possible and valid expansions of `str`. If none are
|
||||
found, `[str]` is returned.
|
||||
|
||||
Valid expansions are:
|
||||
|
||||
```js
|
||||
/^(.*,)+(.+)?$/
|
||||
// {a,b,...}
|
||||
```
|
||||
|
||||
A comma separated list of options, like `{a,b}` or `{a,{b,c}}` or `{,a,}`.
|
||||
|
||||
```js
|
||||
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
|
||||
// {x..y[..incr]}
|
||||
```
|
||||
|
||||
A numeric sequence from `x` to `y` inclusive, with optional increment.
|
||||
If `x` or `y` start with a leading `0`, all the numbers will be padded
|
||||
to have equal length. Negative numbers and backwards iteration work too.
|
||||
|
||||
```js
|
||||
/^-?\d+\.\.-?\d+(\.\.-?\d+)?$/
|
||||
// {x..y[..incr]}
|
||||
```
|
||||
|
||||
An alphabetic sequence from `x` to `y` inclusive, with optional increment.
|
||||
`x` and `y` must be exactly one character, and if given, `incr` must be a
|
||||
number.
|
||||
|
||||
For compatibility reasons, the string `${` is not eligible for brace expansion.
|
||||
|
||||
## Installation
|
||||
|
||||
With [npm](https://npmjs.org) do:
|
||||
|
||||
```bash
|
||||
npm install brace-expansion
|
||||
```
|
||||
|
||||
## Contributors
|
||||
|
||||
- [Julian Gruber](https://github.com/juliangruber)
|
||||
- [Isaac Z. Schlueter](https://github.com/isaacs)
|
||||
|
||||
## Sponsors
|
||||
|
||||
This module is proudly supported by my [Sponsors](https://github.com/juliangruber/sponsors)!
|
||||
|
||||
Do you want to support modules like this to improve their quality, stability and weigh in on new features? Then please consider donating to my [Patreon](https://www.patreon.com/juliangruber). Not sure how much of my modules you're using? Try [feross/thanks](https://github.com/feross/thanks)!
|
||||
|
||||
## License
|
||||
|
||||
(MIT)
|
||||
|
||||
Copyright (c) 2013 Julian Gruber <julian@juliangruber.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
var concatMap = require('concat-map');
|
||||
var balanced = require('balanced-match');
|
||||
|
||||
module.exports = expandTop;
|
||||
|
||||
var escSlash = '\0SLASH'+Math.random()+'\0';
|
||||
var escOpen = '\0OPEN'+Math.random()+'\0';
|
||||
var escClose = '\0CLOSE'+Math.random()+'\0';
|
||||
var escComma = '\0COMMA'+Math.random()+'\0';
|
||||
var escPeriod = '\0PERIOD'+Math.random()+'\0';
|
||||
|
||||
function numeric(str) {
|
||||
return parseInt(str, 10) == str
|
||||
? parseInt(str, 10)
|
||||
: str.charCodeAt(0);
|
||||
}
|
||||
|
||||
function escapeBraces(str) {
|
||||
return str.split('\\\\').join(escSlash)
|
||||
.split('\\{').join(escOpen)
|
||||
.split('\\}').join(escClose)
|
||||
.split('\\,').join(escComma)
|
||||
.split('\\.').join(escPeriod);
|
||||
}
|
||||
|
||||
function unescapeBraces(str) {
|
||||
return str.split(escSlash).join('\\')
|
||||
.split(escOpen).join('{')
|
||||
.split(escClose).join('}')
|
||||
.split(escComma).join(',')
|
||||
.split(escPeriod).join('.');
|
||||
}
|
||||
|
||||
|
||||
// Basically just str.split(","), but handling cases
|
||||
// where we have nested braced sections, which should be
|
||||
// treated as individual members, like {a,{b,c},d}
|
||||
function parseCommaParts(str) {
|
||||
if (!str)
|
||||
return [''];
|
||||
|
||||
var parts = [];
|
||||
var m = balanced('{', '}', str);
|
||||
|
||||
if (!m)
|
||||
return str.split(',');
|
||||
|
||||
var pre = m.pre;
|
||||
var body = m.body;
|
||||
var post = m.post;
|
||||
var p = pre.split(',');
|
||||
|
||||
p[p.length-1] += '{' + body + '}';
|
||||
var postParts = parseCommaParts(post);
|
||||
if (post.length) {
|
||||
p[p.length-1] += postParts.shift();
|
||||
p.push.apply(p, postParts);
|
||||
}
|
||||
|
||||
parts.push.apply(parts, p);
|
||||
|
||||
return parts;
|
||||
}
|
||||
|
||||
function expandTop(str) {
|
||||
if (!str)
|
||||
return [];
|
||||
|
||||
// I don't know why Bash 4.3 does this, but it does.
|
||||
// Anything starting with {} will have the first two bytes preserved
|
||||
// but *only* at the top level, so {},a}b will not expand to anything,
|
||||
// but a{},b}c will be expanded to [a}c,abc].
|
||||
// One could argue that this is a bug in Bash, but since the goal of
|
||||
// this module is to match Bash's rules, we escape a leading {}
|
||||
if (str.substr(0, 2) === '{}') {
|
||||
str = '\\{\\}' + str.substr(2);
|
||||
}
|
||||
|
||||
return expand(escapeBraces(str), true).map(unescapeBraces);
|
||||
}
|
||||
|
||||
function identity(e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
function embrace(str) {
|
||||
return '{' + str + '}';
|
||||
}
|
||||
function isPadded(el) {
|
||||
return /^-?0\d/.test(el);
|
||||
}
|
||||
|
||||
function lte(i, y) {
|
||||
return i <= y;
|
||||
}
|
||||
function gte(i, y) {
|
||||
return i >= y;
|
||||
}
|
||||
|
||||
function expand(str, isTop) {
|
||||
var expansions = [];
|
||||
|
||||
var m = balanced('{', '}', str);
|
||||
if (!m || /\$$/.test(m.pre)) return [str];
|
||||
|
||||
var isNumericSequence = /^-?\d+\.\.-?\d+(?:\.\.-?\d+)?$/.test(m.body);
|
||||
var isAlphaSequence = /^[a-zA-Z]\.\.[a-zA-Z](?:\.\.-?\d+)?$/.test(m.body);
|
||||
var isSequence = isNumericSequence || isAlphaSequence;
|
||||
var isOptions = m.body.indexOf(',') >= 0;
|
||||
if (!isSequence && !isOptions) {
|
||||
// {a},b}
|
||||
if (m.post.match(/,.*\}/)) {
|
||||
str = m.pre + '{' + m.body + escClose + m.post;
|
||||
return expand(str);
|
||||
}
|
||||
return [str];
|
||||
}
|
||||
|
||||
var n;
|
||||
if (isSequence) {
|
||||
n = m.body.split(/\.\./);
|
||||
} else {
|
||||
n = parseCommaParts(m.body);
|
||||
if (n.length === 1) {
|
||||
// x{{a,b}}y ==> x{a}y x{b}y
|
||||
n = expand(n[0], false).map(embrace);
|
||||
if (n.length === 1) {
|
||||
var post = m.post.length
|
||||
? expand(m.post, false)
|
||||
: [''];
|
||||
return post.map(function(p) {
|
||||
return m.pre + n[0] + p;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// at this point, n is the parts, and we know it's not a comma set
|
||||
// with a single entry.
|
||||
|
||||
// no need to expand pre, since it is guaranteed to be free of brace-sets
|
||||
var pre = m.pre;
|
||||
var post = m.post.length
|
||||
? expand(m.post, false)
|
||||
: [''];
|
||||
|
||||
var N;
|
||||
|
||||
if (isSequence) {
|
||||
var x = numeric(n[0]);
|
||||
var y = numeric(n[1]);
|
||||
var width = Math.max(n[0].length, n[1].length)
|
||||
var incr = n.length == 3
|
||||
? Math.abs(numeric(n[2]))
|
||||
: 1;
|
||||
var test = lte;
|
||||
var reverse = y < x;
|
||||
if (reverse) {
|
||||
incr *= -1;
|
||||
test = gte;
|
||||
}
|
||||
var pad = n.some(isPadded);
|
||||
|
||||
N = [];
|
||||
|
||||
for (var i = x; test(i, y); i += incr) {
|
||||
var c;
|
||||
if (isAlphaSequence) {
|
||||
c = String.fromCharCode(i);
|
||||
if (c === '\\')
|
||||
c = '';
|
||||
} else {
|
||||
c = String(i);
|
||||
if (pad) {
|
||||
var need = width - c.length;
|
||||
if (need > 0) {
|
||||
var z = new Array(need + 1).join('0');
|
||||
if (i < 0)
|
||||
c = '-' + z + c.slice(1);
|
||||
else
|
||||
c = z + c;
|
||||
}
|
||||
}
|
||||
}
|
||||
N.push(c);
|
||||
}
|
||||
} else {
|
||||
N = concatMap(n, function(el) { return expand(el, false) });
|
||||
}
|
||||
|
||||
for (var j = 0; j < N.length; j++) {
|
||||
for (var k = 0; k < post.length; k++) {
|
||||
var expansion = pre + N[j] + post[k];
|
||||
if (!isTop || isSequence || expansion)
|
||||
expansions.push(expansion);
|
||||
}
|
||||
}
|
||||
|
||||
return expansions;
|
||||
}
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "brace-expansion",
|
||||
"description": "Brace expansion as known from sh/bash",
|
||||
"version": "1.1.11",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/juliangruber/brace-expansion.git"
|
||||
},
|
||||
"homepage": "https://github.com/juliangruber/brace-expansion",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "tape test/*.js",
|
||||
"gentest": "bash test/generate.sh",
|
||||
"bench": "matcha test/perf/bench.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"matcha": "^0.7.0",
|
||||
"tape": "^4.6.0"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": {
|
||||
"name": "Julian Gruber",
|
||||
"email": "mail@juliangruber.com",
|
||||
"url": "http://juliangruber.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": [
|
||||
"ie/8..latest",
|
||||
"firefox/20..latest",
|
||||
"firefox/nightly",
|
||||
"chrome/25..latest",
|
||||
"chrome/canary",
|
||||
"opera/12..latest",
|
||||
"opera/next",
|
||||
"safari/5.1..latest",
|
||||
"ipad/6.0..latest",
|
||||
"iphone/6.0..latest",
|
||||
"android-browser/4.2..latest"
|
||||
]
|
||||
}
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
concat-map
|
||||
==========
|
||||
|
||||
Concatenative mapdashery.
|
||||
|
||||
[](http://ci.testling.com/substack/node-concat-map)
|
||||
|
||||
[](http://travis-ci.org/substack/node-concat-map)
|
||||
|
||||
example
|
||||
=======
|
||||
|
||||
``` js
|
||||
var concatMap = require('concat-map');
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
console.dir(ys);
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
```
|
||||
[ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]
|
||||
```
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
``` js
|
||||
var concatMap = require('concat-map')
|
||||
```
|
||||
|
||||
concatMap(xs, fn)
|
||||
-----------------
|
||||
|
||||
Return an array of concatenated elements by calling `fn(x, i)` for each element
|
||||
`x` and each index `i` in the array `xs`.
|
||||
|
||||
When `fn(x, i)` returns an array, its result will be concatenated with the
|
||||
result array. If `fn(x, i)` returns anything else, that value will be pushed
|
||||
onto the end of the result array.
|
||||
|
||||
install
|
||||
=======
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install concat-map
|
||||
```
|
||||
|
||||
license
|
||||
=======
|
||||
|
||||
MIT
|
||||
|
||||
notes
|
||||
=====
|
||||
|
||||
This module was written while sitting high above the ground in a tree.
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
var concatMap = require('../');
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
console.dir(ys);
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
module.exports = function (xs, fn) {
|
||||
var res = [];
|
||||
for (var i = 0; i < xs.length; i++) {
|
||||
var x = fn(xs[i], i);
|
||||
if (isArray(x)) res.push.apply(res, x);
|
||||
else res.push(x);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
var isArray = Array.isArray || function (xs) {
|
||||
return Object.prototype.toString.call(xs) === '[object Array]';
|
||||
};
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"name" : "concat-map",
|
||||
"description" : "concatenative mapdashery",
|
||||
"version" : "0.0.1",
|
||||
"repository" : {
|
||||
"type" : "git",
|
||||
"url" : "git://github.com/substack/node-concat-map.git"
|
||||
},
|
||||
"main" : "index.js",
|
||||
"keywords" : [
|
||||
"concat",
|
||||
"concatMap",
|
||||
"map",
|
||||
"functional",
|
||||
"higher-order"
|
||||
],
|
||||
"directories" : {
|
||||
"example" : "example",
|
||||
"test" : "test"
|
||||
},
|
||||
"scripts" : {
|
||||
"test" : "tape test/*.js"
|
||||
},
|
||||
"devDependencies" : {
|
||||
"tape" : "~2.4.0"
|
||||
},
|
||||
"license" : "MIT",
|
||||
"author" : {
|
||||
"name" : "James Halliday",
|
||||
"email" : "mail@substack.net",
|
||||
"url" : "http://substack.net"
|
||||
},
|
||||
"testling" : {
|
||||
"files" : "test/*.js",
|
||||
"browsers" : {
|
||||
"ie" : [ 6, 7, 8, 9 ],
|
||||
"ff" : [ 3.5, 10, 15.0 ],
|
||||
"chrome" : [ 10, 22 ],
|
||||
"safari" : [ 5.1 ],
|
||||
"opera" : [ 12 ]
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
var concatMap = require('../');
|
||||
var test = require('tape');
|
||||
|
||||
test('empty or not', function (t) {
|
||||
var xs = [ 1, 2, 3, 4, 5, 6 ];
|
||||
var ixes = [];
|
||||
var ys = concatMap(xs, function (x, ix) {
|
||||
ixes.push(ix);
|
||||
return x % 2 ? [ x - 0.1, x, x + 0.1 ] : [];
|
||||
});
|
||||
t.same(ys, [ 0.9, 1, 1.1, 2.9, 3, 3.1, 4.9, 5, 5.1 ]);
|
||||
t.same(ixes, [ 0, 1, 2, 3, 4, 5 ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('always something', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x === 'b' ? [ 'B', 'B', 'B' ] : [ x ];
|
||||
});
|
||||
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('scalars', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function (x) {
|
||||
return x === 'b' ? [ 'B', 'B', 'B' ] : x;
|
||||
});
|
||||
t.same(ys, [ 'a', 'B', 'B', 'B', 'c', 'd' ]);
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('undefs', function (t) {
|
||||
var xs = [ 'a', 'b', 'c', 'd' ];
|
||||
var ys = concatMap(xs, function () {});
|
||||
t.same(ys, [ undefined, undefined, undefined, undefined ]);
|
||||
t.end();
|
||||
});
|
||||
+1
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
||||
- 0.8
|
||||
- 0.10
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
Copyright (c) 2012, 2013 Thorsten Lorenz <thlorenz@gmx.de>
|
||||
Copyright (c) 2012 James Halliday <mail@substack.net>
|
||||
Copyright (c) 2009 Thomas Robinson <280north.com>
|
||||
|
||||
This software is released under the MIT license:
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
deep-is
|
||||
==========
|
||||
|
||||
Node's `assert.deepEqual() algorithm` as a standalone module. Exactly like
|
||||
[deep-equal](https://github.com/substack/node-deep-equal) except for the fact that `deepEqual(NaN, NaN) === true`.
|
||||
|
||||
This module is around [5 times faster](https://gist.github.com/2790507)
|
||||
than wrapping `assert.deepEqual()` in a `try/catch`.
|
||||
|
||||
[](http://ci.testling.com/thlorenz/deep-is)
|
||||
|
||||
[](http://travis-ci.org/thlorenz/deep-is)
|
||||
|
||||
example
|
||||
=======
|
||||
|
||||
``` js
|
||||
var equal = require('deep-is');
|
||||
console.dir([
|
||||
equal(
|
||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
||||
),
|
||||
equal(
|
||||
{ x : 5, y : [6] },
|
||||
{ x : 5, y : 6 }
|
||||
)
|
||||
]);
|
||||
```
|
||||
|
||||
methods
|
||||
=======
|
||||
|
||||
var deepIs = require('deep-is')
|
||||
|
||||
deepIs(a, b)
|
||||
---------------
|
||||
|
||||
Compare objects `a` and `b`, returning whether they are equal according to a
|
||||
recursive equality algorithm.
|
||||
|
||||
install
|
||||
=======
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm install deep-is
|
||||
```
|
||||
|
||||
test
|
||||
====
|
||||
|
||||
With [npm](http://npmjs.org) do:
|
||||
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
license
|
||||
=======
|
||||
|
||||
Copyright (c) 2012, 2013 Thorsten Lorenz <thlorenz@gmx.de>
|
||||
Copyright (c) 2012 James Halliday <mail@substack.net>
|
||||
|
||||
Derived largely from node's assert module, which has the copyright statement:
|
||||
|
||||
Copyright (c) 2009 Thomas Robinson <280north.com>
|
||||
|
||||
Released under the MIT license, see LICENSE for details.
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
var equal = require('../');
|
||||
console.dir([
|
||||
equal(
|
||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
||||
),
|
||||
equal(
|
||||
{ x : 5, y : [6] },
|
||||
{ x : 5, y : 6 }
|
||||
)
|
||||
]);
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
var pSlice = Array.prototype.slice;
|
||||
var Object_keys = typeof Object.keys === 'function'
|
||||
? Object.keys
|
||||
: function (obj) {
|
||||
var keys = [];
|
||||
for (var key in obj) keys.push(key);
|
||||
return keys;
|
||||
}
|
||||
;
|
||||
|
||||
var deepEqual = module.exports = function (actual, expected) {
|
||||
// enforce Object.is +0 !== -0
|
||||
if (actual === 0 && expected === 0) {
|
||||
return areZerosEqual(actual, expected);
|
||||
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
} else if (actual === expected) {
|
||||
return true;
|
||||
|
||||
} else if (actual instanceof Date && expected instanceof Date) {
|
||||
return actual.getTime() === expected.getTime();
|
||||
|
||||
} else if (isNumberNaN(actual)) {
|
||||
return isNumberNaN(expected);
|
||||
|
||||
// 7.3. Other pairs that do not both pass typeof value == 'object',
|
||||
// equivalence is determined by ==.
|
||||
} else if (typeof actual != 'object' && typeof expected != 'object') {
|
||||
return actual == expected;
|
||||
|
||||
// 7.4. For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected);
|
||||
}
|
||||
};
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined;
|
||||
}
|
||||
|
||||
function isArguments(object) {
|
||||
return Object.prototype.toString.call(object) == '[object Arguments]';
|
||||
}
|
||||
|
||||
function isNumberNaN(value) {
|
||||
// NaN === NaN -> false
|
||||
return typeof value == 'number' && value !== value;
|
||||
}
|
||||
|
||||
function areZerosEqual(zeroA, zeroB) {
|
||||
// (1 / +0|0) -> Infinity, but (1 / -0) -> -Infinity and (Infinity !== -Infinity)
|
||||
return (1 / zeroA) === (1 / zeroB);
|
||||
}
|
||||
|
||||
function objEquiv(a, b) {
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
||||
return false;
|
||||
|
||||
// an identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) return false;
|
||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
||||
// Converting to array solves the problem.
|
||||
if (isArguments(a)) {
|
||||
if (!isArguments(b)) {
|
||||
return false;
|
||||
}
|
||||
a = pSlice.call(a);
|
||||
b = pSlice.call(b);
|
||||
return deepEqual(a, b);
|
||||
}
|
||||
try {
|
||||
var ka = Object_keys(a),
|
||||
kb = Object_keys(b),
|
||||
key, i;
|
||||
} catch (e) {//happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length != kb.length)
|
||||
return false;
|
||||
//the same set of keys (although not necessarily the same order),
|
||||
ka.sort();
|
||||
kb.sort();
|
||||
//~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
if (ka[i] != kb[i])
|
||||
return false;
|
||||
}
|
||||
//equivalent values for every corresponding key, and
|
||||
//~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
if (!deepEqual(a[key], b[key])) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "deep-is",
|
||||
"version": "0.1.3",
|
||||
"description": "node's assert.deepEqual algorithm except for NaN being equal to NaN",
|
||||
"main": "index.js",
|
||||
"directories": {
|
||||
"lib": ".",
|
||||
"example": "example",
|
||||
"test": "test"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tape test/*.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tape": "~1.0.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/thlorenz/deep-is.git"
|
||||
},
|
||||
"keywords": [
|
||||
"equality",
|
||||
"equal",
|
||||
"compare"
|
||||
],
|
||||
"author": {
|
||||
"name": "Thorsten Lorenz",
|
||||
"email": "thlorenz@gmx.de",
|
||||
"url": "http://thlorenz.com"
|
||||
},
|
||||
"license": {
|
||||
"type": "MIT",
|
||||
"url": "https://github.com/thlorenz/deep-is/blob/master/LICENSE"
|
||||
},
|
||||
"testling": {
|
||||
"files": "test/*.js",
|
||||
"browsers": {
|
||||
"ie": [
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9
|
||||
],
|
||||
"ff": [
|
||||
3.5,
|
||||
10,
|
||||
15
|
||||
],
|
||||
"chrome": [
|
||||
10,
|
||||
22
|
||||
],
|
||||
"safari": [
|
||||
5.1
|
||||
],
|
||||
"opera": [
|
||||
12
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
var test = require('tape');
|
||||
var equal = require('../');
|
||||
|
||||
test('NaN and 0 values', function (t) {
|
||||
t.ok(equal(NaN, NaN));
|
||||
t.notOk(equal(0, NaN));
|
||||
t.ok(equal(0, 0));
|
||||
t.notOk(equal(0, 1));
|
||||
t.end();
|
||||
});
|
||||
|
||||
|
||||
test('nested NaN values', function (t) {
|
||||
t.ok(equal([ NaN, 1, NaN ], [ NaN, 1, NaN ]));
|
||||
t.end();
|
||||
});
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
var test = require('tape');
|
||||
var equal = require('../');
|
||||
|
||||
test('equal', function (t) {
|
||||
t.ok(equal(
|
||||
{ a : [ 2, 3 ], b : [ 4 ] },
|
||||
{ a : [ 2, 3 ], b : [ 4 ] }
|
||||
));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('not equal', function (t) {
|
||||
t.notOk(equal(
|
||||
{ x : 5, y : [6] },
|
||||
{ x : 5, y : 6 }
|
||||
));
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('nested nulls', function (t) {
|
||||
t.ok(equal([ null, null, null ], [ null, null, null ]));
|
||||
t.end();
|
||||
});
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
var test = require('tape');
|
||||
var equal = require('../');
|
||||
|
||||
test('0 values', function (t) {
|
||||
t.ok(equal( 0, 0), ' 0 === 0');
|
||||
t.ok(equal( 0, +0), ' 0 === +0');
|
||||
t.ok(equal(+0, +0), '+0 === +0');
|
||||
t.ok(equal(-0, -0), '-0 === -0');
|
||||
|
||||
t.notOk(equal(-0, 0), '-0 !== 0');
|
||||
t.notOk(equal(-0, +0), '-0 !== +0');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
Copyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
## Escodegen
|
||||
[](http://badge.fury.io/js/escodegen)
|
||||
[](http://travis-ci.org/estools/escodegen)
|
||||
[](https://david-dm.org/estools/escodegen)
|
||||
[](https://david-dm.org/estools/escodegen#info=devDependencies)
|
||||
|
||||
Escodegen ([escodegen](http://github.com/estools/escodegen)) is an
|
||||
[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
||||
(also popularly known as [JavaScript](http://en.wikipedia.org/wiki/JavaScript))
|
||||
code generator from [Mozilla's Parser API](https://developer.mozilla.org/en/SpiderMonkey/Parser_API)
|
||||
AST. See the [online generator](https://estools.github.io/escodegen/demo/index.html)
|
||||
for a demo.
|
||||
|
||||
|
||||
### Install
|
||||
|
||||
Escodegen can be used in a web browser:
|
||||
|
||||
<script src="escodegen.browser.js"></script>
|
||||
|
||||
escodegen.browser.js can be found in tagged revisions on GitHub.
|
||||
|
||||
Or in a Node.js application via npm:
|
||||
|
||||
npm install escodegen
|
||||
|
||||
### Usage
|
||||
|
||||
A simple example: the program
|
||||
|
||||
escodegen.generate({
|
||||
type: 'BinaryExpression',
|
||||
operator: '+',
|
||||
left: { type: 'Literal', value: 40 },
|
||||
right: { type: 'Literal', value: 2 }
|
||||
});
|
||||
|
||||
produces the string `'40 + 2'`.
|
||||
|
||||
See the [API page](https://github.com/estools/escodegen/wiki/API) for
|
||||
options. To run the tests, execute `npm test` in the root directory.
|
||||
|
||||
### Building browser bundle / minified browser bundle
|
||||
|
||||
At first, execute `npm install` to install the all dev dependencies.
|
||||
After that,
|
||||
|
||||
npm run-script build
|
||||
|
||||
will generate `escodegen.browser.js`, which can be used in browser environments.
|
||||
|
||||
And,
|
||||
|
||||
npm run-script build-min
|
||||
|
||||
will generate the minified file `escodegen.browser.min.js`.
|
||||
|
||||
### License
|
||||
|
||||
#### Escodegen
|
||||
|
||||
Copyright (C) 2012 [Yusuke Suzuki](http://github.com/Constellation)
|
||||
(twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+77
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*jslint sloppy:true node:true */
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
root = path.join(path.dirname(fs.realpathSync(__filename)), '..'),
|
||||
esprima = require('esprima'),
|
||||
escodegen = require(root),
|
||||
optionator = require('optionator')({
|
||||
prepend: 'Usage: escodegen [options] file...',
|
||||
options: [
|
||||
{
|
||||
option: 'config',
|
||||
alias: 'c',
|
||||
type: 'String',
|
||||
description: 'configuration json for escodegen'
|
||||
}
|
||||
]
|
||||
}),
|
||||
args = optionator.parse(process.argv),
|
||||
files = args._,
|
||||
options,
|
||||
esprimaOptions = {
|
||||
raw: true,
|
||||
tokens: true,
|
||||
range: true,
|
||||
comment: true
|
||||
};
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log(optionator.generateHelp());
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (args.config) {
|
||||
try {
|
||||
options = JSON.parse(fs.readFileSync(args.config, 'utf-8'));
|
||||
} catch (err) {
|
||||
console.error('Error parsing config: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
files.forEach(function (filename) {
|
||||
var content = fs.readFileSync(filename, 'utf-8'),
|
||||
syntax = esprima.parse(content, esprimaOptions);
|
||||
|
||||
if (options.comment) {
|
||||
escodegen.attachComments(syntax, syntax.comments, syntax.tokens);
|
||||
}
|
||||
|
||||
console.log(escodegen.generate(syntax, options));
|
||||
});
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*jslint sloppy:true node:true */
|
||||
|
||||
var fs = require('fs'),
|
||||
path = require('path'),
|
||||
root = path.join(path.dirname(fs.realpathSync(__filename)), '..'),
|
||||
escodegen = require(root),
|
||||
optionator = require('optionator')({
|
||||
prepend: 'Usage: esgenerate [options] file.json ...',
|
||||
options: [
|
||||
{
|
||||
option: 'config',
|
||||
alias: 'c',
|
||||
type: 'String',
|
||||
description: 'configuration json for escodegen'
|
||||
}
|
||||
]
|
||||
}),
|
||||
args = optionator.parse(process.argv),
|
||||
files = args._,
|
||||
options;
|
||||
|
||||
if (files.length === 0) {
|
||||
console.log(optionator.generateHelp());
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (args.config) {
|
||||
try {
|
||||
options = JSON.parse(fs.readFileSync(args.config, 'utf-8'))
|
||||
} catch (err) {
|
||||
console.error('Error parsing config: ', err);
|
||||
}
|
||||
}
|
||||
|
||||
files.forEach(function (filename) {
|
||||
var content = fs.readFileSync(filename, 'utf-8');
|
||||
console.log(escodegen.generate(JSON.parse(content), options));
|
||||
});
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+2647
File diff suppressed because it is too large
Load Diff
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"name": "escodegen",
|
||||
"description": "ECMAScript code generator",
|
||||
"homepage": "http://github.com/estools/escodegen",
|
||||
"main": "escodegen.js",
|
||||
"bin": {
|
||||
"esgenerate": "./bin/esgenerate.js",
|
||||
"escodegen": "./bin/escodegen.js"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE.BSD",
|
||||
"README.md",
|
||||
"bin",
|
||||
"escodegen.js",
|
||||
"package.json"
|
||||
],
|
||||
"version": "2.0.0",
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "http://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/estools/escodegen.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"estraverse": "^5.2.0",
|
||||
"esutils": "^2.0.2",
|
||||
"esprima": "^4.0.1",
|
||||
"optionator": "^0.8.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"source-map": "~0.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"acorn": "^7.3.1",
|
||||
"bluebird": "^3.4.7",
|
||||
"bower-registry-client": "^1.0.0",
|
||||
"chai": "^4.2.0",
|
||||
"chai-exclude": "^2.0.2",
|
||||
"commonjs-everywhere": "^0.9.7",
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-eslint": "^3.0.1",
|
||||
"gulp-mocha": "^3.0.1",
|
||||
"semver": "^5.1.0"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "gulp travis",
|
||||
"unit-test": "gulp test",
|
||||
"lint": "gulp lint",
|
||||
"release": "node tools/release.js",
|
||||
"build-min": "./node_modules/.bin/cjsify -ma path: tools/entry-point.js > escodegen.browser.min.js",
|
||||
"build": "./node_modules/.bin/cjsify -a path: tools/entry-point.js > escodegen.browser.js"
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
v1.3.0 - June 19, 2020
|
||||
|
||||
* [`c92dd7f`](https://github.com/eslint/eslint-visitor-keys/commit/c92dd7ff96f0044dba12d681406a025b92b4c437) Update: add `ChainExpression` node (#12) (Toru Nagashima)
|
||||
|
||||
v1.2.0 - June 4, 2020
|
||||
|
||||
* [`21f28bf`](https://github.com/eslint/eslint-visitor-keys/commit/21f28bf11be5329d740a8bf6bdbcd0ef13bbf1a2) Update: added exported in exportAllDeclaration key (#10) (Anix)
|
||||
|
||||
v1.1.0 - August 13, 2019
|
||||
|
||||
* [`9331cc0`](https://github.com/eslint/eslint-visitor-keys/commit/9331cc09e756e65b9044c9186445a474b037fac6) Update: add ImportExpression (#8) (Toru Nagashima)
|
||||
* [`5967f58`](https://github.com/eslint/eslint-visitor-keys/commit/5967f583b04f17fba9226aaa394e45d476d2b8af) Chore: add supported Node.js versions to CI (#7) (Kai Cataldo)
|
||||
* [`6f7c60f`](https://github.com/eslint/eslint-visitor-keys/commit/6f7c60fef2ceec9f6323202df718321cec45cab0) Upgrade: eslint-release@1.0.0 (#5) (Teddy Katz)
|
||||
|
||||
v1.0.0 - December 18, 2017
|
||||
|
||||
* 1f6bd38 Breaking: update keys (#4) (Toru Nagashima)
|
||||
|
||||
v0.1.0 - November 17, 2017
|
||||
|
||||
* 17b4a88 Chore: update `repository` field in package.json (#3) (Toru Nagashima)
|
||||
* a5a026b New: eslint-visitor-keys (#1) (Toru Nagashima)
|
||||
* a1a48b8 Update: Change license to Apache 2 (#2) (Ilya Volodin)
|
||||
* 2204715 Initial commit (Toru Nagashima)
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright contributors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
# eslint-visitor-keys
|
||||
|
||||
[](https://www.npmjs.com/package/eslint-visitor-keys)
|
||||
[](http://www.npmtrends.com/eslint-visitor-keys)
|
||||
[](https://travis-ci.org/eslint/eslint-visitor-keys)
|
||||
[](https://david-dm.org/eslint/eslint-visitor-keys)
|
||||
|
||||
Constants and utilities about visitor keys to traverse AST.
|
||||
|
||||
## 💿 Installation
|
||||
|
||||
Use [npm] to install.
|
||||
|
||||
```bash
|
||||
$ npm install eslint-visitor-keys
|
||||
```
|
||||
|
||||
### Requirements
|
||||
|
||||
- [Node.js] 4.0.0 or later.
|
||||
|
||||
## 📖 Usage
|
||||
|
||||
```js
|
||||
const evk = require("eslint-visitor-keys")
|
||||
```
|
||||
|
||||
### evk.KEYS
|
||||
|
||||
> type: `{ [type: string]: string[] | undefined }`
|
||||
|
||||
Visitor keys. This keys are frozen.
|
||||
|
||||
This is an object. Keys are the type of [ESTree] nodes. Their values are an array of property names which have child nodes.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
console.log(evk.KEYS.AssignmentExpression) // → ["left", "right"]
|
||||
```
|
||||
|
||||
### evk.getKeys(node)
|
||||
|
||||
> type: `(node: object) => string[]`
|
||||
|
||||
Get the visitor keys of a given AST node.
|
||||
|
||||
This is similar to `Object.keys(node)` of ES Standard, but some keys are excluded: `parent`, `leadingComments`, `trailingComments`, and names which start with `_`.
|
||||
|
||||
This will be used to traverse unknown nodes.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
const node = {
|
||||
type: "AssignmentExpression",
|
||||
left: { type: "Identifier", name: "foo" },
|
||||
right: { type: "Literal", value: 0 }
|
||||
}
|
||||
console.log(evk.getKeys(node)) // → ["type", "left", "right"]
|
||||
```
|
||||
|
||||
### evk.unionWith(additionalKeys)
|
||||
|
||||
> type: `(additionalKeys: object) => { [type: string]: string[] | undefined }`
|
||||
|
||||
Make the union set with `evk.KEYS` and the given keys.
|
||||
|
||||
- The order of keys is, `additionalKeys` is at first, then `evk.KEYS` is concatenated after that.
|
||||
- It removes duplicated keys as keeping the first one.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
console.log(evk.unionWith({
|
||||
MethodDefinition: ["decorators"]
|
||||
})) // → { ..., MethodDefinition: ["decorators", "key", "value"], ... }
|
||||
```
|
||||
|
||||
## 📰 Change log
|
||||
|
||||
See [GitHub releases](https://github.com/eslint/eslint-visitor-keys/releases).
|
||||
|
||||
## 🍻 Contributing
|
||||
|
||||
Welcome. See [ESLint contribution guidelines](https://eslint.org/docs/developer-guide/contributing/).
|
||||
|
||||
### Development commands
|
||||
|
||||
- `npm test` runs tests and measures code coverage.
|
||||
- `npm run lint` checks source codes with ESLint.
|
||||
- `npm run coverage` opens the code coverage report of the previous test with your default browser.
|
||||
- `npm run release` publishes this package to [npm] registory.
|
||||
|
||||
|
||||
[npm]: https://www.npmjs.com/
|
||||
[Node.js]: https://nodejs.org/en/
|
||||
[ESTree]: https://github.com/estree/estree
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* @author Toru Nagashima <https://github.com/mysticatea>
|
||||
* See LICENSE file in root directory for full license.
|
||||
*/
|
||||
"use strict";
|
||||
|
||||
const KEYS = require("./visitor-keys.json");
|
||||
|
||||
// Types.
|
||||
const NODE_TYPES = Object.freeze(Object.keys(KEYS));
|
||||
|
||||
// Freeze the keys.
|
||||
for (const type of NODE_TYPES) {
|
||||
Object.freeze(KEYS[type]);
|
||||
}
|
||||
Object.freeze(KEYS);
|
||||
|
||||
// List to ignore keys.
|
||||
const KEY_BLACKLIST = new Set([
|
||||
"parent",
|
||||
"leadingComments",
|
||||
"trailingComments"
|
||||
]);
|
||||
|
||||
/**
|
||||
* Check whether a given key should be used or not.
|
||||
* @param {string} key The key to check.
|
||||
* @returns {boolean} `true` if the key should be used.
|
||||
*/
|
||||
function filterKey(key) {
|
||||
return !KEY_BLACKLIST.has(key) && key[0] !== "_";
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public interfaces
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = Object.freeze({
|
||||
|
||||
/**
|
||||
* Visitor keys.
|
||||
* @type {{ [type: string]: string[] | undefined }}
|
||||
*/
|
||||
KEYS,
|
||||
|
||||
/**
|
||||
* Get visitor keys of a given node.
|
||||
* @param {Object} node The AST node to get keys.
|
||||
* @returns {string[]} Visitor keys of the node.
|
||||
*/
|
||||
getKeys(node) {
|
||||
return Object.keys(node).filter(filterKey);
|
||||
},
|
||||
|
||||
// Disable valid-jsdoc rule because it reports syntax error on the type of @returns.
|
||||
// eslint-disable-next-line valid-jsdoc
|
||||
/**
|
||||
* Make the union set with `KEYS` and given keys.
|
||||
* @param {Object} additionalKeys The additional keys.
|
||||
* @returns {{ [type: string]: string[] | undefined }} The union set.
|
||||
*/
|
||||
unionWith(additionalKeys) {
|
||||
const retv = Object.assign({}, KEYS);
|
||||
|
||||
for (const type of Object.keys(additionalKeys)) {
|
||||
if (retv.hasOwnProperty(type)) {
|
||||
const keys = new Set(additionalKeys[type]);
|
||||
|
||||
for (const key of retv[type]) {
|
||||
keys.add(key);
|
||||
}
|
||||
|
||||
retv[type] = Object.freeze(Array.from(keys));
|
||||
} else {
|
||||
retv[type] = Object.freeze(Array.from(additionalKeys[type]));
|
||||
}
|
||||
}
|
||||
|
||||
return Object.freeze(retv);
|
||||
}
|
||||
});
|
||||
Generated
Vendored
+284
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"AssignmentExpression": [
|
||||
"left",
|
||||
"right"
|
||||
],
|
||||
"AssignmentPattern": [
|
||||
"left",
|
||||
"right"
|
||||
],
|
||||
"ArrayExpression": [
|
||||
"elements"
|
||||
],
|
||||
"ArrayPattern": [
|
||||
"elements"
|
||||
],
|
||||
"ArrowFunctionExpression": [
|
||||
"params",
|
||||
"body"
|
||||
],
|
||||
"AwaitExpression": [
|
||||
"argument"
|
||||
],
|
||||
"BlockStatement": [
|
||||
"body"
|
||||
],
|
||||
"BinaryExpression": [
|
||||
"left",
|
||||
"right"
|
||||
],
|
||||
"BreakStatement": [
|
||||
"label"
|
||||
],
|
||||
"CallExpression": [
|
||||
"callee",
|
||||
"arguments"
|
||||
],
|
||||
"CatchClause": [
|
||||
"param",
|
||||
"body"
|
||||
],
|
||||
"ChainExpression": [
|
||||
"expression"
|
||||
],
|
||||
"ClassBody": [
|
||||
"body"
|
||||
],
|
||||
"ClassDeclaration": [
|
||||
"id",
|
||||
"superClass",
|
||||
"body"
|
||||
],
|
||||
"ClassExpression": [
|
||||
"id",
|
||||
"superClass",
|
||||
"body"
|
||||
],
|
||||
"ConditionalExpression": [
|
||||
"test",
|
||||
"consequent",
|
||||
"alternate"
|
||||
],
|
||||
"ContinueStatement": [
|
||||
"label"
|
||||
],
|
||||
"DebuggerStatement": [],
|
||||
"DoWhileStatement": [
|
||||
"body",
|
||||
"test"
|
||||
],
|
||||
"EmptyStatement": [],
|
||||
"ExportAllDeclaration": [
|
||||
"exported",
|
||||
"source"
|
||||
],
|
||||
"ExportDefaultDeclaration": [
|
||||
"declaration"
|
||||
],
|
||||
"ExportNamedDeclaration": [
|
||||
"declaration",
|
||||
"specifiers",
|
||||
"source"
|
||||
],
|
||||
"ExportSpecifier": [
|
||||
"exported",
|
||||
"local"
|
||||
],
|
||||
"ExpressionStatement": [
|
||||
"expression"
|
||||
],
|
||||
"ExperimentalRestProperty": [
|
||||
"argument"
|
||||
],
|
||||
"ExperimentalSpreadProperty": [
|
||||
"argument"
|
||||
],
|
||||
"ForStatement": [
|
||||
"init",
|
||||
"test",
|
||||
"update",
|
||||
"body"
|
||||
],
|
||||
"ForInStatement": [
|
||||
"left",
|
||||
"right",
|
||||
"body"
|
||||
],
|
||||
"ForOfStatement": [
|
||||
"left",
|
||||
"right",
|
||||
"body"
|
||||
],
|
||||
"FunctionDeclaration": [
|
||||
"id",
|
||||
"params",
|
||||
"body"
|
||||
],
|
||||
"FunctionExpression": [
|
||||
"id",
|
||||
"params",
|
||||
"body"
|
||||
],
|
||||
"Identifier": [],
|
||||
"IfStatement": [
|
||||
"test",
|
||||
"consequent",
|
||||
"alternate"
|
||||
],
|
||||
"ImportDeclaration": [
|
||||
"specifiers",
|
||||
"source"
|
||||
],
|
||||
"ImportDefaultSpecifier": [
|
||||
"local"
|
||||
],
|
||||
"ImportExpression": [
|
||||
"source"
|
||||
],
|
||||
"ImportNamespaceSpecifier": [
|
||||
"local"
|
||||
],
|
||||
"ImportSpecifier": [
|
||||
"imported",
|
||||
"local"
|
||||
],
|
||||
"JSXAttribute": [
|
||||
"name",
|
||||
"value"
|
||||
],
|
||||
"JSXClosingElement": [
|
||||
"name"
|
||||
],
|
||||
"JSXElement": [
|
||||
"openingElement",
|
||||
"children",
|
||||
"closingElement"
|
||||
],
|
||||
"JSXEmptyExpression": [],
|
||||
"JSXExpressionContainer": [
|
||||
"expression"
|
||||
],
|
||||
"JSXIdentifier": [],
|
||||
"JSXMemberExpression": [
|
||||
"object",
|
||||
"property"
|
||||
],
|
||||
"JSXNamespacedName": [
|
||||
"namespace",
|
||||
"name"
|
||||
],
|
||||
"JSXOpeningElement": [
|
||||
"name",
|
||||
"attributes"
|
||||
],
|
||||
"JSXSpreadAttribute": [
|
||||
"argument"
|
||||
],
|
||||
"JSXText": [],
|
||||
"JSXFragment": [
|
||||
"openingFragment",
|
||||
"children",
|
||||
"closingFragment"
|
||||
],
|
||||
"Literal": [],
|
||||
"LabeledStatement": [
|
||||
"label",
|
||||
"body"
|
||||
],
|
||||
"LogicalExpression": [
|
||||
"left",
|
||||
"right"
|
||||
],
|
||||
"MemberExpression": [
|
||||
"object",
|
||||
"property"
|
||||
],
|
||||
"MetaProperty": [
|
||||
"meta",
|
||||
"property"
|
||||
],
|
||||
"MethodDefinition": [
|
||||
"key",
|
||||
"value"
|
||||
],
|
||||
"NewExpression": [
|
||||
"callee",
|
||||
"arguments"
|
||||
],
|
||||
"ObjectExpression": [
|
||||
"properties"
|
||||
],
|
||||
"ObjectPattern": [
|
||||
"properties"
|
||||
],
|
||||
"Program": [
|
||||
"body"
|
||||
],
|
||||
"Property": [
|
||||
"key",
|
||||
"value"
|
||||
],
|
||||
"RestElement": [
|
||||
"argument"
|
||||
],
|
||||
"ReturnStatement": [
|
||||
"argument"
|
||||
],
|
||||
"SequenceExpression": [
|
||||
"expressions"
|
||||
],
|
||||
"SpreadElement": [
|
||||
"argument"
|
||||
],
|
||||
"Super": [],
|
||||
"SwitchStatement": [
|
||||
"discriminant",
|
||||
"cases"
|
||||
],
|
||||
"SwitchCase": [
|
||||
"test",
|
||||
"consequent"
|
||||
],
|
||||
"TaggedTemplateExpression": [
|
||||
"tag",
|
||||
"quasi"
|
||||
],
|
||||
"TemplateElement": [],
|
||||
"TemplateLiteral": [
|
||||
"quasis",
|
||||
"expressions"
|
||||
],
|
||||
"ThisExpression": [],
|
||||
"ThrowStatement": [
|
||||
"argument"
|
||||
],
|
||||
"TryStatement": [
|
||||
"block",
|
||||
"handler",
|
||||
"finalizer"
|
||||
],
|
||||
"UnaryExpression": [
|
||||
"argument"
|
||||
],
|
||||
"UpdateExpression": [
|
||||
"argument"
|
||||
],
|
||||
"VariableDeclaration": [
|
||||
"declarations"
|
||||
],
|
||||
"VariableDeclarator": [
|
||||
"id",
|
||||
"init"
|
||||
],
|
||||
"WhileStatement": [
|
||||
"test",
|
||||
"body"
|
||||
],
|
||||
"WithStatement": [
|
||||
"object",
|
||||
"body"
|
||||
],
|
||||
"YieldExpression": [
|
||||
"argument"
|
||||
]
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "eslint-visitor-keys",
|
||||
"version": "1.3.0",
|
||||
"description": "Constants and utilities about visitor keys to traverse AST.",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"eslint": "^4.7.2",
|
||||
"eslint-config-eslint": "^4.0.0",
|
||||
"eslint-release": "^1.0.0",
|
||||
"mocha": "^3.5.3",
|
||||
"nyc": "^11.2.1",
|
||||
"opener": "^1.4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint lib tests/lib",
|
||||
"pretest": "npm run -s lint",
|
||||
"test": "nyc mocha tests/lib",
|
||||
"coverage": "nyc report --reporter lcov && opener coverage/lcov-report/index.html",
|
||||
"generate-release": "eslint-generate-release",
|
||||
"generate-alpharelease": "eslint-generate-prerelease alpha",
|
||||
"generate-betarelease": "eslint-generate-prerelease beta",
|
||||
"generate-rcrelease": "eslint-generate-prerelease rc",
|
||||
"publish-release": "eslint-publish-release"
|
||||
},
|
||||
"repository": "eslint/eslint-visitor-keys",
|
||||
"keywords": [],
|
||||
"author": "Toru Nagashima (https://github.com/mysticatea)",
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/eslint/eslint-visitor-keys/issues"
|
||||
},
|
||||
"homepage": "https://github.com/eslint/eslint-visitor-keys#readme"
|
||||
}
|
||||
+509
@@ -0,0 +1,509 @@
|
||||
v7.3.1 - December 5, 2020
|
||||
|
||||
* [`fef6f4a`](https://github.com/eslint/espree/commit/fef6f4a2803d959304c6961527044bd9da39ac92) Upgrade: acorn-jsx@5.3.1 (#459) (Milos Djermanovic)
|
||||
* [`0e09d9a`](https://github.com/eslint/espree/commit/0e09d9a4f213cb87073a6a87cb7d6317b77d1a23) Chore: Add tests for ecmaVersion default value (#460) (Milos Djermanovic)
|
||||
* [`4c70052`](https://github.com/eslint/espree/commit/4c70052df0b0ba903602c1f838918cbc07ee5eca) Docs: Fix some minor typos in the READMEs (#455) (Noah Doersing)
|
||||
|
||||
v7.3.0 - August 22, 2020
|
||||
|
||||
* [`4ba3eef`](https://github.com/eslint/espree/commit/4ba3eefdc4b32784565822b34f11977e99ca1a19) Chore: move to GitHub Actions (#449) (Kai Cataldo)
|
||||
* [`bd0a405`](https://github.com/eslint/espree/commit/bd0a405ffbe4962bcf5aa225ed3861a6a15cb827) Update: support logical assignment and numeric separators (#448) (Toru Nagashima)
|
||||
|
||||
v7.2.0 - July 17, 2020
|
||||
|
||||
* [`91c2d58`](https://github.com/eslint/espree/commit/91c2d5896889042058399cd64de4b218c5add0eb) Docs: Add security policy (#447) (Nicholas C. Zakas)
|
||||
* [`872645c`](https://github.com/eslint/espree/commit/872645cea0bee08960b93c097f84153d44b44d7f) Update: support optional chaining (#446) (Toru Nagashima)
|
||||
* [`0cc7800`](https://github.com/eslint/espree/commit/0cc78007c933564f32fd849bd8022992845c3ac1) Docs: Clean up LICENSE file (#445) (Nicholas C. Zakas)
|
||||
|
||||
v7.1.0 - June 4, 2020
|
||||
|
||||
* [`75e80bc`](https://github.com/eslint/espree/commit/75e80bc1b5a100f64b09b2c7bf47c5168417d890) Update: support `??` operator, `import.meta`, and `export * as ns` (#441) (Toru Nagashima)
|
||||
* [`ad0543c`](https://github.com/eslint/espree/commit/ad0543c8b9f6981857ebebf23a37589a656e61a6) Chore: added fixlint in Makefile.js (#440) (Anix)
|
||||
|
||||
v7.0.0 - May 7, 2020
|
||||
|
||||
* [`8fe2efc`](https://github.com/eslint/espree/commit/8fe2efc00902e7f1680af00a6279e1aecb3c5b47) Breaking: drop Node v8 support (#429) (Kai Cataldo)
|
||||
* [`6048bfe`](https://github.com/eslint/espree/commit/6048bfe3939fa7dc162c0b3c4b043bb410736b0b) Docs: documenting public API (fixes #431) (#442) (Anix)
|
||||
* [`9a4cff3`](https://github.com/eslint/espree/commit/9a4cff3626d50a88428ca1b66610a2bdedd774dd) Chore: added tests for options normalize (#439) (Anix)
|
||||
* [`99707f3`](https://github.com/eslint/espree/commit/99707f3f9d337ca719dce5720106f98b65bba7b1) Chore: added lockfiles to .gitignore (#438) (Anix)
|
||||
* [`9b91bcc`](https://github.com/eslint/espree/commit/9b91bccacea15c75025a62bae828f83598aef5fe) Docs: new site for docs (#436) (Anix)
|
||||
|
||||
v6.2.1 - March 10, 2020
|
||||
|
||||
* [`d6d7480`](https://github.com/eslint/espree/commit/d6d7480e424960159007caea86f209f696138734) Upgrade: acorn 7.1.1, Regex DOS vuln (fixes #435) (#434) (James)
|
||||
|
||||
v6.2.0 - March 2, 2020
|
||||
|
||||
* [`ced1b68`](https://github.com/eslint/espree/commit/ced1b6810b991531e6d3788ebd5a322fc5c7d463) Update: update acorn-jsx and fix failing test (#432) (Kai Cataldo)
|
||||
* [`acb8776`](https://github.com/eslint/espree/commit/acb8776d369abf9e02f79142879e9b1a4774f938) Update: add latestEcmaVersion & supportedEcmaVersions (#430) (Kai Cataldo)
|
||||
|
||||
v6.1.2 - October 20, 2019
|
||||
|
||||
* [`70c4970`](https://github.com/eslint/espree/commit/70c4970e5eba6f060e1e32a22d231647f2d0e0f8) Fix: misuse token types (fixes #393, refs eslint/eslint#11018) (#426) (Toru Nagashima)
|
||||
|
||||
v6.1.1 - August 23, 2019
|
||||
|
||||
* [`ba81546`](https://github.com/eslint/espree/commit/ba81546e8552ec0f779aae7e03668c334630484e) Upgrade: dev deps to latest (#424) (薛定谔的猫)
|
||||
* [`bbe0119`](https://github.com/eslint/espree/commit/bbe01195fb57e24634d18825d39b820ed1767e95) Upgrade: acorn-jsx@5.0.2 (#423) (薛定谔的猫)
|
||||
* [`c0635ba`](https://github.com/eslint/espree/commit/c0635bac4cd891cb612fb81655012e2579f4e2b1) Docs: update readme to mention ES2020 (#422) (Kai Cataldo)
|
||||
|
||||
v6.1.0 - August 18, 2019
|
||||
|
||||
* [`9870c55`](https://github.com/eslint/espree/commit/9870c553efd3eb1bd22b4b3bb5220896c5cb6933) Update: improve error messaging when validating ecmaVersion (#421) (Kai Cataldo)
|
||||
* [`3f49224`](https://github.com/eslint/espree/commit/3f49224eb05f6b8cb1b996ce424a99c40978b389) Fix: tokenize the latest right curly brace (fixes #403) (#419) (finico)
|
||||
* [`f5e58cc`](https://github.com/eslint/espree/commit/f5e58cc5e9030793baca3426366b8d7286ef5b89) Update: support bigint and dynamic import (#415) (Toru Nagashima)
|
||||
|
||||
v6.0.0 - June 21, 2019
|
||||
|
||||
* [`a988a36`](https://github.com/eslint/espree/commit/a988a36e436a1ab6c84005ba0adb6cf9c262c1ec) Build: add node 12 (#414) (薛定谔的猫)
|
||||
|
||||
v6.0.0-alpha.0 - April 12, 2019
|
||||
|
||||
* [`493d464`](https://github.com/eslint/espree/commit/493d464e1564aea0ea33000389771d42ddece2cb) Breaking: validate parser options (fixes #384) (#412) (薛定谔的猫)
|
||||
|
||||
v5.0.1 - February 15, 2019
|
||||
|
||||
* [`c40e2fc`](https://github.com/eslint/espree/commit/c40e2fcedf81ff06151e82bdf655d2d0d29e71b8) Upgrade: acorn@6.0.7 (#407) (Kai Cataldo)
|
||||
|
||||
v5.0.0 - December 5, 2018
|
||||
|
||||
* [`1bcd563`](https://github.com/eslint/espree/commit/1bcd563d4eb4b4032d2662cc5ccd3bfd841b39d7) Breaking: remove attachComment (#405) (Kai Cataldo)
|
||||
* [`35623ee`](https://github.com/eslint/espree/commit/35623ee07289c9199eef8b735c97cb3d3d08d5b8) Chore: update linting config (#406) (Kai Cataldo)
|
||||
* [`4b86a7d`](https://github.com/eslint/espree/commit/4b86a7dc7c447c11bb6530e46dc43428ce2bd372) Build: add node 11 (#400) (薛定谔的猫)
|
||||
* [`7c278d6`](https://github.com/eslint/espree/commit/7c278d6acc6b5db86b803d0cd21b830deb6f569e) Fix: build failing due to incorrectly super() call (fixes #398) (#399) (薛定谔的猫)
|
||||
* [`6ebc219`](https://github.com/eslint/espree/commit/6ebc21947166399a0b4918d4a1beb9d610650336) Upgrade: eslint & eslint-config-eslint (#387) (薛定谔的猫)
|
||||
|
||||
v4.1.0 - October 24, 2018
|
||||
|
||||
* 8eadb88 Upgrade: acorn 6, acorn-jsx 5, and istanbul (#391) (Toru Nagashima)
|
||||
* 0f2edb8 Upgrade: eslint-release@1.0.0 (#392) (Teddy Katz)
|
||||
* 560b6f7 Update: VisitorKeys depend on eslint-visitor-keys (#389) (othree)
|
||||
* 6bf2ebf Docs: Fix some typos in the README (#386) (Hugo Locurcio)
|
||||
|
||||
v4.0.0 - June 21, 2018
|
||||
|
||||
|
||||
|
||||
v4.0.0-rc.0 - June 9, 2018
|
||||
|
||||
* d8224c4 Build: Adding rc release script to package.json (#383) (Kevin Partington)
|
||||
* 4207773 Build: add node 10 (#381) (薛定谔的猫)
|
||||
* cd9da7e Update: upgrade acorn to support two ES2019 syntax (#380) (Toru Nagashima)
|
||||
* 8cb3ceb Chore: remove Object.assign polyfill (#382) (薛定谔的猫)
|
||||
|
||||
v4.0.0-alpha.1 - May 28, 2018
|
||||
|
||||
* 56c5a9c Fix: remove workarounds for acorn < 4 (#372) (Rouven Weßling)
|
||||
* fd305e5 Upgrade: eslint-release to v0.11.1 (#376) (Teddy Katz)
|
||||
|
||||
v4.0.0-alpha.0 - March 30, 2018
|
||||
|
||||
* 95fa890 Build: fix typos in package.json release scripts (#375) (Teddy Katz)
|
||||
* 6284e09 Breaking: remove experimentalObjectRestSpread option (#374) (Teddy Katz)
|
||||
* 0df063f Breaking: require Node.js 6+, upgrade acorn-jsx@4.1.1 (fixes #345) (#371) (薛定谔的猫)
|
||||
* 0252144 Upgrade: acorn 5.5.1 (#370) (Rouven Weßling)
|
||||
|
||||
v3.5.4 - March 4, 2018
|
||||
|
||||
* 706167b Upgrade: acorn 5.5.0 (#369) (Toru Nagashima)
|
||||
|
||||
v3.5.3 - February 2, 2018
|
||||
|
||||
* 70f9859 Upgrade: acorn 5.4.0 (#367) (Toru Nagashima)
|
||||
* cea4823 Chore: Adding .gitattributes file (#366) (Kevin Partington)
|
||||
* 4160aee Upgrade: acorn v5.3.0 (#365) (Toru Nagashima)
|
||||
|
||||
v3.5.2 - November 10, 2017
|
||||
|
||||
* 019b70a Fix: Remove blockBindings from docs (fixes #307, fixes #339) (#356) (Jan Pilzer)
|
||||
* b2016cb Chore: refactoring rest/spread properties (#361) (Toru Nagashima)
|
||||
* 59c9d06 Chore: upgrade acorn@5.2 (fixes #358) (#360) (Toru Nagashima)
|
||||
* 06c35c9 Chore: add .npmrc (#359) (Toru Nagashima)
|
||||
|
||||
v3.5.1 - September 15, 2017
|
||||
|
||||
* 5eb1388 Fix: Fix parsing of async keyword-named object methods (#352) (#353) (Mark Banner)
|
||||
|
||||
v3.5.0 - August 5, 2017
|
||||
|
||||
* 4d442a1 Update: add initial support for ES2018 (#348) (Teddy Katz)
|
||||
* d4bdcb6 Fix: Make template token objects adhere to token object structure (#343) (Ian Christian Myers)
|
||||
* 9ac671a Upgrade: acorn to 5.1.1 (#347) (Teddy Katz)
|
||||
* 16e1fec Docs: Specify default values of options (fixes #325) (#342) (Jan Pilzer)
|
||||
* be85b8e Fix: async shorthand properties (fixes #340) (#341) (Toru Nagashima)
|
||||
|
||||
v3.4.3 - May 5, 2017
|
||||
|
||||
* 343590a Fix: add AwaitExpression to espree.Syntax (fixes #331) (#332) (Teddy Katz)
|
||||
|
||||
v3.4.2 - April 21, 2017
|
||||
|
||||
* c99e436 Upgrade: eslint to 2.13.1 (#328) (Teddy Katz)
|
||||
* 628cf3a Fix: don't mutate user-provided configs (fixes #329) (#330) (Teddy Katz)
|
||||
|
||||
v3.4.1 - March 31, 2017
|
||||
|
||||
* a3ae0bd Upgrade: acorn to 5.0.1 (#327) (Teddy Katz)
|
||||
* 15ef24f Docs: Add badges (#326) (Jan Pilzer)
|
||||
* 652990a Fix: raise error for trailing commas after rest properties (fixes #310) (#323) (Teddy Katz)
|
||||
* 9d86ba5 Upgrade: acorn to ^4.0.11 (#317) (Toru Nagashima)
|
||||
* a3442b5 Chore: fix tests for Node 6+ (#315) (Teddy Katz)
|
||||
|
||||
v3.4.0 - February 2, 2017
|
||||
|
||||
* f55fa51 Build: Lock acorn to v4.0.4 (#314) (Kai Cataldo)
|
||||
* 58f75be Fix:generic error for invalid ecmaVersion(fixes eslint#7405) (#303) (Scott Stern)
|
||||
* d6b383d Docs: Update license copyright (Nicholas C. Zakas)
|
||||
* e5df542 Update: To support year in ecmaVersion number (fixes #300) (#301) (Gyandeep Singh)
|
||||
|
||||
v3.3.2 - September 29, 2016
|
||||
|
||||
* 7d3e2fc Fix: reset `isAsync` flag for each property (fixes #298) (#299) (Toru Nagashima)
|
||||
|
||||
v3.3.1 - September 26, 2016
|
||||
|
||||
* 80abdce Fix: `}` token followed by template had been lost (fixes #293) (#294) (Toru Nagashima)
|
||||
* 9810bab Fix: parsing error on `async` as property name. (#295) (Toru Nagashima)
|
||||
|
||||
v3.3.0 - September 20, 2016
|
||||
|
||||
* 92b04b1 Update: create-test script (fixes #291) (#292) (Jamund Ferguson)
|
||||
|
||||
v3.2.0 - September 16, 2016
|
||||
|
||||
* 5a37f80 Build: Update release tool (Nicholas C. Zakas)
|
||||
* 9bbcad8 Update: Upgrade Acorn to support ES2017 (fixes #287) (#290) (Jamund Ferguson)
|
||||
* 8d9767d Build: Add CI release scripts (Nicholas C. Zakas)
|
||||
|
||||
v3.1.7 - July 29, 2016
|
||||
|
||||
* 8f6cfbd Build: Add CI release (Nicholas C. Zakas)
|
||||
* ff15922 Fix: Catch ES2016 invalid syntax (fixes #284) (#285) (Nicholas C. Zakas)
|
||||
|
||||
v3.1.6 - June 15, 2016
|
||||
|
||||
* a90edc2 Upgrade: acorn 3.2.0 (fixes #279) (#280) (Toru Nagashima)
|
||||
|
||||
v3.1.5 - May 27, 2016
|
||||
|
||||
* 7df2e4a Fix: Convert ~ and ! prefix tokens to esprima (fixes #274) (#276) (Daniel Tschinder)
|
||||
|
||||
v3.1.4 - April 21, 2016
|
||||
|
||||
* e044705 Fix: remove extra leading comments at node level (fixes #264) (Kai Cataldo)
|
||||
* 25c27fb Chore: Remove jQuery copyright from header of each file (Kai Cataldo)
|
||||
* 10709f0 Chore: Add jQuery Foundation copyright (Nicholas C. Zakas)
|
||||
* d754b32 Upgrade: Acorn 3.1.0 (fixes #270) (Toru Nagashima)
|
||||
* 3a90886 Docs: replace a dead link with the correct contributing guide URL (Shinnosuke Watanabe)
|
||||
* 55184a2 Build: replace optimist with a simple native method (Shinnosuke Watanabe)
|
||||
* c7e5a13 Fix: Disallow namespaces objects in JSX (fixes #261) (Kai Cataldo)
|
||||
* 22290b9 Fix: Add test for leading comments (fixes #136) (Kai Cataldo)
|
||||
|
||||
v3.1.3 - March 18, 2016
|
||||
|
||||
* 98441cb Fix: Fix behavior of ignoring comments within previous nodes (refs #256) (Kai Cataldo)
|
||||
|
||||
v3.1.2 - March 14, 2016
|
||||
|
||||
* a2b23ca Fix: Ensure 'var let' works (fixes #149) (Nicholas C. Zakas)
|
||||
* 5783282 Fix: Make obj.await work in modules (fixes #258) (Nicholas C. Zakas)
|
||||
* d1b4929 Fix: leading comments added from previous node (fixes #256) (Kai Cataldo)
|
||||
|
||||
v3.1.1 - February 26, 2016
|
||||
|
||||
* 3614e81 Fix: exponentiation operator token (fixes #254) (Nicholas C. Zakas)
|
||||
|
||||
v3.1.0 - February 25, 2016
|
||||
|
||||
* da35d98 New: Support ecmaVersion 7 (fixes #246) (Nicholas C. Zakas)
|
||||
|
||||
v3.0.2 - February 19, 2016
|
||||
|
||||
* 0973cda Build: Update release script (Nicholas C. Zakas)
|
||||
* 106000f Fix: use the plugins feature of acorn (fixes #250) (Toru Nagashima)
|
||||
* 36d84c7 Build: Add tests (fixes #243) (Nicholas C. Zakas)
|
||||
|
||||
v3.0.1 - February 2, 2016
|
||||
|
||||
* ecfe4c8 Upgrade: eslint-config-eslint to 3.0.0 (Nicholas C. Zakas)
|
||||
* ea6261e Fix: Object rest/spread in assign (fixes #247) (Nicholas C. Zakas)
|
||||
* 7e57ee0 Docs: fix `options.comment` typo (xuezu)
|
||||
* dd5863e Build: Add prerelease script (Nicholas C. Zakas)
|
||||
* 0b409ee Upgrade: eslint-release to 0.2.0 (Nicholas C. Zakas)
|
||||
|
||||
v3.0.0 - January 20, 2016
|
||||
|
||||
* 5ff65f6 Upgrade: Change Esprima version to latest (Nicholas C. Zakas)
|
||||
* a8badcc Upgrade: eslint-release to 0.1.4 (Nicholas C. Zakas)
|
||||
* 34d195b Build: Switch to eslint-release (Nicholas C. Zakas)
|
||||
* a0ddc30 Breaking: Remove binary scripts (Nicholas C. Zakas)
|
||||
* 02b5284 Build: Fix package.json dependencies (Nicholas C. Zakas)
|
||||
* b07696f Fix: tests for importing keywords (fixes #225) (Toru Nagashima)
|
||||
* 2e2808a Build: Add node@5 to CI (fixes #237) (alberto)
|
||||
* 445c685 Update: Unrecognized license format in package.json (fixes #234) (alberto)
|
||||
* 61cb5ee Update: Remove duplicated acorn-jsx dep (fixes #232) (alberto)
|
||||
* df5b71c Upgrade: eslint and eslint-config-eslint (fixes #231) (alberto)
|
||||
* ef7a06d Fix: lastToken not reset between calls to parse (fixes #229) (alberto)
|
||||
* cdf8407 New: ecmaFeatures.impliedStrict (fixes: #227) (Nick Evans)
|
||||
|
||||
v3.0.0-alpha-2 - December 9, 2015
|
||||
|
||||
* 3.0.0-alpha-2 (Nicholas C. Zakas)
|
||||
* Breaking: move ecmaFeatures into ecmaVersion (fixes #222) (Nicholas C. Zakas)
|
||||
* New: Export VisitorKeys (fixes #220) (Nicholas C. Zakas)
|
||||
|
||||
v3.0.0-alpha-1 - December 1, 2015
|
||||
|
||||
* 3.0.0-alpha-1 (Nicholas C. Zakas)
|
||||
* Fix: parse unicode escapes in identifiers (fixes #181) (Nicholas C. Zakas)
|
||||
* Fix: Ensur object rest works in destructed arg (fixes #213) (Nicholas C. Zakas)
|
||||
* Breaking: Switch to Acorn (fixes #200) (Nicholas C. Zakas)
|
||||
* Update: Add tokens to tests (fixes #203) (Nicholas C. Zakas)
|
||||
* Docs: Update README (Nicholas C. Zakas)
|
||||
|
||||
v2.2.5 - September 15, 2015
|
||||
|
||||
* 2.2.5 (Nicholas C. Zakas)
|
||||
* Fix: Ensure node type is correct for destructured (fixes #195) (Nicholas C. Zakas)
|
||||
|
||||
v2.2.4 - August 13, 2015
|
||||
|
||||
* 2.2.4 (Nicholas C. Zakas)
|
||||
* Fix: newlines in arrow functions (fixes #172) (Jamund Ferguson)
|
||||
* Fix: nested arrow function as default param (fixes #145) (Jamund Ferguson)
|
||||
* Fix: Rest Params & Arrow Functions (fixes #187) (Jamund Ferguson)
|
||||
* Fix: trailing commas in import/export (fixes #148) (Jamund Ferguson)
|
||||
* Build: Added sudo false to Travis to build faster (fixes #177) (KahWee Teng)
|
||||
|
||||
v2.2.3 - July 22, 2015
|
||||
|
||||
* 2.2.3 (Nicholas C. Zakas)
|
||||
* Fix: Incorrect error location (fixes #173) (Nicholas C. Zakas)
|
||||
|
||||
v2.2.2 - July 16, 2015
|
||||
|
||||
* 2.2.2 (Nicholas C. Zakas)
|
||||
* 2.2.1 (Nicholas C. Zakas)
|
||||
* Fix: Yield as identifier in arrow func args (fixes #165) (Nicholas C. Zakas)
|
||||
* Fix: Allow AssignmentExpression in object spread (fixes #167) (Nicholas C. Zakas)
|
||||
|
||||
v2.2.1 - July 16, 2015
|
||||
|
||||
* 2.2.1 (Nicholas C. Zakas)
|
||||
|
||||
v2.2.0 - July 15, 2015
|
||||
|
||||
* 2.2.0 (Nicholas C. Zakas)
|
||||
* New: Add experimental object rest/spread (fixes #163) (Nicholas C. Zakas)
|
||||
* Fix: npm browserify (fixes #156) (Jason Laster)
|
||||
|
||||
v2.1.0 - July 10, 2015
|
||||
|
||||
* 2.1.0 (Nicholas C. Zakas)
|
||||
* Fix: Leading comments for anonymous classes (fixes #155, fixes #158) (Toru Nagashima)
|
||||
* New: Add newTarget option (fixes #157) (Nicholas C. Zakas)
|
||||
|
||||
v2.0.4 - June 26, 2015
|
||||
|
||||
* 2.0.4 (Nicholas C. Zakas)
|
||||
* Docs: added missing `ecmaFeatures.superInFunctions` option from doc (Clément Fiorio)
|
||||
* Fix: "await" is a future reserved word (fixes #151) (Jose Roberto Vidal)
|
||||
|
||||
v2.0.3 - June 2, 2015
|
||||
|
||||
* 2.0.3 (Nicholas C. Zakas)
|
||||
* Fix: Incomplete Switch Statement Hangs (Fixes #146) (Jamund Ferguson)
|
||||
* Docs: Clarify ecmaFeatures usage (Dan Wolff)
|
||||
|
||||
v2.0.2 - April 28, 2015
|
||||
|
||||
* 2.0.2 (Nicholas C. Zakas)
|
||||
* Fix: Allow yield without value as function param (fixes #134) (Nicholas C. Zakas)
|
||||
* Fix: Allow computed generators in classes (fixes #123) (Nicholas C. Zakas)
|
||||
* Fix: Don't allow arrow function rest param (fixes #130) (Nicholas C. Zakas)
|
||||
|
||||
v2.0.1 - April 11, 2015
|
||||
|
||||
* 2.0.1 (Nicholas C. Zakas)
|
||||
* Fix: Yield should parse without an argument (fixes #121) (Nicholas C. Zakas)
|
||||
|
||||
v2.0.0 - April 4, 2015
|
||||
|
||||
* 2.0.0 (Nicholas C. Zakas)
|
||||
* Docs: Update README with latest info (Nicholas C. Zakas)
|
||||
* Breaking: Use ESTree format for default params (fixes #114) (Nicholas C. Zakas)
|
||||
* New: Add Super node (fixes #115) (Nicholas C. Zakas)
|
||||
* Breaking: Switch to RestElement for rest args (fixes #84) (Nicholas C. Zakas)
|
||||
* Docs: Correct license info on README (fixes #117) (AJ Ortega)
|
||||
* Breaking: Remove guardedHandlers/handlers from try (fixes #71) (Nicholas C. Zakas)
|
||||
|
||||
v1.12.3 - March 28, 2015
|
||||
|
||||
* 1.12.3 (Nicholas C. Zakas)
|
||||
* Fix: Tagged template strings (fixes #110) (Nicholas C. Zakas)
|
||||
|
||||
v1.12.2 - March 21, 2015
|
||||
|
||||
* 1.12.2 (Nicholas C. Zakas)
|
||||
* Fix: Destructured arg for catch (fixes #105) (Nicholas C. Zakas)
|
||||
|
||||
v1.12.1 - March 21, 2015
|
||||
|
||||
* 1.12.1 (Nicholas C. Zakas)
|
||||
* Fix: Disallow octals in template strings (fixes #96) (Nicholas C. Zakas)
|
||||
* Fix: Template string parsing (fixes #95) (Nicholas C. Zakas)
|
||||
* Fix: shorthand properties named get or set (fixes #100) (Brandon Mills)
|
||||
* Fix: bad error in parsing invalid class setter (fixes #98) (Marsup)
|
||||
|
||||
v1.12.0 - March 14, 2015
|
||||
|
||||
* 1.12.0 (Nicholas C. Zakas)
|
||||
* Fix: Update broken tests (Nicholas C. Zakas)
|
||||
* New: Add sourceType to Program node (fixes #93) (Nicholas C. Zakas)
|
||||
* Allow spread in more places (fixes #89) (Nicholas C. Zakas)
|
||||
* Fix: Deeply nested template literals (fixes #86) (Nicholas C. Zakas)
|
||||
* Fix: Allow super in classes by default (fixes #87) (Nicholas C. Zakas)
|
||||
* Fix: generator methods in classes (fixes #85) (Jamund Ferguson)
|
||||
* Remove XJS note from Esprima-FB incompatibilities (Joe Lencioni)
|
||||
|
||||
v1.11.0 - March 7, 2015
|
||||
|
||||
* 1.11.0 (Nicholas C. Zakas)
|
||||
* Fix: Don't allow default export class by mistake (fixes #82) (Nicholas C. Zakas)
|
||||
* Fix: Export default function should be FunctionDeclaration (fixes #81) (Nicholas C. Zakas)
|
||||
* Fix: Ensure class declarations must have IDs outside of exports (refs #72) (Nicholas C. Zakas)
|
||||
* Fix: export class expression support (refs #72) (Jamund Ferguson)
|
||||
* Update: Add tests for sourceType=module (refs #72) (Nicholas C. Zakas)
|
||||
* Fix: Class name should be id (fixes #78) (Nicholas C. Zakas)
|
||||
* Fix: disallow import/export in functions (refs #72) (Jamund Ferguson)
|
||||
* Test: strict mode enforced in modules (refs #72) (Jamund Ferguson)
|
||||
* New: Add modules feature flag (refs #72) (Nicholas C. Zakas)
|
||||
* merging upstream and solving conflicts for PR #43 (Caridy Patino)
|
||||
* New: Add ES6 module support (fixes #35) (Caridy Patino)
|
||||
* Update: Add TryStatement.handler (fixes #69) (Brandon Mills)
|
||||
* Fix: Destructured Defaults (fixes #56) (Jamund Ferguson)
|
||||
* Update: Refactor out comment attachment logic (Nicholas C. Zakas)
|
||||
|
||||
v1.10.0 - March 1, 2015
|
||||
|
||||
* 1.10.0 (Nicholas C. Zakas)
|
||||
* New: Support ES6 classes (refs #10) (Nicholas C. Zakas)
|
||||
* Docs: Update README.md (Jamund Ferguson)
|
||||
|
||||
v1.9.1 - February 21, 2015
|
||||
|
||||
* 1.9.1 (Nicholas C. Zakas)
|
||||
* Fix: Allow let/const in switchcase (fixes #54) (Nicholas C. Zakas)
|
||||
|
||||
v1.9.0 - February 21, 2015
|
||||
|
||||
* 1.9.0 (Nicholas C. Zakas)
|
||||
* Fix: Extend property method range and loc to include params (fixes #36) (Brandon Mills)
|
||||
* New: spread operator (refs #10) (Jamund Ferguson)
|
||||
* Fix: incorrectly parsed arrow fragment (refs #58) (Jamund Ferguson)
|
||||
* New: Rest Parameter (refs: #10) (Jamund Ferguson)
|
||||
* New: Destructuring (refs #10) (Jamund Ferguson)
|
||||
|
||||
v1.8.1 - February 7, 2015
|
||||
|
||||
* 1.8.1 (Nicholas C. Zakas)
|
||||
* Build: Add Node.js 0.12 testing (Nicholas C. Zakas)
|
||||
* Fix: Actuall fix tokenization issue with templates (fixes #44) (Nicholas C. Zakas)
|
||||
|
||||
v1.8.0 - February 6, 2015
|
||||
|
||||
* 1.8.0 (Nicholas C. Zakas)
|
||||
* New: Support for Arrow Functions (refs #10) (Jamund Ferguson)
|
||||
* New: Allow super references in functions (refs #10) (Nicholas C. Zakas)
|
||||
* Update create-test.js (Jamund Ferguson)
|
||||
* Fix: Tokenization for template strings (fixes #44) (Nicholas C. Zakas)
|
||||
* New: Allow return in global scope (fixes #46) (Nicholas C. Zakas)
|
||||
|
||||
v1.7.1 - January 23, 2015
|
||||
|
||||
* 1.7.1 (Nicholas C. Zakas)
|
||||
* Fix: When ecmaFeatures.forOf is true, check for operater is "undefined" when match keyword is "in" (fixes #39) (Peter Chanthamynavong)
|
||||
|
||||
v1.7.0 - January 23, 2015
|
||||
|
||||
* 1.7.0 (Nicholas C. Zakas)
|
||||
* New: Add support for template strings (FredKSchott)
|
||||
* New: Add support for default parameters (refs #10) (Jamund Ferguson)
|
||||
* New: Add support for unicode code point escape sequences (FredKSchott)
|
||||
|
||||
v1.6.0 - January 10, 2015
|
||||
|
||||
* 1.6.0 (Nicholas C. Zakas)
|
||||
* Update: Make comment attachment tests look at whole AST (Nicholas C. Zakas)
|
||||
* Docs: Update README to reflect feature flags (Nicholas C. Zakas)
|
||||
* Docs: Add a couple more FAQs to README (Nicholas C. Zakas)
|
||||
* New: Add support for duplicate object literal properties (FredKSchott)
|
||||
* New: Implement generators (refs #10) (Nicholas C. Zakas)
|
||||
|
||||
v1.5.0 - December 29, 2014
|
||||
|
||||
* 1.5.0 (Nicholas C. Zakas)
|
||||
* Docs: Update README with compat info (Nicholas C. Zakas)
|
||||
* Update: Add regex parsing test (Nicholas C. Zakas)
|
||||
* Update: s/XJS/JSX/g (Nicholas C. Zakas)
|
||||
* Build: Update release script (Nicholas C. Zakas)
|
||||
* Update: Move SyntaxTree to ast-node-factory.js (FredKSchott)
|
||||
* New: Add JSX parsing (fixes #26) (Nicholas C. Zakas)
|
||||
* Update: Switch location marker logic (fixes #15) (Nicholas C. Zakas)
|
||||
* 1.4.0 (Nicholas C. Zakas)
|
||||
|
||||
v1.4.0 - December 23, 2014
|
||||
|
||||
* 1.4.0 (Nicholas C. Zakas)
|
||||
* Fix: Parsing issues with property methods (fixes #21) (Nicholas C. Zakas)
|
||||
* New: Add support for shorthand properties (refs #10) (Nicholas C. Zakas)
|
||||
* New: Add support for object literal method shorthand (refs #10) (Nicholas C. Zakas)
|
||||
* Fix: Ensure comments are attached for return (fixes #2) (Nicholas C. Zakas)
|
||||
* Build: Ensure CHANGELOG.md is committed on release (Nicholas C. Zakas)
|
||||
* 1.3.1 (Nicholas C. Zakas)
|
||||
|
||||
v1.3.1 - December 22, 2014
|
||||
|
||||
* 1.3.1 (Nicholas C. Zakas)
|
||||
* Fix: Add all files to npm package (fixes #17) (Nicholas C. Zakas)
|
||||
* Update: Move Messages to separate file (Nicholas C. Zakas)
|
||||
* Docs: Removed unnecessary comment (Nicholas C. Zakas)
|
||||
* 1.3.0 (Nicholas C. Zakas)
|
||||
|
||||
v1.3.0 - December 21, 2014
|
||||
|
||||
* 1.3.0 (Nicholas C. Zakas)
|
||||
* Build: Add release scripts (Nicholas C. Zakas)
|
||||
* New: Add computed object literal properties (refs #10) (Nicholas C. Zakas)
|
||||
* Build: Fix commands in Makefile.js (Nicholas C. Zakas)
|
||||
* Docs: Add FAQ to README (Nicholas C. Zakas)
|
||||
* Fix: Don't allow let/const in for loops (fixes #14) (Nicholas C. Zakas)
|
||||
* New: Support for-of loops (refs #10) (Nicholas C. Zakas)
|
||||
* Update: Change .ast.js files to .result.js files (Nicholas C. Zakas)
|
||||
* New: Support ES6 octal literals (Nicholas C. Zakas)
|
||||
* New: Ability to parse binary literals (Nicholas C. Zakas)
|
||||
* Update: More tests for regex u flag (Nicholas C. Zakas)
|
||||
* Update: Switch to using ecmaFeatures (Nicholas C. Zakas)
|
||||
* Update: Add comment attachment tests (Nicholas C. Zakas)
|
||||
* Update README.md (Jamund Ferguson)
|
||||
* New: Add u and y regex flags (refs #10) (Nicholas C. Zakas)
|
||||
* Update: Cleanup tests (Nicholas C. Zakas)
|
||||
* New: Add ecmascript flag (fixes #7) (Nicholas C. Zakas)
|
||||
* Docs: Update README with build commands (Nicholas C. Zakas)
|
||||
* Update: Move some things around (Nicholas C. Zakas)
|
||||
* Update: Read version number from package.json (Nicholas C. Zakas)
|
||||
* Update: Move AST node types to separate file (Nicholas C. Zakas)
|
||||
* Update: Remove duplicate file (Nicholas C. Zakas)
|
||||
* Update: Move token information to a separate file (Nicholas C. Zakas)
|
||||
* Update: Bring in Makefile.js for linting and browserify (Nicholas C. Zakas)
|
||||
* Update: Fix ESLint warnings, remove check-version (Nicholas C. Zakas)
|
||||
* Update: Move Position and SourceLocation to separate file (Nicholas C. Zakas)
|
||||
* Update: Move syntax checks into separate file (Nicholas C. Zakas)
|
||||
* Update: Remove UMD format (Nicholas C. Zakas)
|
||||
* Docs: Update README with more info (Nicholas C. Zakas)
|
||||
* Update: remove npm-debug.log from tracked files (Brandon Mills)
|
||||
* Docs: Remove redundant 'features' in readme (Matthias Oßwald)
|
||||
* Docs: Fix a link to Wikipedia (Ryuichi Okumura)
|
||||
* Update: Split parsing tests into smaller files (Nicholas C. Zakas)
|
||||
* Update: Normalize values in tests (Nicholas C. Zakas)
|
||||
* Update: CommonJSify test file (Nicholas C. Zakas)
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) Open JS Foundation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
[](https://www.npmjs.com/package/espree)
|
||||
[](https://travis-ci.org/eslint/espree)
|
||||
[](https://www.npmjs.com/package/espree)
|
||||
[](https://www.bountysource.com/trackers/9348450-eslint?utm_source=9348450&utm_medium=shield&utm_campaign=TRACKER_BADGE)
|
||||
|
||||
# Espree
|
||||
|
||||
Espree started out as a fork of [Esprima](http://esprima.org) v1.2.2, the last stable published released of Esprima before work on ECMAScript 6 began. Espree is now built on top of [Acorn](https://github.com/ternjs/acorn), which has a modular architecture that allows extension of core functionality. The goal of Espree is to produce output that is similar to Esprima with a similar API so that it can be used in place of Esprima.
|
||||
|
||||
## Usage
|
||||
|
||||
Install:
|
||||
|
||||
```
|
||||
npm i espree
|
||||
```
|
||||
|
||||
And in your Node.js code:
|
||||
|
||||
```javascript
|
||||
const espree = require("espree");
|
||||
|
||||
const ast = espree.parse(code);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
### `parse()`
|
||||
|
||||
`parse` parses the given code and returns a abstract syntax tree (AST). It takes two parameters.
|
||||
|
||||
- `code` [string]() - the code which needs to be parsed.
|
||||
- `options (Optional)` [Object]() - read more about this [here](#options).
|
||||
|
||||
```javascript
|
||||
const espree = require("espree");
|
||||
|
||||
const ast = espree.parse(code, options);
|
||||
```
|
||||
|
||||
**Example :**
|
||||
|
||||
```js
|
||||
const ast = espree.parse('let foo = "bar"', { ecmaVersion: 6 });
|
||||
console.log(ast);
|
||||
```
|
||||
|
||||
<details><summary>Output</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
Node {
|
||||
type: 'Program',
|
||||
start: 0,
|
||||
end: 15,
|
||||
body: [
|
||||
Node {
|
||||
type: 'VariableDeclaration',
|
||||
start: 0,
|
||||
end: 15,
|
||||
declarations: [Array],
|
||||
kind: 'let'
|
||||
}
|
||||
],
|
||||
sourceType: 'script'
|
||||
}
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
### `tokenize()`
|
||||
|
||||
`tokenize` returns the tokens of a given code. It takes two parameters.
|
||||
|
||||
- `code` [string]() - the code which needs to be parsed.
|
||||
- `options (Optional)` [Object]() - read more about this [here](#options).
|
||||
|
||||
Even if `options` is empty or undefined or `options.tokens` is `false`, it assigns it to `true` in order to get the `tokens` array
|
||||
|
||||
**Example :**
|
||||
|
||||
```js
|
||||
const tokens = espree.tokenize('let foo = "bar"', { ecmaVersion: 6 });
|
||||
console.log(tokens);
|
||||
```
|
||||
|
||||
<details><summary>Output</summary>
|
||||
<p>
|
||||
|
||||
```
|
||||
Token { type: 'Keyword', value: 'let', start: 0, end: 3 },
|
||||
Token { type: 'Identifier', value: 'foo', start: 4, end: 7 },
|
||||
Token { type: 'Punctuator', value: '=', start: 8, end: 9 },
|
||||
Token { type: 'String', value: '"bar"', start: 10, end: 15 }
|
||||
```
|
||||
|
||||
</p>
|
||||
</details>
|
||||
|
||||
### `version`
|
||||
|
||||
Returns the current `espree` version
|
||||
|
||||
### `VisitorKeys`
|
||||
|
||||
Returns all visitor keys for traversing the AST from [eslint-visitor-keys](https://github.com/eslint/eslint-visitor-keys)
|
||||
|
||||
### `latestEcmaVersion`
|
||||
|
||||
Returns the latest ECMAScript supported by `espree`
|
||||
|
||||
### `supportedEcmaVersions`
|
||||
|
||||
Returns an array of all supported ECMAScript versions
|
||||
|
||||
## Options
|
||||
|
||||
```js
|
||||
const options = {
|
||||
// attach range information to each node
|
||||
range: false,
|
||||
|
||||
// attach line/column location information to each node
|
||||
loc: false,
|
||||
|
||||
// create a top-level comments array containing all comments
|
||||
comment: false,
|
||||
|
||||
// create a top-level tokens array containing all tokens
|
||||
tokens: false,
|
||||
|
||||
// Set to 3, 5 (default), 6, 7, 8, 9, 10, 11, or 12 to specify the version of ECMAScript syntax you want to use.
|
||||
// You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), 2018 (same as 9), 2019 (same as 10), 2020 (same as 11), or 2021 (same as 12) to use the year-based naming.
|
||||
ecmaVersion: 5,
|
||||
|
||||
// specify which type of script you're parsing ("script" or "module")
|
||||
sourceType: "script",
|
||||
|
||||
// specify additional language features
|
||||
ecmaFeatures: {
|
||||
|
||||
// enable JSX parsing
|
||||
jsx: false,
|
||||
|
||||
// enable return in global scope
|
||||
globalReturn: false,
|
||||
|
||||
// enable implied strict mode (if ecmaVersion >= 5)
|
||||
impliedStrict: false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Esprima Compatibility Going Forward
|
||||
|
||||
The primary goal is to produce the exact same AST structure and tokens as Esprima, and that takes precedence over anything else. (The AST structure being the [ESTree](https://github.com/estree/estree) API with JSX extensions.) Separate from that, Espree may deviate from what Esprima outputs in terms of where and how comments are attached, as well as what additional information is available on AST nodes. That is to say, Espree may add more things to the AST nodes than Esprima does but the overall AST structure produced will be the same.
|
||||
|
||||
Espree may also deviate from Esprima in the interface it exposes.
|
||||
|
||||
## Contributing
|
||||
|
||||
Issues and pull requests will be triaged and responded to as quickly as possible. We operate under the [ESLint Contributor Guidelines](http://eslint.org/docs/developer-guide/contributing), so please be sure to read them before contributing. If you're not sure where to dig in, check out the [issues](https://github.com/eslint/espree/issues).
|
||||
|
||||
Espree is licensed under a permissive BSD 2-clause license.
|
||||
|
||||
## Security Policy
|
||||
|
||||
We work hard to ensure that Espree is safe for everyone and that security issues are addressed quickly and responsibly. Read the full [security policy](https://github.com/eslint/.github/blob/master/SECURITY.md).
|
||||
|
||||
## Build Commands
|
||||
|
||||
* `npm test` - run all linting and tests
|
||||
* `npm run lint` - run all linting
|
||||
* `npm run browserify` - creates a version of Espree that is usable in a browser
|
||||
|
||||
## Differences from Espree 2.x
|
||||
|
||||
* The `tokenize()` method does not use `ecmaFeatures`. Any string will be tokenized completely based on ECMAScript 6 semantics.
|
||||
* Trailing whitespace no longer is counted as part of a node.
|
||||
* `let` and `const` declarations are no longer parsed by default. You must opt-in by using an `ecmaVersion` newer than `5` or setting `sourceType` to `module`.
|
||||
* The `esparse` and `esvalidate` binary scripts have been removed.
|
||||
* There is no `tolerant` option. We will investigate adding this back in the future.
|
||||
|
||||
## Known Incompatibilities
|
||||
|
||||
In an effort to help those wanting to transition from other parsers to Espree, the following is a list of noteworthy incompatibilities with other parsers. These are known differences that we do not intend to change.
|
||||
|
||||
### Esprima 1.2.2
|
||||
|
||||
* Esprima counts trailing whitespace as part of each AST node while Espree does not. In Espree, the end of a node is where the last token occurs.
|
||||
* Espree does not parse `let` and `const` declarations by default.
|
||||
* Error messages returned for parsing errors are different.
|
||||
* There are two addition properties on every node and token: `start` and `end`. These represent the same data as `range` and are used internally by Acorn.
|
||||
|
||||
### Esprima 2.x
|
||||
|
||||
* Esprima 2.x uses a different comment attachment algorithm that results in some comments being added in different places than Espree. The algorithm Espree uses is the same one used in Esprima 1.2.2.
|
||||
|
||||
## Frequently Asked Questions
|
||||
|
||||
### Why another parser
|
||||
|
||||
[ESLint](http://eslint.org) had been relying on Esprima as its parser from the beginning. While that was fine when the JavaScript language was evolving slowly, the pace of development increased dramatically and Esprima had fallen behind. ESLint, like many other tools reliant on Esprima, has been stuck in using new JavaScript language features until Esprima updates, and that caused our users frustration.
|
||||
|
||||
We decided the only way for us to move forward was to create our own parser, bringing us inline with JSHint and JSLint, and allowing us to keep implementing new features as we need them. We chose to fork Esprima instead of starting from scratch in order to move as quickly as possible with a compatible API.
|
||||
|
||||
With Espree 2.0.0, we are no longer a fork of Esprima but rather a translation layer between Acorn and Esprima syntax. This allows us to put work back into a community-supported parser (Acorn) that is continuing to grow and evolve while maintaining an Esprima-compatible parser for those utilities still built on Esprima.
|
||||
|
||||
### Have you tried working with Esprima?
|
||||
|
||||
Yes. Since the start of ESLint, we've regularly filed bugs and feature requests with Esprima and will continue to do so. However, there are some different philosophies around how the projects work that need to be worked through. The initial goal was to have Espree track Esprima and eventually merge the two back together, but we ultimately decided that building on top of Acorn was a better choice due to Acorn's plugin support.
|
||||
|
||||
### Why don't you just use Acorn?
|
||||
|
||||
Acorn is a great JavaScript parser that produces an AST that is compatible with Esprima. Unfortunately, ESLint relies on more than just the AST to do its job. It relies on Esprima's tokens and comment attachment features to get a complete picture of the source code. We investigated switching to Acorn, but the inconsistencies between Esprima and Acorn created too much work for a project like ESLint.
|
||||
|
||||
We are building on top of Acorn, however, so that we can contribute back and help make Acorn even better.
|
||||
|
||||
### What ECMAScript features do you support?
|
||||
|
||||
Espree supports all ECMAScript 2020 features and partially supports ECMAScript 2021 features.
|
||||
|
||||
Because ECMAScript 2021 is still under development, we are implementing features as they are finalized. Currently, Espree supports:
|
||||
|
||||
* [Logical Assignment Operators](https://github.com/tc39/proposal-logical-assignment)
|
||||
* [Numeric Separators](https://github.com/tc39/proposal-numeric-separator)
|
||||
|
||||
See [finished-proposals.md](https://github.com/tc39/proposals/blob/master/finished-proposals.md) to know what features are finalized.
|
||||
|
||||
### How do you determine which experimental features to support?
|
||||
|
||||
In general, we do not support experimental JavaScript features. We may make exceptions from time to time depending on the maturity of the features.
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
/**
|
||||
* @fileoverview Main Espree file that converts Acorn into Esprima output.
|
||||
*
|
||||
* This file contains code from the following MIT-licensed projects:
|
||||
* 1. Acorn
|
||||
* 2. Babylon
|
||||
* 3. Babel-ESLint
|
||||
*
|
||||
* This file also contains code from Esprima, which is BSD licensed.
|
||||
*
|
||||
* Acorn is Copyright 2012-2015 Acorn Contributors (https://github.com/marijnh/acorn/blob/master/AUTHORS)
|
||||
* Babylon is Copyright 2014-2015 various contributors (https://github.com/babel/babel/blob/master/packages/babylon/AUTHORS)
|
||||
* Babel-ESLint is Copyright 2014-2015 Sebastian McKenzie <sebmck@gmail.com>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Esprima is Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/* eslint no-undefined:0, no-use-before-define: 0 */
|
||||
|
||||
"use strict";
|
||||
|
||||
const acorn = require("acorn");
|
||||
const jsx = require("acorn-jsx");
|
||||
const astNodeTypes = require("./lib/ast-node-types");
|
||||
const espree = require("./lib/espree");
|
||||
const { getLatestEcmaVersion, getSupportedEcmaVersions } = require("./lib/options");
|
||||
|
||||
// To initialize lazily.
|
||||
const parsers = {
|
||||
_regular: null,
|
||||
_jsx: null,
|
||||
|
||||
get regular() {
|
||||
if (this._regular === null) {
|
||||
this._regular = acorn.Parser.extend(espree());
|
||||
}
|
||||
return this._regular;
|
||||
},
|
||||
|
||||
get jsx() {
|
||||
if (this._jsx === null) {
|
||||
this._jsx = acorn.Parser.extend(jsx(), espree());
|
||||
}
|
||||
return this._jsx;
|
||||
},
|
||||
|
||||
get(options) {
|
||||
const useJsx = Boolean(
|
||||
options &&
|
||||
options.ecmaFeatures &&
|
||||
options.ecmaFeatures.jsx
|
||||
);
|
||||
|
||||
return useJsx ? this.jsx : this.regular;
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Tokenizer
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Tokenizes the given code.
|
||||
* @param {string} code The code to tokenize.
|
||||
* @param {Object} options Options defining how to tokenize.
|
||||
* @returns {Token[]} An array of tokens.
|
||||
* @throws {SyntaxError} If the input code is invalid.
|
||||
* @private
|
||||
*/
|
||||
function tokenize(code, options) {
|
||||
const Parser = parsers.get(options);
|
||||
|
||||
// Ensure to collect tokens.
|
||||
if (!options || options.tokens !== true) {
|
||||
options = Object.assign({}, options, { tokens: true }); // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
return new Parser(options, code).tokenize();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Parser
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Parses the given code.
|
||||
* @param {string} code The code to tokenize.
|
||||
* @param {Object} options Options defining how to tokenize.
|
||||
* @returns {ASTNode} The "Program" AST node.
|
||||
* @throws {SyntaxError} If the input code is invalid.
|
||||
*/
|
||||
function parse(code, options) {
|
||||
const Parser = parsers.get(options);
|
||||
|
||||
return new Parser(options, code).parse();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
exports.version = require("./package.json").version;
|
||||
|
||||
exports.tokenize = tokenize;
|
||||
|
||||
exports.parse = parse;
|
||||
|
||||
// Deep copy.
|
||||
/* istanbul ignore next */
|
||||
exports.Syntax = (function() {
|
||||
let name,
|
||||
types = {};
|
||||
|
||||
if (typeof Object.create === "function") {
|
||||
types = Object.create(null);
|
||||
}
|
||||
|
||||
for (name in astNodeTypes) {
|
||||
if (Object.hasOwnProperty.call(astNodeTypes, name)) {
|
||||
types[name] = astNodeTypes[name];
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof Object.freeze === "function") {
|
||||
Object.freeze(types);
|
||||
}
|
||||
|
||||
return types;
|
||||
}());
|
||||
|
||||
/* istanbul ignore next */
|
||||
exports.VisitorKeys = (function() {
|
||||
return require("eslint-visitor-keys").KEYS;
|
||||
}());
|
||||
|
||||
exports.latestEcmaVersion = getLatestEcmaVersion();
|
||||
|
||||
exports.supportedEcmaVersions = getSupportedEcmaVersions();
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @fileoverview The AST node types produced by the parser.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// None!
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
AssignmentExpression: "AssignmentExpression",
|
||||
AssignmentPattern: "AssignmentPattern",
|
||||
ArrayExpression: "ArrayExpression",
|
||||
ArrayPattern: "ArrayPattern",
|
||||
ArrowFunctionExpression: "ArrowFunctionExpression",
|
||||
AwaitExpression: "AwaitExpression",
|
||||
BlockStatement: "BlockStatement",
|
||||
BinaryExpression: "BinaryExpression",
|
||||
BreakStatement: "BreakStatement",
|
||||
CallExpression: "CallExpression",
|
||||
CatchClause: "CatchClause",
|
||||
ClassBody: "ClassBody",
|
||||
ClassDeclaration: "ClassDeclaration",
|
||||
ClassExpression: "ClassExpression",
|
||||
ConditionalExpression: "ConditionalExpression",
|
||||
ContinueStatement: "ContinueStatement",
|
||||
DoWhileStatement: "DoWhileStatement",
|
||||
DebuggerStatement: "DebuggerStatement",
|
||||
EmptyStatement: "EmptyStatement",
|
||||
ExpressionStatement: "ExpressionStatement",
|
||||
ForStatement: "ForStatement",
|
||||
ForInStatement: "ForInStatement",
|
||||
ForOfStatement: "ForOfStatement",
|
||||
FunctionDeclaration: "FunctionDeclaration",
|
||||
FunctionExpression: "FunctionExpression",
|
||||
Identifier: "Identifier",
|
||||
IfStatement: "IfStatement",
|
||||
Literal: "Literal",
|
||||
LabeledStatement: "LabeledStatement",
|
||||
LogicalExpression: "LogicalExpression",
|
||||
MemberExpression: "MemberExpression",
|
||||
MetaProperty: "MetaProperty",
|
||||
MethodDefinition: "MethodDefinition",
|
||||
NewExpression: "NewExpression",
|
||||
ObjectExpression: "ObjectExpression",
|
||||
ObjectPattern: "ObjectPattern",
|
||||
Program: "Program",
|
||||
Property: "Property",
|
||||
RestElement: "RestElement",
|
||||
ReturnStatement: "ReturnStatement",
|
||||
SequenceExpression: "SequenceExpression",
|
||||
SpreadElement: "SpreadElement",
|
||||
Super: "Super",
|
||||
SwitchCase: "SwitchCase",
|
||||
SwitchStatement: "SwitchStatement",
|
||||
TaggedTemplateExpression: "TaggedTemplateExpression",
|
||||
TemplateElement: "TemplateElement",
|
||||
TemplateLiteral: "TemplateLiteral",
|
||||
ThisExpression: "ThisExpression",
|
||||
ThrowStatement: "ThrowStatement",
|
||||
TryStatement: "TryStatement",
|
||||
UnaryExpression: "UnaryExpression",
|
||||
UpdateExpression: "UpdateExpression",
|
||||
VariableDeclaration: "VariableDeclaration",
|
||||
VariableDeclarator: "VariableDeclarator",
|
||||
WhileStatement: "WhileStatement",
|
||||
WithStatement: "WithStatement",
|
||||
YieldExpression: "YieldExpression",
|
||||
JSXIdentifier: "JSXIdentifier",
|
||||
JSXNamespacedName: "JSXNamespacedName",
|
||||
JSXMemberExpression: "JSXMemberExpression",
|
||||
JSXEmptyExpression: "JSXEmptyExpression",
|
||||
JSXExpressionContainer: "JSXExpressionContainer",
|
||||
JSXElement: "JSXElement",
|
||||
JSXClosingElement: "JSXClosingElement",
|
||||
JSXOpeningElement: "JSXOpeningElement",
|
||||
JSXAttribute: "JSXAttribute",
|
||||
JSXSpreadAttribute: "JSXSpreadAttribute",
|
||||
JSXText: "JSXText",
|
||||
ExportDefaultDeclaration: "ExportDefaultDeclaration",
|
||||
ExportNamedDeclaration: "ExportNamedDeclaration",
|
||||
ExportAllDeclaration: "ExportAllDeclaration",
|
||||
ExportSpecifier: "ExportSpecifier",
|
||||
ImportDeclaration: "ImportDeclaration",
|
||||
ImportSpecifier: "ImportSpecifier",
|
||||
ImportDefaultSpecifier: "ImportDefaultSpecifier",
|
||||
ImportNamespaceSpecifier: "ImportNamespaceSpecifier"
|
||||
};
|
||||
+286
@@ -0,0 +1,286 @@
|
||||
"use strict";
|
||||
|
||||
/* eslint-disable no-param-reassign*/
|
||||
const TokenTranslator = require("./token-translator");
|
||||
const { normalizeOptions } = require("./options");
|
||||
|
||||
const STATE = Symbol("espree's internal state");
|
||||
const ESPRIMA_FINISH_NODE = Symbol("espree's esprimaFinishNode");
|
||||
|
||||
|
||||
/**
|
||||
* Converts an Acorn comment to a Esprima comment.
|
||||
* @param {boolean} block True if it's a block comment, false if not.
|
||||
* @param {string} text The text of the comment.
|
||||
* @param {int} start The index at which the comment starts.
|
||||
* @param {int} end The index at which the comment ends.
|
||||
* @param {Location} startLoc The location at which the comment starts.
|
||||
* @param {Location} endLoc The location at which the comment ends.
|
||||
* @returns {Object} The comment object.
|
||||
* @private
|
||||
*/
|
||||
function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc) {
|
||||
const comment = {
|
||||
type: block ? "Block" : "Line",
|
||||
value: text
|
||||
};
|
||||
|
||||
if (typeof start === "number") {
|
||||
comment.start = start;
|
||||
comment.end = end;
|
||||
comment.range = [start, end];
|
||||
}
|
||||
|
||||
if (typeof startLoc === "object") {
|
||||
comment.loc = {
|
||||
start: startLoc,
|
||||
end: endLoc
|
||||
};
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
module.exports = () => Parser => {
|
||||
const tokTypes = Object.assign({}, Parser.acorn.tokTypes);
|
||||
|
||||
if (Parser.acornJsx) {
|
||||
Object.assign(tokTypes, Parser.acornJsx.tokTypes);
|
||||
}
|
||||
|
||||
return class Espree extends Parser {
|
||||
constructor(opts, code) {
|
||||
if (typeof opts !== "object" || opts === null) {
|
||||
opts = {};
|
||||
}
|
||||
if (typeof code !== "string" && !(code instanceof String)) {
|
||||
code = String(code);
|
||||
}
|
||||
|
||||
const options = normalizeOptions(opts);
|
||||
const ecmaFeatures = options.ecmaFeatures || {};
|
||||
const tokenTranslator =
|
||||
options.tokens === true
|
||||
? new TokenTranslator(tokTypes, code)
|
||||
: null;
|
||||
|
||||
// Initialize acorn parser.
|
||||
super({
|
||||
|
||||
// TODO: use {...options} when spread is supported(Node.js >= 8.3.0).
|
||||
ecmaVersion: options.ecmaVersion,
|
||||
sourceType: options.sourceType,
|
||||
ranges: options.ranges,
|
||||
locations: options.locations,
|
||||
|
||||
// Truthy value is true for backward compatibility.
|
||||
allowReturnOutsideFunction: Boolean(ecmaFeatures.globalReturn),
|
||||
|
||||
// Collect tokens
|
||||
onToken: token => {
|
||||
if (tokenTranslator) {
|
||||
|
||||
// Use `tokens`, `ecmaVersion`, and `jsxAttrValueToken` in the state.
|
||||
tokenTranslator.onToken(token, this[STATE]);
|
||||
}
|
||||
if (token.type !== tokTypes.eof) {
|
||||
this[STATE].lastToken = token;
|
||||
}
|
||||
},
|
||||
|
||||
// Collect comments
|
||||
onComment: (block, text, start, end, startLoc, endLoc) => {
|
||||
if (this[STATE].comments) {
|
||||
const comment = convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc);
|
||||
|
||||
this[STATE].comments.push(comment);
|
||||
}
|
||||
}
|
||||
}, code);
|
||||
|
||||
// Initialize internal state.
|
||||
this[STATE] = {
|
||||
tokens: tokenTranslator ? [] : null,
|
||||
comments: options.comment === true ? [] : null,
|
||||
impliedStrict: ecmaFeatures.impliedStrict === true && this.options.ecmaVersion >= 5,
|
||||
ecmaVersion: this.options.ecmaVersion,
|
||||
jsxAttrValueToken: false,
|
||||
lastToken: null
|
||||
};
|
||||
}
|
||||
|
||||
tokenize() {
|
||||
do {
|
||||
this.next();
|
||||
} while (this.type !== tokTypes.eof);
|
||||
|
||||
// Consume the final eof token
|
||||
this.next();
|
||||
|
||||
const extra = this[STATE];
|
||||
const tokens = extra.tokens;
|
||||
|
||||
if (extra.comments) {
|
||||
tokens.comments = extra.comments;
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
finishNode(...args) {
|
||||
const result = super.finishNode(...args);
|
||||
|
||||
return this[ESPRIMA_FINISH_NODE](result);
|
||||
}
|
||||
|
||||
finishNodeAt(...args) {
|
||||
const result = super.finishNodeAt(...args);
|
||||
|
||||
return this[ESPRIMA_FINISH_NODE](result);
|
||||
}
|
||||
|
||||
parse() {
|
||||
const extra = this[STATE];
|
||||
const program = super.parse();
|
||||
|
||||
program.sourceType = this.options.sourceType;
|
||||
|
||||
if (extra.comments) {
|
||||
program.comments = extra.comments;
|
||||
}
|
||||
if (extra.tokens) {
|
||||
program.tokens = extra.tokens;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust opening and closing position of program to match Esprima.
|
||||
* Acorn always starts programs at range 0 whereas Esprima starts at the
|
||||
* first AST node's start (the only real difference is when there's leading
|
||||
* whitespace or leading comments). Acorn also counts trailing whitespace
|
||||
* as part of the program whereas Esprima only counts up to the last token.
|
||||
*/
|
||||
if (program.range) {
|
||||
program.range[0] = program.body.length ? program.body[0].range[0] : program.range[0];
|
||||
program.range[1] = extra.lastToken ? extra.lastToken.range[1] : program.range[1];
|
||||
}
|
||||
if (program.loc) {
|
||||
program.loc.start = program.body.length ? program.body[0].loc.start : program.loc.start;
|
||||
program.loc.end = extra.lastToken ? extra.lastToken.loc.end : program.loc.end;
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
parseTopLevel(node) {
|
||||
if (this[STATE].impliedStrict) {
|
||||
this.strict = true;
|
||||
}
|
||||
return super.parseTopLevel(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default raise method to throw Esprima-style errors.
|
||||
* @param {int} pos The position of the error.
|
||||
* @param {string} message The error message.
|
||||
* @throws {SyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
raise(pos, message) {
|
||||
const loc = Parser.acorn.getLineInfo(this.input, pos);
|
||||
const err = new SyntaxError(message);
|
||||
|
||||
err.index = pos;
|
||||
err.lineNumber = loc.line;
|
||||
err.column = loc.column + 1; // acorn uses 0-based columns
|
||||
throw err;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default raise method to throw Esprima-style errors.
|
||||
* @param {int} pos The position of the error.
|
||||
* @param {string} message The error message.
|
||||
* @throws {SyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
raiseRecoverable(pos, message) {
|
||||
this.raise(pos, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the default unexpected method to throw Esprima-style errors.
|
||||
* @param {int} pos The position of the error.
|
||||
* @throws {SyntaxError} A syntax error.
|
||||
* @returns {void}
|
||||
*/
|
||||
unexpected(pos) {
|
||||
let message = "Unexpected token";
|
||||
|
||||
if (pos !== null && pos !== void 0) {
|
||||
this.pos = pos;
|
||||
|
||||
if (this.options.locations) {
|
||||
while (this.pos < this.lineStart) {
|
||||
this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
|
||||
--this.curLine;
|
||||
}
|
||||
}
|
||||
|
||||
this.nextToken();
|
||||
}
|
||||
|
||||
if (this.end > this.start) {
|
||||
message += ` ${this.input.slice(this.start, this.end)}`;
|
||||
}
|
||||
|
||||
this.raise(this.start, message);
|
||||
}
|
||||
|
||||
/*
|
||||
* Esprima-FB represents JSX strings as tokens called "JSXText", but Acorn-JSX
|
||||
* uses regular tt.string without any distinction between this and regular JS
|
||||
* strings. As such, we intercept an attempt to read a JSX string and set a flag
|
||||
* on extra so that when tokens are converted, the next token will be switched
|
||||
* to JSXText via onToken.
|
||||
*/
|
||||
jsx_readString(quote) { // eslint-disable-line camelcase
|
||||
const result = super.jsx_readString(quote);
|
||||
|
||||
if (this.type === tokTypes.string) {
|
||||
this[STATE].jsxAttrValueToken = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs last-minute Esprima-specific compatibility checks and fixes.
|
||||
* @param {ASTNode} result The node to check.
|
||||
* @returns {ASTNode} The finished node.
|
||||
*/
|
||||
[ESPRIMA_FINISH_NODE](result) {
|
||||
|
||||
// Acorn doesn't count the opening and closing backticks as part of templates
|
||||
// so we have to adjust ranges/locations appropriately.
|
||||
if (result.type === "TemplateElement") {
|
||||
|
||||
// additional adjustment needed if ${ is the last token
|
||||
const terminalDollarBraceL = this.input.slice(result.end, result.end + 2) === "${";
|
||||
|
||||
if (result.range) {
|
||||
result.range[0]--;
|
||||
result.range[1] += (terminalDollarBraceL ? 2 : 1);
|
||||
}
|
||||
|
||||
if (result.loc) {
|
||||
result.loc.start.column--;
|
||||
result.loc.end.column += (terminalDollarBraceL ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.type.indexOf("Function") > -1 && !result.generator) {
|
||||
result.generator = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
};
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* @fileoverview The list of feature flags supported by the parser and their default
|
||||
* settings.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// None!
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
// React JSX parsing
|
||||
jsx: false,
|
||||
|
||||
// allow return statement in global scope
|
||||
globalReturn: false,
|
||||
|
||||
// allow implied strict mode
|
||||
impliedStrict: false
|
||||
};
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @fileoverview A collection of methods for processing Espree's options.
|
||||
* @author Kai Cataldo
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
const DEFAULT_ECMA_VERSION = 5;
|
||||
const SUPPORTED_VERSIONS = [
|
||||
3,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12
|
||||
];
|
||||
|
||||
/**
|
||||
* Normalize ECMAScript version from the initial config
|
||||
* @param {number} ecmaVersion ECMAScript version from the initial config
|
||||
* @throws {Error} throws an error if the ecmaVersion is invalid.
|
||||
* @returns {number} normalized ECMAScript version
|
||||
*/
|
||||
function normalizeEcmaVersion(ecmaVersion = DEFAULT_ECMA_VERSION) {
|
||||
if (typeof ecmaVersion !== "number") {
|
||||
throw new Error(`ecmaVersion must be a number. Received value of type ${typeof ecmaVersion} instead.`);
|
||||
}
|
||||
|
||||
let version = ecmaVersion;
|
||||
|
||||
// Calculate ECMAScript edition number from official year version starting with
|
||||
// ES2015, which corresponds with ES6 (or a difference of 2009).
|
||||
if (version >= 2015) {
|
||||
version -= 2009;
|
||||
}
|
||||
|
||||
if (!SUPPORTED_VERSIONS.includes(version)) {
|
||||
throw new Error("Invalid ecmaVersion.");
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize sourceType from the initial config
|
||||
* @param {string} sourceType to normalize
|
||||
* @throws {Error} throw an error if sourceType is invalid
|
||||
* @returns {string} normalized sourceType
|
||||
*/
|
||||
function normalizeSourceType(sourceType = "script") {
|
||||
if (sourceType === "script" || sourceType === "module") {
|
||||
return sourceType;
|
||||
}
|
||||
throw new Error("Invalid sourceType.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize parserOptions
|
||||
* @param {Object} options the parser options to normalize
|
||||
* @throws {Error} throw an error if found invalid option.
|
||||
* @returns {Object} normalized options
|
||||
*/
|
||||
function normalizeOptions(options) {
|
||||
const ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
|
||||
const sourceType = normalizeSourceType(options.sourceType);
|
||||
const ranges = options.range === true;
|
||||
const locations = options.loc === true;
|
||||
|
||||
if (sourceType === "module" && ecmaVersion < 6) {
|
||||
throw new Error("sourceType 'module' is not supported when ecmaVersion < 2015. Consider adding `{ ecmaVersion: 2015 }` to the parser options.");
|
||||
}
|
||||
return Object.assign({}, options, { ecmaVersion, sourceType, ranges, locations });
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest ECMAScript version supported by Espree.
|
||||
* @returns {number} The latest ECMAScript version.
|
||||
*/
|
||||
function getLatestEcmaVersion() {
|
||||
return SUPPORTED_VERSIONS[SUPPORTED_VERSIONS.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of ECMAScript versions supported by Espree.
|
||||
* @returns {number[]} An array containing the supported ECMAScript versions.
|
||||
*/
|
||||
function getSupportedEcmaVersions() {
|
||||
return [...SUPPORTED_VERSIONS];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
normalizeOptions,
|
||||
getLatestEcmaVersion,
|
||||
getSupportedEcmaVersions
|
||||
};
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* @fileoverview Translates tokens between Acorn format and Esprima format.
|
||||
* @author Nicholas C. Zakas
|
||||
*/
|
||||
/* eslint no-underscore-dangle: 0 */
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// none!
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Private
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// Esprima Token Types
|
||||
const Token = {
|
||||
Boolean: "Boolean",
|
||||
EOF: "<end>",
|
||||
Identifier: "Identifier",
|
||||
Keyword: "Keyword",
|
||||
Null: "Null",
|
||||
Numeric: "Numeric",
|
||||
Punctuator: "Punctuator",
|
||||
String: "String",
|
||||
RegularExpression: "RegularExpression",
|
||||
Template: "Template",
|
||||
JSXIdentifier: "JSXIdentifier",
|
||||
JSXText: "JSXText"
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts part of a template into an Esprima token.
|
||||
* @param {AcornToken[]} tokens The Acorn tokens representing the template.
|
||||
* @param {string} code The source code.
|
||||
* @returns {EsprimaToken} The Esprima equivalent of the template token.
|
||||
* @private
|
||||
*/
|
||||
function convertTemplatePart(tokens, code) {
|
||||
const firstToken = tokens[0],
|
||||
lastTemplateToken = tokens[tokens.length - 1];
|
||||
|
||||
const token = {
|
||||
type: Token.Template,
|
||||
value: code.slice(firstToken.start, lastTemplateToken.end)
|
||||
};
|
||||
|
||||
if (firstToken.loc) {
|
||||
token.loc = {
|
||||
start: firstToken.loc.start,
|
||||
end: lastTemplateToken.loc.end
|
||||
};
|
||||
}
|
||||
|
||||
if (firstToken.range) {
|
||||
token.start = firstToken.range[0];
|
||||
token.end = lastTemplateToken.range[1];
|
||||
token.range = [token.start, token.end];
|
||||
}
|
||||
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains logic to translate Acorn tokens into Esprima tokens.
|
||||
* @param {Object} acornTokTypes The Acorn token types.
|
||||
* @param {string} code The source code Acorn is parsing. This is necessary
|
||||
* to correct the "value" property of some tokens.
|
||||
* @constructor
|
||||
*/
|
||||
function TokenTranslator(acornTokTypes, code) {
|
||||
|
||||
// token types
|
||||
this._acornTokTypes = acornTokTypes;
|
||||
|
||||
// token buffer for templates
|
||||
this._tokens = [];
|
||||
|
||||
// track the last curly brace
|
||||
this._curlyBrace = null;
|
||||
|
||||
// the source code
|
||||
this._code = code;
|
||||
|
||||
}
|
||||
|
||||
TokenTranslator.prototype = {
|
||||
constructor: TokenTranslator,
|
||||
|
||||
/**
|
||||
* Translates a single Esprima token to a single Acorn token. This may be
|
||||
* inaccurate due to how templates are handled differently in Esprima and
|
||||
* Acorn, but should be accurate for all other tokens.
|
||||
* @param {AcornToken} token The Acorn token to translate.
|
||||
* @param {Object} extra Espree extra object.
|
||||
* @returns {EsprimaToken} The Esprima version of the token.
|
||||
*/
|
||||
translate(token, extra) {
|
||||
|
||||
const type = token.type,
|
||||
tt = this._acornTokTypes;
|
||||
|
||||
if (type === tt.name) {
|
||||
token.type = Token.Identifier;
|
||||
|
||||
// TODO: See if this is an Acorn bug
|
||||
if (token.value === "static") {
|
||||
token.type = Token.Keyword;
|
||||
}
|
||||
|
||||
if (extra.ecmaVersion > 5 && (token.value === "yield" || token.value === "let")) {
|
||||
token.type = Token.Keyword;
|
||||
}
|
||||
|
||||
} else if (type === tt.semi || type === tt.comma ||
|
||||
type === tt.parenL || type === tt.parenR ||
|
||||
type === tt.braceL || type === tt.braceR ||
|
||||
type === tt.dot || type === tt.bracketL ||
|
||||
type === tt.colon || type === tt.question ||
|
||||
type === tt.bracketR || type === tt.ellipsis ||
|
||||
type === tt.arrow || type === tt.jsxTagStart ||
|
||||
type === tt.incDec || type === tt.starstar ||
|
||||
type === tt.jsxTagEnd || type === tt.prefix ||
|
||||
type === tt.questionDot ||
|
||||
(type.binop && !type.keyword) ||
|
||||
type.isAssign) {
|
||||
|
||||
token.type = Token.Punctuator;
|
||||
token.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.jsxName) {
|
||||
token.type = Token.JSXIdentifier;
|
||||
} else if (type.label === "jsxText" || type === tt.jsxAttrValueToken) {
|
||||
token.type = Token.JSXText;
|
||||
} else if (type.keyword) {
|
||||
if (type.keyword === "true" || type.keyword === "false") {
|
||||
token.type = Token.Boolean;
|
||||
} else if (type.keyword === "null") {
|
||||
token.type = Token.Null;
|
||||
} else {
|
||||
token.type = Token.Keyword;
|
||||
}
|
||||
} else if (type === tt.num) {
|
||||
token.type = Token.Numeric;
|
||||
token.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.string) {
|
||||
|
||||
if (extra.jsxAttrValueToken) {
|
||||
extra.jsxAttrValueToken = false;
|
||||
token.type = Token.JSXText;
|
||||
} else {
|
||||
token.type = Token.String;
|
||||
}
|
||||
|
||||
token.value = this._code.slice(token.start, token.end);
|
||||
} else if (type === tt.regexp) {
|
||||
token.type = Token.RegularExpression;
|
||||
const value = token.value;
|
||||
|
||||
token.regex = {
|
||||
flags: value.flags,
|
||||
pattern: value.pattern
|
||||
};
|
||||
token.value = `/${value.pattern}/${value.flags}`;
|
||||
}
|
||||
|
||||
return token;
|
||||
},
|
||||
|
||||
/**
|
||||
* Function to call during Acorn's onToken handler.
|
||||
* @param {AcornToken} token The Acorn token.
|
||||
* @param {Object} extra The Espree extra object.
|
||||
* @returns {void}
|
||||
*/
|
||||
onToken(token, extra) {
|
||||
|
||||
const that = this,
|
||||
tt = this._acornTokTypes,
|
||||
tokens = extra.tokens,
|
||||
templateTokens = this._tokens;
|
||||
|
||||
/**
|
||||
* Flushes the buffered template tokens and resets the template
|
||||
* tracking.
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
function translateTemplateTokens() {
|
||||
tokens.push(convertTemplatePart(that._tokens, that._code));
|
||||
that._tokens = [];
|
||||
}
|
||||
|
||||
if (token.type === tt.eof) {
|
||||
|
||||
// might be one last curlyBrace
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.type === tt.backQuote) {
|
||||
|
||||
// if there's already a curly, it's not part of the template
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
templateTokens.push(token);
|
||||
|
||||
// it's the end
|
||||
if (templateTokens.length > 1) {
|
||||
translateTemplateTokens();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.dollarBraceL) {
|
||||
templateTokens.push(token);
|
||||
translateTemplateTokens();
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.braceR) {
|
||||
|
||||
// if there's already a curly, it's not part of the template
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
}
|
||||
|
||||
// store new curly for later
|
||||
this._curlyBrace = token;
|
||||
return;
|
||||
}
|
||||
if (token.type === tt.template || token.type === tt.invalidTemplate) {
|
||||
if (this._curlyBrace) {
|
||||
templateTokens.push(this._curlyBrace);
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
templateTokens.push(token);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._curlyBrace) {
|
||||
tokens.push(this.translate(this._curlyBrace, extra));
|
||||
this._curlyBrace = null;
|
||||
}
|
||||
|
||||
tokens.push(this.translate(token, extra));
|
||||
}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = TokenTranslator;
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* @fileoverview The visitor keys for the node types Espree supports
|
||||
* @author Nicholas C. Zakas
|
||||
*
|
||||
* This file contains code from estraverse-fb.
|
||||
*
|
||||
* The MIT license. Copyright (c) 2014 Ingvar Stepanyan
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Requirements
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// None!
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Public
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
module.exports = {
|
||||
|
||||
// ECMAScript
|
||||
AssignmentExpression: ["left", "right"],
|
||||
AssignmentPattern: ["left", "right"],
|
||||
ArrayExpression: ["elements"],
|
||||
ArrayPattern: ["elements"],
|
||||
ArrowFunctionExpression: ["params", "body"],
|
||||
BlockStatement: ["body"],
|
||||
BinaryExpression: ["left", "right"],
|
||||
BreakStatement: ["label"],
|
||||
CallExpression: ["callee", "arguments"],
|
||||
CatchClause: ["param", "body"],
|
||||
ClassBody: ["body"],
|
||||
ClassDeclaration: ["id", "superClass", "body"],
|
||||
ClassExpression: ["id", "superClass", "body"],
|
||||
ConditionalExpression: ["test", "consequent", "alternate"],
|
||||
ContinueStatement: ["label"],
|
||||
DebuggerStatement: [],
|
||||
DirectiveStatement: [],
|
||||
DoWhileStatement: ["body", "test"],
|
||||
EmptyStatement: [],
|
||||
ExportAllDeclaration: ["source"],
|
||||
ExportDefaultDeclaration: ["declaration"],
|
||||
ExportNamedDeclaration: ["declaration", "specifiers", "source"],
|
||||
ExportSpecifier: ["exported", "local"],
|
||||
ExpressionStatement: ["expression"],
|
||||
ForStatement: ["init", "test", "update", "body"],
|
||||
ForInStatement: ["left", "right", "body"],
|
||||
ForOfStatement: ["left", "right", "body"],
|
||||
FunctionDeclaration: ["id", "params", "body"],
|
||||
FunctionExpression: ["id", "params", "body"],
|
||||
Identifier: [],
|
||||
IfStatement: ["test", "consequent", "alternate"],
|
||||
ImportDeclaration: ["specifiers", "source"],
|
||||
ImportDefaultSpecifier: ["local"],
|
||||
ImportNamespaceSpecifier: ["local"],
|
||||
ImportSpecifier: ["imported", "local"],
|
||||
Literal: [],
|
||||
LabeledStatement: ["label", "body"],
|
||||
LogicalExpression: ["left", "right"],
|
||||
MemberExpression: ["object", "property"],
|
||||
MetaProperty: ["meta", "property"],
|
||||
MethodDefinition: ["key", "value"],
|
||||
ModuleSpecifier: [],
|
||||
NewExpression: ["callee", "arguments"],
|
||||
ObjectExpression: ["properties"],
|
||||
ObjectPattern: ["properties"],
|
||||
Program: ["body"],
|
||||
Property: ["key", "value"],
|
||||
RestElement: ["argument"],
|
||||
ReturnStatement: ["argument"],
|
||||
SequenceExpression: ["expressions"],
|
||||
SpreadElement: ["argument"],
|
||||
Super: [],
|
||||
SwitchStatement: ["discriminant", "cases"],
|
||||
SwitchCase: ["test", "consequent"],
|
||||
TaggedTemplateExpression: ["tag", "quasi"],
|
||||
TemplateElement: [],
|
||||
TemplateLiteral: ["quasis", "expressions"],
|
||||
ThisExpression: [],
|
||||
ThrowStatement: ["argument"],
|
||||
TryStatement: ["block", "handler", "finalizer"],
|
||||
UnaryExpression: ["argument"],
|
||||
UpdateExpression: ["argument"],
|
||||
VariableDeclaration: ["declarations"],
|
||||
VariableDeclarator: ["id", "init"],
|
||||
WhileStatement: ["test", "body"],
|
||||
WithStatement: ["object", "body"],
|
||||
YieldExpression: ["argument"],
|
||||
|
||||
// JSX
|
||||
JSXIdentifier: [],
|
||||
JSXNamespacedName: ["namespace", "name"],
|
||||
JSXMemberExpression: ["object", "property"],
|
||||
JSXEmptyExpression: [],
|
||||
JSXExpressionContainer: ["expression"],
|
||||
JSXElement: ["openingElement", "closingElement", "children"],
|
||||
JSXClosingElement: ["name"],
|
||||
JSXOpeningElement: ["name", "attributes"],
|
||||
JSXAttribute: ["name", "value"],
|
||||
JSXText: null,
|
||||
JSXSpreadAttribute: ["argument"]
|
||||
};
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "espree",
|
||||
"description": "An Esprima-compatible JavaScript parser built on Acorn",
|
||||
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
||||
"homepage": "https://github.com/eslint/espree",
|
||||
"main": "espree.js",
|
||||
"version": "7.3.1",
|
||||
"files": [
|
||||
"lib",
|
||||
"espree.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"repository": "eslint/espree",
|
||||
"bugs": {
|
||||
"url": "http://github.com/eslint/espree.git"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^7.4.0",
|
||||
"acorn-jsx": "^5.3.1",
|
||||
"eslint-visitor-keys": "^1.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^16.5.0",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^6.0.1",
|
||||
"eslint-config-eslint": "^5.0.1",
|
||||
"eslint-plugin-node": "^9.1.0",
|
||||
"eslint-release": "^1.0.0",
|
||||
"esprima": "latest",
|
||||
"esprima-fb": "^8001.2001.0-dev-harmony-fb",
|
||||
"json-diff": "^0.5.4",
|
||||
"leche": "^2.3.0",
|
||||
"mocha": "^6.2.0",
|
||||
"nyc": "^14.1.1",
|
||||
"regenerate": "^1.4.0",
|
||||
"shelljs": "^0.3.0",
|
||||
"shelljs-nodecli": "^0.1.1",
|
||||
"unicode-6.3.0": "^0.7.5"
|
||||
},
|
||||
"keywords": [
|
||||
"ast",
|
||||
"ecmascript",
|
||||
"javascript",
|
||||
"parser",
|
||||
"syntax",
|
||||
"acorn"
|
||||
],
|
||||
"scripts": {
|
||||
"generate-regex": "node tools/generate-identifier-regex.js",
|
||||
"test": "npm run-script lint && node Makefile.js test",
|
||||
"lint": "node Makefile.js lint",
|
||||
"fixlint": "node Makefile.js lint --fix",
|
||||
"sync-docs": "node Makefile.js docs",
|
||||
"browserify": "node Makefile.js browserify",
|
||||
"generate-release": "eslint-generate-release",
|
||||
"generate-alpharelease": "eslint-generate-prerelease alpha",
|
||||
"generate-betarelease": "eslint-generate-prerelease beta",
|
||||
"generate-rcrelease": "eslint-generate-prerelease rc",
|
||||
"publish-release": "eslint-publish-release"
|
||||
}
|
||||
}
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
2018-06-17: Version 4.0.1
|
||||
|
||||
* Fix parsing async get/set in a class (issue 1861, 1875)
|
||||
* Account for different return statement argument (issue 1829, 1897, 1928)
|
||||
* Correct the handling of HTML comment when parsing a module (issue 1841)
|
||||
* Fix incorrect parse async with proto-identifier-shorthand (issue 1847)
|
||||
* Fix negative column in binary expression (issue 1844)
|
||||
* Fix incorrect YieldExpression in object methods (issue 1834)
|
||||
* Various documentation fixes
|
||||
|
||||
2017-06-10: Version 4.0.0
|
||||
|
||||
* Support ES2017 async function and await expression (issue 1079)
|
||||
* Support ES2017 trailing commas in function parameters (issue 1550)
|
||||
* Explicitly distinguish parsing a module vs a script (issue 1576)
|
||||
* Fix JSX non-empty container (issue 1786)
|
||||
* Allow JSX element in a yield expression (issue 1765)
|
||||
* Allow `in` expression in a concise body with a function body (issue 1793)
|
||||
* Setter function argument must not be a rest parameter (issue 1693)
|
||||
* Limit strict mode directive to functions with a simple parameter list (issue 1677)
|
||||
* Prohibit any escape sequence in a reserved word (issue 1612)
|
||||
* Only permit hex digits in hex escape sequence (issue 1619)
|
||||
* Prohibit labelled class/generator/function declaration (issue 1484)
|
||||
* Limit function declaration as if statement clause only in non-strict mode (issue 1657)
|
||||
* Tolerate missing ) in a with and do-while statement (issue 1481)
|
||||
|
||||
2016-12-22: Version 3.1.3
|
||||
|
||||
* Support binding patterns as rest element (issue 1681)
|
||||
* Account for different possible arguments of a yield expression (issue 1469)
|
||||
|
||||
2016-11-24: Version 3.1.2
|
||||
|
||||
* Ensure that import specifier is more restrictive (issue 1615)
|
||||
* Fix duplicated JSX tokens (issue 1613)
|
||||
* Scan template literal in a JSX expression container (issue 1622)
|
||||
* Improve XHTML entity scanning in JSX (issue 1629)
|
||||
|
||||
2016-10-31: Version 3.1.1
|
||||
|
||||
* Fix assignment expression problem in an export declaration (issue 1596)
|
||||
* Fix incorrect tokenization of hex digits (issue 1605)
|
||||
|
||||
2016-10-09: Version 3.1.0
|
||||
|
||||
* Do not implicitly collect comments when comment attachment is specified (issue 1553)
|
||||
* Fix incorrect handling of duplicated proto shorthand fields (issue 1485)
|
||||
* Prohibit initialization in some variants of for statements (issue 1309, 1561)
|
||||
* Fix incorrect parsing of export specifier (issue 1578)
|
||||
* Fix ESTree compatibility for assignment pattern (issue 1575)
|
||||
|
||||
2016-09-03: Version 3.0.0
|
||||
|
||||
* Support ES2016 exponentiation expression (issue 1490)
|
||||
* Support JSX syntax (issue 1467)
|
||||
* Use the latest Unicode 8.0 (issue 1475)
|
||||
* Add the support for syntax node delegate (issue 1435)
|
||||
* Fix ESTree compatibility on meta property (issue 1338)
|
||||
* Fix ESTree compatibility on default parameter value (issue 1081)
|
||||
* Fix ESTree compatibility on try handler (issue 1030)
|
||||
|
||||
2016-08-23: Version 2.7.3
|
||||
|
||||
* Fix tokenizer confusion with a comment (issue 1493, 1516)
|
||||
|
||||
2016-02-02: Version 2.7.2
|
||||
|
||||
* Fix out-of-bound error location in an invalid string literal (issue 1457)
|
||||
* Fix shorthand object destructuring defaults in variable declarations (issue 1459)
|
||||
|
||||
2015-12-10: Version 2.7.1
|
||||
|
||||
* Do not allow trailing comma in a variable declaration (issue 1360)
|
||||
* Fix assignment to `let` in non-strict mode (issue 1376)
|
||||
* Fix missing delegate property in YieldExpression (issue 1407)
|
||||
|
||||
2015-10-22: Version 2.7.0
|
||||
|
||||
* Fix the handling of semicolon in a break statement (issue 1044)
|
||||
* Run the test suite with major web browsers (issue 1259, 1317)
|
||||
* Allow `let` as an identifier in non-strict mode (issue 1289)
|
||||
* Attach orphaned comments as `innerComments` (issue 1328)
|
||||
* Add the support for token delegator (issue 1332)
|
||||
|
||||
2015-09-01: Version 2.6.0
|
||||
|
||||
* Properly allow or prohibit `let` in a binding identifier/pattern (issue 1048, 1098)
|
||||
* Add sourceType field for Program node (issue 1159)
|
||||
* Ensure that strict mode reserved word binding throw an error (issue 1171)
|
||||
* Run the test suite with Node.js and IE 11 on Windows (issue 1294)
|
||||
* Allow binding pattern with no initializer in a for statement (issue 1301)
|
||||
|
||||
2015-07-31: Version 2.5.0
|
||||
|
||||
* Run the test suite in a browser environment (issue 1004)
|
||||
* Ensure a comma between imported default binding and named imports (issue 1046)
|
||||
* Distinguish `yield` as a keyword vs an identifier (issue 1186)
|
||||
* Support ES6 meta property `new.target` (issue 1203)
|
||||
* Fix the syntax node for yield with expression (issue 1223)
|
||||
* Fix the check of duplicated proto in property names (issue 1225)
|
||||
* Fix ES6 Unicode escape in identifier name (issue 1229)
|
||||
* Support ES6 IdentifierStart and IdentifierPart (issue 1232)
|
||||
* Treat await as a reserved word when parsing as a module (issue 1234)
|
||||
* Recognize identifier characters from Unicode SMP (issue 1244)
|
||||
* Ensure that export and import can be followed by a comma (issue 1250)
|
||||
* Fix yield operator precedence (issue 1262)
|
||||
|
||||
2015-07-01: Version 2.4.1
|
||||
|
||||
* Fix some cases of comment attachment (issue 1071, 1175)
|
||||
* Fix the handling of destructuring in function arguments (issue 1193)
|
||||
* Fix invalid ranges in assignment expression (issue 1201)
|
||||
|
||||
2015-06-26: Version 2.4.0
|
||||
|
||||
* Support ES6 for-of iteration (issue 1047)
|
||||
* Support ES6 spread arguments (issue 1169)
|
||||
* Minimize npm payload (issue 1191)
|
||||
|
||||
2015-06-16: Version 2.3.0
|
||||
|
||||
* Support ES6 generator (issue 1033)
|
||||
* Improve parsing of regular expressions with `u` flag (issue 1179)
|
||||
|
||||
2015-04-17: Version 2.2.0
|
||||
|
||||
* Support ES6 import and export declarations (issue 1000)
|
||||
* Fix line terminator before arrow not recognized as error (issue 1009)
|
||||
* Support ES6 destructuring (issue 1045)
|
||||
* Support ES6 template literal (issue 1074)
|
||||
* Fix the handling of invalid/incomplete string escape sequences (issue 1106)
|
||||
* Fix ES3 static member access restriction (issue 1120)
|
||||
* Support for `super` in ES6 class (issue 1147)
|
||||
|
||||
2015-03-09: Version 2.1.0
|
||||
|
||||
* Support ES6 class (issue 1001)
|
||||
* Support ES6 rest parameter (issue 1011)
|
||||
* Expand the location of property getter, setter, and methods (issue 1029)
|
||||
* Enable TryStatement transition to a single handler (issue 1031)
|
||||
* Support ES6 computed property name (issue 1037)
|
||||
* Tolerate unclosed block comment (issue 1041)
|
||||
* Support ES6 lexical declaration (issue 1065)
|
||||
|
||||
2015-02-06: Version 2.0.0
|
||||
|
||||
* Support ES6 arrow function (issue 517)
|
||||
* Support ES6 Unicode code point escape (issue 521)
|
||||
* Improve the speed and accuracy of comment attachment (issue 522)
|
||||
* Support ES6 default parameter (issue 519)
|
||||
* Support ES6 regular expression flags (issue 557)
|
||||
* Fix scanning of implicit octal literals (issue 565)
|
||||
* Fix the handling of automatic semicolon insertion (issue 574)
|
||||
* Support ES6 method definition (issue 620)
|
||||
* Support ES6 octal integer literal (issue 621)
|
||||
* Support ES6 binary integer literal (issue 622)
|
||||
* Support ES6 object literal property value shorthand (issue 624)
|
||||
|
||||
2015-03-03: Version 1.2.5
|
||||
|
||||
* Fix scanning of implicit octal literals (issue 565)
|
||||
|
||||
2015-02-05: Version 1.2.4
|
||||
|
||||
* Fix parsing of LeftHandSideExpression in ForInStatement (issue 560)
|
||||
* Fix the handling of automatic semicolon insertion (issue 574)
|
||||
|
||||
2015-01-18: Version 1.2.3
|
||||
|
||||
* Fix division by this (issue 616)
|
||||
|
||||
2014-05-18: Version 1.2.2
|
||||
|
||||
* Fix duplicated tokens when collecting comments (issue 537)
|
||||
|
||||
2014-05-04: Version 1.2.1
|
||||
|
||||
* Ensure that Program node may still have leading comments (issue 536)
|
||||
|
||||
2014-04-29: Version 1.2.0
|
||||
|
||||
* Fix semicolon handling for expression statement (issue 462, 533)
|
||||
* Disallow escaped characters in regular expression flags (issue 503)
|
||||
* Performance improvement for location tracking (issue 520)
|
||||
* Improve the speed of comment attachment (issue 522)
|
||||
|
||||
2014-03-26: Version 1.1.1
|
||||
|
||||
* Fix token handling of forward slash after an array literal (issue 512)
|
||||
|
||||
2014-03-23: Version 1.1.0
|
||||
|
||||
* Optionally attach comments to the owning syntax nodes (issue 197)
|
||||
* Simplify binary parsing with stack-based shift reduce (issue 352)
|
||||
* Always include the raw source of literals (issue 376)
|
||||
* Add optional input source information (issue 386)
|
||||
* Tokenizer API for pure lexical scanning (issue 398)
|
||||
* Improve the web site and its online demos (issue 337, 400, 404)
|
||||
* Performance improvement for location tracking (issue 417, 424)
|
||||
* Support HTML comment syntax (issue 451)
|
||||
* Drop support for legacy browsers (issue 474)
|
||||
|
||||
2013-08-27: Version 1.0.4
|
||||
|
||||
* Minimize the payload for packages (issue 362)
|
||||
* Fix missing cases on an empty switch statement (issue 436)
|
||||
* Support escaped ] in regexp literal character classes (issue 442)
|
||||
* Tolerate invalid left-hand side expression (issue 130)
|
||||
|
||||
2013-05-17: Version 1.0.3
|
||||
|
||||
* Variable declaration needs at least one declarator (issue 391)
|
||||
* Fix benchmark's variance unit conversion (issue 397)
|
||||
* IE < 9: \v should be treated as vertical tab (issue 405)
|
||||
* Unary expressions should always have prefix: true (issue 418)
|
||||
* Catch clause should only accept an identifier (issue 423)
|
||||
* Tolerate setters without parameter (issue 426)
|
||||
|
||||
2012-11-02: Version 1.0.2
|
||||
|
||||
Improvement:
|
||||
|
||||
* Fix esvalidate JUnit output upon a syntax error (issue 374)
|
||||
|
||||
2012-10-28: Version 1.0.1
|
||||
|
||||
Improvements:
|
||||
|
||||
* esvalidate understands shebang in a Unix shell script (issue 361)
|
||||
* esvalidate treats fatal parsing failure as an error (issue 361)
|
||||
* Reduce Node.js package via .npmignore (issue 362)
|
||||
|
||||
2012-10-22: Version 1.0.0
|
||||
|
||||
Initial release.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
[](https://www.npmjs.com/package/esprima)
|
||||
[](https://www.npmjs.com/package/esprima)
|
||||
[](https://travis-ci.org/jquery/esprima)
|
||||
[](https://codecov.io/github/jquery/esprima)
|
||||
|
||||
**Esprima** ([esprima.org](http://esprima.org), BSD license) is a high performance,
|
||||
standard-compliant [ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
||||
parser written in ECMAScript (also popularly known as
|
||||
[JavaScript](https://en.wikipedia.org/wiki/JavaScript)).
|
||||
Esprima is created and maintained by [Ariya Hidayat](https://twitter.com/ariyahidayat),
|
||||
with the help of [many contributors](https://github.com/jquery/esprima/contributors).
|
||||
|
||||
### Features
|
||||
|
||||
- Full support for ECMAScript 2017 ([ECMA-262 8th Edition](http://www.ecma-international.org/publications/standards/Ecma-262.htm))
|
||||
- Sensible [syntax tree format](https://github.com/estree/estree/blob/master/es5.md) as standardized by [ESTree project](https://github.com/estree/estree)
|
||||
- Experimental support for [JSX](https://facebook.github.io/jsx/), a syntax extension for [React](https://facebook.github.io/react/)
|
||||
- Optional tracking of syntax node location (index-based and line-column)
|
||||
- [Heavily tested](http://esprima.org/test/ci.html) (~1500 [unit tests](https://github.com/jquery/esprima/tree/master/test/fixtures) with [full code coverage](https://codecov.io/github/jquery/esprima))
|
||||
|
||||
### API
|
||||
|
||||
Esprima can be used to perform [lexical analysis](https://en.wikipedia.org/wiki/Lexical_analysis) (tokenization) or [syntactic analysis](https://en.wikipedia.org/wiki/Parsing) (parsing) of a JavaScript program.
|
||||
|
||||
A simple example on Node.js REPL:
|
||||
|
||||
```javascript
|
||||
> var esprima = require('esprima');
|
||||
> var program = 'const answer = 42';
|
||||
|
||||
> esprima.tokenize(program);
|
||||
[ { type: 'Keyword', value: 'const' },
|
||||
{ type: 'Identifier', value: 'answer' },
|
||||
{ type: 'Punctuator', value: '=' },
|
||||
{ type: 'Numeric', value: '42' } ]
|
||||
|
||||
> esprima.parseScript(program);
|
||||
{ type: 'Program',
|
||||
body:
|
||||
[ { type: 'VariableDeclaration',
|
||||
declarations: [Object],
|
||||
kind: 'const' } ],
|
||||
sourceType: 'script' }
|
||||
```
|
||||
|
||||
For more information, please read the [complete documentation](http://esprima.org/doc).
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*jslint sloppy:true node:true rhino:true */
|
||||
|
||||
var fs, esprima, fname, forceFile, content, options, syntax;
|
||||
|
||||
if (typeof require === 'function') {
|
||||
fs = require('fs');
|
||||
try {
|
||||
esprima = require('esprima');
|
||||
} catch (e) {
|
||||
esprima = require('../');
|
||||
}
|
||||
} else if (typeof load === 'function') {
|
||||
try {
|
||||
load('esprima.js');
|
||||
} catch (e) {
|
||||
load('../esprima.js');
|
||||
}
|
||||
}
|
||||
|
||||
// Shims to Node.js objects when running under Rhino.
|
||||
if (typeof console === 'undefined' && typeof process === 'undefined') {
|
||||
console = { log: print };
|
||||
fs = { readFileSync: readFile };
|
||||
process = { argv: arguments, exit: quit };
|
||||
process.argv.unshift('esparse.js');
|
||||
process.argv.unshift('rhino');
|
||||
}
|
||||
|
||||
function showUsage() {
|
||||
console.log('Usage:');
|
||||
console.log(' esparse [options] [file.js]');
|
||||
console.log();
|
||||
console.log('Available options:');
|
||||
console.log();
|
||||
console.log(' --comment Gather all line and block comments in an array');
|
||||
console.log(' --loc Include line-column location info for each syntax node');
|
||||
console.log(' --range Include index-based range for each syntax node');
|
||||
console.log(' --raw Display the raw value of literals');
|
||||
console.log(' --tokens List all tokens in an array');
|
||||
console.log(' --tolerant Tolerate errors on a best-effort basis (experimental)');
|
||||
console.log(' -v, --version Shows program version');
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
options = {};
|
||||
|
||||
process.argv.splice(2).forEach(function (entry) {
|
||||
|
||||
if (forceFile || entry === '-' || entry.slice(0, 1) !== '-') {
|
||||
if (typeof fname === 'string') {
|
||||
console.log('Error: more than one input file.');
|
||||
process.exit(1);
|
||||
} else {
|
||||
fname = entry;
|
||||
}
|
||||
} else if (entry === '-h' || entry === '--help') {
|
||||
showUsage();
|
||||
} else if (entry === '-v' || entry === '--version') {
|
||||
console.log('ECMAScript Parser (using Esprima version', esprima.version, ')');
|
||||
console.log();
|
||||
process.exit(0);
|
||||
} else if (entry === '--comment') {
|
||||
options.comment = true;
|
||||
} else if (entry === '--loc') {
|
||||
options.loc = true;
|
||||
} else if (entry === '--range') {
|
||||
options.range = true;
|
||||
} else if (entry === '--raw') {
|
||||
options.raw = true;
|
||||
} else if (entry === '--tokens') {
|
||||
options.tokens = true;
|
||||
} else if (entry === '--tolerant') {
|
||||
options.tolerant = true;
|
||||
} else if (entry === '--') {
|
||||
forceFile = true;
|
||||
} else {
|
||||
console.log('Error: unknown option ' + entry + '.');
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
// Special handling for regular expression literal since we need to
|
||||
// convert it to a string literal, otherwise it will be decoded
|
||||
// as object "{}" and the regular expression would be lost.
|
||||
function adjustRegexLiteral(key, value) {
|
||||
if (key === 'value' && value instanceof RegExp) {
|
||||
value = value.toString();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function run(content) {
|
||||
syntax = esprima.parse(content, options);
|
||||
console.log(JSON.stringify(syntax, adjustRegexLiteral, 4));
|
||||
}
|
||||
|
||||
try {
|
||||
if (fname && (fname !== '-' || forceFile)) {
|
||||
run(fs.readFileSync(fname, 'utf-8'));
|
||||
} else {
|
||||
var content = '';
|
||||
process.stdin.resume();
|
||||
process.stdin.on('data', function(chunk) {
|
||||
content += chunk;
|
||||
});
|
||||
process.stdin.on('end', function() {
|
||||
run(content);
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('Error: ' + e.message);
|
||||
process.exit(1);
|
||||
}
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
#!/usr/bin/env node
|
||||
/*
|
||||
Copyright JS Foundation and other contributors, https://js.foundation/
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*jslint sloppy:true plusplus:true node:true rhino:true */
|
||||
/*global phantom:true */
|
||||
|
||||
var fs, system, esprima, options, fnames, forceFile, count;
|
||||
|
||||
if (typeof esprima === 'undefined') {
|
||||
// PhantomJS can only require() relative files
|
||||
if (typeof phantom === 'object') {
|
||||
fs = require('fs');
|
||||
system = require('system');
|
||||
esprima = require('./esprima');
|
||||
} else if (typeof require === 'function') {
|
||||
fs = require('fs');
|
||||
try {
|
||||
esprima = require('esprima');
|
||||
} catch (e) {
|
||||
esprima = require('../');
|
||||
}
|
||||
} else if (typeof load === 'function') {
|
||||
try {
|
||||
load('esprima.js');
|
||||
} catch (e) {
|
||||
load('../esprima.js');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shims to Node.js objects when running under PhantomJS 1.7+.
|
||||
if (typeof phantom === 'object') {
|
||||
fs.readFileSync = fs.read;
|
||||
process = {
|
||||
argv: [].slice.call(system.args),
|
||||
exit: phantom.exit,
|
||||
on: function (evt, callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
process.argv.unshift('phantomjs');
|
||||
}
|
||||
|
||||
// Shims to Node.js objects when running under Rhino.
|
||||
if (typeof console === 'undefined' && typeof process === 'undefined') {
|
||||
console = { log: print };
|
||||
fs = { readFileSync: readFile };
|
||||
process = {
|
||||
argv: arguments,
|
||||
exit: quit,
|
||||
on: function (evt, callback) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
process.argv.unshift('esvalidate.js');
|
||||
process.argv.unshift('rhino');
|
||||
}
|
||||
|
||||
function showUsage() {
|
||||
console.log('Usage:');
|
||||
console.log(' esvalidate [options] [file.js...]');
|
||||
console.log();
|
||||
console.log('Available options:');
|
||||
console.log();
|
||||
console.log(' --format=type Set the report format, plain (default) or junit');
|
||||
console.log(' -v, --version Print program version');
|
||||
console.log();
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
options = {
|
||||
format: 'plain'
|
||||
};
|
||||
|
||||
fnames = [];
|
||||
|
||||
process.argv.splice(2).forEach(function (entry) {
|
||||
|
||||
if (forceFile || entry === '-' || entry.slice(0, 1) !== '-') {
|
||||
fnames.push(entry);
|
||||
} else if (entry === '-h' || entry === '--help') {
|
||||
showUsage();
|
||||
} else if (entry === '-v' || entry === '--version') {
|
||||
console.log('ECMAScript Validator (using Esprima version', esprima.version, ')');
|
||||
console.log();
|
||||
process.exit(0);
|
||||
} else if (entry.slice(0, 9) === '--format=') {
|
||||
options.format = entry.slice(9);
|
||||
if (options.format !== 'plain' && options.format !== 'junit') {
|
||||
console.log('Error: unknown report format ' + options.format + '.');
|
||||
process.exit(1);
|
||||
}
|
||||
} else if (entry === '--') {
|
||||
forceFile = true;
|
||||
} else {
|
||||
console.log('Error: unknown option ' + entry + '.');
|
||||
process.exit(1);
|
||||
}
|
||||
});
|
||||
|
||||
if (fnames.length === 0) {
|
||||
fnames.push('');
|
||||
}
|
||||
|
||||
if (options.format === 'junit') {
|
||||
console.log('<?xml version="1.0" encoding="UTF-8"?>');
|
||||
console.log('<testsuites>');
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
function run(fname, content) {
|
||||
var timestamp, syntax, name;
|
||||
try {
|
||||
if (typeof content !== 'string') {
|
||||
throw content;
|
||||
}
|
||||
|
||||
if (content[0] === '#' && content[1] === '!') {
|
||||
content = '//' + content.substr(2, content.length);
|
||||
}
|
||||
|
||||
timestamp = Date.now();
|
||||
syntax = esprima.parse(content, { tolerant: true });
|
||||
|
||||
if (options.format === 'junit') {
|
||||
|
||||
name = fname;
|
||||
if (name.lastIndexOf('/') >= 0) {
|
||||
name = name.slice(name.lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
console.log('<testsuite name="' + fname + '" errors="0" ' +
|
||||
' failures="' + syntax.errors.length + '" ' +
|
||||
' tests="' + syntax.errors.length + '" ' +
|
||||
' time="' + Math.round((Date.now() - timestamp) / 1000) +
|
||||
'">');
|
||||
|
||||
syntax.errors.forEach(function (error) {
|
||||
var msg = error.message;
|
||||
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
|
||||
console.log(' <testcase name="Line ' + error.lineNumber + ': ' + msg + '" ' +
|
||||
' time="0">');
|
||||
console.log(' <error type="SyntaxError" message="' + error.message + '">' +
|
||||
error.message + '(' + name + ':' + error.lineNumber + ')' +
|
||||
'</error>');
|
||||
console.log(' </testcase>');
|
||||
});
|
||||
|
||||
console.log('</testsuite>');
|
||||
|
||||
} else if (options.format === 'plain') {
|
||||
|
||||
syntax.errors.forEach(function (error) {
|
||||
var msg = error.message;
|
||||
msg = msg.replace(/^Line\ [0-9]*\:\ /, '');
|
||||
msg = fname + ':' + error.lineNumber + ': ' + msg;
|
||||
console.log(msg);
|
||||
++count;
|
||||
});
|
||||
|
||||
}
|
||||
} catch (e) {
|
||||
++count;
|
||||
if (options.format === 'junit') {
|
||||
console.log('<testsuite name="' + fname + '" errors="1" failures="0" tests="1" ' +
|
||||
' time="' + Math.round((Date.now() - timestamp) / 1000) + '">');
|
||||
console.log(' <testcase name="' + e.message + '" ' + ' time="0">');
|
||||
console.log(' <error type="ParseError" message="' + e.message + '">' +
|
||||
e.message + '(' + fname + ((e.lineNumber) ? ':' + e.lineNumber : '') +
|
||||
')</error>');
|
||||
console.log(' </testcase>');
|
||||
console.log('</testsuite>');
|
||||
} else {
|
||||
console.log(fname + ':' + e.lineNumber + ': ' + e.message.replace(/^Line\ [0-9]*\:\ /, ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fnames.forEach(function (fname) {
|
||||
var content = '';
|
||||
try {
|
||||
if (fname && (fname !== '-' || forceFile)) {
|
||||
content = fs.readFileSync(fname, 'utf-8');
|
||||
} else {
|
||||
fname = '';
|
||||
process.stdin.resume();
|
||||
process.stdin.on('data', function(chunk) {
|
||||
content += chunk;
|
||||
});
|
||||
process.stdin.on('end', function() {
|
||||
run(fname, content);
|
||||
});
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
content = e;
|
||||
}
|
||||
run(fname, content);
|
||||
});
|
||||
|
||||
process.on('exit', function () {
|
||||
if (options.format === 'junit') {
|
||||
console.log('</testsuites>');
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (count === 0 && typeof phantom === 'object') {
|
||||
process.exit(0);
|
||||
}
|
||||
});
|
||||
+6709
File diff suppressed because one or more lines are too long
+112
@@ -0,0 +1,112 @@
|
||||
{
|
||||
"name": "esprima",
|
||||
"description": "ECMAScript parsing infrastructure for multipurpose analysis",
|
||||
"homepage": "http://esprima.org",
|
||||
"main": "dist/esprima.js",
|
||||
"bin": {
|
||||
"esparse": "./bin/esparse.js",
|
||||
"esvalidate": "./bin/esvalidate.js"
|
||||
},
|
||||
"version": "4.0.1",
|
||||
"files": [
|
||||
"bin",
|
||||
"dist/esprima.js"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"author": {
|
||||
"name": "Ariya Hidayat",
|
||||
"email": "ariya.hidayat@gmail.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Ariya Hidayat",
|
||||
"email": "ariya.hidayat@gmail.com",
|
||||
"web": "http://ariya.ofilabs.com"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jquery/esprima.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jquery/esprima/issues"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"devDependencies": {
|
||||
"codecov.io": "~0.1.6",
|
||||
"escomplex-js": "1.2.0",
|
||||
"everything.js": "~1.0.3",
|
||||
"glob": "~7.1.0",
|
||||
"istanbul": "~0.4.0",
|
||||
"json-diff": "~0.3.1",
|
||||
"karma": "~1.3.0",
|
||||
"karma-chrome-launcher": "~2.0.0",
|
||||
"karma-detect-browsers": "~2.2.3",
|
||||
"karma-edge-launcher": "~0.2.0",
|
||||
"karma-firefox-launcher": "~1.0.0",
|
||||
"karma-ie-launcher": "~1.0.0",
|
||||
"karma-mocha": "~1.3.0",
|
||||
"karma-safari-launcher": "~1.0.0",
|
||||
"karma-safaritechpreview-launcher": "~0.0.4",
|
||||
"karma-sauce-launcher": "~1.1.0",
|
||||
"lodash": "~3.10.1",
|
||||
"mocha": "~3.2.0",
|
||||
"node-tick-processor": "~0.0.2",
|
||||
"regenerate": "~1.3.2",
|
||||
"temp": "~0.8.3",
|
||||
"tslint": "~5.1.0",
|
||||
"typescript": "~2.3.2",
|
||||
"typescript-formatter": "~5.1.3",
|
||||
"unicode-8.0.0": "~0.7.0",
|
||||
"webpack": "~1.14.0"
|
||||
},
|
||||
"keywords": [
|
||||
"ast",
|
||||
"ecmascript",
|
||||
"esprima",
|
||||
"javascript",
|
||||
"parser",
|
||||
"syntax"
|
||||
],
|
||||
"scripts": {
|
||||
"check-version": "node test/check-version.js",
|
||||
"tslint": "tslint src/*.ts",
|
||||
"code-style": "tsfmt --verify src/*.ts && tsfmt --verify test/*.js",
|
||||
"format-code": "tsfmt -r src/*.ts && tsfmt -r test/*.js",
|
||||
"complexity": "node test/check-complexity.js",
|
||||
"static-analysis": "npm run check-version && npm run tslint && npm run code-style && npm run complexity",
|
||||
"hostile-env-tests": "node test/hostile-environment-tests.js",
|
||||
"unit-tests": "node test/unit-tests.js",
|
||||
"api-tests": "mocha -R dot test/api-tests.js",
|
||||
"grammar-tests": "node test/grammar-tests.js",
|
||||
"regression-tests": "node test/regression-tests.js",
|
||||
"all-tests": "npm run verify-line-ending && npm run generate-fixtures && npm run unit-tests && npm run api-tests && npm run grammar-tests && npm run regression-tests && npm run hostile-env-tests",
|
||||
"verify-line-ending": "node test/verify-line-ending.js",
|
||||
"generate-fixtures": "node tools/generate-fixtures.js",
|
||||
"browser-tests": "npm run compile && npm run generate-fixtures && cd test && karma start --single-run",
|
||||
"saucelabs-evergreen": "cd test && karma start saucelabs-evergreen.conf.js",
|
||||
"saucelabs-safari": "cd test && karma start saucelabs-safari.conf.js",
|
||||
"saucelabs-ie": "cd test && karma start saucelabs-ie.conf.js",
|
||||
"saucelabs": "npm run saucelabs-evergreen && npm run saucelabs-ie && npm run saucelabs-safari",
|
||||
"analyze-coverage": "istanbul cover test/unit-tests.js",
|
||||
"check-coverage": "istanbul check-coverage --statement 100 --branch 100 --function 100",
|
||||
"dynamic-analysis": "npm run analyze-coverage && npm run check-coverage",
|
||||
"compile": "tsc -p src/ && webpack && node tools/fixupbundle.js",
|
||||
"test": "npm run compile && npm run all-tests && npm run static-analysis && npm run dynamic-analysis",
|
||||
"prepublish": "npm run compile",
|
||||
"profile": "node --prof test/profile.js && mv isolate*.log v8.log && node-tick-processor",
|
||||
"benchmark-parser": "node -expose_gc test/benchmark-parser.js",
|
||||
"benchmark-tokenizer": "node --expose_gc test/benchmark-tokenizer.js",
|
||||
"benchmark": "npm run benchmark-parser && npm run benchmark-tokenizer",
|
||||
"codecov": "istanbul report cobertura && codecov < ./coverage/cobertura-coverage.xml",
|
||||
"downstream": "node test/downstream.js",
|
||||
"travis": "npm test",
|
||||
"circleci": "npm test && npm run codecov && npm run downstream",
|
||||
"appveyor": "npm run compile && npm run all-tests && npm run browser-tests",
|
||||
"droneio": "npm run compile && npm run all-tests && npm run saucelabs",
|
||||
"generate-regex": "node tools/generate-identifier-regex.js",
|
||||
"generate-xhtml-entities": "node tools/generate-xhtml-entities.js"
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"immed": true,
|
||||
"eqnull": true,
|
||||
"latedef": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"quotmark": "single",
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
|
||||
"node": true
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+153
@@ -0,0 +1,153 @@
|
||||
### Estraverse [](http://travis-ci.org/estools/estraverse)
|
||||
|
||||
Estraverse ([estraverse](http://github.com/estools/estraverse)) is
|
||||
[ECMAScript](http://www.ecma-international.org/publications/standards/Ecma-262.htm)
|
||||
traversal functions from [esmangle project](http://github.com/estools/esmangle).
|
||||
|
||||
### Documentation
|
||||
|
||||
You can find usage docs at [wiki page](https://github.com/estools/estraverse/wiki/Usage).
|
||||
|
||||
### Example Usage
|
||||
|
||||
The following code will output all variables declared at the root of a file.
|
||||
|
||||
```javascript
|
||||
estraverse.traverse(ast, {
|
||||
enter: function (node, parent) {
|
||||
if (node.type == 'FunctionExpression' || node.type == 'FunctionDeclaration')
|
||||
return estraverse.VisitorOption.Skip;
|
||||
},
|
||||
leave: function (node, parent) {
|
||||
if (node.type == 'VariableDeclarator')
|
||||
console.log(node.id.name);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
We can use `this.skip`, `this.remove` and `this.break` functions instead of using Skip, Remove and Break.
|
||||
|
||||
```javascript
|
||||
estraverse.traverse(ast, {
|
||||
enter: function (node) {
|
||||
this.break();
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
And estraverse provides `estraverse.replace` function. When returning node from `enter`/`leave`, current node is replaced with it.
|
||||
|
||||
```javascript
|
||||
result = estraverse.replace(tree, {
|
||||
enter: function (node) {
|
||||
// Replace it with replaced.
|
||||
if (node.type === 'Literal')
|
||||
return replaced;
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
By passing `visitor.keys` mapping, we can extend estraverse traversing functionality.
|
||||
|
||||
```javascript
|
||||
// This tree contains a user-defined `TestExpression` node.
|
||||
var tree = {
|
||||
type: 'TestExpression',
|
||||
|
||||
// This 'argument' is the property containing the other **node**.
|
||||
argument: {
|
||||
type: 'Literal',
|
||||
value: 20
|
||||
},
|
||||
|
||||
// This 'extended' is the property not containing the other **node**.
|
||||
extended: true
|
||||
};
|
||||
estraverse.traverse(tree, {
|
||||
enter: function (node) { },
|
||||
|
||||
// Extending the existing traversing rules.
|
||||
keys: {
|
||||
// TargetNodeName: [ 'keys', 'containing', 'the', 'other', '**node**' ]
|
||||
TestExpression: ['argument']
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
By passing `visitor.fallback` option, we can control the behavior when encountering unknown nodes.
|
||||
|
||||
```javascript
|
||||
// This tree contains a user-defined `TestExpression` node.
|
||||
var tree = {
|
||||
type: 'TestExpression',
|
||||
|
||||
// This 'argument' is the property containing the other **node**.
|
||||
argument: {
|
||||
type: 'Literal',
|
||||
value: 20
|
||||
},
|
||||
|
||||
// This 'extended' is the property not containing the other **node**.
|
||||
extended: true
|
||||
};
|
||||
estraverse.traverse(tree, {
|
||||
enter: function (node) { },
|
||||
|
||||
// Iterating the child **nodes** of unknown nodes.
|
||||
fallback: 'iteration'
|
||||
});
|
||||
```
|
||||
|
||||
When `visitor.fallback` is a function, we can determine which keys to visit on each node.
|
||||
|
||||
```javascript
|
||||
// This tree contains a user-defined `TestExpression` node.
|
||||
var tree = {
|
||||
type: 'TestExpression',
|
||||
|
||||
// This 'argument' is the property containing the other **node**.
|
||||
argument: {
|
||||
type: 'Literal',
|
||||
value: 20
|
||||
},
|
||||
|
||||
// This 'extended' is the property not containing the other **node**.
|
||||
extended: true
|
||||
};
|
||||
estraverse.traverse(tree, {
|
||||
enter: function (node) { },
|
||||
|
||||
// Skip the `argument` property of each node
|
||||
fallback: function(node) {
|
||||
return Object.keys(node).filter(function(key) {
|
||||
return key !== 'argument';
|
||||
});
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### License
|
||||
|
||||
Copyright (C) 2012-2016 [Yusuke Suzuki](http://github.com/Constellation)
|
||||
(twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+801
@@ -0,0 +1,801 @@
|
||||
/*
|
||||
Copyright (C) 2012-2013 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/*jslint vars:false, bitwise:true*/
|
||||
/*jshint indent:4*/
|
||||
/*global exports:true*/
|
||||
(function clone(exports) {
|
||||
'use strict';
|
||||
|
||||
var Syntax,
|
||||
VisitorOption,
|
||||
VisitorKeys,
|
||||
BREAK,
|
||||
SKIP,
|
||||
REMOVE;
|
||||
|
||||
function deepCopy(obj) {
|
||||
var ret = {}, key, val;
|
||||
for (key in obj) {
|
||||
if (obj.hasOwnProperty(key)) {
|
||||
val = obj[key];
|
||||
if (typeof val === 'object' && val !== null) {
|
||||
ret[key] = deepCopy(val);
|
||||
} else {
|
||||
ret[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// based on LLVM libc++ upper_bound / lower_bound
|
||||
// MIT License
|
||||
|
||||
function upperBound(array, func) {
|
||||
var diff, len, i, current;
|
||||
|
||||
len = array.length;
|
||||
i = 0;
|
||||
|
||||
while (len) {
|
||||
diff = len >>> 1;
|
||||
current = i + diff;
|
||||
if (func(array[current])) {
|
||||
len = diff;
|
||||
} else {
|
||||
i = current + 1;
|
||||
len -= diff + 1;
|
||||
}
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
Syntax = {
|
||||
AssignmentExpression: 'AssignmentExpression',
|
||||
AssignmentPattern: 'AssignmentPattern',
|
||||
ArrayExpression: 'ArrayExpression',
|
||||
ArrayPattern: 'ArrayPattern',
|
||||
ArrowFunctionExpression: 'ArrowFunctionExpression',
|
||||
AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7.
|
||||
BlockStatement: 'BlockStatement',
|
||||
BinaryExpression: 'BinaryExpression',
|
||||
BreakStatement: 'BreakStatement',
|
||||
CallExpression: 'CallExpression',
|
||||
CatchClause: 'CatchClause',
|
||||
ChainExpression: 'ChainExpression',
|
||||
ClassBody: 'ClassBody',
|
||||
ClassDeclaration: 'ClassDeclaration',
|
||||
ClassExpression: 'ClassExpression',
|
||||
ComprehensionBlock: 'ComprehensionBlock', // CAUTION: It's deferred to ES7.
|
||||
ComprehensionExpression: 'ComprehensionExpression', // CAUTION: It's deferred to ES7.
|
||||
ConditionalExpression: 'ConditionalExpression',
|
||||
ContinueStatement: 'ContinueStatement',
|
||||
DebuggerStatement: 'DebuggerStatement',
|
||||
DirectiveStatement: 'DirectiveStatement',
|
||||
DoWhileStatement: 'DoWhileStatement',
|
||||
EmptyStatement: 'EmptyStatement',
|
||||
ExportAllDeclaration: 'ExportAllDeclaration',
|
||||
ExportDefaultDeclaration: 'ExportDefaultDeclaration',
|
||||
ExportNamedDeclaration: 'ExportNamedDeclaration',
|
||||
ExportSpecifier: 'ExportSpecifier',
|
||||
ExpressionStatement: 'ExpressionStatement',
|
||||
ForStatement: 'ForStatement',
|
||||
ForInStatement: 'ForInStatement',
|
||||
ForOfStatement: 'ForOfStatement',
|
||||
FunctionDeclaration: 'FunctionDeclaration',
|
||||
FunctionExpression: 'FunctionExpression',
|
||||
GeneratorExpression: 'GeneratorExpression', // CAUTION: It's deferred to ES7.
|
||||
Identifier: 'Identifier',
|
||||
IfStatement: 'IfStatement',
|
||||
ImportExpression: 'ImportExpression',
|
||||
ImportDeclaration: 'ImportDeclaration',
|
||||
ImportDefaultSpecifier: 'ImportDefaultSpecifier',
|
||||
ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
|
||||
ImportSpecifier: 'ImportSpecifier',
|
||||
Literal: 'Literal',
|
||||
LabeledStatement: 'LabeledStatement',
|
||||
LogicalExpression: 'LogicalExpression',
|
||||
MemberExpression: 'MemberExpression',
|
||||
MetaProperty: 'MetaProperty',
|
||||
MethodDefinition: 'MethodDefinition',
|
||||
ModuleSpecifier: 'ModuleSpecifier',
|
||||
NewExpression: 'NewExpression',
|
||||
ObjectExpression: 'ObjectExpression',
|
||||
ObjectPattern: 'ObjectPattern',
|
||||
Program: 'Program',
|
||||
Property: 'Property',
|
||||
RestElement: 'RestElement',
|
||||
ReturnStatement: 'ReturnStatement',
|
||||
SequenceExpression: 'SequenceExpression',
|
||||
SpreadElement: 'SpreadElement',
|
||||
Super: 'Super',
|
||||
SwitchStatement: 'SwitchStatement',
|
||||
SwitchCase: 'SwitchCase',
|
||||
TaggedTemplateExpression: 'TaggedTemplateExpression',
|
||||
TemplateElement: 'TemplateElement',
|
||||
TemplateLiteral: 'TemplateLiteral',
|
||||
ThisExpression: 'ThisExpression',
|
||||
ThrowStatement: 'ThrowStatement',
|
||||
TryStatement: 'TryStatement',
|
||||
UnaryExpression: 'UnaryExpression',
|
||||
UpdateExpression: 'UpdateExpression',
|
||||
VariableDeclaration: 'VariableDeclaration',
|
||||
VariableDeclarator: 'VariableDeclarator',
|
||||
WhileStatement: 'WhileStatement',
|
||||
WithStatement: 'WithStatement',
|
||||
YieldExpression: 'YieldExpression'
|
||||
};
|
||||
|
||||
VisitorKeys = {
|
||||
AssignmentExpression: ['left', 'right'],
|
||||
AssignmentPattern: ['left', 'right'],
|
||||
ArrayExpression: ['elements'],
|
||||
ArrayPattern: ['elements'],
|
||||
ArrowFunctionExpression: ['params', 'body'],
|
||||
AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7.
|
||||
BlockStatement: ['body'],
|
||||
BinaryExpression: ['left', 'right'],
|
||||
BreakStatement: ['label'],
|
||||
CallExpression: ['callee', 'arguments'],
|
||||
CatchClause: ['param', 'body'],
|
||||
ChainExpression: ['expression'],
|
||||
ClassBody: ['body'],
|
||||
ClassDeclaration: ['id', 'superClass', 'body'],
|
||||
ClassExpression: ['id', 'superClass', 'body'],
|
||||
ComprehensionBlock: ['left', 'right'], // CAUTION: It's deferred to ES7.
|
||||
ComprehensionExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
|
||||
ConditionalExpression: ['test', 'consequent', 'alternate'],
|
||||
ContinueStatement: ['label'],
|
||||
DebuggerStatement: [],
|
||||
DirectiveStatement: [],
|
||||
DoWhileStatement: ['body', 'test'],
|
||||
EmptyStatement: [],
|
||||
ExportAllDeclaration: ['source'],
|
||||
ExportDefaultDeclaration: ['declaration'],
|
||||
ExportNamedDeclaration: ['declaration', 'specifiers', 'source'],
|
||||
ExportSpecifier: ['exported', 'local'],
|
||||
ExpressionStatement: ['expression'],
|
||||
ForStatement: ['init', 'test', 'update', 'body'],
|
||||
ForInStatement: ['left', 'right', 'body'],
|
||||
ForOfStatement: ['left', 'right', 'body'],
|
||||
FunctionDeclaration: ['id', 'params', 'body'],
|
||||
FunctionExpression: ['id', 'params', 'body'],
|
||||
GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7.
|
||||
Identifier: [],
|
||||
IfStatement: ['test', 'consequent', 'alternate'],
|
||||
ImportExpression: ['source'],
|
||||
ImportDeclaration: ['specifiers', 'source'],
|
||||
ImportDefaultSpecifier: ['local'],
|
||||
ImportNamespaceSpecifier: ['local'],
|
||||
ImportSpecifier: ['imported', 'local'],
|
||||
Literal: [],
|
||||
LabeledStatement: ['label', 'body'],
|
||||
LogicalExpression: ['left', 'right'],
|
||||
MemberExpression: ['object', 'property'],
|
||||
MetaProperty: ['meta', 'property'],
|
||||
MethodDefinition: ['key', 'value'],
|
||||
ModuleSpecifier: [],
|
||||
NewExpression: ['callee', 'arguments'],
|
||||
ObjectExpression: ['properties'],
|
||||
ObjectPattern: ['properties'],
|
||||
Program: ['body'],
|
||||
Property: ['key', 'value'],
|
||||
RestElement: [ 'argument' ],
|
||||
ReturnStatement: ['argument'],
|
||||
SequenceExpression: ['expressions'],
|
||||
SpreadElement: ['argument'],
|
||||
Super: [],
|
||||
SwitchStatement: ['discriminant', 'cases'],
|
||||
SwitchCase: ['test', 'consequent'],
|
||||
TaggedTemplateExpression: ['tag', 'quasi'],
|
||||
TemplateElement: [],
|
||||
TemplateLiteral: ['quasis', 'expressions'],
|
||||
ThisExpression: [],
|
||||
ThrowStatement: ['argument'],
|
||||
TryStatement: ['block', 'handler', 'finalizer'],
|
||||
UnaryExpression: ['argument'],
|
||||
UpdateExpression: ['argument'],
|
||||
VariableDeclaration: ['declarations'],
|
||||
VariableDeclarator: ['id', 'init'],
|
||||
WhileStatement: ['test', 'body'],
|
||||
WithStatement: ['object', 'body'],
|
||||
YieldExpression: ['argument']
|
||||
};
|
||||
|
||||
// unique id
|
||||
BREAK = {};
|
||||
SKIP = {};
|
||||
REMOVE = {};
|
||||
|
||||
VisitorOption = {
|
||||
Break: BREAK,
|
||||
Skip: SKIP,
|
||||
Remove: REMOVE
|
||||
};
|
||||
|
||||
function Reference(parent, key) {
|
||||
this.parent = parent;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
Reference.prototype.replace = function replace(node) {
|
||||
this.parent[this.key] = node;
|
||||
};
|
||||
|
||||
Reference.prototype.remove = function remove() {
|
||||
if (Array.isArray(this.parent)) {
|
||||
this.parent.splice(this.key, 1);
|
||||
return true;
|
||||
} else {
|
||||
this.replace(null);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
function Element(node, path, wrap, ref) {
|
||||
this.node = node;
|
||||
this.path = path;
|
||||
this.wrap = wrap;
|
||||
this.ref = ref;
|
||||
}
|
||||
|
||||
function Controller() { }
|
||||
|
||||
// API:
|
||||
// return property path array from root to current node
|
||||
Controller.prototype.path = function path() {
|
||||
var i, iz, j, jz, result, element;
|
||||
|
||||
function addToPath(result, path) {
|
||||
if (Array.isArray(path)) {
|
||||
for (j = 0, jz = path.length; j < jz; ++j) {
|
||||
result.push(path[j]);
|
||||
}
|
||||
} else {
|
||||
result.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
// root node
|
||||
if (!this.__current.path) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// first node is sentinel, second node is root element
|
||||
result = [];
|
||||
for (i = 2, iz = this.__leavelist.length; i < iz; ++i) {
|
||||
element = this.__leavelist[i];
|
||||
addToPath(result, element.path);
|
||||
}
|
||||
addToPath(result, this.__current.path);
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// return type of current node
|
||||
Controller.prototype.type = function () {
|
||||
var node = this.current();
|
||||
return node.type || this.__current.wrap;
|
||||
};
|
||||
|
||||
// API:
|
||||
// return array of parent elements
|
||||
Controller.prototype.parents = function parents() {
|
||||
var i, iz, result;
|
||||
|
||||
// first node is sentinel
|
||||
result = [];
|
||||
for (i = 1, iz = this.__leavelist.length; i < iz; ++i) {
|
||||
result.push(this.__leavelist[i].node);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// return current node
|
||||
Controller.prototype.current = function current() {
|
||||
return this.__current.node;
|
||||
};
|
||||
|
||||
Controller.prototype.__execute = function __execute(callback, element) {
|
||||
var previous, result;
|
||||
|
||||
result = undefined;
|
||||
|
||||
previous = this.__current;
|
||||
this.__current = element;
|
||||
this.__state = null;
|
||||
if (callback) {
|
||||
result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node);
|
||||
}
|
||||
this.__current = previous;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
// API:
|
||||
// notify control skip / break
|
||||
Controller.prototype.notify = function notify(flag) {
|
||||
this.__state = flag;
|
||||
};
|
||||
|
||||
// API:
|
||||
// skip child nodes of current node
|
||||
Controller.prototype.skip = function () {
|
||||
this.notify(SKIP);
|
||||
};
|
||||
|
||||
// API:
|
||||
// break traversals
|
||||
Controller.prototype['break'] = function () {
|
||||
this.notify(BREAK);
|
||||
};
|
||||
|
||||
// API:
|
||||
// remove node
|
||||
Controller.prototype.remove = function () {
|
||||
this.notify(REMOVE);
|
||||
};
|
||||
|
||||
Controller.prototype.__initialize = function(root, visitor) {
|
||||
this.visitor = visitor;
|
||||
this.root = root;
|
||||
this.__worklist = [];
|
||||
this.__leavelist = [];
|
||||
this.__current = null;
|
||||
this.__state = null;
|
||||
this.__fallback = null;
|
||||
if (visitor.fallback === 'iteration') {
|
||||
this.__fallback = Object.keys;
|
||||
} else if (typeof visitor.fallback === 'function') {
|
||||
this.__fallback = visitor.fallback;
|
||||
}
|
||||
|
||||
this.__keys = VisitorKeys;
|
||||
if (visitor.keys) {
|
||||
this.__keys = Object.assign(Object.create(this.__keys), visitor.keys);
|
||||
}
|
||||
};
|
||||
|
||||
function isNode(node) {
|
||||
if (node == null) {
|
||||
return false;
|
||||
}
|
||||
return typeof node === 'object' && typeof node.type === 'string';
|
||||
}
|
||||
|
||||
function isProperty(nodeType, key) {
|
||||
return (nodeType === Syntax.ObjectExpression || nodeType === Syntax.ObjectPattern) && 'properties' === key;
|
||||
}
|
||||
|
||||
function candidateExistsInLeaveList(leavelist, candidate) {
|
||||
for (var i = leavelist.length - 1; i >= 0; --i) {
|
||||
if (leavelist[i].node === candidate) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Controller.prototype.traverse = function traverse(root, visitor) {
|
||||
var worklist,
|
||||
leavelist,
|
||||
element,
|
||||
node,
|
||||
nodeType,
|
||||
ret,
|
||||
key,
|
||||
current,
|
||||
current2,
|
||||
candidates,
|
||||
candidate,
|
||||
sentinel;
|
||||
|
||||
this.__initialize(root, visitor);
|
||||
|
||||
sentinel = {};
|
||||
|
||||
// reference
|
||||
worklist = this.__worklist;
|
||||
leavelist = this.__leavelist;
|
||||
|
||||
// initialize
|
||||
worklist.push(new Element(root, null, null, null));
|
||||
leavelist.push(new Element(null, null, null, null));
|
||||
|
||||
while (worklist.length) {
|
||||
element = worklist.pop();
|
||||
|
||||
if (element === sentinel) {
|
||||
element = leavelist.pop();
|
||||
|
||||
ret = this.__execute(visitor.leave, element);
|
||||
|
||||
if (this.__state === BREAK || ret === BREAK) {
|
||||
return;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (element.node) {
|
||||
|
||||
ret = this.__execute(visitor.enter, element);
|
||||
|
||||
if (this.__state === BREAK || ret === BREAK) {
|
||||
return;
|
||||
}
|
||||
|
||||
worklist.push(sentinel);
|
||||
leavelist.push(element);
|
||||
|
||||
if (this.__state === SKIP || ret === SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
node = element.node;
|
||||
nodeType = node.type || element.wrap;
|
||||
candidates = this.__keys[nodeType];
|
||||
if (!candidates) {
|
||||
if (this.__fallback) {
|
||||
candidates = this.__fallback(node);
|
||||
} else {
|
||||
throw new Error('Unknown node type ' + nodeType + '.');
|
||||
}
|
||||
}
|
||||
|
||||
current = candidates.length;
|
||||
while ((current -= 1) >= 0) {
|
||||
key = candidates[current];
|
||||
candidate = node[key];
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(candidate)) {
|
||||
current2 = candidate.length;
|
||||
while ((current2 -= 1) >= 0) {
|
||||
if (!candidate[current2]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (candidateExistsInLeaveList(leavelist, candidate[current2])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isProperty(nodeType, candidates[current])) {
|
||||
element = new Element(candidate[current2], [key, current2], 'Property', null);
|
||||
} else if (isNode(candidate[current2])) {
|
||||
element = new Element(candidate[current2], [key, current2], null, null);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
worklist.push(element);
|
||||
}
|
||||
} else if (isNode(candidate)) {
|
||||
if (candidateExistsInLeaveList(leavelist, candidate)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
worklist.push(new Element(candidate, key, null, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Controller.prototype.replace = function replace(root, visitor) {
|
||||
var worklist,
|
||||
leavelist,
|
||||
node,
|
||||
nodeType,
|
||||
target,
|
||||
element,
|
||||
current,
|
||||
current2,
|
||||
candidates,
|
||||
candidate,
|
||||
sentinel,
|
||||
outer,
|
||||
key;
|
||||
|
||||
function removeElem(element) {
|
||||
var i,
|
||||
key,
|
||||
nextElem,
|
||||
parent;
|
||||
|
||||
if (element.ref.remove()) {
|
||||
// When the reference is an element of an array.
|
||||
key = element.ref.key;
|
||||
parent = element.ref.parent;
|
||||
|
||||
// If removed from array, then decrease following items' keys.
|
||||
i = worklist.length;
|
||||
while (i--) {
|
||||
nextElem = worklist[i];
|
||||
if (nextElem.ref && nextElem.ref.parent === parent) {
|
||||
if (nextElem.ref.key < key) {
|
||||
break;
|
||||
}
|
||||
--nextElem.ref.key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.__initialize(root, visitor);
|
||||
|
||||
sentinel = {};
|
||||
|
||||
// reference
|
||||
worklist = this.__worklist;
|
||||
leavelist = this.__leavelist;
|
||||
|
||||
// initialize
|
||||
outer = {
|
||||
root: root
|
||||
};
|
||||
element = new Element(root, null, null, new Reference(outer, 'root'));
|
||||
worklist.push(element);
|
||||
leavelist.push(element);
|
||||
|
||||
while (worklist.length) {
|
||||
element = worklist.pop();
|
||||
|
||||
if (element === sentinel) {
|
||||
element = leavelist.pop();
|
||||
|
||||
target = this.__execute(visitor.leave, element);
|
||||
|
||||
// node may be replaced with null,
|
||||
// so distinguish between undefined and null in this place
|
||||
if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
|
||||
// replace
|
||||
element.ref.replace(target);
|
||||
}
|
||||
|
||||
if (this.__state === REMOVE || target === REMOVE) {
|
||||
removeElem(element);
|
||||
}
|
||||
|
||||
if (this.__state === BREAK || target === BREAK) {
|
||||
return outer.root;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
target = this.__execute(visitor.enter, element);
|
||||
|
||||
// node may be replaced with null,
|
||||
// so distinguish between undefined and null in this place
|
||||
if (target !== undefined && target !== BREAK && target !== SKIP && target !== REMOVE) {
|
||||
// replace
|
||||
element.ref.replace(target);
|
||||
element.node = target;
|
||||
}
|
||||
|
||||
if (this.__state === REMOVE || target === REMOVE) {
|
||||
removeElem(element);
|
||||
element.node = null;
|
||||
}
|
||||
|
||||
if (this.__state === BREAK || target === BREAK) {
|
||||
return outer.root;
|
||||
}
|
||||
|
||||
// node may be null
|
||||
node = element.node;
|
||||
if (!node) {
|
||||
continue;
|
||||
}
|
||||
|
||||
worklist.push(sentinel);
|
||||
leavelist.push(element);
|
||||
|
||||
if (this.__state === SKIP || target === SKIP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodeType = node.type || element.wrap;
|
||||
candidates = this.__keys[nodeType];
|
||||
if (!candidates) {
|
||||
if (this.__fallback) {
|
||||
candidates = this.__fallback(node);
|
||||
} else {
|
||||
throw new Error('Unknown node type ' + nodeType + '.');
|
||||
}
|
||||
}
|
||||
|
||||
current = candidates.length;
|
||||
while ((current -= 1) >= 0) {
|
||||
key = candidates[current];
|
||||
candidate = node[key];
|
||||
if (!candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Array.isArray(candidate)) {
|
||||
current2 = candidate.length;
|
||||
while ((current2 -= 1) >= 0) {
|
||||
if (!candidate[current2]) {
|
||||
continue;
|
||||
}
|
||||
if (isProperty(nodeType, candidates[current])) {
|
||||
element = new Element(candidate[current2], [key, current2], 'Property', new Reference(candidate, current2));
|
||||
} else if (isNode(candidate[current2])) {
|
||||
element = new Element(candidate[current2], [key, current2], null, new Reference(candidate, current2));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
worklist.push(element);
|
||||
}
|
||||
} else if (isNode(candidate)) {
|
||||
worklist.push(new Element(candidate, key, null, new Reference(node, key)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return outer.root;
|
||||
};
|
||||
|
||||
function traverse(root, visitor) {
|
||||
var controller = new Controller();
|
||||
return controller.traverse(root, visitor);
|
||||
}
|
||||
|
||||
function replace(root, visitor) {
|
||||
var controller = new Controller();
|
||||
return controller.replace(root, visitor);
|
||||
}
|
||||
|
||||
function extendCommentRange(comment, tokens) {
|
||||
var target;
|
||||
|
||||
target = upperBound(tokens, function search(token) {
|
||||
return token.range[0] > comment.range[0];
|
||||
});
|
||||
|
||||
comment.extendedRange = [comment.range[0], comment.range[1]];
|
||||
|
||||
if (target !== tokens.length) {
|
||||
comment.extendedRange[1] = tokens[target].range[0];
|
||||
}
|
||||
|
||||
target -= 1;
|
||||
if (target >= 0) {
|
||||
comment.extendedRange[0] = tokens[target].range[1];
|
||||
}
|
||||
|
||||
return comment;
|
||||
}
|
||||
|
||||
function attachComments(tree, providedComments, tokens) {
|
||||
// At first, we should calculate extended comment ranges.
|
||||
var comments = [], comment, len, i, cursor;
|
||||
|
||||
if (!tree.range) {
|
||||
throw new Error('attachComments needs range information');
|
||||
}
|
||||
|
||||
// tokens array is empty, we attach comments to tree as 'leadingComments'
|
||||
if (!tokens.length) {
|
||||
if (providedComments.length) {
|
||||
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
||||
comment = deepCopy(providedComments[i]);
|
||||
comment.extendedRange = [0, tree.range[0]];
|
||||
comments.push(comment);
|
||||
}
|
||||
tree.leadingComments = comments;
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
|
||||
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
||||
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
|
||||
}
|
||||
|
||||
// This is based on John Freeman's implementation.
|
||||
cursor = 0;
|
||||
traverse(tree, {
|
||||
enter: function (node) {
|
||||
var comment;
|
||||
|
||||
while (cursor < comments.length) {
|
||||
comment = comments[cursor];
|
||||
if (comment.extendedRange[1] > node.range[0]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (comment.extendedRange[1] === node.range[0]) {
|
||||
if (!node.leadingComments) {
|
||||
node.leadingComments = [];
|
||||
}
|
||||
node.leadingComments.push(comment);
|
||||
comments.splice(cursor, 1);
|
||||
} else {
|
||||
cursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already out of owned node
|
||||
if (cursor === comments.length) {
|
||||
return VisitorOption.Break;
|
||||
}
|
||||
|
||||
if (comments[cursor].extendedRange[0] > node.range[1]) {
|
||||
return VisitorOption.Skip;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
cursor = 0;
|
||||
traverse(tree, {
|
||||
leave: function (node) {
|
||||
var comment;
|
||||
|
||||
while (cursor < comments.length) {
|
||||
comment = comments[cursor];
|
||||
if (node.range[1] < comment.extendedRange[0]) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (node.range[1] === comment.extendedRange[0]) {
|
||||
if (!node.trailingComments) {
|
||||
node.trailingComments = [];
|
||||
}
|
||||
node.trailingComments.push(comment);
|
||||
comments.splice(cursor, 1);
|
||||
} else {
|
||||
cursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// already out of owned node
|
||||
if (cursor === comments.length) {
|
||||
return VisitorOption.Break;
|
||||
}
|
||||
|
||||
if (comments[cursor].extendedRange[0] > node.range[1]) {
|
||||
return VisitorOption.Skip;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
exports.Syntax = Syntax;
|
||||
exports.traverse = traverse;
|
||||
exports.replace = replace;
|
||||
exports.attachComments = attachComments;
|
||||
exports.VisitorKeys = VisitorKeys;
|
||||
exports.VisitorOption = VisitorOption;
|
||||
exports.Controller = Controller;
|
||||
exports.cloneEnvironment = function () { return clone({}); };
|
||||
|
||||
return exports;
|
||||
}(exports));
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
Copyright (C) 2014 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp'),
|
||||
git = require('gulp-git'),
|
||||
bump = require('gulp-bump'),
|
||||
filter = require('gulp-filter'),
|
||||
tagVersion = require('gulp-tag-version');
|
||||
|
||||
var TEST = [ 'test/*.js' ];
|
||||
var POWERED = [ 'powered-test/*.js' ];
|
||||
var SOURCE = [ 'src/**/*.js' ];
|
||||
|
||||
/**
|
||||
* Bumping version number and tagging the repository with it.
|
||||
* Please read http://semver.org/
|
||||
*
|
||||
* You can use the commands
|
||||
*
|
||||
* gulp patch # makes v0.1.0 -> v0.1.1
|
||||
* gulp feature # makes v0.1.1 -> v0.2.0
|
||||
* gulp release # makes v0.2.1 -> v1.0.0
|
||||
*
|
||||
* To bump the version numbers accordingly after you did a patch,
|
||||
* introduced a feature or made a backwards-incompatible release.
|
||||
*/
|
||||
|
||||
function inc(importance) {
|
||||
// get all the files to bump version in
|
||||
return gulp.src(['./package.json'])
|
||||
// bump the version number in those files
|
||||
.pipe(bump({type: importance}))
|
||||
// save it back to filesystem
|
||||
.pipe(gulp.dest('./'))
|
||||
// commit the changed version number
|
||||
.pipe(git.commit('Bumps package version'))
|
||||
// read only one file to get the version number
|
||||
.pipe(filter('package.json'))
|
||||
// **tag it in the repository**
|
||||
.pipe(tagVersion({
|
||||
prefix: ''
|
||||
}));
|
||||
}
|
||||
|
||||
gulp.task('patch', [ ], function () { return inc('patch'); })
|
||||
gulp.task('minor', [ ], function () { return inc('minor'); })
|
||||
gulp.task('major', [ ], function () { return inc('major'); })
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "estraverse",
|
||||
"description": "ECMAScript JS AST traversal functions",
|
||||
"homepage": "https://github.com/estools/estraverse",
|
||||
"main": "estraverse.js",
|
||||
"version": "5.2.0",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "http://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/estools/estraverse.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-preset-env": "^1.6.1",
|
||||
"babel-register": "^6.3.13",
|
||||
"chai": "^2.1.1",
|
||||
"espree": "^1.11.0",
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-bump": "^0.2.2",
|
||||
"gulp-filter": "^2.0.0",
|
||||
"gulp-git": "^1.0.1",
|
||||
"gulp-tag-version": "^1.3.0",
|
||||
"jshint": "^2.5.6",
|
||||
"mocha": "^2.1.0"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "npm run-script lint && npm run-script unit-test",
|
||||
"lint": "jshint estraverse.js",
|
||||
"unit-test": "mocha --compilers js:babel-register"
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
### esutils [](http://travis-ci.org/estools/esutils)
|
||||
esutils ([esutils](http://github.com/estools/esutils)) is
|
||||
utility box for ECMAScript language tools.
|
||||
|
||||
### API
|
||||
|
||||
### ast
|
||||
|
||||
#### ast.isExpression(node)
|
||||
|
||||
Returns true if `node` is an Expression as defined in ECMA262 edition 5.1 section
|
||||
[11](https://es5.github.io/#x11).
|
||||
|
||||
#### ast.isStatement(node)
|
||||
|
||||
Returns true if `node` is a Statement as defined in ECMA262 edition 5.1 section
|
||||
[12](https://es5.github.io/#x12).
|
||||
|
||||
#### ast.isIterationStatement(node)
|
||||
|
||||
Returns true if `node` is an IterationStatement as defined in ECMA262 edition
|
||||
5.1 section [12.6](https://es5.github.io/#x12.6).
|
||||
|
||||
#### ast.isSourceElement(node)
|
||||
|
||||
Returns true if `node` is a SourceElement as defined in ECMA262 edition 5.1
|
||||
section [14](https://es5.github.io/#x14).
|
||||
|
||||
#### ast.trailingStatement(node)
|
||||
|
||||
Returns `Statement?` if `node` has trailing `Statement`.
|
||||
```js
|
||||
if (cond)
|
||||
consequent;
|
||||
```
|
||||
When taking this `IfStatement`, returns `consequent;` statement.
|
||||
|
||||
#### ast.isProblematicIfStatement(node)
|
||||
|
||||
Returns true if `node` is a problematic IfStatement. If `node` is a problematic `IfStatement`, `node` cannot be represented as an one on one JavaScript code.
|
||||
```js
|
||||
{
|
||||
type: 'IfStatement',
|
||||
consequent: {
|
||||
type: 'WithStatement',
|
||||
body: {
|
||||
type: 'IfStatement',
|
||||
consequent: {type: 'EmptyStatement'}
|
||||
}
|
||||
},
|
||||
alternate: {type: 'EmptyStatement'}
|
||||
}
|
||||
```
|
||||
The above node cannot be represented as a JavaScript code, since the top level `else` alternate belongs to an inner `IfStatement`.
|
||||
|
||||
|
||||
### code
|
||||
|
||||
#### code.isDecimalDigit(code)
|
||||
|
||||
Return true if provided code is decimal digit.
|
||||
|
||||
#### code.isHexDigit(code)
|
||||
|
||||
Return true if provided code is hexadecimal digit.
|
||||
|
||||
#### code.isOctalDigit(code)
|
||||
|
||||
Return true if provided code is octal digit.
|
||||
|
||||
#### code.isWhiteSpace(code)
|
||||
|
||||
Return true if provided code is white space. White space characters are formally defined in ECMA262.
|
||||
|
||||
#### code.isLineTerminator(code)
|
||||
|
||||
Return true if provided code is line terminator. Line terminator characters are formally defined in ECMA262.
|
||||
|
||||
#### code.isIdentifierStart(code)
|
||||
|
||||
Return true if provided code can be the first character of ECMA262 Identifier. They are formally defined in ECMA262.
|
||||
|
||||
#### code.isIdentifierPart(code)
|
||||
|
||||
Return true if provided code can be the trailing character of ECMA262 Identifier. They are formally defined in ECMA262.
|
||||
|
||||
### keyword
|
||||
|
||||
#### keyword.isKeywordES5(id, strict)
|
||||
|
||||
Returns `true` if provided identifier string is a Keyword or Future Reserved Word
|
||||
in ECMA262 edition 5.1. They are formally defined in ECMA262 sections
|
||||
[7.6.1.1](http://es5.github.io/#x7.6.1.1) and [7.6.1.2](http://es5.github.io/#x7.6.1.2),
|
||||
respectively. If the `strict` flag is truthy, this function additionally checks whether
|
||||
`id` is a Keyword or Future Reserved Word under strict mode.
|
||||
|
||||
#### keyword.isKeywordES6(id, strict)
|
||||
|
||||
Returns `true` if provided identifier string is a Keyword or Future Reserved Word
|
||||
in ECMA262 edition 6. They are formally defined in ECMA262 sections
|
||||
[11.6.2.1](http://ecma-international.org/ecma-262/6.0/#sec-keywords) and
|
||||
[11.6.2.2](http://ecma-international.org/ecma-262/6.0/#sec-future-reserved-words),
|
||||
respectively. If the `strict` flag is truthy, this function additionally checks whether
|
||||
`id` is a Keyword or Future Reserved Word under strict mode.
|
||||
|
||||
#### keyword.isReservedWordES5(id, strict)
|
||||
|
||||
Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 5.1.
|
||||
They are formally defined in ECMA262 section [7.6.1](http://es5.github.io/#x7.6.1).
|
||||
If the `strict` flag is truthy, this function additionally checks whether `id`
|
||||
is a Reserved Word under strict mode.
|
||||
|
||||
#### keyword.isReservedWordES6(id, strict)
|
||||
|
||||
Returns `true` if provided identifier string is a Reserved Word in ECMA262 edition 6.
|
||||
They are formally defined in ECMA262 section [11.6.2](http://ecma-international.org/ecma-262/6.0/#sec-reserved-words).
|
||||
If the `strict` flag is truthy, this function additionally checks whether `id`
|
||||
is a Reserved Word under strict mode.
|
||||
|
||||
#### keyword.isRestrictedWord(id)
|
||||
|
||||
Returns `true` if provided identifier string is one of `eval` or `arguments`.
|
||||
They are restricted in strict mode code throughout ECMA262 edition 5.1 and
|
||||
in ECMA262 edition 6 section [12.1.1](http://ecma-international.org/ecma-262/6.0/#sec-identifiers-static-semantics-early-errors).
|
||||
|
||||
#### keyword.isIdentifierNameES5(id)
|
||||
|
||||
Return true if provided identifier string is an IdentifierName as specified in
|
||||
ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6).
|
||||
|
||||
#### keyword.isIdentifierNameES6(id)
|
||||
|
||||
Return true if provided identifier string is an IdentifierName as specified in
|
||||
ECMA262 edition 6 section [11.6](http://ecma-international.org/ecma-262/6.0/#sec-names-and-keywords).
|
||||
|
||||
#### keyword.isIdentifierES5(id, strict)
|
||||
|
||||
Return true if provided identifier string is an Identifier as specified in
|
||||
ECMA262 edition 5.1 section [7.6](https://es5.github.io/#x7.6). If the `strict`
|
||||
flag is truthy, this function additionally checks whether `id` is an Identifier
|
||||
under strict mode.
|
||||
|
||||
#### keyword.isIdentifierES6(id, strict)
|
||||
|
||||
Return true if provided identifier string is an Identifier as specified in
|
||||
ECMA262 edition 6 section [12.1](http://ecma-international.org/ecma-262/6.0/#sec-identifiers).
|
||||
If the `strict` flag is truthy, this function additionally checks whether `id`
|
||||
is an Identifier under strict mode.
|
||||
|
||||
### License
|
||||
|
||||
Copyright (C) 2013 [Yusuke Suzuki](http://github.com/Constellation)
|
||||
(twitter: [@Constellation](http://twitter.com/Constellation)) and other contributors.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS'
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function isExpression(node) {
|
||||
if (node == null) { return false; }
|
||||
switch (node.type) {
|
||||
case 'ArrayExpression':
|
||||
case 'AssignmentExpression':
|
||||
case 'BinaryExpression':
|
||||
case 'CallExpression':
|
||||
case 'ConditionalExpression':
|
||||
case 'FunctionExpression':
|
||||
case 'Identifier':
|
||||
case 'Literal':
|
||||
case 'LogicalExpression':
|
||||
case 'MemberExpression':
|
||||
case 'NewExpression':
|
||||
case 'ObjectExpression':
|
||||
case 'SequenceExpression':
|
||||
case 'ThisExpression':
|
||||
case 'UnaryExpression':
|
||||
case 'UpdateExpression':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isIterationStatement(node) {
|
||||
if (node == null) { return false; }
|
||||
switch (node.type) {
|
||||
case 'DoWhileStatement':
|
||||
case 'ForInStatement':
|
||||
case 'ForStatement':
|
||||
case 'WhileStatement':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isStatement(node) {
|
||||
if (node == null) { return false; }
|
||||
switch (node.type) {
|
||||
case 'BlockStatement':
|
||||
case 'BreakStatement':
|
||||
case 'ContinueStatement':
|
||||
case 'DebuggerStatement':
|
||||
case 'DoWhileStatement':
|
||||
case 'EmptyStatement':
|
||||
case 'ExpressionStatement':
|
||||
case 'ForInStatement':
|
||||
case 'ForStatement':
|
||||
case 'IfStatement':
|
||||
case 'LabeledStatement':
|
||||
case 'ReturnStatement':
|
||||
case 'SwitchStatement':
|
||||
case 'ThrowStatement':
|
||||
case 'TryStatement':
|
||||
case 'VariableDeclaration':
|
||||
case 'WhileStatement':
|
||||
case 'WithStatement':
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isSourceElement(node) {
|
||||
return isStatement(node) || node != null && node.type === 'FunctionDeclaration';
|
||||
}
|
||||
|
||||
function trailingStatement(node) {
|
||||
switch (node.type) {
|
||||
case 'IfStatement':
|
||||
if (node.alternate != null) {
|
||||
return node.alternate;
|
||||
}
|
||||
return node.consequent;
|
||||
|
||||
case 'LabeledStatement':
|
||||
case 'ForStatement':
|
||||
case 'ForInStatement':
|
||||
case 'WhileStatement':
|
||||
case 'WithStatement':
|
||||
return node.body;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isProblematicIfStatement(node) {
|
||||
var current;
|
||||
|
||||
if (node.type !== 'IfStatement') {
|
||||
return false;
|
||||
}
|
||||
if (node.alternate == null) {
|
||||
return false;
|
||||
}
|
||||
current = node.consequent;
|
||||
do {
|
||||
if (current.type === 'IfStatement') {
|
||||
if (current.alternate == null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
current = trailingStatement(current);
|
||||
} while (current);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isExpression: isExpression,
|
||||
isStatement: isStatement,
|
||||
isIterationStatement: isIterationStatement,
|
||||
isSourceElement: isSourceElement,
|
||||
isProblematicIfStatement: isProblematicIfStatement,
|
||||
|
||||
trailingStatement: trailingStatement
|
||||
};
|
||||
}());
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+135
File diff suppressed because one or more lines are too long
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var code = require('./code');
|
||||
|
||||
function isStrictModeReservedWordES6(id) {
|
||||
switch (id) {
|
||||
case 'implements':
|
||||
case 'interface':
|
||||
case 'package':
|
||||
case 'private':
|
||||
case 'protected':
|
||||
case 'public':
|
||||
case 'static':
|
||||
case 'let':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isKeywordES5(id, strict) {
|
||||
// yield should not be treated as keyword under non-strict mode.
|
||||
if (!strict && id === 'yield') {
|
||||
return false;
|
||||
}
|
||||
return isKeywordES6(id, strict);
|
||||
}
|
||||
|
||||
function isKeywordES6(id, strict) {
|
||||
if (strict && isStrictModeReservedWordES6(id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (id.length) {
|
||||
case 2:
|
||||
return (id === 'if') || (id === 'in') || (id === 'do');
|
||||
case 3:
|
||||
return (id === 'var') || (id === 'for') || (id === 'new') || (id === 'try');
|
||||
case 4:
|
||||
return (id === 'this') || (id === 'else') || (id === 'case') ||
|
||||
(id === 'void') || (id === 'with') || (id === 'enum');
|
||||
case 5:
|
||||
return (id === 'while') || (id === 'break') || (id === 'catch') ||
|
||||
(id === 'throw') || (id === 'const') || (id === 'yield') ||
|
||||
(id === 'class') || (id === 'super');
|
||||
case 6:
|
||||
return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
|
||||
(id === 'switch') || (id === 'export') || (id === 'import');
|
||||
case 7:
|
||||
return (id === 'default') || (id === 'finally') || (id === 'extends');
|
||||
case 8:
|
||||
return (id === 'function') || (id === 'continue') || (id === 'debugger');
|
||||
case 10:
|
||||
return (id === 'instanceof');
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isReservedWordES5(id, strict) {
|
||||
return id === 'null' || id === 'true' || id === 'false' || isKeywordES5(id, strict);
|
||||
}
|
||||
|
||||
function isReservedWordES6(id, strict) {
|
||||
return id === 'null' || id === 'true' || id === 'false' || isKeywordES6(id, strict);
|
||||
}
|
||||
|
||||
function isRestrictedWord(id) {
|
||||
return id === 'eval' || id === 'arguments';
|
||||
}
|
||||
|
||||
function isIdentifierNameES5(id) {
|
||||
var i, iz, ch;
|
||||
|
||||
if (id.length === 0) { return false; }
|
||||
|
||||
ch = id.charCodeAt(0);
|
||||
if (!code.isIdentifierStartES5(ch)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 1, iz = id.length; i < iz; ++i) {
|
||||
ch = id.charCodeAt(i);
|
||||
if (!code.isIdentifierPartES5(ch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function decodeUtf16(lead, trail) {
|
||||
return (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000;
|
||||
}
|
||||
|
||||
function isIdentifierNameES6(id) {
|
||||
var i, iz, ch, lowCh, check;
|
||||
|
||||
if (id.length === 0) { return false; }
|
||||
|
||||
check = code.isIdentifierStartES6;
|
||||
for (i = 0, iz = id.length; i < iz; ++i) {
|
||||
ch = id.charCodeAt(i);
|
||||
if (0xD800 <= ch && ch <= 0xDBFF) {
|
||||
++i;
|
||||
if (i >= iz) { return false; }
|
||||
lowCh = id.charCodeAt(i);
|
||||
if (!(0xDC00 <= lowCh && lowCh <= 0xDFFF)) {
|
||||
return false;
|
||||
}
|
||||
ch = decodeUtf16(ch, lowCh);
|
||||
}
|
||||
if (!check(ch)) {
|
||||
return false;
|
||||
}
|
||||
check = code.isIdentifierPartES6;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function isIdentifierES5(id, strict) {
|
||||
return isIdentifierNameES5(id) && !isReservedWordES5(id, strict);
|
||||
}
|
||||
|
||||
function isIdentifierES6(id, strict) {
|
||||
return isIdentifierNameES6(id) && !isReservedWordES6(id, strict);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isKeywordES5: isKeywordES5,
|
||||
isKeywordES6: isKeywordES6,
|
||||
isReservedWordES5: isReservedWordES5,
|
||||
isReservedWordES6: isReservedWordES6,
|
||||
isRestrictedWord: isRestrictedWord,
|
||||
isIdentifierNameES5: isIdentifierNameES5,
|
||||
isIdentifierNameES6: isIdentifierNameES6,
|
||||
isIdentifierES5: isIdentifierES5,
|
||||
isIdentifierES6: isIdentifierES6
|
||||
};
|
||||
}());
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright (C) 2013 Yusuke Suzuki <utatane.tea@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
exports.ast = require('./ast');
|
||||
exports.code = require('./code');
|
||||
exports.keyword = require('./keyword');
|
||||
}());
|
||||
/* vim: set sw=4 ts=4 et tw=80 : */
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "esutils",
|
||||
"description": "utility box for ECMAScript language tools",
|
||||
"homepage": "https://github.com/estools/esutils",
|
||||
"main": "lib/utils.js",
|
||||
"version": "2.0.3",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"directories": {
|
||||
"lib": "./lib"
|
||||
},
|
||||
"files": [
|
||||
"LICENSE.BSD",
|
||||
"README.md",
|
||||
"lib"
|
||||
],
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "Yusuke Suzuki",
|
||||
"email": "utatane.tea@gmail.com",
|
||||
"web": "http://github.com/Constellation"
|
||||
}
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "http://github.com/estools/esutils.git"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chai": "~1.7.2",
|
||||
"coffee-script": "~1.6.3",
|
||||
"jshint": "2.6.3",
|
||||
"mocha": "~2.2.1",
|
||||
"regenerate": "~1.3.1",
|
||||
"unicode-9.0.0": "~0.7.0"
|
||||
},
|
||||
"license": "BSD-2-Clause",
|
||||
"scripts": {
|
||||
"test": "npm run-script lint && npm run-script unit-test",
|
||||
"lint": "jshint lib/*.js",
|
||||
"unit-test": "mocha --compilers coffee:coffee-script -R spec",
|
||||
"generate-regex": "node tools/generate-identifier-regex.js"
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
(MIT License)
|
||||
|
||||
Copyright (c) 2013 [Ramesh Nair](http://www.hiddentao.com/)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
# fast-levenshtein - Levenshtein algorithm in Javascript
|
||||
|
||||
[](http://travis-ci.org/hiddentao/fast-levenshtein)
|
||||
[](https://badge.fury.io/js/fast-levenshtein)
|
||||
[](https://www.npmjs.com/package/fast-levenshtein)
|
||||
[](https://twitter.com/hiddentao)
|
||||
|
||||
An efficient Javascript implementation of the [Levenshtein algorithm](http://en.wikipedia.org/wiki/Levenshtein_distance) with locale-specific collator support.
|
||||
|
||||
## Features
|
||||
|
||||
* Works in node.js and in the browser.
|
||||
* Better performance than other implementations by not needing to store the whole matrix ([more info](http://www.codeproject.com/Articles/13525/Fast-memory-efficient-Levenshtein-algorithm)).
|
||||
* Locale-sensitive string comparisions if needed.
|
||||
* Comprehensive test suite and performance benchmark.
|
||||
* Small: <1 KB minified and gzipped
|
||||
|
||||
## Installation
|
||||
|
||||
### node.js
|
||||
|
||||
Install using [npm](http://npmjs.org/):
|
||||
|
||||
```bash
|
||||
$ npm install fast-levenshtein
|
||||
```
|
||||
|
||||
### Browser
|
||||
|
||||
Using bower:
|
||||
|
||||
```bash
|
||||
$ bower install fast-levenshtein
|
||||
```
|
||||
|
||||
If you are not using any module loader system then the API will then be accessible via the `window.Levenshtein` object.
|
||||
|
||||
## Examples
|
||||
|
||||
**Default usage**
|
||||
|
||||
```javascript
|
||||
var levenshtein = require('fast-levenshtein');
|
||||
|
||||
var distance = levenshtein.get('back', 'book'); // 2
|
||||
var distance = levenshtein.get('我愛你', '我叫你'); // 1
|
||||
```
|
||||
|
||||
**Locale-sensitive string comparisons**
|
||||
|
||||
It supports using [Intl.Collator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Collator) for locale-sensitive string comparisons:
|
||||
|
||||
```javascript
|
||||
var levenshtein = require('fast-levenshtein');
|
||||
|
||||
levenshtein.get('mikailovitch', 'Mikhaïlovitch', { useCollator: true});
|
||||
// 1
|
||||
```
|
||||
|
||||
## Building and Testing
|
||||
|
||||
To build the code and run the tests:
|
||||
|
||||
```bash
|
||||
$ npm install -g grunt-cli
|
||||
$ npm install
|
||||
$ npm run build
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
_Thanks to [Titus Wormer](https://github.com/wooorm) for [encouraging me](https://github.com/hiddentao/fast-levenshtein/issues/1) to do this._
|
||||
|
||||
Benchmarked against other node.js levenshtein distance modules (on Macbook Air 2012, Core i7, 8GB RAM):
|
||||
|
||||
```bash
|
||||
Running suite Implementation comparison [benchmark/speed.js]...
|
||||
>> levenshtein-edit-distance x 234 ops/sec ±3.02% (73 runs sampled)
|
||||
>> levenshtein-component x 422 ops/sec ±4.38% (83 runs sampled)
|
||||
>> levenshtein-deltas x 283 ops/sec ±3.83% (78 runs sampled)
|
||||
>> natural x 255 ops/sec ±0.76% (88 runs sampled)
|
||||
>> levenshtein x 180 ops/sec ±3.55% (86 runs sampled)
|
||||
>> fast-levenshtein x 1,792 ops/sec ±2.72% (95 runs sampled)
|
||||
Benchmark done.
|
||||
Fastest test is fast-levenshtein at 4.2x faster than levenshtein-component
|
||||
```
|
||||
|
||||
You can run this benchmark yourself by doing:
|
||||
|
||||
```bash
|
||||
$ npm install
|
||||
$ npm run build
|
||||
$ npm run benchmark
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
If you wish to submit a pull request please update and/or create new tests for any changes you make and ensure the grunt build passes.
|
||||
|
||||
See [CONTRIBUTING.md](https://github.com/hiddentao/fast-levenshtein/blob/master/CONTRIBUTING.md) for details.
|
||||
|
||||
## License
|
||||
|
||||
MIT - see [LICENSE.md](https://github.com/hiddentao/fast-levenshtein/blob/master/LICENSE.md)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user