mirror of https://gitee.com/bigwinds/arangodb
Bump jshint to 2.9.2
This commit is contained in:
parent
f81c946fd7
commit
2bd0f59d9d
|
@ -5,7 +5,6 @@
|
|||
"esnext": true,
|
||||
"forin": true,
|
||||
"freeze": true,
|
||||
"globalstrict": true,
|
||||
"immed": true,
|
||||
"indent": 2,
|
||||
"laxbreak": true,
|
||||
|
|
|
@ -37,9 +37,20 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Object.defineProperty(Object.prototype, '_shallowCopy', {
|
||||
set(value) {
|
||||
if (this === Object.prototype) {
|
||||
throw new TypeError(`Can not override Object.prototype._shallowCopy!`);
|
||||
}
|
||||
Object.defineProperty(this, '_shallowCopy', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value
|
||||
});
|
||||
},
|
||||
get() {
|
||||
var self = this;
|
||||
return this.propertyKeys.reduce(function (previous, key) {
|
||||
return Object.prototype.propertyKeys.reduce(function (previous, key) {
|
||||
previous[key] = self[key];
|
||||
return previous;
|
||||
}, {});
|
||||
|
@ -55,7 +66,18 @@ Object.defineProperty(Object.prototype, 'propertyKeys', {
|
|||
return Object.keys(this).filter(function (key) {
|
||||
return (key.charAt(0) !== '_' && key.charAt(0) !== '$');
|
||||
});
|
||||
}
|
||||
},
|
||||
set(value) {
|
||||
if (this === Object.prototype) {
|
||||
throw new TypeError(`Can not override Object.prototype.propertyKeys!`);
|
||||
}
|
||||
Object.defineProperty(this, 'propertyKeys', {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
writable: true,
|
||||
value
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,9 @@
|
|||
# JSHint, A Static Code Analysis Tool for JavaScript
|
||||
|
||||
\[ [Use it online](http://jshint.com/) • [About](http://jshint.com/about/) •
|
||||
\[ [Use it online](http://jshint.com/) •
|
||||
[Docs](http://jshint.com/docs/) • [FAQ](http://jshint.com/docs/faq) •
|
||||
[Install](http://jshint.com/install/) • [Hack](http://jshint.com/hack/) •
|
||||
[Install](http://jshint.com/install/) •
|
||||
[Contribute](http://jshint.com/contribute/) •
|
||||
[Blog](http://jshint.com/blog/) • [Twitter](https://twitter.com/jshint/) \]
|
||||
|
||||
[](https://www.npmjs.com/package/jshint)
|
||||
|
@ -12,10 +13,33 @@
|
|||
[](https://david-dm.org/jshint/jshint#info=devDependencies)
|
||||
[](https://coveralls.io/r/jshint/jshint?branch=master)
|
||||
|
||||
JSHint is a community-driven tool to detect errors and potential problems
|
||||
in JavaScript code. It is very flexible so you can easily adjust it to your
|
||||
particular coding guidelines and the environment you expect your code to
|
||||
execute in.
|
||||
JSHint is a community-driven tool to detect errors and potential problems in
|
||||
JavaScript code and to enforce your team's coding conventions. It is very
|
||||
flexible so you can easily adjust it to your particular coding guidelines and
|
||||
the environment you expect your code to execute in. JSHint is open source and
|
||||
will always stay this way.
|
||||
|
||||
## Our goal
|
||||
|
||||
The goal of this project is to help JavaScript developers write complex programs
|
||||
without worrying about typos and language gotchas.
|
||||
|
||||
Any code base eventually becomes huge at some point, and simple mistakes—that
|
||||
would not show themselves when written—can become show stoppers and waste
|
||||
hours of debugging. And this is when static code analysis tools come into play
|
||||
and help developers to spot such problems. JSHint scans a program written in
|
||||
JavaScript and reports about commonly made mistakes and potential bugs. The
|
||||
potential problem could be a syntax error, a bug due to implicit type
|
||||
conversion, a leaking variable or something else.
|
||||
|
||||
Only 15% of all programs linted on [jshint.com](http://jshint.com) pass the
|
||||
JSHint checks. In all other cases, JSHint finds some red flags that could've
|
||||
been bugs or potential problems.
|
||||
|
||||
Please note, that while static code analysis tools can spot many different kind
|
||||
of mistakes, it can't detect if your program is correct, fast or has memory
|
||||
leaks. You should always combine tools like JSHint with unit and functional
|
||||
tests as well as with code reviews.
|
||||
|
||||
## Reporting a bug
|
||||
|
||||
|
@ -31,25 +55,56 @@ JSHint including but not limited to:
|
|||
Before reporting a bug look around to see if there are any open or closed tickets
|
||||
that cover your issue. And remember the wisdom: pull request > bug report > tweet.
|
||||
|
||||
## Issue Priority
|
||||
## Who uses JSHint?
|
||||
|
||||
- *P1:* Something is throwing exceptions; broken JSHint backward compatibility.
|
||||
- *P2:* Something is not being parsed correctly.
|
||||
- *P3:* Features that the core team will work on once P2s and P1s are done.
|
||||
- *P4:* Patches welcome; The request is good, but low priority.
|
||||
Engineers from these companies and projects use JSHint:
|
||||
|
||||
* [Mozilla](https://www.mozilla.org/)
|
||||
* [Wikipedia](https://wikipedia.org/)
|
||||
* [Facebook](https://facebook.com/)
|
||||
* [Twitter](https://twitter.com/)
|
||||
* [Bootstrap](http://getbootstrap.com/)
|
||||
* [Disqus](https://disqus.com/)
|
||||
* [Medium](https://medium.com/)
|
||||
* [Yahoo!](https://yahoo.com/)
|
||||
* [SmugMug](http://smugmug.com/)
|
||||
* [jQuery](http://jquery.com/)
|
||||
* [PDF.js](http://mozilla.github.io/pdf.js)
|
||||
* [Coursera](http://coursera.com/)
|
||||
* [Adobe Brackets](http://brackets.io/)
|
||||
* [Apache Cordova](http://cordova.io/)
|
||||
* [RedHat](http://redhat.com/)
|
||||
* [SoundCloud](http://soundcloud.com/)
|
||||
* [Nodejitsu](http://nodejitsu.com/)
|
||||
* [Yelp](https://yelp.com/)
|
||||
* [Voxer](http://voxer.com/)
|
||||
* [EnyoJS](http://enyojs.com/)
|
||||
* [QuickenLoans](http://quickenloans.com/)
|
||||
* [oDesk](http://www.odesk.com/)
|
||||
* [Cloud9](http://c9.io/)
|
||||
* [CodeClimate](https://codeclimate.com/)
|
||||
* [Pandoo TEK](http://pandootek.com/)
|
||||
* [Zendesk](http://zendesk.com/)
|
||||
* [Apache CouchDB](http://couchdb.apache.org/)
|
||||
|
||||
And many more!
|
||||
|
||||
## License
|
||||
|
||||
JSHint is distributed under the MIT License. One file and one file only
|
||||
(src/stable/jshint.js) is distributed under the slightly modified MIT License.
|
||||
Most files are published using [the standard MIT Expat
|
||||
license](https://www.gnu.org/licenses/license-list.html#Expat). One file,
|
||||
however, is provided under a slightly modified version of that license. The
|
||||
so-called [JSON license](https://www.gnu.org/licenses/license-list.html#JSON)
|
||||
is a non-free license, and unfortunately, we can't change it due to historical
|
||||
reasons. This license is included as an in-line within the file it concerns.
|
||||
|
||||
## The JSHint Team
|
||||
|
||||
JSHint is maintained by [Rick Waldron](https://github.com/rwaldron/), [Caitlin
|
||||
Potter](https://github.com/caitp/), [Mike
|
||||
Sherov](https://github.com/mikesherov/), and [Mike
|
||||
Pennisi](https://github.com/jugglinmike/).
|
||||
JSHint is currently maintained by [Rick Waldron](https://github.com/rwaldron/),
|
||||
[Caitlin Potter](https://github.com/caitp/), [Mike
|
||||
Sherov](https://github.com/mikesherov/), [Mike
|
||||
Pennisi](https://github.com/jugglinmike/), and [Luke
|
||||
Page](https://github.com/lukeapage).
|
||||
|
||||
## Thank you!
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -3,4 +3,6 @@ node_js:
|
|||
- 0.10
|
||||
- 0.11
|
||||
|
||||
sudo: false
|
||||
|
||||
script: npm run coveralls
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
#htmlparser2
|
||||
# htmlparser2
|
||||
|
||||
[](https://npmjs.org/package/htmlparser2)
|
||||
[](https://npmjs.org/package/htmlparser2)
|
||||
[](http://travis-ci.org/fb55/htmlparser2)
|
||||
[](https://coveralls.io/r/fb55/htmlparser2)
|
||||
|
||||
A forgiving HTML/XML/RSS parser written in JS for NodeJS. The parser can handle streams (chunked data) and supports custom handlers for writing custom DOMs/output.
|
||||
A forgiving HTML/XML/RSS parser. The parser can handle streams and provides a callback interface.
|
||||
|
||||
##Installing
|
||||
## Installation
|
||||
npm install htmlparser2
|
||||
|
||||
A live demo of htmlparser2 is available at http://demos.forbeslindesay.co.uk/htmlparser2/
|
||||
A live demo of htmlparser2 is available [here](http://demos.forbeslindesay.co.uk/htmlparser2/).
|
||||
|
||||
##Usage
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var htmlparser = require("htmlparser2");
|
||||
|
@ -30,7 +30,7 @@ var parser = new htmlparser.Parser({
|
|||
console.log("That's it?!");
|
||||
}
|
||||
}
|
||||
});
|
||||
}, {decodeEntities: true});
|
||||
parser.write("Xyz <script type='text/javascript'>var foo = '<<bar>>';</ script>");
|
||||
parser.end();
|
||||
```
|
||||
|
@ -44,14 +44,16 @@ JS! Hooray!
|
|||
That's it?!
|
||||
```
|
||||
|
||||
Read more about the parser in the [wiki](https://github.com/fb55/htmlparser2/wiki/Parser-options).
|
||||
## Documentation
|
||||
|
||||
##Get a DOM
|
||||
Read more about the parser and its options in the [wiki](https://github.com/fb55/htmlparser2/wiki/Parser-options).
|
||||
|
||||
## Get a DOM
|
||||
The `DomHandler` (known as `DefaultHandler` in the original `htmlparser` module) produces a DOM (document object model) that can be manipulated using the [`DomUtils`](https://github.com/fb55/DomUtils) helper.
|
||||
|
||||
The `DomHandler`, while still bundled with this module, was moved to its [own module](https://github.com/fb55/domhandler). Have a look at it for further information.
|
||||
|
||||
##Parsing RSS/RDF/Atom Feeds
|
||||
## Parsing RSS/RDF/Atom Feeds
|
||||
|
||||
```javascript
|
||||
new htmlparser.FeedHandler(function(<error> error, <object> feed){
|
||||
|
@ -59,7 +61,9 @@ new htmlparser.FeedHandler(function(<error> error, <object> feed){
|
|||
});
|
||||
```
|
||||
|
||||
##Performance
|
||||
Note: While the provided feed handler works for most feeds, you might want to use [danmactough/node-feedparser](https://github.com/danmactough/node-feedparser), which is much better tested and actively maintained.
|
||||
|
||||
## Performance
|
||||
|
||||
After having some artificial benchmarks for some time, __@AndreasMadsen__ published his [`htmlparser-benchmark`](https://github.com/AndreasMadsen/htmlparser-benchmark), which benchmarks HTML parses based on real-world websites.
|
||||
|
||||
|
@ -78,9 +82,10 @@ parse5 : 22.0439 ms/file ± 15.3743
|
|||
sax : 49.6513 ms/file ± 26.6032
|
||||
```
|
||||
|
||||
##How is this different from [node-htmlparser](https://github.com/tautologistics/node-htmlparser)?
|
||||
## How does this module differ from [node-htmlparser](https://github.com/tautologistics/node-htmlparser)?
|
||||
|
||||
This is a fork of the `htmlparser` module. The main difference is that this is intended to be used only with node (it runs on other platforms using [browserify](https://github.com/substack/node-browserify)). `htmlparser2` was rewritten multiple times and, while it maintains an API that's compatible with `htmlparser` in most cases, the projects don't share any code anymore.
|
||||
|
||||
The parser now provides a callback interface close to [sax.js](https://github.com/isaacs/sax-js) (originally targeted at [readabilitySAX](https://github.com/fb55/readabilitysax)). As a result, old handlers won't work anymore.
|
||||
|
||||
The `DefaultHandler` and the `RssHandler` were renamed to clarify their purpose (to `DomHandler` and `FeedHandler`). The old names are still available when requiring `htmlparser2`, so your code should work as expected.
|
||||
The `DefaultHandler` and the `RssHandler` were renamed to clarify their purpose (to `DomHandler` and `FeedHandler`). The old names are still available when requiring `htmlparser2`, your code should work as expected.
|
||||
|
|
|
@ -3,7 +3,7 @@ var Tokenizer = require("./Tokenizer.js");
|
|||
/*
|
||||
Options:
|
||||
|
||||
xmlMode: Special behavior for script/style tags (true by default)
|
||||
xmlMode: Disables the special behavior for script/style tags (false by default)
|
||||
lowerCaseAttributeNames: call .toLowerCase for each attribute name (true if xmlMode is `false`)
|
||||
lowerCaseTags: call .toLowerCase for each tag name (true if xmlMode is `false`)
|
||||
*/
|
||||
|
@ -36,7 +36,7 @@ var formTags = {
|
|||
var openImpliesClose = {
|
||||
tr : { tr:true, th:true, td:true },
|
||||
th : { th:true },
|
||||
td : { thead:true, td:true },
|
||||
td : { thead:true, th:true, td:true },
|
||||
body : { head:true, link:true, script:true },
|
||||
li : { li:true },
|
||||
p : { p:true },
|
||||
|
@ -87,7 +87,7 @@ var voidElements = {
|
|||
use: true,
|
||||
stop: true,
|
||||
polyline: true,
|
||||
polygone: true
|
||||
polygon: true
|
||||
};
|
||||
|
||||
var re_nameEnd = /\s|\//;
|
||||
|
|
19
js/node/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/LICENSE
generated
vendored
Normal file
19
js/node/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
Copyright Node.js contributors. All rights reserved.
|
||||
|
||||
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.
|
|
@ -21,8 +21,12 @@
|
|||
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
function isArray(ar) {
|
||||
return Array.isArray(ar);
|
||||
|
||||
function isArray(arg) {
|
||||
if (Array.isArray) {
|
||||
return Array.isArray(arg);
|
||||
}
|
||||
return objectToString(arg) === '[object Array]';
|
||||
}
|
||||
exports.isArray = isArray;
|
||||
|
||||
|
@ -62,7 +66,7 @@ function isUndefined(arg) {
|
|||
exports.isUndefined = isUndefined;
|
||||
|
||||
function isRegExp(re) {
|
||||
return isObject(re) && objectToString(re) === '[object RegExp]';
|
||||
return objectToString(re) === '[object RegExp]';
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
|
@ -72,13 +76,12 @@ function isObject(arg) {
|
|||
exports.isObject = isObject;
|
||||
|
||||
function isDate(d) {
|
||||
return isObject(d) && objectToString(d) === '[object Date]';
|
||||
return objectToString(d) === '[object Date]';
|
||||
}
|
||||
exports.isDate = isDate;
|
||||
|
||||
function isError(e) {
|
||||
return isObject(e) &&
|
||||
(objectToString(e) === '[object Error]' || e instanceof Error);
|
||||
return (objectToString(e) === '[object Error]' || e instanceof Error);
|
||||
}
|
||||
exports.isError = isError;
|
||||
|
||||
|
@ -97,11 +100,8 @@ function isPrimitive(arg) {
|
|||
}
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
function isBuffer(arg) {
|
||||
return Buffer.isBuffer(arg);
|
||||
}
|
||||
exports.isBuffer = isBuffer;
|
||||
exports.isBuffer = Buffer.isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "core-util-is",
|
||||
"version": "1.0.1",
|
||||
"version": "1.0.2",
|
||||
"description": "The `util.is*` functions introduced in Node v0.12.",
|
||||
"main": "lib/util.js",
|
||||
"repository": {
|
||||
|
@ -27,20 +27,27 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/isaacs/core-util-is/issues"
|
||||
},
|
||||
"readme": "# core-util-is\n\nThe `util.is*` functions introduced in Node v0.12.\n",
|
||||
"readmeFilename": "README.md",
|
||||
"homepage": "https://github.com/isaacs/core-util-is",
|
||||
"_id": "core-util-is@1.0.1",
|
||||
"dist": {
|
||||
"shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538",
|
||||
"tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz"
|
||||
"scripts": {
|
||||
"test": "tap test.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tap": "^2.3.0"
|
||||
},
|
||||
"gitHead": "a177da234df5638b363ddc15fa324619a38577c8",
|
||||
"homepage": "https://github.com/isaacs/core-util-is#readme",
|
||||
"_id": "core-util-is@1.0.2",
|
||||
"_shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
|
||||
"_from": "core-util-is@>=1.0.0 <1.1.0",
|
||||
"_npmVersion": "1.3.23",
|
||||
"_npmVersion": "3.3.2",
|
||||
"_nodeVersion": "4.0.0",
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "b5fd54220aa2bc5ab57aab7140c940754503c1a7",
|
||||
"tarball": "http://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
|
@ -48,7 +55,6 @@
|
|||
}
|
||||
],
|
||||
"directories": {},
|
||||
"_shasum": "6b07085aef9a3ccac6ee53bf9d3df0c1521a5538",
|
||||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.1.tgz",
|
||||
"scripts": {}
|
||||
"_resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
||||
|
|
68
js/node/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/test.js
generated
vendored
Normal file
68
js/node/node_modules/jshint/node_modules/htmlparser2/node_modules/readable-stream/node_modules/core-util-is/test.js
generated
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
var assert = require('tap');
|
||||
|
||||
var t = require('./lib/util');
|
||||
|
||||
assert.equal(t.isArray([]), true);
|
||||
assert.equal(t.isArray({}), false);
|
||||
|
||||
assert.equal(t.isBoolean(null), false);
|
||||
assert.equal(t.isBoolean(true), true);
|
||||
assert.equal(t.isBoolean(false), true);
|
||||
|
||||
assert.equal(t.isNull(null), true);
|
||||
assert.equal(t.isNull(undefined), false);
|
||||
assert.equal(t.isNull(false), false);
|
||||
assert.equal(t.isNull(), false);
|
||||
|
||||
assert.equal(t.isNullOrUndefined(null), true);
|
||||
assert.equal(t.isNullOrUndefined(undefined), true);
|
||||
assert.equal(t.isNullOrUndefined(false), false);
|
||||
assert.equal(t.isNullOrUndefined(), true);
|
||||
|
||||
assert.equal(t.isNumber(null), false);
|
||||
assert.equal(t.isNumber('1'), false);
|
||||
assert.equal(t.isNumber(1), true);
|
||||
|
||||
assert.equal(t.isString(null), false);
|
||||
assert.equal(t.isString('1'), true);
|
||||
assert.equal(t.isString(1), false);
|
||||
|
||||
assert.equal(t.isSymbol(null), false);
|
||||
assert.equal(t.isSymbol('1'), false);
|
||||
assert.equal(t.isSymbol(1), false);
|
||||
assert.equal(t.isSymbol(Symbol()), true);
|
||||
|
||||
assert.equal(t.isUndefined(null), false);
|
||||
assert.equal(t.isUndefined(undefined), true);
|
||||
assert.equal(t.isUndefined(false), false);
|
||||
assert.equal(t.isUndefined(), true);
|
||||
|
||||
assert.equal(t.isRegExp(null), false);
|
||||
assert.equal(t.isRegExp('1'), false);
|
||||
assert.equal(t.isRegExp(new RegExp()), true);
|
||||
|
||||
assert.equal(t.isObject({}), true);
|
||||
assert.equal(t.isObject([]), true);
|
||||
assert.equal(t.isObject(new RegExp()), true);
|
||||
assert.equal(t.isObject(new Date()), true);
|
||||
|
||||
assert.equal(t.isDate(null), false);
|
||||
assert.equal(t.isDate('1'), false);
|
||||
assert.equal(t.isDate(new Date()), true);
|
||||
|
||||
assert.equal(t.isError(null), false);
|
||||
assert.equal(t.isError({ err: true }), false);
|
||||
assert.equal(t.isError(new Error()), true);
|
||||
|
||||
assert.equal(t.isFunction(null), false);
|
||||
assert.equal(t.isFunction({ }), false);
|
||||
assert.equal(t.isFunction(function() {}), true);
|
||||
|
||||
assert.equal(t.isPrimitive(null), true);
|
||||
assert.equal(t.isPrimitive(''), true);
|
||||
assert.equal(t.isPrimitive(0), true);
|
||||
assert.equal(t.isPrimitive(new Date()), false);
|
||||
|
||||
assert.equal(t.isBuffer(null), false);
|
||||
assert.equal(t.isBuffer({}), false);
|
||||
assert.equal(t.isBuffer(new Buffer(0)), true);
|
|
@ -1,106 +0,0 @@
|
|||
// Copyright Joyent, Inc. and other Node contributors.
|
||||
//
|
||||
// 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.
|
||||
|
||||
// NOTE: These type checking functions intentionally don't use `instanceof`
|
||||
// because it is fragile and can be easily faked with `Object.create()`.
|
||||
function isArray(ar) {
|
||||
return Array.isArray(ar);
|
||||
}
|
||||
exports.isArray = isArray;
|
||||
|
||||
function isBoolean(arg) {
|
||||
return typeof arg === 'boolean';
|
||||
}
|
||||
exports.isBoolean = isBoolean;
|
||||
|
||||
function isNull(arg) {
|
||||
return arg === null;
|
||||
}
|
||||
exports.isNull = isNull;
|
||||
|
||||
function isNullOrUndefined(arg) {
|
||||
return arg == null;
|
||||
}
|
||||
exports.isNullOrUndefined = isNullOrUndefined;
|
||||
|
||||
function isNumber(arg) {
|
||||
return typeof arg === 'number';
|
||||
}
|
||||
exports.isNumber = isNumber;
|
||||
|
||||
function isString(arg) {
|
||||
return typeof arg === 'string';
|
||||
}
|
||||
exports.isString = isString;
|
||||
|
||||
function isSymbol(arg) {
|
||||
return typeof arg === 'symbol';
|
||||
}
|
||||
exports.isSymbol = isSymbol;
|
||||
|
||||
function isUndefined(arg) {
|
||||
return arg === void 0;
|
||||
}
|
||||
exports.isUndefined = isUndefined;
|
||||
|
||||
function isRegExp(re) {
|
||||
return isObject(re) && objectToString(re) === '[object RegExp]';
|
||||
}
|
||||
exports.isRegExp = isRegExp;
|
||||
|
||||
function isObject(arg) {
|
||||
return typeof arg === 'object' && arg !== null;
|
||||
}
|
||||
exports.isObject = isObject;
|
||||
|
||||
function isDate(d) {
|
||||
return isObject(d) && objectToString(d) === '[object Date]';
|
||||
}
|
||||
exports.isDate = isDate;
|
||||
|
||||
function isError(e) {
|
||||
return isObject(e) && objectToString(e) === '[object Error]';
|
||||
}
|
||||
exports.isError = isError;
|
||||
|
||||
function isFunction(arg) {
|
||||
return typeof arg === 'function';
|
||||
}
|
||||
exports.isFunction = isFunction;
|
||||
|
||||
function isPrimitive(arg) {
|
||||
return arg === null ||
|
||||
typeof arg === 'boolean' ||
|
||||
typeof arg === 'number' ||
|
||||
typeof arg === 'string' ||
|
||||
typeof arg === 'symbol' || // ES6 symbol
|
||||
typeof arg === 'undefined';
|
||||
}
|
||||
exports.isPrimitive = isPrimitive;
|
||||
|
||||
function isBuffer(arg) {
|
||||
return arg instanceof Buffer;
|
||||
}
|
||||
exports.isBuffer = isBuffer;
|
||||
|
||||
function objectToString(o) {
|
||||
return Object.prototype.toString.call(o);
|
||||
}
|
|
@ -27,25 +27,9 @@
|
|||
"bugs": {
|
||||
"url": "https://github.com/isaacs/inherits/issues"
|
||||
},
|
||||
"homepage": "https://github.com/isaacs/inherits#readme",
|
||||
"_id": "inherits@2.0.1",
|
||||
"dist": {
|
||||
"shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
||||
"tarball": "http://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"
|
||||
},
|
||||
"_from": "inherits@>=2.0.1 <2.1.0",
|
||||
"_npmVersion": "1.3.8",
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
}
|
||||
],
|
||||
"directories": {},
|
||||
"_shasum": "b17d08d326b4423e568eff719f91b0b1cbdf69f1",
|
||||
"_resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
|
||||
"homepage": "https://github.com/isaacs/inherits"
|
||||
"_from": "inherits@>=2.0.1 <2.1.0"
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "readable-stream",
|
||||
"version": "1.1.13",
|
||||
"version": "1.1.14",
|
||||
"description": "Streams3, a user-land copy of the stream library from Node.js v0.11.x",
|
||||
"main": "readable.js",
|
||||
"dependencies": {
|
||||
|
@ -33,23 +33,27 @@
|
|||
"url": "http://blog.izs.me/"
|
||||
},
|
||||
"license": "MIT",
|
||||
"gitHead": "3b672fd7ae92acf5b4ffdbabf74b372a0a56b051",
|
||||
"gitHead": "52550840cb1d6e8a98ef9a909a4bea360bc6f7da",
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/readable-stream/issues"
|
||||
},
|
||||
"homepage": "https://github.com/isaacs/readable-stream",
|
||||
"_id": "readable-stream@1.1.13",
|
||||
"_shasum": "f6eef764f514c89e2b9e23146a75ba106756d23e",
|
||||
"_id": "readable-stream@1.1.14",
|
||||
"_shasum": "7cf4c54ef648e3813084c636dd2079e166c081d9",
|
||||
"_from": "readable-stream@>=1.1.0 <1.2.0",
|
||||
"_npmVersion": "1.4.23",
|
||||
"_npmVersion": "3.8.3",
|
||||
"_nodeVersion": "5.10.1",
|
||||
"_npmUser": {
|
||||
"name": "rvagg",
|
||||
"email": "rod@vagg.org"
|
||||
"name": "cwmma",
|
||||
"email": "calvin.metcalf@gmail.com"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "7cf4c54ef648e3813084c636dd2079e166c081d9",
|
||||
"tarball": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
"email": "isaacs@npmjs.com"
|
||||
},
|
||||
{
|
||||
"name": "tootallnate",
|
||||
|
@ -58,13 +62,18 @@
|
|||
{
|
||||
"name": "rvagg",
|
||||
"email": "rod@vagg.org"
|
||||
},
|
||||
{
|
||||
"name": "cwmma",
|
||||
"email": "calvin.metcalf@gmail.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "f6eef764f514c89e2b9e23146a75ba106756d23e",
|
||||
"tarball": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz"
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/readable-stream-1.1.14.tgz_1460563293219_0.5682175166439265"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.13.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
"_resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
|
||||
"readme": "ERROR: No README data found!",
|
||||
"homepage": "https://github.com/isaacs/readable-stream#readme"
|
||||
}
|
||||
|
|
|
@ -5,3 +5,6 @@ exports.Writable = require('./lib/_stream_writable.js');
|
|||
exports.Duplex = require('./lib/_stream_duplex.js');
|
||||
exports.Transform = require('./lib/_stream_transform.js');
|
||||
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
||||
if (!process.browser && process.env.READABLE_STREAM === 'disable') {
|
||||
module.exports = require('stream');
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "htmlparser2",
|
||||
"description": "Fast & forgiving HTML/XML/RSS parser",
|
||||
"version": "3.8.2",
|
||||
"version": "3.8.3",
|
||||
"author": {
|
||||
"name": "Felix Boehm",
|
||||
"email": "me@feedic.com"
|
||||
|
@ -71,13 +71,13 @@
|
|||
"it": true
|
||||
}
|
||||
},
|
||||
"gitHead": "748d3da71dc664afb8357aabfe6c4a6f74644a0e",
|
||||
"homepage": "https://github.com/fb55/htmlparser2",
|
||||
"_id": "htmlparser2@3.8.2",
|
||||
"_shasum": "0d6bc3471d01e9766fc2c274cbac1d55b36c009c",
|
||||
"gitHead": "44e48f58526de05d2639199f4baaaef235521f6b",
|
||||
"homepage": "https://github.com/fb55/htmlparser2#readme",
|
||||
"_id": "htmlparser2@3.8.3",
|
||||
"_shasum": "996c28b191516a8be86501a7d79757e5c70c1068",
|
||||
"_from": "htmlparser2@>=3.8.0 <3.9.0",
|
||||
"_npmVersion": "2.1.5",
|
||||
"_nodeVersion": "0.10.32",
|
||||
"_npmVersion": "2.11.1",
|
||||
"_nodeVersion": "2.2.1",
|
||||
"_npmUser": {
|
||||
"name": "feedic",
|
||||
"email": "me@feedic.com"
|
||||
|
@ -89,9 +89,9 @@
|
|||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "0d6bc3471d01e9766fc2c274cbac1d55b36c009c",
|
||||
"tarball": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz"
|
||||
"shasum": "996c28b191516a8be86501a7d79757e5c70c1068",
|
||||
"tarball": "http://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz"
|
||||
},
|
||||
"_resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.2.tgz",
|
||||
"_resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "Implicit close tags",
|
||||
"options": {},
|
||||
"html": "<ol><li class=test><div><table style=width:100%><tr><td colspan=2><h3>Heading</h3><tr><td><div>Div</div><td><div>Div2</div></table></div><li><div><h3>Heading 2</h3></div></li></ol><p>Para<h4>Heading 4</h4>",
|
||||
"html": "<ol><li class=test><div><table style=width:100%><tr><th>TH<td colspan=2><h3>Heading</h3><tr><td><div>Div</div><td><div>Div2</div></table></div><li><div><h3>Heading 2</h3></div></li></ol><p>Para<h4>Heading 4</h4>",
|
||||
"expected": [
|
||||
{ "event": "opentagname", "data": [ "ol" ] },
|
||||
{ "event": "opentag", "data": [ "ol", {} ] },
|
||||
|
@ -15,6 +15,10 @@
|
|||
{ "event": "opentag", "data": [ "table", { "style": "width:100%" } ] },
|
||||
{ "event": "opentagname", "data": [ "tr" ] },
|
||||
{ "event": "opentag", "data": [ "tr", {} ] },
|
||||
{ "event": "opentagname", "data": [ "th" ] },
|
||||
{ "event": "opentag", "data": [ "th", {} ] },
|
||||
{ "event": "text", "data": [ "TH" ] },
|
||||
{ "event": "closetag", "data": [ "th" ] },
|
||||
{ "event": "opentagname", "data": [ "td" ] },
|
||||
{ "event": "attribute", "data": [ "colspan", "2" ] },
|
||||
{ "event": "opentag", "data": [ "td", { "colspan": "2" } ] },
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
The ISC License
|
||||
|
||||
Copyright (c) Isaac Z. Schlueter and Contributors
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@ -0,0 +1,216 @@
|
|||
# minimatch
|
||||
|
||||
A minimal matching utility.
|
||||
|
||||
[](http://travis-ci.org/isaacs/minimatch)
|
||||
|
||||
|
||||
This is the matching library used internally by npm.
|
||||
|
||||
It works by converting glob expressions into JavaScript `RegExp`
|
||||
objects.
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var minimatch = require("minimatch")
|
||||
|
||||
minimatch("bar.foo", "*.foo") // true!
|
||||
minimatch("bar.foo", "*.bar") // false!
|
||||
minimatch("bar.foo", "*.+(bar|foo)", { debug: true }) // true, and noisy!
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
Supports these glob features:
|
||||
|
||||
* Brace Expansion
|
||||
* Extended glob matching
|
||||
* "Globstar" `**` matching
|
||||
|
||||
See:
|
||||
|
||||
* `man sh`
|
||||
* `man bash`
|
||||
* `man 3 fnmatch`
|
||||
* `man 5 gitignore`
|
||||
|
||||
## Minimatch Class
|
||||
|
||||
Create a minimatch object by instanting the `minimatch.Minimatch` class.
|
||||
|
||||
```javascript
|
||||
var Minimatch = require("minimatch").Minimatch
|
||||
var mm = new Minimatch(pattern, options)
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
* `pattern` The original pattern the minimatch object represents.
|
||||
* `options` The options supplied to the constructor.
|
||||
* `set` A 2-dimensional array of regexp or string expressions.
|
||||
Each row in the
|
||||
array corresponds to a brace-expanded pattern. Each item in the row
|
||||
corresponds to a single path-part. For example, the pattern
|
||||
`{a,b/c}/d` would expand to a set of patterns like:
|
||||
|
||||
[ [ a, d ]
|
||||
, [ b, c, d ] ]
|
||||
|
||||
If a portion of the pattern doesn't have any "magic" in it
|
||||
(that is, it's something like `"foo"` rather than `fo*o?`), then it
|
||||
will be left as a string rather than converted to a regular
|
||||
expression.
|
||||
|
||||
* `regexp` Created by the `makeRe` method. A single regular expression
|
||||
expressing the entire pattern. This is useful in cases where you wish
|
||||
to use the pattern somewhat like `fnmatch(3)` with `FNM_PATH` enabled.
|
||||
* `negate` True if the pattern is negated.
|
||||
* `comment` True if the pattern is a comment.
|
||||
* `empty` True if the pattern is `""`.
|
||||
|
||||
### Methods
|
||||
|
||||
* `makeRe` Generate the `regexp` member if necessary, and return it.
|
||||
Will return `false` if the pattern is invalid.
|
||||
* `match(fname)` Return true if the filename matches the pattern, or
|
||||
false otherwise.
|
||||
* `matchOne(fileArray, patternArray, partial)` Take a `/`-split
|
||||
filename, and match it against a single row in the `regExpSet`. This
|
||||
method is mainly for internal use, but is exposed so that it can be
|
||||
used by a glob-walker that needs to avoid excessive filesystem calls.
|
||||
|
||||
All other methods are internal, and will be called as necessary.
|
||||
|
||||
## Functions
|
||||
|
||||
The top-level exported function has a `cache` property, which is an LRU
|
||||
cache set to store 100 items. So, calling these methods repeatedly
|
||||
with the same pattern and options will use the same Minimatch object,
|
||||
saving the cost of parsing it multiple times.
|
||||
|
||||
### minimatch(path, pattern, options)
|
||||
|
||||
Main export. Tests a path against the pattern using the options.
|
||||
|
||||
```javascript
|
||||
var isJS = minimatch(file, "*.js", { matchBase: true })
|
||||
```
|
||||
|
||||
### minimatch.filter(pattern, options)
|
||||
|
||||
Returns a function that tests its
|
||||
supplied argument, suitable for use with `Array.filter`. Example:
|
||||
|
||||
```javascript
|
||||
var javascripts = fileList.filter(minimatch.filter("*.js", {matchBase: true}))
|
||||
```
|
||||
|
||||
### minimatch.match(list, pattern, options)
|
||||
|
||||
Match against the list of
|
||||
files, in the style of fnmatch or glob. If nothing is matched, and
|
||||
options.nonull is set, then return a list containing the pattern itself.
|
||||
|
||||
```javascript
|
||||
var javascripts = minimatch.match(fileList, "*.js", {matchBase: true}))
|
||||
```
|
||||
|
||||
### minimatch.makeRe(pattern, options)
|
||||
|
||||
Make a regular expression object from the pattern.
|
||||
|
||||
## Options
|
||||
|
||||
All options are `false` by default.
|
||||
|
||||
### debug
|
||||
|
||||
Dump a ton of stuff to stderr.
|
||||
|
||||
### nobrace
|
||||
|
||||
Do not expand `{a,b}` and `{1..3}` brace sets.
|
||||
|
||||
### noglobstar
|
||||
|
||||
Disable `**` matching against multiple folder names.
|
||||
|
||||
### dot
|
||||
|
||||
Allow patterns to match filenames starting with a period, even if
|
||||
the pattern does not explicitly have a period in that spot.
|
||||
|
||||
Note that by default, `a/**/b` will **not** match `a/.d/b`, unless `dot`
|
||||
is set.
|
||||
|
||||
### noext
|
||||
|
||||
Disable "extglob" style patterns like `+(a|b)`.
|
||||
|
||||
### nocase
|
||||
|
||||
Perform a case-insensitive match.
|
||||
|
||||
### nonull
|
||||
|
||||
When a match is not found by `minimatch.match`, return a list containing
|
||||
the pattern itself if this option is set. When not set, an empty list
|
||||
is returned if there are no matches.
|
||||
|
||||
### matchBase
|
||||
|
||||
If set, then patterns without slashes will be matched
|
||||
against the basename of the path if it contains slashes. For example,
|
||||
`a?b` would match the path `/xyz/123/acb`, but not `/xyz/acb/123`.
|
||||
|
||||
### nocomment
|
||||
|
||||
Suppress the behavior of treating `#` at the start of a pattern as a
|
||||
comment.
|
||||
|
||||
### nonegate
|
||||
|
||||
Suppress the behavior of treating a leading `!` character as negation.
|
||||
|
||||
### flipNegate
|
||||
|
||||
Returns from negate expressions the same as if they were not negated.
|
||||
(Ie, true on a hit, false on a miss.)
|
||||
|
||||
|
||||
## Comparisons to other fnmatch/glob implementations
|
||||
|
||||
While strict compliance with the existing standards is a worthwhile
|
||||
goal, some discrepancies exist between minimatch and other
|
||||
implementations, and are intentional.
|
||||
|
||||
If the pattern starts with a `!` character, then it is negated. Set the
|
||||
`nonegate` flag to suppress this behavior, and treat leading `!`
|
||||
characters normally. This is perhaps relevant if you wish to start the
|
||||
pattern with a negative extglob pattern like `!(a|B)`. Multiple `!`
|
||||
characters at the start of a pattern will negate the pattern multiple
|
||||
times.
|
||||
|
||||
If a pattern starts with `#`, then it is treated as a comment, and
|
||||
will not match anything. Use `\#` to match a literal `#` at the
|
||||
start of a line, or set the `nocomment` flag to suppress this behavior.
|
||||
|
||||
The double-star character `**` is supported by default, unless the
|
||||
`noglobstar` flag is set. This is supported in the manner of bsdglob
|
||||
and bash 4.1, where `**` only has special significance if it is the only
|
||||
thing in a path part. That is, `a/**/b` will match `a/x/y/b`, but
|
||||
`a/**b` will not.
|
||||
|
||||
If an escaped pattern has no matches, and the `nonull` flag is set,
|
||||
then minimatch.match returns the pattern as-provided, rather than
|
||||
interpreting the character escapes. For example,
|
||||
`minimatch.match([], "\\*a\\?")` will return `"\\*a\\?"` rather than
|
||||
`"*a?"`. This is akin to setting the `nullglob` option in bash, except
|
||||
that it does not resolve escaped pattern characters.
|
||||
|
||||
If brace expansion is not disabled, then it is performed before any
|
||||
other interpretation of the glob pattern. Thus, a pattern like
|
||||
`+(a|{b),c)}`, which would not be valid in bash or zsh, is expanded
|
||||
**first** into the set of `+(a|b)` and `+(a|c)`, and those patterns are
|
||||
checked for validity. Since those two are valid, matching proceeds.
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,912 @@
|
|||
module.exports = minimatch
|
||||
minimatch.Minimatch = Minimatch
|
||||
|
||||
var path = { sep: '/' }
|
||||
try {
|
||||
path = require('path')
|
||||
} catch (er) {}
|
||||
|
||||
var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}
|
||||
var expand = require('brace-expansion')
|
||||
|
||||
// any single thing other than /
|
||||
// don't need to escape / when using new RegExp()
|
||||
var qmark = '[^/]'
|
||||
|
||||
// * => any number of characters
|
||||
var star = qmark + '*?'
|
||||
|
||||
// ** when dots are allowed. Anything goes, except .. and .
|
||||
// not (^ or / followed by one or two dots followed by $ or /),
|
||||
// followed by anything, any number of times.
|
||||
var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'
|
||||
|
||||
// not a ^ or / followed by a dot,
|
||||
// followed by anything, any number of times.
|
||||
var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'
|
||||
|
||||
// characters that need to be escaped in RegExp.
|
||||
var reSpecials = charSet('().*{}+?[]^$\\!')
|
||||
|
||||
// "abc" -> { a:true, b:true, c:true }
|
||||
function charSet (s) {
|
||||
return s.split('').reduce(function (set, c) {
|
||||
set[c] = true
|
||||
return set
|
||||
}, {})
|
||||
}
|
||||
|
||||
// normalizes slashes.
|
||||
var slashSplit = /\/+/
|
||||
|
||||
minimatch.filter = filter
|
||||
function filter (pattern, options) {
|
||||
options = options || {}
|
||||
return function (p, i, list) {
|
||||
return minimatch(p, pattern, options)
|
||||
}
|
||||
}
|
||||
|
||||
function ext (a, b) {
|
||||
a = a || {}
|
||||
b = b || {}
|
||||
var t = {}
|
||||
Object.keys(b).forEach(function (k) {
|
||||
t[k] = b[k]
|
||||
})
|
||||
Object.keys(a).forEach(function (k) {
|
||||
t[k] = a[k]
|
||||
})
|
||||
return t
|
||||
}
|
||||
|
||||
minimatch.defaults = function (def) {
|
||||
if (!def || !Object.keys(def).length) return minimatch
|
||||
|
||||
var orig = minimatch
|
||||
|
||||
var m = function minimatch (p, pattern, options) {
|
||||
return orig.minimatch(p, pattern, ext(def, options))
|
||||
}
|
||||
|
||||
m.Minimatch = function Minimatch (pattern, options) {
|
||||
return new orig.Minimatch(pattern, ext(def, options))
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
Minimatch.defaults = function (def) {
|
||||
if (!def || !Object.keys(def).length) return Minimatch
|
||||
return minimatch.defaults(def).Minimatch
|
||||
}
|
||||
|
||||
function minimatch (p, pattern, options) {
|
||||
if (typeof pattern !== 'string') {
|
||||
throw new TypeError('glob pattern string required')
|
||||
}
|
||||
|
||||
if (!options) options = {}
|
||||
|
||||
// shortcut: comments match nothing.
|
||||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||||
return false
|
||||
}
|
||||
|
||||
// "" only matches ""
|
||||
if (pattern.trim() === '') return p === ''
|
||||
|
||||
return new Minimatch(pattern, options).match(p)
|
||||
}
|
||||
|
||||
function Minimatch (pattern, options) {
|
||||
if (!(this instanceof Minimatch)) {
|
||||
return new Minimatch(pattern, options)
|
||||
}
|
||||
|
||||
if (typeof pattern !== 'string') {
|
||||
throw new TypeError('glob pattern string required')
|
||||
}
|
||||
|
||||
if (!options) options = {}
|
||||
pattern = pattern.trim()
|
||||
|
||||
// windows support: need to use /, not \
|
||||
if (path.sep !== '/') {
|
||||
pattern = pattern.split(path.sep).join('/')
|
||||
}
|
||||
|
||||
this.options = options
|
||||
this.set = []
|
||||
this.pattern = pattern
|
||||
this.regexp = null
|
||||
this.negate = false
|
||||
this.comment = false
|
||||
this.empty = false
|
||||
|
||||
// make the set of regexps etc.
|
||||
this.make()
|
||||
}
|
||||
|
||||
Minimatch.prototype.debug = function () {}
|
||||
|
||||
Minimatch.prototype.make = make
|
||||
function make () {
|
||||
// don't do it more than once.
|
||||
if (this._made) return
|
||||
|
||||
var pattern = this.pattern
|
||||
var options = this.options
|
||||
|
||||
// empty patterns and comments match nothing.
|
||||
if (!options.nocomment && pattern.charAt(0) === '#') {
|
||||
this.comment = true
|
||||
return
|
||||
}
|
||||
if (!pattern) {
|
||||
this.empty = true
|
||||
return
|
||||
}
|
||||
|
||||
// step 1: figure out negation, etc.
|
||||
this.parseNegate()
|
||||
|
||||
// step 2: expand braces
|
||||
var set = this.globSet = this.braceExpand()
|
||||
|
||||
if (options.debug) this.debug = console.error
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// step 3: now we have a set, so turn each one into a series of path-portion
|
||||
// matching patterns.
|
||||
// These will be regexps, except in the case of "**", which is
|
||||
// set to the GLOBSTAR object for globstar behavior,
|
||||
// and will not contain any / characters
|
||||
set = this.globParts = set.map(function (s) {
|
||||
return s.split(slashSplit)
|
||||
})
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// glob --> regexps
|
||||
set = set.map(function (s, si, set) {
|
||||
return s.map(this.parse, this)
|
||||
}, this)
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
// filter out everything that didn't compile properly.
|
||||
set = set.filter(function (s) {
|
||||
return s.indexOf(false) === -1
|
||||
})
|
||||
|
||||
this.debug(this.pattern, set)
|
||||
|
||||
this.set = set
|
||||
}
|
||||
|
||||
Minimatch.prototype.parseNegate = parseNegate
|
||||
function parseNegate () {
|
||||
var pattern = this.pattern
|
||||
var negate = false
|
||||
var options = this.options
|
||||
var negateOffset = 0
|
||||
|
||||
if (options.nonegate) return
|
||||
|
||||
for (var i = 0, l = pattern.length
|
||||
; i < l && pattern.charAt(i) === '!'
|
||||
; i++) {
|
||||
negate = !negate
|
||||
negateOffset++
|
||||
}
|
||||
|
||||
if (negateOffset) this.pattern = pattern.substr(negateOffset)
|
||||
this.negate = negate
|
||||
}
|
||||
|
||||
// Brace expansion:
|
||||
// a{b,c}d -> abd acd
|
||||
// a{b,}c -> abc ac
|
||||
// a{0..3}d -> a0d a1d a2d a3d
|
||||
// a{b,c{d,e}f}g -> abg acdfg acefg
|
||||
// a{b,c}d{e,f}g -> abdeg acdeg abdeg abdfg
|
||||
//
|
||||
// Invalid sets are not expanded.
|
||||
// a{2..}b -> a{2..}b
|
||||
// a{b}c -> a{b}c
|
||||
minimatch.braceExpand = function (pattern, options) {
|
||||
return braceExpand(pattern, options)
|
||||
}
|
||||
|
||||
Minimatch.prototype.braceExpand = braceExpand
|
||||
|
||||
function braceExpand (pattern, options) {
|
||||
if (!options) {
|
||||
if (this instanceof Minimatch) {
|
||||
options = this.options
|
||||
} else {
|
||||
options = {}
|
||||
}
|
||||
}
|
||||
|
||||
pattern = typeof pattern === 'undefined'
|
||||
? this.pattern : pattern
|
||||
|
||||
if (typeof pattern === 'undefined') {
|
||||
throw new Error('undefined pattern')
|
||||
}
|
||||
|
||||
if (options.nobrace ||
|
||||
!pattern.match(/\{.*\}/)) {
|
||||
// shortcut. no need to expand.
|
||||
return [pattern]
|
||||
}
|
||||
|
||||
return expand(pattern)
|
||||
}
|
||||
|
||||
// parse a component of the expanded set.
|
||||
// At this point, no pattern may contain "/" in it
|
||||
// so we're going to return a 2d array, where each entry is the full
|
||||
// pattern, split on '/', and then turned into a regular expression.
|
||||
// A regexp is made at the end which joins each array with an
|
||||
// escaped /, and another full one which joins each regexp with |.
|
||||
//
|
||||
// Following the lead of Bash 4.1, note that "**" only has special meaning
|
||||
// when it is the *only* thing in a path portion. Otherwise, any series
|
||||
// of * is equivalent to a single *. Globstar behavior is enabled by
|
||||
// default, and can be disabled by setting options.noglobstar.
|
||||
Minimatch.prototype.parse = parse
|
||||
var SUBPARSE = {}
|
||||
function parse (pattern, isSub) {
|
||||
var options = this.options
|
||||
|
||||
// shortcuts
|
||||
if (!options.noglobstar && pattern === '**') return GLOBSTAR
|
||||
if (pattern === '') return ''
|
||||
|
||||
var re = ''
|
||||
var hasMagic = !!options.nocase
|
||||
var escaping = false
|
||||
// ? => one single character
|
||||
var patternListStack = []
|
||||
var negativeLists = []
|
||||
var plType
|
||||
var stateChar
|
||||
var inClass = false
|
||||
var reClassStart = -1
|
||||
var classStart = -1
|
||||
// . and .. never match anything that doesn't start with .,
|
||||
// even when options.dot is set.
|
||||
var patternStart = pattern.charAt(0) === '.' ? '' // anything
|
||||
// not (start or / followed by . or .. followed by / or end)
|
||||
: options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))'
|
||||
: '(?!\\.)'
|
||||
var self = this
|
||||
|
||||
function clearStateChar () {
|
||||
if (stateChar) {
|
||||
// we had some state-tracking character
|
||||
// that wasn't consumed by this pass.
|
||||
switch (stateChar) {
|
||||
case '*':
|
||||
re += star
|
||||
hasMagic = true
|
||||
break
|
||||
case '?':
|
||||
re += qmark
|
||||
hasMagic = true
|
||||
break
|
||||
default:
|
||||
re += '\\' + stateChar
|
||||
break
|
||||
}
|
||||
self.debug('clearStateChar %j %j', stateChar, re)
|
||||
stateChar = false
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0, len = pattern.length, c
|
||||
; (i < len) && (c = pattern.charAt(i))
|
||||
; i++) {
|
||||
this.debug('%s\t%s %s %j', pattern, i, re, c)
|
||||
|
||||
// skip over any that are escaped.
|
||||
if (escaping && reSpecials[c]) {
|
||||
re += '\\' + c
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case '/':
|
||||
// completely not allowed, even escaped.
|
||||
// Should already be path-split by now.
|
||||
return false
|
||||
|
||||
case '\\':
|
||||
clearStateChar()
|
||||
escaping = true
|
||||
continue
|
||||
|
||||
// the various stateChar values
|
||||
// for the "extglob" stuff.
|
||||
case '?':
|
||||
case '*':
|
||||
case '+':
|
||||
case '@':
|
||||
case '!':
|
||||
this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c)
|
||||
|
||||
// all of those are literals inside a class, except that
|
||||
// the glob [!a] means [^a] in regexp
|
||||
if (inClass) {
|
||||
this.debug(' in class')
|
||||
if (c === '!' && i === classStart + 1) c = '^'
|
||||
re += c
|
||||
continue
|
||||
}
|
||||
|
||||
// if we already have a stateChar, then it means
|
||||
// that there was something like ** or +? in there.
|
||||
// Handle the stateChar, then proceed with this one.
|
||||
self.debug('call clearStateChar %j', stateChar)
|
||||
clearStateChar()
|
||||
stateChar = c
|
||||
// if extglob is disabled, then +(asdf|foo) isn't a thing.
|
||||
// just clear the statechar *now*, rather than even diving into
|
||||
// the patternList stuff.
|
||||
if (options.noext) clearStateChar()
|
||||
continue
|
||||
|
||||
case '(':
|
||||
if (inClass) {
|
||||
re += '('
|
||||
continue
|
||||
}
|
||||
|
||||
if (!stateChar) {
|
||||
re += '\\('
|
||||
continue
|
||||
}
|
||||
|
||||
plType = stateChar
|
||||
patternListStack.push({
|
||||
type: plType,
|
||||
start: i - 1,
|
||||
reStart: re.length
|
||||
})
|
||||
// negation is (?:(?!js)[^/]*)
|
||||
re += stateChar === '!' ? '(?:(?!(?:' : '(?:'
|
||||
this.debug('plType %j %j', stateChar, re)
|
||||
stateChar = false
|
||||
continue
|
||||
|
||||
case ')':
|
||||
if (inClass || !patternListStack.length) {
|
||||
re += '\\)'
|
||||
continue
|
||||
}
|
||||
|
||||
clearStateChar()
|
||||
hasMagic = true
|
||||
re += ')'
|
||||
var pl = patternListStack.pop()
|
||||
plType = pl.type
|
||||
// negation is (?:(?!js)[^/]*)
|
||||
// The others are (?:<pattern>)<type>
|
||||
switch (plType) {
|
||||
case '!':
|
||||
negativeLists.push(pl)
|
||||
re += ')[^/]*?)'
|
||||
pl.reEnd = re.length
|
||||
break
|
||||
case '?':
|
||||
case '+':
|
||||
case '*':
|
||||
re += plType
|
||||
break
|
||||
case '@': break // the default anyway
|
||||
}
|
||||
continue
|
||||
|
||||
case '|':
|
||||
if (inClass || !patternListStack.length || escaping) {
|
||||
re += '\\|'
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
clearStateChar()
|
||||
re += '|'
|
||||
continue
|
||||
|
||||
// these are mostly the same in regexp and glob
|
||||
case '[':
|
||||
// swallow any state-tracking char before the [
|
||||
clearStateChar()
|
||||
|
||||
if (inClass) {
|
||||
re += '\\' + c
|
||||
continue
|
||||
}
|
||||
|
||||
inClass = true
|
||||
classStart = i
|
||||
reClassStart = re.length
|
||||
re += c
|
||||
continue
|
||||
|
||||
case ']':
|
||||
// a right bracket shall lose its special
|
||||
// meaning and represent itself in
|
||||
// a bracket expression if it occurs
|
||||
// first in the list. -- POSIX.2 2.8.3.2
|
||||
if (i === classStart + 1 || !inClass) {
|
||||
re += '\\' + c
|
||||
escaping = false
|
||||
continue
|
||||
}
|
||||
|
||||
// handle the case where we left a class open.
|
||||
// "[z-a]" is valid, equivalent to "\[z-a\]"
|
||||
if (inClass) {
|
||||
// split where the last [ was, make sure we don't have
|
||||
// an invalid re. if so, re-walk the contents of the
|
||||
// would-be class to re-translate any characters that
|
||||
// were passed through as-is
|
||||
// TODO: It would probably be faster to determine this
|
||||
// without a try/catch and a new RegExp, but it's tricky
|
||||
// to do safely. For now, this is safe and works.
|
||||
var cs = pattern.substring(classStart + 1, i)
|
||||
try {
|
||||
RegExp('[' + cs + ']')
|
||||
} catch (er) {
|
||||
// not a valid class!
|
||||
var sp = this.parse(cs, SUBPARSE)
|
||||
re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'
|
||||
hasMagic = hasMagic || sp[1]
|
||||
inClass = false
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// finish up the class.
|
||||
hasMagic = true
|
||||
inClass = false
|
||||
re += c
|
||||
continue
|
||||
|
||||
default:
|
||||
// swallow any state char that wasn't consumed
|
||||
clearStateChar()
|
||||
|
||||
if (escaping) {
|
||||
// no need
|
||||
escaping = false
|
||||
} else if (reSpecials[c]
|
||||
&& !(c === '^' && inClass)) {
|
||||
re += '\\'
|
||||
}
|
||||
|
||||
re += c
|
||||
|
||||
} // switch
|
||||
} // for
|
||||
|
||||
// handle the case where we left a class open.
|
||||
// "[abc" is valid, equivalent to "\[abc"
|
||||
if (inClass) {
|
||||
// split where the last [ was, and escape it
|
||||
// this is a huge pita. We now have to re-walk
|
||||
// the contents of the would-be class to re-translate
|
||||
// any characters that were passed through as-is
|
||||
cs = pattern.substr(classStart + 1)
|
||||
sp = this.parse(cs, SUBPARSE)
|
||||
re = re.substr(0, reClassStart) + '\\[' + sp[0]
|
||||
hasMagic = hasMagic || sp[1]
|
||||
}
|
||||
|
||||
// handle the case where we had a +( thing at the *end*
|
||||
// of the pattern.
|
||||
// each pattern list stack adds 3 chars, and we need to go through
|
||||
// and escape any | chars that were passed through as-is for the regexp.
|
||||
// Go through and escape them, taking care not to double-escape any
|
||||
// | chars that were already escaped.
|
||||
for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) {
|
||||
var tail = re.slice(pl.reStart + 3)
|
||||
// maybe some even number of \, then maybe 1 \, followed by a |
|
||||
tail = tail.replace(/((?:\\{2})*)(\\?)\|/g, function (_, $1, $2) {
|
||||
if (!$2) {
|
||||
// the | isn't already escaped, so escape it.
|
||||
$2 = '\\'
|
||||
}
|
||||
|
||||
// need to escape all those slashes *again*, without escaping the
|
||||
// one that we need for escaping the | character. As it works out,
|
||||
// escaping an even number of slashes can be done by simply repeating
|
||||
// it exactly after itself. That's why this trick works.
|
||||
//
|
||||
// I am sorry that you have to see this.
|
||||
return $1 + $1 + $2 + '|'
|
||||
})
|
||||
|
||||
this.debug('tail=%j\n %s', tail, tail)
|
||||
var t = pl.type === '*' ? star
|
||||
: pl.type === '?' ? qmark
|
||||
: '\\' + pl.type
|
||||
|
||||
hasMagic = true
|
||||
re = re.slice(0, pl.reStart) + t + '\\(' + tail
|
||||
}
|
||||
|
||||
// handle trailing things that only matter at the very end.
|
||||
clearStateChar()
|
||||
if (escaping) {
|
||||
// trailing \\
|
||||
re += '\\\\'
|
||||
}
|
||||
|
||||
// only need to apply the nodot start if the re starts with
|
||||
// something that could conceivably capture a dot
|
||||
var addPatternStart = false
|
||||
switch (re.charAt(0)) {
|
||||
case '.':
|
||||
case '[':
|
||||
case '(': addPatternStart = true
|
||||
}
|
||||
|
||||
// Hack to work around lack of negative lookbehind in JS
|
||||
// A pattern like: *.!(x).!(y|z) needs to ensure that a name
|
||||
// like 'a.xyz.yz' doesn't match. So, the first negative
|
||||
// lookahead, has to look ALL the way ahead, to the end of
|
||||
// the pattern.
|
||||
for (var n = negativeLists.length - 1; n > -1; n--) {
|
||||
var nl = negativeLists[n]
|
||||
|
||||
var nlBefore = re.slice(0, nl.reStart)
|
||||
var nlFirst = re.slice(nl.reStart, nl.reEnd - 8)
|
||||
var nlLast = re.slice(nl.reEnd - 8, nl.reEnd)
|
||||
var nlAfter = re.slice(nl.reEnd)
|
||||
|
||||
nlLast += nlAfter
|
||||
|
||||
// Handle nested stuff like *(*.js|!(*.json)), where open parens
|
||||
// mean that we should *not* include the ) in the bit that is considered
|
||||
// "after" the negated section.
|
||||
var openParensBefore = nlBefore.split('(').length - 1
|
||||
var cleanAfter = nlAfter
|
||||
for (i = 0; i < openParensBefore; i++) {
|
||||
cleanAfter = cleanAfter.replace(/\)[+*?]?/, '')
|
||||
}
|
||||
nlAfter = cleanAfter
|
||||
|
||||
var dollar = ''
|
||||
if (nlAfter === '' && isSub !== SUBPARSE) {
|
||||
dollar = '$'
|
||||
}
|
||||
var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast
|
||||
re = newRe
|
||||
}
|
||||
|
||||
// if the re is not "" at this point, then we need to make sure
|
||||
// it doesn't match against an empty path part.
|
||||
// Otherwise a/* will match a/, which it should not.
|
||||
if (re !== '' && hasMagic) {
|
||||
re = '(?=.)' + re
|
||||
}
|
||||
|
||||
if (addPatternStart) {
|
||||
re = patternStart + re
|
||||
}
|
||||
|
||||
// parsing just a piece of a larger pattern.
|
||||
if (isSub === SUBPARSE) {
|
||||
return [re, hasMagic]
|
||||
}
|
||||
|
||||
// skip the regexp for non-magical patterns
|
||||
// unescape anything in it, though, so that it'll be
|
||||
// an exact match against a file etc.
|
||||
if (!hasMagic) {
|
||||
return globUnescape(pattern)
|
||||
}
|
||||
|
||||
var flags = options.nocase ? 'i' : ''
|
||||
var regExp = new RegExp('^' + re + '$', flags)
|
||||
|
||||
regExp._glob = pattern
|
||||
regExp._src = re
|
||||
|
||||
return regExp
|
||||
}
|
||||
|
||||
minimatch.makeRe = function (pattern, options) {
|
||||
return new Minimatch(pattern, options || {}).makeRe()
|
||||
}
|
||||
|
||||
Minimatch.prototype.makeRe = makeRe
|
||||
function makeRe () {
|
||||
if (this.regexp || this.regexp === false) return this.regexp
|
||||
|
||||
// at this point, this.set is a 2d array of partial
|
||||
// pattern strings, or "**".
|
||||
//
|
||||
// It's better to use .match(). This function shouldn't
|
||||
// be used, really, but it's pretty convenient sometimes,
|
||||
// when you just want to work with a regex.
|
||||
var set = this.set
|
||||
|
||||
if (!set.length) {
|
||||
this.regexp = false
|
||||
return this.regexp
|
||||
}
|
||||
var options = this.options
|
||||
|
||||
var twoStar = options.noglobstar ? star
|
||||
: options.dot ? twoStarDot
|
||||
: twoStarNoDot
|
||||
var flags = options.nocase ? 'i' : ''
|
||||
|
||||
var re = set.map(function (pattern) {
|
||||
return pattern.map(function (p) {
|
||||
return (p === GLOBSTAR) ? twoStar
|
||||
: (typeof p === 'string') ? regExpEscape(p)
|
||||
: p._src
|
||||
}).join('\\\/')
|
||||
}).join('|')
|
||||
|
||||
// must match entire pattern
|
||||
// ending in a * or ** will make it less strict.
|
||||
re = '^(?:' + re + ')$'
|
||||
|
||||
// can match anything, as long as it's not this.
|
||||
if (this.negate) re = '^(?!' + re + ').*$'
|
||||
|
||||
try {
|
||||
this.regexp = new RegExp(re, flags)
|
||||
} catch (ex) {
|
||||
this.regexp = false
|
||||
}
|
||||
return this.regexp
|
||||
}
|
||||
|
||||
minimatch.match = function (list, pattern, options) {
|
||||
options = options || {}
|
||||
var mm = new Minimatch(pattern, options)
|
||||
list = list.filter(function (f) {
|
||||
return mm.match(f)
|
||||
})
|
||||
if (mm.options.nonull && !list.length) {
|
||||
list.push(pattern)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
Minimatch.prototype.match = match
|
||||
function match (f, partial) {
|
||||
this.debug('match', f, this.pattern)
|
||||
// short-circuit in the case of busted things.
|
||||
// comments, etc.
|
||||
if (this.comment) return false
|
||||
if (this.empty) return f === ''
|
||||
|
||||
if (f === '/' && partial) return true
|
||||
|
||||
var options = this.options
|
||||
|
||||
// windows: need to use /, not \
|
||||
if (path.sep !== '/') {
|
||||
f = f.split(path.sep).join('/')
|
||||
}
|
||||
|
||||
// treat the test path as a set of pathparts.
|
||||
f = f.split(slashSplit)
|
||||
this.debug(this.pattern, 'split', f)
|
||||
|
||||
// just ONE of the pattern sets in this.set needs to match
|
||||
// in order for it to be valid. If negating, then just one
|
||||
// match means that we have failed.
|
||||
// Either way, return on the first hit.
|
||||
|
||||
var set = this.set
|
||||
this.debug(this.pattern, 'set', set)
|
||||
|
||||
// Find the basename of the path by looking for the last non-empty segment
|
||||
var filename
|
||||
var i
|
||||
for (i = f.length - 1; i >= 0; i--) {
|
||||
filename = f[i]
|
||||
if (filename) break
|
||||
}
|
||||
|
||||
for (i = 0; i < set.length; i++) {
|
||||
var pattern = set[i]
|
||||
var file = f
|
||||
if (options.matchBase && pattern.length === 1) {
|
||||
file = [filename]
|
||||
}
|
||||
var hit = this.matchOne(file, pattern, partial)
|
||||
if (hit) {
|
||||
if (options.flipNegate) return true
|
||||
return !this.negate
|
||||
}
|
||||
}
|
||||
|
||||
// didn't get any hits. this is success if it's a negative
|
||||
// pattern, failure otherwise.
|
||||
if (options.flipNegate) return false
|
||||
return this.negate
|
||||
}
|
||||
|
||||
// set partial to true to test if, for example,
|
||||
// "/a/b" matches the start of "/*/b/*/d"
|
||||
// Partial means, if you run out of file before you run
|
||||
// out of pattern, then that's fine, as long as all
|
||||
// the parts match.
|
||||
Minimatch.prototype.matchOne = function (file, pattern, partial) {
|
||||
var options = this.options
|
||||
|
||||
this.debug('matchOne',
|
||||
{ 'this': this, file: file, pattern: pattern })
|
||||
|
||||
this.debug('matchOne', file.length, pattern.length)
|
||||
|
||||
for (var fi = 0,
|
||||
pi = 0,
|
||||
fl = file.length,
|
||||
pl = pattern.length
|
||||
; (fi < fl) && (pi < pl)
|
||||
; fi++, pi++) {
|
||||
this.debug('matchOne loop')
|
||||
var p = pattern[pi]
|
||||
var f = file[fi]
|
||||
|
||||
this.debug(pattern, p, f)
|
||||
|
||||
// should be impossible.
|
||||
// some invalid regexp stuff in the set.
|
||||
if (p === false) return false
|
||||
|
||||
if (p === GLOBSTAR) {
|
||||
this.debug('GLOBSTAR', [pattern, p, f])
|
||||
|
||||
// "**"
|
||||
// a/**/b/**/c would match the following:
|
||||
// a/b/x/y/z/c
|
||||
// a/x/y/z/b/c
|
||||
// a/b/x/b/x/c
|
||||
// a/b/c
|
||||
// To do this, take the rest of the pattern after
|
||||
// the **, and see if it would match the file remainder.
|
||||
// If so, return success.
|
||||
// If not, the ** "swallows" a segment, and try again.
|
||||
// This is recursively awful.
|
||||
//
|
||||
// a/**/b/**/c matching a/b/x/y/z/c
|
||||
// - a matches a
|
||||
// - doublestar
|
||||
// - matchOne(b/x/y/z/c, b/**/c)
|
||||
// - b matches b
|
||||
// - doublestar
|
||||
// - matchOne(x/y/z/c, c) -> no
|
||||
// - matchOne(y/z/c, c) -> no
|
||||
// - matchOne(z/c, c) -> no
|
||||
// - matchOne(c, c) yes, hit
|
||||
var fr = fi
|
||||
var pr = pi + 1
|
||||
if (pr === pl) {
|
||||
this.debug('** at the end')
|
||||
// a ** at the end will just swallow the rest.
|
||||
// We have found a match.
|
||||
// however, it will not swallow /.x, unless
|
||||
// options.dot is set.
|
||||
// . and .. are *never* matched by **, for explosively
|
||||
// exponential reasons.
|
||||
for (; fi < fl; fi++) {
|
||||
if (file[fi] === '.' || file[fi] === '..' ||
|
||||
(!options.dot && file[fi].charAt(0) === '.')) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// ok, let's see if we can swallow whatever we can.
|
||||
while (fr < fl) {
|
||||
var swallowee = file[fr]
|
||||
|
||||
this.debug('\nglobstar while', file, fr, pattern, pr, swallowee)
|
||||
|
||||
// XXX remove this slice. Just pass the start index.
|
||||
if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) {
|
||||
this.debug('globstar found match!', fr, fl, swallowee)
|
||||
// found a match.
|
||||
return true
|
||||
} else {
|
||||
// can't swallow "." or ".." ever.
|
||||
// can only swallow ".foo" when explicitly asked.
|
||||
if (swallowee === '.' || swallowee === '..' ||
|
||||
(!options.dot && swallowee.charAt(0) === '.')) {
|
||||
this.debug('dot detected!', file, fr, pattern, pr)
|
||||
break
|
||||
}
|
||||
|
||||
// ** swallows a segment, and continue.
|
||||
this.debug('globstar swallow a segment, and continue')
|
||||
fr++
|
||||
}
|
||||
}
|
||||
|
||||
// no match was found.
|
||||
// However, in partial mode, we can't say this is necessarily over.
|
||||
// If there's more *pattern* left, then
|
||||
if (partial) {
|
||||
// ran out of file
|
||||
this.debug('\n>>> no match, partial?', file, fr, pattern, pr)
|
||||
if (fr === fl) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// something other than **
|
||||
// non-magic patterns just have to match exactly
|
||||
// patterns with magic have been turned into regexps.
|
||||
var hit
|
||||
if (typeof p === 'string') {
|
||||
if (options.nocase) {
|
||||
hit = f.toLowerCase() === p.toLowerCase()
|
||||
} else {
|
||||
hit = f === p
|
||||
}
|
||||
this.debug('string match', p, f, hit)
|
||||
} else {
|
||||
hit = f.match(p)
|
||||
this.debug('pattern match', p, f, hit)
|
||||
}
|
||||
|
||||
if (!hit) return false
|
||||
}
|
||||
|
||||
// Note: ending in / means that we'll get a final ""
|
||||
// at the end of the pattern. This can only match a
|
||||
// corresponding "" at the end of the file.
|
||||
// If the file ends in /, then it can only match a
|
||||
// a pattern that ends in /, unless the pattern just
|
||||
// doesn't have any more for it. But, a/b/ should *not*
|
||||
// match "a/b/*", even though "" matches against the
|
||||
// [^/]*? pattern, except in partial mode, where it might
|
||||
// simply not be reached yet.
|
||||
// However, a/b/ should still satisfy a/*
|
||||
|
||||
// now either we fell off the end of the pattern, or we're done.
|
||||
if (fi === fl && pi === pl) {
|
||||
// ran out of pattern and filename at the same time.
|
||||
// an exact hit!
|
||||
return true
|
||||
} else if (fi === fl) {
|
||||
// ran out of file, but still had pattern left.
|
||||
// this is ok if we're doing the match as part of
|
||||
// a glob fs traversal.
|
||||
return partial
|
||||
} else if (pi === pl) {
|
||||
// ran out of pattern, still have file left.
|
||||
// this is only acceptable if we're on the very last
|
||||
// empty segment of a file with a trailing slash.
|
||||
// a/* should match a/b/
|
||||
var emptyFileEnd = (fi === fl - 1) && (file[fi] === '')
|
||||
return emptyFileEnd
|
||||
}
|
||||
|
||||
// should be unreachable.
|
||||
throw new Error('wtf?')
|
||||
}
|
||||
|
||||
// replace stuff like \* with *
|
||||
function globUnescape (s) {
|
||||
return s.replace(/\\(.)/g, '$1')
|
||||
}
|
||||
|
||||
function regExpEscape (s) {
|
||||
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
||||
}
|
3
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/.npmignore
generated
vendored
Normal file
3
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
test
|
||||
.gitignore
|
||||
.travis.yml
|
122
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/README.md
generated
vendored
Normal file
122
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/README.md
generated
vendored
Normal file
|
@ -0,0 +1,122 @@
|
|||
# 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://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 seperated 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)
|
||||
|
||||
## 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.
|
8
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/example.js
generated
vendored
Normal file
8
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/example.js
generated
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
var expand = require('./');
|
||||
|
||||
console.log(expand('http://any.org/archive{1996..1999}/vol{1..4}/part{a,b,c}.html'));
|
||||
console.log(expand('http://www.numericals.com/file{1..100..10}.txt'));
|
||||
console.log(expand('http://www.letters.com/file{a..z..2}.txt'));
|
||||
console.log(expand('mkdir /usr/local/src/bash/{old,new,dist,bugs}'));
|
||||
console.log(expand('chown root /usr/{ucb/{ex,edit},lib/{ex?.?*,how_ex}}'));
|
||||
|
191
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/index.js
generated
vendored
Normal file
191
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/index.js
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
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 [];
|
||||
|
||||
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 = /^(.*,)+(.+)?$/.test(m.body);
|
||||
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;
|
||||
}
|
||||
|
5
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/.npmignore
generated
vendored
Normal file
5
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/.npmignore
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
test
|
||||
.gitignore
|
||||
.travis.yml
|
||||
Makefile
|
||||
example.js
|
21
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/LICENSE.md
generated
vendored
Normal file
21
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/LICENSE.md
generated
vendored
Normal file
|
@ -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
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/README.md
generated
vendored
Normal file
91
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/README.md
generated
vendored
Normal file
|
@ -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', '']`.
|
||||
|
||||
### 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 ]`.
|
||||
|
||||
## 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.
|
58
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/index.js
generated
vendored
Normal file
58
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/index.js
generated
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
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 < str.length && 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;
|
||||
}
|
76
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/package.json
generated
vendored
Normal file
76
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/package.json
generated
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"name": "balanced-match",
|
||||
"description": "Match balanced character pairs, like \"{\" and \"}\"",
|
||||
"version": "0.4.1",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"tape": "~4.5.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"
|
||||
]
|
||||
},
|
||||
"gitHead": "7004b289baaaab6a832f4901735e29d37cc2a863",
|
||||
"bugs": {
|
||||
"url": "https://github.com/juliangruber/balanced-match/issues"
|
||||
},
|
||||
"_id": "balanced-match@0.4.1",
|
||||
"_shasum": "19053e2e0748eadb379da6c09d455cf5e1039335",
|
||||
"_from": "balanced-match@>=0.4.1 <0.5.0",
|
||||
"_npmVersion": "3.8.6",
|
||||
"_nodeVersion": "6.0.0",
|
||||
"_npmUser": {
|
||||
"name": "juliangruber",
|
||||
"email": "julian@juliangruber.com"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "19053e2e0748eadb379da6c09d455cf5e1039335",
|
||||
"tarball": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "juliangruber",
|
||||
"email": "julian@juliangruber.com"
|
||||
}
|
||||
],
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/balanced-match-0.4.1.tgz_1462129663650_0.39764496590942144"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.1.tgz"
|
||||
}
|
4
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/.travis.yml
generated
vendored
Normal file
4
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/.travis.yml
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.4
|
||||
- 0.6
|
18
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/LICENSE
generated
vendored
Normal file
18
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/LICENSE
generated
vendored
Normal file
|
@ -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
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/README.markdown
generated
vendored
Normal file
62
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/README.markdown
generated
vendored
Normal file
|
@ -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
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/example/map.js
generated
vendored
Normal file
6
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/example/map.js
generated
vendored
Normal file
|
@ -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
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/index.js
generated
vendored
Normal file
13
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/index.js
generated
vendored
Normal file
|
@ -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]';
|
||||
};
|
83
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/package.json
generated
vendored
Normal file
83
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/package.json
generated
vendored
Normal file
|
@ -0,0 +1,83 @@
|
|||
{
|
||||
"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
|
||||
],
|
||||
"chrome": [
|
||||
10,
|
||||
22
|
||||
],
|
||||
"safari": [
|
||||
5.1
|
||||
],
|
||||
"opera": [
|
||||
12
|
||||
]
|
||||
}
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/substack/node-concat-map/issues"
|
||||
},
|
||||
"homepage": "https://github.com/substack/node-concat-map",
|
||||
"_id": "concat-map@0.0.1",
|
||||
"dist": {
|
||||
"shasum": "d8a96bd77fd68df7793a73036a3ba0d5405d477b",
|
||||
"tarball": "http://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
},
|
||||
"_from": "concat-map@0.0.1",
|
||||
"_npmVersion": "1.3.21",
|
||||
"_npmUser": {
|
||||
"name": "substack",
|
||||
"email": "mail@substack.net"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "substack",
|
||||
"email": "mail@substack.net"
|
||||
}
|
||||
],
|
||||
"_shasum": "d8a96bd77fd68df7793a73036a3ba0d5405d477b",
|
||||
"_resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
39
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/test/map.js
generated
vendored
Normal file
39
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map/test/map.js
generated
vendored
Normal file
|
@ -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();
|
||||
});
|
78
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/package.json
generated
vendored
Normal file
78
js/node/node_modules/jshint/node_modules/minimatch/node_modules/brace-expansion/package.json
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
{
|
||||
"name": "brace-expansion",
|
||||
"description": "Brace expansion as known from sh/bash",
|
||||
"version": "1.1.4",
|
||||
"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"
|
||||
},
|
||||
"dependencies": {
|
||||
"balanced-match": "^0.4.1",
|
||||
"concat-map": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tape": "4.5.1"
|
||||
},
|
||||
"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"
|
||||
]
|
||||
},
|
||||
"gitHead": "1660b75d0bf03b022e7888b576cd5a4080692c1d",
|
||||
"bugs": {
|
||||
"url": "https://github.com/juliangruber/brace-expansion/issues"
|
||||
},
|
||||
"_id": "brace-expansion@1.1.4",
|
||||
"_shasum": "464a204c77f482c085c2a36c456bbfbafb67a127",
|
||||
"_from": "brace-expansion@>=1.0.0 <2.0.0",
|
||||
"_npmVersion": "3.8.6",
|
||||
"_nodeVersion": "6.0.0",
|
||||
"_npmUser": {
|
||||
"name": "juliangruber",
|
||||
"email": "julian@juliangruber.com"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "464a204c77f482c085c2a36c456bbfbafb67a127",
|
||||
"tarball": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.4.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "juliangruber",
|
||||
"email": "julian@juliangruber.com"
|
||||
},
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "isaacs@npmjs.com"
|
||||
}
|
||||
],
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-12-west.internal.npmjs.com",
|
||||
"tmp": "tmp/brace-expansion-1.1.4.tgz_1462130058897_0.14984136167913675"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.4.tgz"
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
{
|
||||
"author": {
|
||||
"name": "Isaac Z. Schlueter",
|
||||
"email": "i@izs.me",
|
||||
"url": "http://blog.izs.me"
|
||||
},
|
||||
"name": "minimatch",
|
||||
"description": "a glob matcher in javascript",
|
||||
"version": "2.0.10",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/isaacs/minimatch.git"
|
||||
},
|
||||
"main": "minimatch.js",
|
||||
"scripts": {
|
||||
"posttest": "standard minimatch.js test/*.js",
|
||||
"test": "tap test/*.js",
|
||||
"prepublish": "browserify -o browser.js -e minimatch.js -s minimatch --bare"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"browserify": "^9.0.3",
|
||||
"standard": "^3.7.2",
|
||||
"tap": "^1.2.0"
|
||||
},
|
||||
"license": "ISC",
|
||||
"files": [
|
||||
"minimatch.js",
|
||||
"browser.js"
|
||||
],
|
||||
"gitHead": "6afb85f0c324b321f76a38df81891e562693e257",
|
||||
"bugs": {
|
||||
"url": "https://github.com/isaacs/minimatch/issues"
|
||||
},
|
||||
"homepage": "https://github.com/isaacs/minimatch#readme",
|
||||
"_id": "minimatch@2.0.10",
|
||||
"_shasum": "8d087c39c6b38c001b97fca7ce6d0e1e80afbac7",
|
||||
"_from": "minimatch@>=2.0.0 <2.1.0",
|
||||
"_npmVersion": "3.1.0",
|
||||
"_nodeVersion": "2.2.1",
|
||||
"_npmUser": {
|
||||
"name": "isaacs",
|
||||
"email": "isaacs@npmjs.com"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "8d087c39c6b38c001b97fca7ce6d0e1e80afbac7",
|
||||
"tarball": "http://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "isaacs",
|
||||
"email": "i@izs.me"
|
||||
}
|
||||
],
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
|
@ -20,9 +20,9 @@ function getStdin(cb) {
|
|||
}
|
||||
|
||||
if (process.argv.indexOf('-h') !== -1 || process.argv.indexOf('--help') !== -1) {
|
||||
console.log('strip-json-comments <input file> > <output file>');
|
||||
console.log('strip-json-comments input-file > output-file');
|
||||
console.log('or');
|
||||
console.log('cat <input file> | strip-json-comments > <output file>');
|
||||
console.log('strip-json-comments < input-file > output-file');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
21
js/node/node_modules/jshint/node_modules/strip-json-comments/license
generated
vendored
Normal file
21
js/node/node_modules/jshint/node_modules/strip-json-comments/license
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.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.
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "strip-json-comments",
|
||||
"version": "1.0.2",
|
||||
"version": "1.0.4",
|
||||
"description": "Strip comments from JSON. Lets you use comments in your JSON files!",
|
||||
"keywords": [
|
||||
"json",
|
||||
|
@ -25,7 +25,7 @@
|
|||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "http://sindresorhus.com"
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"files": [
|
||||
"cli.js",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"url": "git+https://github.com/sindresorhus/strip-json-comments.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "mocha"
|
||||
"test": "mocha --ui tdd"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "*"
|
||||
|
@ -48,31 +48,31 @@
|
|||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"gitHead": "142dd671c71f90fb7fdba440184b1bb64543acb3",
|
||||
"gitHead": "f58348696368583cc5bb18525fe31eacc9bd00e1",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sindresorhus/strip-json-comments/issues"
|
||||
},
|
||||
"homepage": "https://github.com/sindresorhus/strip-json-comments",
|
||||
"_id": "strip-json-comments@1.0.2",
|
||||
"_shasum": "5a48ab96023dbac1b7b8d0ffabf6f63f1677be9f",
|
||||
"_id": "strip-json-comments@1.0.4",
|
||||
"_shasum": "1e15fbcac97d3ee99bf2d73b4c656b082bbafb91",
|
||||
"_from": "strip-json-comments@>=1.0.0 <1.1.0",
|
||||
"_npmVersion": "2.1.2",
|
||||
"_nodeVersion": "0.10.32",
|
||||
"_npmVersion": "2.11.2",
|
||||
"_nodeVersion": "0.12.5",
|
||||
"_npmUser": {
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
},
|
||||
"dist": {
|
||||
"shasum": "1e15fbcac97d3ee99bf2d73b4c656b082bbafb91",
|
||||
"tarball": "http://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "sindresorhus",
|
||||
"email": "sindresorhus@gmail.com"
|
||||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "5a48ab96023dbac1b7b8d0ffabf6f63f1677be9f",
|
||||
"tarball": "http://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.2.tgz",
|
||||
"_resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz",
|
||||
"readme": "ERROR: No README data found!"
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@ This is now possible:
|
|||
|
||||
It will remove single-line comments `//` and multi-line comments `/**/`.
|
||||
|
||||
Also available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin and a [require hook](https://github.com/uTest/autostrip-json-comments).
|
||||
Also available as a [gulp](https://github.com/sindresorhus/gulp-strip-json-comments)/[grunt](https://github.com/sindresorhus/grunt-strip-json-comments)/[broccoli](https://github.com/sindresorhus/broccoli-strip-json-comments) plugin.
|
||||
|
||||
-
|
||||
|
||||
*There's already [json-comments](https://npmjs.org/package/json-comments), but it's only for Node.js and uses a naive regex to strip comments which fails on simple cases like `{"a":"//"}`. This module however parses out the comments.*
|
||||
*There's also [`json-comments`](https://npmjs.org/package/json-comments), but it's only for Node.js, inefficient, bloated as it also minifies, and comes with a `require` hook, which is :(*
|
||||
|
||||
|
||||
## Install
|
||||
|
@ -69,6 +70,11 @@ strip-json-comments < input-file > output-file
|
|||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [`strip-css-comments`](https://github.com/sindresorhus/strip-css-comments)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](http://sindresorhus.com)
|
||||
|
|
20
js/node/node_modules/jshint/node_modules/strip-json-comments/strip-json-comments.js
generated
vendored
20
js/node/node_modules/jshint/node_modules/strip-json-comments/strip-json-comments.js
generated
vendored
|
@ -8,6 +8,9 @@
|
|||
(function () {
|
||||
'use strict';
|
||||
|
||||
var singleComment = 1;
|
||||
var multiComment = 2;
|
||||
|
||||
function stripJsonComments(str) {
|
||||
var currentChar;
|
||||
var nextChar;
|
||||
|
@ -19,8 +22,11 @@
|
|||
currentChar = str[i];
|
||||
nextChar = str[i + 1];
|
||||
|
||||
if (!insideComment && str[i - 1] !== '\\' && currentChar === '"') {
|
||||
insideString = !insideString;
|
||||
if (!insideComment && currentChar === '"') {
|
||||
var escaped = str[i - 1] === '\\' && str[i - 2] !== '\\';
|
||||
if (!insideComment && !escaped && currentChar === '"') {
|
||||
insideString = !insideString;
|
||||
}
|
||||
}
|
||||
|
||||
if (insideString) {
|
||||
|
@ -29,21 +35,21 @@
|
|||
}
|
||||
|
||||
if (!insideComment && currentChar + nextChar === '//') {
|
||||
insideComment = 'single';
|
||||
insideComment = singleComment;
|
||||
i++;
|
||||
} else if (insideComment === 'single' && currentChar + nextChar === '\r\n') {
|
||||
} else if (insideComment === singleComment && currentChar + nextChar === '\r\n') {
|
||||
insideComment = false;
|
||||
i++;
|
||||
ret += currentChar;
|
||||
ret += nextChar;
|
||||
continue;
|
||||
} else if (insideComment === 'single' && currentChar === '\n') {
|
||||
} else if (insideComment === singleComment && currentChar === '\n') {
|
||||
insideComment = false;
|
||||
} else if (!insideComment && currentChar + nextChar === '/*') {
|
||||
insideComment = 'multi';
|
||||
insideComment = multiComment;
|
||||
i++;
|
||||
continue;
|
||||
} else if (insideComment === 'multi' && currentChar + nextChar === '*/') {
|
||||
} else if (insideComment === multiComment && currentChar + nextChar === '*/') {
|
||||
insideComment = false;
|
||||
i++;
|
||||
continue;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "jshint",
|
||||
"version": "2.8.0",
|
||||
"version": "2.9.2",
|
||||
"homepage": "http://jshint.com/",
|
||||
"description": "Static analysis tool for JavaScript",
|
||||
"author": {
|
||||
|
@ -10,7 +10,7 @@
|
|||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jshint/jshint.git"
|
||||
"url": "git+https://github.com/jshint/jshint.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/jshint/jshint/issues"
|
||||
|
@ -19,11 +19,19 @@
|
|||
"jshint": "./bin/jshint"
|
||||
},
|
||||
"scripts": {
|
||||
"browser-test-server": "node tests/helpers/browser/server",
|
||||
"build": "node bin/build",
|
||||
"coverage": "istanbul -- cover ./node_modules/.bin/nodeunit tests/unit",
|
||||
"data": "node scripts/generate-identifier-data",
|
||||
"pretest": "jshint src && jscs src",
|
||||
"test": "nodeunit tests tests/regression tests/unit"
|
||||
"changelog": "conventional-changelog -p jshint -i CHANGELOG.md -w",
|
||||
"github-release": "conventional-github-releaser -p jshint",
|
||||
"test-browser": "node tests/browser",
|
||||
"test-cli": "nodeunit tests/cli.js",
|
||||
"test-node": "npm run test-unit && npm run test-cli && npm run test-regression",
|
||||
"test-regression": "nodeunit tests/regression",
|
||||
"test-unit": "nodeunit tests/unit",
|
||||
"test": "npm run test-node && npm run test-browser"
|
||||
},
|
||||
"main": "./src/jshint.js",
|
||||
"dependencies": {
|
||||
|
@ -38,12 +46,16 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"browserify": "9.x",
|
||||
"conventional-changelog": "0.4.x",
|
||||
"conventional-github-releaser": "0.4.x",
|
||||
"coveralls": "2.11.x",
|
||||
"istanbul": "0.3.x",
|
||||
"jscs": "1.11.x",
|
||||
"jshint": "2.6.x",
|
||||
"mock-stdin": "0.3.x",
|
||||
"nodeunit": "0.9.x",
|
||||
"phantom": "~0.7.2",
|
||||
"phantomjs": "1.9.13",
|
||||
"regenerate": "1.2.x",
|
||||
"sinon": "1.12.x",
|
||||
"unicode-6.3.0": "0.1.x"
|
||||
|
@ -56,12 +68,12 @@
|
|||
"dist",
|
||||
"src"
|
||||
],
|
||||
"gitHead": "e6611af2d180bd2317d5762e85807a481de99ccb",
|
||||
"_id": "jshint@2.8.0",
|
||||
"_shasum": "1d09a3bd913c4cadfa81bf18d582bd85bffe0d44",
|
||||
"_from": "jshint@2.8.0",
|
||||
"_npmVersion": "2.6.0",
|
||||
"_nodeVersion": "0.12.0",
|
||||
"gitHead": "b554ffe61eabf6e3e3a2876a3a377271da308811",
|
||||
"_id": "jshint@2.9.2",
|
||||
"_shasum": "0b12d75f8eafb0823b7bf8efbb265b3262401619",
|
||||
"_from": "jshint@latest",
|
||||
"_npmVersion": "3.3.12",
|
||||
"_nodeVersion": "5.3.0",
|
||||
"_npmUser": {
|
||||
"name": "jugglinmike",
|
||||
"email": "mike@mikepennisi.com"
|
||||
|
@ -81,9 +93,13 @@
|
|||
}
|
||||
],
|
||||
"dist": {
|
||||
"shasum": "1d09a3bd913c4cadfa81bf18d582bd85bffe0d44",
|
||||
"tarball": "http://registry.npmjs.org/jshint/-/jshint-2.8.0.tgz"
|
||||
"shasum": "0b12d75f8eafb0823b7bf8efbb265b3262401619",
|
||||
"tarball": "https://registry.npmjs.org/jshint/-/jshint-2.9.2.tgz"
|
||||
},
|
||||
"_npmOperationalInternal": {
|
||||
"host": "packages-16-east.internal.npmjs.com",
|
||||
"tmp": "tmp/jshint-2.9.2.tgz_1461106429823_0.9580952741671354"
|
||||
},
|
||||
"directories": {},
|
||||
"_resolved": "https://registry.npmjs.org/jshint/-/jshint-2.8.0.tgz"
|
||||
"_resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.2.tgz"
|
||||
}
|
||||
|
|
|
@ -15,6 +15,13 @@ var defReporter = require("./reporters/default").reporter;
|
|||
var OPTIONS = {
|
||||
"config": ["c", "Custom configuration file", "string", false ],
|
||||
"reporter": ["reporter", "Custom reporter (<PATH>|jslint|checkstyle|unix)", "string", undefined ],
|
||||
"prereq": [
|
||||
"prereq",
|
||||
"Comma-separate list of prerequisite (paths). E.g. files which include" +
|
||||
"definitions of global variabls used throughout your project",
|
||||
"string",
|
||||
null
|
||||
],
|
||||
"exclude": ["exclude",
|
||||
"Exclude files matching the given filename pattern (same as .jshintignore)", "string", null],
|
||||
"exclude-path": ["exclude-path", "Pass in a custom jshintignore file path", "string", null],
|
||||
|
@ -74,18 +81,18 @@ function deprecated(text, alt) {
|
|||
function findConfig(file) {
|
||||
var dir = path.dirname(path.resolve(file));
|
||||
var envs = getHomeDir();
|
||||
|
||||
if (!envs)
|
||||
return home;
|
||||
|
||||
var home = path.normalize(path.join(envs, ".jshintrc"));
|
||||
|
||||
var proj = findFile(".jshintrc", dir);
|
||||
var home;
|
||||
|
||||
if (proj)
|
||||
return proj;
|
||||
|
||||
if (shjs.test("-e", home))
|
||||
return home;
|
||||
else if (envs) {
|
||||
home = path.normalize(path.join(envs, ".jshintrc"));
|
||||
|
||||
if (shjs.test("-e", home))
|
||||
return home;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
@ -198,7 +205,8 @@ function loadIgnores(params) {
|
|||
}
|
||||
|
||||
var lines = (file ? shjs.cat(file) : "").split("\n");
|
||||
lines.unshift(params.exclude || "");
|
||||
var exclude = params.exclude || "";
|
||||
lines.unshift.apply(lines, exclude.split(","));
|
||||
|
||||
return lines
|
||||
.filter(function(line) {
|
||||
|
@ -272,7 +280,7 @@ function extract(code, when) {
|
|||
// in between the last </script> tag and this <script> tag to preserve
|
||||
// location information.
|
||||
inscript = true;
|
||||
js.push.apply(js, code.slice(index, parser.endIndex).match(/\n\r|\n|\r/g));
|
||||
js.push.apply(js, code.slice(index, parser.endIndex).match(/\r\n|\n|\r/g));
|
||||
startOffset = null;
|
||||
}
|
||||
|
||||
|
@ -289,7 +297,7 @@ function extract(code, when) {
|
|||
if (!inscript)
|
||||
return;
|
||||
|
||||
var lines = data.split(/\n\r|\n|\r/);
|
||||
var lines = data.split(/\r\n|\n|\r/);
|
||||
|
||||
if (!startOffset) {
|
||||
lines.some(function(line) {
|
||||
|
@ -354,7 +362,7 @@ function extractOffsets(code, when) {
|
|||
// location information.
|
||||
inscript = true;
|
||||
var fragment = code.slice(index, parser.endIndex);
|
||||
var n = (fragment.match(/\n\r|\n|\r/g) || []).length;
|
||||
var n = (fragment.match(/\r\n|\n|\r/g) || []).length;
|
||||
lineCounter += n;
|
||||
startOffset = null;
|
||||
}
|
||||
|
@ -372,7 +380,7 @@ function extractOffsets(code, when) {
|
|||
if (!inscript)
|
||||
return;
|
||||
|
||||
var lines = data.split(/\n\r|\n|\r/);
|
||||
var lines = data.split(/\r\n|\n|\r/);
|
||||
|
||||
if (!startOffset) {
|
||||
lines.some(function(line) {
|
||||
|
@ -596,6 +604,12 @@ var exports = {
|
|||
var results = [];
|
||||
var data = [];
|
||||
|
||||
function mergeCLIPrereq(config) {
|
||||
if (opts.prereq) {
|
||||
config.prereq = (config.prereq || []).concat(opts.prereq.split(/\s*,\s*/));
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.useStdin) {
|
||||
cli.withStdin(function(code) {
|
||||
var config = opts.config;
|
||||
|
@ -610,12 +624,13 @@ var exports = {
|
|||
}
|
||||
|
||||
if (filename && !config) {
|
||||
config = loadNpmConfig(filename) ||
|
||||
exports.loadConfig(findConfig(filename));
|
||||
config = exports.getConfig(filename);
|
||||
}
|
||||
|
||||
config = config || {};
|
||||
|
||||
mergeCLIPrereq(config);
|
||||
|
||||
lint(extract(code, opts.extract), results, config, data, filename);
|
||||
(opts.reporter || defReporter)(results, data, { verbose: opts.verbose });
|
||||
cb(results.length === 0);
|
||||
|
@ -627,6 +642,7 @@ var exports = {
|
|||
files.forEach(function(file) {
|
||||
var config = opts.config || exports.getConfig(file);
|
||||
var code;
|
||||
var errors = [];
|
||||
|
||||
try {
|
||||
code = shjs.cat(file);
|
||||
|
@ -635,19 +651,22 @@ var exports = {
|
|||
exports.exit(1);
|
||||
}
|
||||
|
||||
lint(extract(code, opts.extract), results, config, data, file);
|
||||
mergeCLIPrereq(config);
|
||||
|
||||
if (results.length) {
|
||||
lint(extract(code, opts.extract), errors, config, data, file);
|
||||
|
||||
if (errors.length) {
|
||||
var offsets = extractOffsets(code, opts.extract);
|
||||
if (offsets && offsets.length) {
|
||||
results.forEach(function(errorInfo) {
|
||||
errors.forEach(function(errorInfo) {
|
||||
var line = errorInfo.error.line;
|
||||
if (line >= 0 && line < offsets.length) {
|
||||
var offset = +offsets[line];
|
||||
errorInfo.error.character += offset;
|
||||
if (line >= 0 && line < offsets.length && offsets[line]) {
|
||||
errorInfo.error.character += offsets[line];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
results = results.concat(errors);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -743,6 +762,7 @@ var exports = {
|
|||
verbose: options.verbose,
|
||||
extract: options.extract,
|
||||
filename: options.filename,
|
||||
prereq: options.prereq,
|
||||
useStdin: { "-": true, "/dev/stdin": true }[args[args.length - 1]]
|
||||
}, done));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -342,7 +342,7 @@ Lexer.prototype = {
|
|||
}
|
||||
|
||||
// 2-character punctuators: <= >= == != ++ -- << >> && ||
|
||||
// += -= *= %= &= |= ^= (but not /=, see below)
|
||||
// += -= *= %= &= |= ^= /=
|
||||
if (ch1 === ch2 && ("+-<>&|".indexOf(ch1) >= 0)) {
|
||||
return {
|
||||
type: Token.Punctuator,
|
||||
|
@ -350,7 +350,7 @@ Lexer.prototype = {
|
|||
};
|
||||
}
|
||||
|
||||
if ("<>=!+-*%&|^".indexOf(ch1) >= 0) {
|
||||
if ("<>=!+-*%&|^/".indexOf(ch1) >= 0) {
|
||||
if (ch2 === "=") {
|
||||
return {
|
||||
type: Token.Punctuator,
|
||||
|
@ -364,22 +364,6 @@ Lexer.prototype = {
|
|||
};
|
||||
}
|
||||
|
||||
// Special case: /=.
|
||||
|
||||
if (ch1 === "/") {
|
||||
if (ch2 === "=") {
|
||||
return {
|
||||
type: Token.Punctuator,
|
||||
value: "/="
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
type: Token.Punctuator,
|
||||
value: "/"
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
|
@ -399,6 +383,7 @@ Lexer.prototype = {
|
|||
var rest = this.input.substr(2);
|
||||
var startLine = this.line;
|
||||
var startChar = this.char;
|
||||
var self = this;
|
||||
|
||||
// Create a comment token object and make sure it
|
||||
// has all the data JSHint needs to work with special
|
||||
|
@ -417,6 +402,11 @@ Lexer.prototype = {
|
|||
|
||||
body = body.replace(/\n/g, " ");
|
||||
|
||||
if (label === "/*" && reg.fallsThrough.test(body)) {
|
||||
isSpecial = true;
|
||||
commentType = "falls through";
|
||||
}
|
||||
|
||||
special.forEach(function(str) {
|
||||
if (isSpecial) {
|
||||
return;
|
||||
|
@ -453,6 +443,26 @@ Lexer.prototype = {
|
|||
commentType = "globals";
|
||||
break;
|
||||
default:
|
||||
var options = body.split(":").map(function(v) {
|
||||
return v.replace(/^\s+/, "").replace(/\s+$/, "");
|
||||
});
|
||||
|
||||
if (options.length === 2) {
|
||||
switch (options[0]) {
|
||||
case "ignore":
|
||||
switch (options[1]) {
|
||||
case "start":
|
||||
self.ignoringLinterErrors = true;
|
||||
isSpecial = false;
|
||||
break;
|
||||
case "end":
|
||||
self.ignoringLinterErrors = false;
|
||||
isSpecial = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
commentType = str;
|
||||
}
|
||||
});
|
||||
|
@ -767,12 +777,12 @@ Lexer.prototype = {
|
|||
isAllowedDigit = isOctalDigit;
|
||||
base = 8;
|
||||
|
||||
if (!state.option.esnext) {
|
||||
if (!state.inES6(true)) {
|
||||
this.trigger("warning", {
|
||||
code: "W119",
|
||||
line: this.line,
|
||||
character: this.char,
|
||||
data: [ "Octal integer literal" ]
|
||||
data: [ "Octal integer literal", "6" ]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -785,12 +795,12 @@ Lexer.prototype = {
|
|||
isAllowedDigit = isBinaryDigit;
|
||||
base = 2;
|
||||
|
||||
if (!state.option.esnext) {
|
||||
if (!state.inES6(true)) {
|
||||
this.trigger("warning", {
|
||||
code: "W119",
|
||||
line: this.line,
|
||||
character: this.char,
|
||||
data: [ "Binary integer literal" ]
|
||||
data: [ "Binary integer literal", "6" ]
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1032,10 +1042,15 @@ Lexer.prototype = {
|
|||
var startChar = this.char;
|
||||
var depth = this.templateStarts.length;
|
||||
|
||||
if (!state.option.esnext) {
|
||||
// Only lex template strings in ESNext mode.
|
||||
return null;
|
||||
} else if (this.peek() === "`") {
|
||||
if (this.peek() === "`") {
|
||||
if (!state.inES6(true)) {
|
||||
this.trigger("warning", {
|
||||
code: "W119",
|
||||
line: this.line,
|
||||
character: this.char,
|
||||
data: ["template literal syntax", "6"]
|
||||
});
|
||||
}
|
||||
// Template must start with a backtick.
|
||||
tokenType = Token.TemplateHead;
|
||||
this.templateStarts.push({ line: this.line, char: this.char });
|
||||
|
@ -1434,14 +1449,9 @@ Lexer.prototype = {
|
|||
this.from = this.char;
|
||||
|
||||
// Move to the next non-space character.
|
||||
var start;
|
||||
if (/\s/.test(this.peek())) {
|
||||
start = this.char;
|
||||
|
||||
while (/\s/.test(this.peek())) {
|
||||
this.from += 1;
|
||||
this.skip();
|
||||
}
|
||||
while (/\s/.test(this.peek())) {
|
||||
this.from += 1;
|
||||
this.skip();
|
||||
}
|
||||
|
||||
// Methods that work with multi-line structures and move the
|
||||
|
@ -1506,7 +1516,7 @@ Lexer.prototype = {
|
|||
|
||||
// If we are ignoring linter errors, replace the input with empty string
|
||||
// if it doesn't already at least start or end a multi-line comment
|
||||
if (state.ignoreLinterErrors === true) {
|
||||
if (this.ignoringLinterErrors === true) {
|
||||
if (!startsWith("/*", "//") && !(this.inComment && endsWith("*/"))) {
|
||||
this.input = "";
|
||||
}
|
||||
|
@ -1527,7 +1537,8 @@ Lexer.prototype = {
|
|||
// If there is a limit on line length, warn when lines get too
|
||||
// long.
|
||||
|
||||
if (state.option.maxlen && state.option.maxlen < this.input.length) {
|
||||
if (!this.ignoringLinterErrors && state.option.maxlen &&
|
||||
state.option.maxlen < this.input.length) {
|
||||
var inComment = this.inComment ||
|
||||
startsWith.call(inputTrimmed, "//") ||
|
||||
startsWith.call(inputTrimmed, "/*");
|
||||
|
@ -1616,7 +1627,8 @@ Lexer.prototype = {
|
|||
}
|
||||
|
||||
if (type === "(identifier)") {
|
||||
if (value === "return" || value === "case" || value === "typeof") {
|
||||
if (value === "return" || value === "case" ||
|
||||
value === "typeof" || value === "instanceof") {
|
||||
this.prereg = true;
|
||||
}
|
||||
|
||||
|
@ -1630,6 +1642,10 @@ Lexer.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
if (type === "(template)" || type === "(template middle)") {
|
||||
this.prereg = true;
|
||||
}
|
||||
|
||||
if (!obj) {
|
||||
obj = Object.create(state.syntax[type]);
|
||||
}
|
||||
|
@ -1757,14 +1773,14 @@ Lexer.prototype = {
|
|||
return create("(no subst template)", token.value, null, token);
|
||||
|
||||
case Token.Identifier:
|
||||
this.trigger("Identifier", {
|
||||
this.triggerAsync("Identifier", {
|
||||
line: this.line,
|
||||
char: this.char,
|
||||
from: this.form,
|
||||
from: this.from,
|
||||
name: token.value,
|
||||
raw_name: token.text,
|
||||
isProperty: state.tokens.curr.id === "."
|
||||
});
|
||||
}, checks, function() { return true; });
|
||||
|
||||
/* falls through */
|
||||
case Token.Keyword:
|
||||
|
|
|
@ -20,7 +20,7 @@ var errors = {
|
|||
E010: "'with' is not allowed in strict mode.",
|
||||
|
||||
// Constants
|
||||
E011: "const '{a}' has already been declared.",
|
||||
E011: "'{a}' has already been declared.",
|
||||
E012: "const '{a}' is initialized to 'undefined'.",
|
||||
E013: "Attempting to override '{a}' which is a constant.",
|
||||
|
||||
|
@ -62,15 +62,19 @@ var errors = {
|
|||
E044: null,
|
||||
E045: "Invalid for each loop.",
|
||||
E046: "A yield statement shall be within a generator function (with syntax: `function*`)",
|
||||
E047: null, // Vacant
|
||||
E047: null,
|
||||
E048: "{a} declaration not directly within block.",
|
||||
E049: "A {a} cannot be named '{b}'.",
|
||||
E050: "Mozilla requires the yield expression to be parenthesized here.",
|
||||
E051: "Regular parameters cannot come after default parameters.",
|
||||
E051: null,
|
||||
E052: "Unclosed template literal.",
|
||||
E053: "Export declaration must be in global scope.",
|
||||
E054: "Class properties must be methods. Expected '(' but instead saw '{a}'.",
|
||||
E055: "The '{a}' option cannot be set after any executable code."
|
||||
E055: "The '{a}' option cannot be set after any executable code.",
|
||||
E056: "'{a}' was used before it was declared, which is illegal for '{b}' variables.",
|
||||
E057: "Invalid meta property: '{a}.{b}'.",
|
||||
E058: "Missing semicolon.",
|
||||
E059: "Incompatible values for the '{a}' and '{b}' linting options."
|
||||
};
|
||||
|
||||
var warnings = {
|
||||
|
@ -94,7 +98,8 @@ var warnings = {
|
|||
W018: "Confusing use of '{a}'.",
|
||||
W019: "Use the isNaN function to compare with NaN.",
|
||||
W020: "Read only.",
|
||||
W021: "'{a}' is a function.",
|
||||
W021: "Reassignment of '{a}', which is is a {b}. " +
|
||||
"Use 'var' or 'let' to declare bindings that may change.",
|
||||
W022: "Do not assign to the exception parameter.",
|
||||
W023: "Expected an identifier in an assignment and instead saw a function invocation.",
|
||||
W024: "Expected an identifier and instead saw '{a}' (a reserved word).",
|
||||
|
@ -168,7 +173,7 @@ var warnings = {
|
|||
W089: "The body of a for in should be wrapped in an if statement to filter " +
|
||||
"unwanted properties from the prototype.",
|
||||
W090: "'{a}' is not a statement label.",
|
||||
W091: "'{a}' is out of scope.",
|
||||
W091: null,
|
||||
W093: "Did you mean to return a conditional instead of an assignment?",
|
||||
W094: "Unexpected comma.",
|
||||
W095: "Expected a string and instead saw {a}.",
|
||||
|
@ -180,7 +185,7 @@ var warnings = {
|
|||
W101: "Line is too long.",
|
||||
W102: null,
|
||||
W103: "The '{a}' property is deprecated.",
|
||||
W104: "'{a}' is available in ES6 (use esnext option) or Mozilla JS extensions (use moz).",
|
||||
W104: "'{a}' is available in ES{b} (use 'esversion: {b}') or Mozilla JS extensions (use moz).",
|
||||
W105: "Unexpected {a} in '{b}'.",
|
||||
W106: "Identifier '{a}' is not in camel case.",
|
||||
W107: "Script URL.",
|
||||
|
@ -194,13 +199,13 @@ var warnings = {
|
|||
W116: "Expected '{a}' and instead saw '{b}'.",
|
||||
W117: "'{a}' is not defined.",
|
||||
W118: "'{a}' is only available in Mozilla JavaScript extensions (use moz option).",
|
||||
W119: "'{a}' is only available in ES6 (use esnext option).",
|
||||
W119: "'{a}' is only available in ES{b} (use 'esversion: {b}').",
|
||||
W120: "You might be leaking a variable ({a}) here.",
|
||||
W121: "Extending prototype of native object: '{a}'.",
|
||||
W122: "Invalid typeof value '{a}'",
|
||||
W123: "'{a}' is already defined in outer scope.",
|
||||
W124: "A generator function shall contain a yield statement.",
|
||||
W125: "This line contains non-breaking spaces: http://jshint.com/doc/options/#nonbsp",
|
||||
W125: "This line contains non-breaking spaces: http://jshint.com/docs/options/#nonbsp",
|
||||
W126: "Unnecessary grouping operator.",
|
||||
W127: "Unexpected use of a comma operator.",
|
||||
W128: "Empty array elements require elision=true.",
|
||||
|
@ -210,7 +215,11 @@ var warnings = {
|
|||
W131: "Invalid parameter after rest parameter.",
|
||||
W132: "`var` declarations are forbidden. Use `let` or `const` instead.",
|
||||
W133: "Invalid for-{a} loop left-hand-side: {b}.",
|
||||
W134: "The '{a}' option is only available when linting ECMAScript {b} code."
|
||||
W134: "The '{a}' option is only available when linting ECMAScript {b} code.",
|
||||
W135: "{a} may not be supported by non-browser environments.",
|
||||
W136: "'{a}' must be in function scope.",
|
||||
W137: "Empty destructuring.",
|
||||
W138: "Regular parameters should not come after default parameters."
|
||||
};
|
||||
|
||||
var info = {
|
||||
|
|
|
@ -91,6 +91,8 @@ exports.bool = {
|
|||
* specification. Use this option if you need your program to be executable
|
||||
* in older browsers—such as Internet Explorer 6/7/8/9—and other legacy
|
||||
* JavaScript environments.
|
||||
*
|
||||
* @deprecated Use `esversion: 3` instead.
|
||||
*/
|
||||
es3 : true,
|
||||
|
||||
|
@ -98,6 +100,8 @@ exports.bool = {
|
|||
* This option enables syntax first defined in [the ECMAScript 5.1
|
||||
* specification](http://es5.github.io/). This includes allowing reserved
|
||||
* keywords as object properties.
|
||||
*
|
||||
* @deprecated Use `esversion: 5` instead.
|
||||
*/
|
||||
es5 : true,
|
||||
|
||||
|
@ -258,21 +262,6 @@ exports.bool = {
|
|||
*/
|
||||
singleGroups: false,
|
||||
|
||||
/**
|
||||
* This option requires all functions to run in ECMAScript 5's strict mode.
|
||||
* [Strict mode](https://developer.mozilla.org/en/JavaScript/Strict_mode)
|
||||
* is a way to opt in to a restricted variant of JavaScript. Strict mode
|
||||
* eliminates some JavaScript pitfalls that didn't cause errors by changing
|
||||
* them to produce errors. It also fixes mistakes that made it difficult
|
||||
* for the JavaScript engines to perform certain optimizations.
|
||||
*
|
||||
* *Note:* This option enables strict mode for function scope only. It
|
||||
* *prohibits* the global scoped strict mode because it might break
|
||||
* third-party widgets on your page. If you really want to use global
|
||||
* strict mode, see the *globalstrict* option.
|
||||
*/
|
||||
strict : true,
|
||||
|
||||
/**
|
||||
* When set to true, the use of VariableStatements are forbidden.
|
||||
* For example:
|
||||
|
@ -375,6 +364,8 @@ exports.bool = {
|
|||
* recommended.
|
||||
*
|
||||
* For more info about strict mode see the `strict` option.
|
||||
*
|
||||
* @deprecated Use `strict: "global"`.
|
||||
*/
|
||||
globalstrict: true,
|
||||
|
||||
|
@ -550,13 +541,14 @@ exports.bool = {
|
|||
|
||||
/**
|
||||
* This option tells JSHint that your code uses ECMAScript 6 specific
|
||||
* syntax. Note that these features are not finalized yet and not all
|
||||
* browsers implement them.
|
||||
* syntax. Note that not all browsers implement these features.
|
||||
*
|
||||
* More info:
|
||||
*
|
||||
* * [Draft Specification for ES.next (ECMA-262 Ed.
|
||||
* 6)](http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts)
|
||||
* * [Specification for ECMAScript
|
||||
* 6](http://www.ecma-international.org/ecma-262/6.0/index.html)
|
||||
*
|
||||
* @deprecated Use `esversion: 6` instead.
|
||||
*/
|
||||
esnext : true,
|
||||
|
||||
|
@ -757,7 +749,18 @@ exports.val = {
|
|||
*/
|
||||
maxerr : false,
|
||||
|
||||
predef : false, // predef is deprecated and being replaced by globals
|
||||
/**
|
||||
* This option allows you to control which variables JSHint considers to be
|
||||
* implicitly defined in the environment. Configure it with an array of
|
||||
* string values. Prefixing a variable name with a hyphen (-) character will
|
||||
* remove that name from the collection of predefined variables.
|
||||
*
|
||||
* JSHint will consider variables declared in this way to be read-only.
|
||||
*
|
||||
* This option cannot be specified in-line; it may only be used via the
|
||||
* JavaScript API or from an external configuration file.
|
||||
*/
|
||||
predef : false,
|
||||
|
||||
/**
|
||||
* This option can be used to specify a white list of global variables that
|
||||
|
@ -772,6 +775,9 @@ exports.val = {
|
|||
* See also the "environment" options: a set of options to be used as short
|
||||
* hand for enabling global variables defined in common JavaScript
|
||||
* environments.
|
||||
*
|
||||
* To configure `globals` within an individual file, see [Inline
|
||||
* Configuration](http://jshint.com/docs/#inline-configuration).
|
||||
*/
|
||||
globals : false,
|
||||
|
||||
|
@ -871,6 +877,25 @@ exports.val = {
|
|||
*/
|
||||
shadow : false,
|
||||
|
||||
/**
|
||||
* This option requires the code to run in ECMAScript 5's strict mode.
|
||||
* [Strict mode](https://developer.mozilla.org/en/JavaScript/Strict_mode)
|
||||
* is a way to opt in to a restricted variant of JavaScript. Strict mode
|
||||
* eliminates some JavaScript pitfalls that didn't cause errors by changing
|
||||
* them to produce errors. It also fixes mistakes that made it difficult
|
||||
* for the JavaScript engines to perform certain optimizations.
|
||||
*
|
||||
* - "global" - there must be a `"use strict";` directive at global level
|
||||
* - "implied" - lint the code as if there is the `"use strict";` directive
|
||||
* - false - disable warnings about strict mode
|
||||
* - true - there must be a `"use strict";` directive at function level;
|
||||
* this is preferable for scripts intended to be loaded in web
|
||||
* browsers directly because enabling strict mode globally
|
||||
* could adversely effect other scripts running on the same
|
||||
* page
|
||||
*/
|
||||
strict : true,
|
||||
|
||||
/**
|
||||
* This option warns when you define and never use your variables. It is very
|
||||
* useful for general code cleanup, especially when used in addition to
|
||||
|
@ -921,8 +946,24 @@ exports.val = {
|
|||
// end - stop ignoring lines, starting on the next line
|
||||
// line - ignore warnings / errors for just a single line
|
||||
// (this option does not bypass the lexer)
|
||||
ignoreDelimiters: false // array of start/end delimiters used to ignore
|
||||
// certain chunks from code
|
||||
|
||||
ignoreDelimiters: false, // array of start/end delimiters used to ignore
|
||||
// certain chunks from code
|
||||
|
||||
/**
|
||||
* This option is used to specify the ECMAScript version to which the code
|
||||
* must adhere. It can assume one of the following values:
|
||||
* - `3` - If you need your program to be executable
|
||||
* in older browsers—such as Internet Explorer 6/7/8/9—and other legacy
|
||||
* JavaScript environments
|
||||
* - `5` - To enable syntax first defined in [the ECMAScript 5.1
|
||||
* specification](http://www.ecma-international.org/ecma-262/5.1/index.html).
|
||||
* This includes allowing reserved keywords as object properties.
|
||||
* - `6` - To tell JSHint that your code uses [ECMAScript
|
||||
* 6](http://www.ecma-international.org/ecma-262/6.0/index.html) specific
|
||||
* syntax. Note that not all browsers implement them.
|
||||
*/
|
||||
esversion: 5
|
||||
};
|
||||
|
||||
// These are JSHint boolean options which are shared with JSLint
|
||||
|
|
|
@ -31,7 +31,7 @@ exports.identifier = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/;
|
|||
exports.javascriptURL = /^(?:javascript|jscript|ecmascript|vbscript|livescript)\s*:/i;
|
||||
|
||||
// Catches /* falls through */ comments (ft)
|
||||
exports.fallsThrough = /^\s*\/\*\s*falls?\sthrough\s*\*\/\s*$/;
|
||||
exports.fallsThrough = /^\s*falls?\sthrough\s*$/;
|
||||
|
||||
// very conservative rule (eg: only one space between the start of the comment and the first character)
|
||||
// to relax the maxlen option
|
||||
|
|
|
@ -0,0 +1,857 @@
|
|||
"use strict";
|
||||
|
||||
var _ = require("lodash");
|
||||
var events = require("events");
|
||||
|
||||
// Used to denote membership in lookup tables (a primitive value such as `true`
|
||||
// would be silently rejected for the property name "__proto__" in some
|
||||
// environments)
|
||||
var marker = {};
|
||||
|
||||
/**
|
||||
* Creates a scope manager that handles variables and labels, storing usages
|
||||
* and resolving when variables are used and undefined
|
||||
*/
|
||||
var scopeManager = function(state, predefined, exported, declared) {
|
||||
|
||||
var _current;
|
||||
var _scopeStack = [];
|
||||
|
||||
function _newScope(type) {
|
||||
_current = {
|
||||
"(labels)": Object.create(null),
|
||||
"(usages)": Object.create(null),
|
||||
"(breakLabels)": Object.create(null),
|
||||
"(parent)": _current,
|
||||
"(type)": type,
|
||||
"(params)": (type === "functionparams" || type === "catchparams") ? [] : null
|
||||
};
|
||||
_scopeStack.push(_current);
|
||||
}
|
||||
|
||||
_newScope("global");
|
||||
_current["(predefined)"] = predefined;
|
||||
|
||||
var _currentFunctBody = _current; // this is the block after the params = function
|
||||
|
||||
var usedPredefinedAndGlobals = Object.create(null);
|
||||
var impliedGlobals = Object.create(null);
|
||||
var unuseds = [];
|
||||
var emitter = new events.EventEmitter();
|
||||
|
||||
function warning(code, token) {
|
||||
emitter.emit("warning", {
|
||||
code: code,
|
||||
token: token,
|
||||
data: _.slice(arguments, 2)
|
||||
});
|
||||
}
|
||||
|
||||
function error(code, token) {
|
||||
emitter.emit("warning", {
|
||||
code: code,
|
||||
token: token,
|
||||
data: _.slice(arguments, 2)
|
||||
});
|
||||
}
|
||||
|
||||
function _setupUsages(labelName) {
|
||||
if (!_current["(usages)"][labelName]) {
|
||||
_current["(usages)"][labelName] = {
|
||||
"(modified)": [],
|
||||
"(reassigned)": [],
|
||||
"(tokens)": []
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var _getUnusedOption = function(unused_opt) {
|
||||
if (unused_opt === undefined) {
|
||||
unused_opt = state.option.unused;
|
||||
}
|
||||
|
||||
if (unused_opt === true) {
|
||||
unused_opt = "last-param";
|
||||
}
|
||||
|
||||
return unused_opt;
|
||||
};
|
||||
|
||||
var _warnUnused = function(name, tkn, type, unused_opt) {
|
||||
var line = tkn.line;
|
||||
var chr = tkn.from;
|
||||
var raw_name = tkn.raw_text || name;
|
||||
|
||||
unused_opt = _getUnusedOption(unused_opt);
|
||||
|
||||
var warnable_types = {
|
||||
"vars": ["var"],
|
||||
"last-param": ["var", "param"],
|
||||
"strict": ["var", "param", "last-param"]
|
||||
};
|
||||
|
||||
if (unused_opt) {
|
||||
if (warnable_types[unused_opt] && warnable_types[unused_opt].indexOf(type) !== -1) {
|
||||
warning("W098", { line: line, from: chr }, raw_name);
|
||||
}
|
||||
}
|
||||
|
||||
// inconsistent - see gh-1894
|
||||
if (unused_opt || type === "var") {
|
||||
unuseds.push({
|
||||
name: name,
|
||||
line: line,
|
||||
character: chr
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks the current scope for unused identifiers
|
||||
*/
|
||||
function _checkForUnused() {
|
||||
// function params are handled specially
|
||||
// assume that parameters are the only thing declared in the param scope
|
||||
if (_current["(type)"] === "functionparams") {
|
||||
_checkParams();
|
||||
return;
|
||||
}
|
||||
var curentLabels = _current["(labels)"];
|
||||
for (var labelName in curentLabels) {
|
||||
if (curentLabels[labelName]) {
|
||||
if (curentLabels[labelName]["(type)"] !== "exception" &&
|
||||
curentLabels[labelName]["(unused)"]) {
|
||||
_warnUnused(labelName, curentLabels[labelName]["(token)"], "var");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current scope for unused parameters
|
||||
* Must be called in a function parameter scope
|
||||
*/
|
||||
function _checkParams() {
|
||||
var params = _current["(params)"];
|
||||
|
||||
if (!params) {
|
||||
return;
|
||||
}
|
||||
|
||||
var param = params.pop();
|
||||
var unused_opt;
|
||||
|
||||
while (param) {
|
||||
var label = _current["(labels)"][param];
|
||||
|
||||
unused_opt = _getUnusedOption(state.funct["(unusedOption)"]);
|
||||
|
||||
// 'undefined' is a special case for (function(window, undefined) { ... })();
|
||||
// patterns.
|
||||
if (param === "undefined")
|
||||
return;
|
||||
|
||||
if (label["(unused)"]) {
|
||||
_warnUnused(param, label["(token)"], "param", state.funct["(unusedOption)"]);
|
||||
} else if (unused_opt === "last-param") {
|
||||
return;
|
||||
}
|
||||
|
||||
param = params.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the relevant label's scope, searching from nearest outwards
|
||||
* @returns {Object} the scope the label was found in
|
||||
*/
|
||||
function _getLabel(labelName) {
|
||||
for (var i = _scopeStack.length - 1 ; i >= 0; --i) {
|
||||
var scopeLabels = _scopeStack[i]["(labels)"];
|
||||
if (scopeLabels[labelName]) {
|
||||
return scopeLabels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function usedSoFarInCurrentFunction(labelName) {
|
||||
// used so far in this whole function and any sub functions
|
||||
for (var i = _scopeStack.length - 1; i >= 0; i--) {
|
||||
var current = _scopeStack[i];
|
||||
if (current["(usages)"][labelName]) {
|
||||
return current["(usages)"][labelName];
|
||||
}
|
||||
if (current === _currentFunctBody) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function _checkOuterShadow(labelName, token) {
|
||||
|
||||
// only check if shadow is outer
|
||||
if (state.option.shadow !== "outer") {
|
||||
return;
|
||||
}
|
||||
|
||||
var isGlobal = _currentFunctBody["(type)"] === "global",
|
||||
isNewFunction = _current["(type)"] === "functionparams";
|
||||
|
||||
var outsideCurrentFunction = !isGlobal;
|
||||
for (var i = 0; i < _scopeStack.length; i++) {
|
||||
var stackItem = _scopeStack[i];
|
||||
|
||||
if (!isNewFunction && _scopeStack[i + 1] === _currentFunctBody) {
|
||||
outsideCurrentFunction = false;
|
||||
}
|
||||
if (outsideCurrentFunction && stackItem["(labels)"][labelName]) {
|
||||
warning("W123", token, labelName);
|
||||
}
|
||||
if (stackItem["(breakLabels)"][labelName]) {
|
||||
warning("W123", token, labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _latedefWarning(type, labelName, token) {
|
||||
if (state.option.latedef) {
|
||||
// if either latedef is strict and this is a function
|
||||
// or this is not a function
|
||||
if ((state.option.latedef === true && type === "function") ||
|
||||
type !== "function") {
|
||||
warning("W003", token, labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scopeManagerInst = {
|
||||
|
||||
on: function(names, listener) {
|
||||
names.split(" ").forEach(function(name) {
|
||||
emitter.on(name, listener);
|
||||
});
|
||||
},
|
||||
|
||||
isPredefined: function(labelName) {
|
||||
return !this.has(labelName) && _.has(_scopeStack[0]["(predefined)"], labelName);
|
||||
},
|
||||
|
||||
/**
|
||||
* Tell the manager we are entering a new block of code
|
||||
* @param {string} [type] - The type of the block. Valid values are
|
||||
* "functionparams", "catchparams" and
|
||||
* "functionouter"
|
||||
*/
|
||||
stack: function(type) {
|
||||
var previousScope = _current;
|
||||
_newScope(type);
|
||||
|
||||
if (!type && previousScope["(type)"] === "functionparams") {
|
||||
|
||||
_current["(isFuncBody)"] = true;
|
||||
_current["(context)"] = _currentFunctBody;
|
||||
_currentFunctBody = _current;
|
||||
}
|
||||
},
|
||||
|
||||
unstack: function() {
|
||||
// jshint proto: true
|
||||
var subScope = _scopeStack.length > 1 ? _scopeStack[_scopeStack.length - 2] : null;
|
||||
var isUnstackingFunctionBody = _current === _currentFunctBody,
|
||||
isUnstackingFunctionParams = _current["(type)"] === "functionparams",
|
||||
isUnstackingFunctionOuter = _current["(type)"] === "functionouter";
|
||||
|
||||
var i, j;
|
||||
var currentUsages = _current["(usages)"];
|
||||
var currentLabels = _current["(labels)"];
|
||||
var usedLabelNameList = Object.keys(currentUsages);
|
||||
|
||||
if (currentUsages.__proto__ && usedLabelNameList.indexOf("__proto__") === -1) {
|
||||
usedLabelNameList.push("__proto__");
|
||||
}
|
||||
|
||||
for (i = 0; i < usedLabelNameList.length; i++) {
|
||||
var usedLabelName = usedLabelNameList[i];
|
||||
|
||||
var usage = currentUsages[usedLabelName];
|
||||
var usedLabel = currentLabels[usedLabelName];
|
||||
if (usedLabel) {
|
||||
var usedLabelType = usedLabel["(type)"];
|
||||
|
||||
if (usedLabel["(useOutsideOfScope)"] && !state.option.funcscope) {
|
||||
var usedTokens = usage["(tokens)"];
|
||||
if (usedTokens) {
|
||||
for (j = 0; j < usedTokens.length; j++) {
|
||||
// Keep the consistency of https://github.com/jshint/jshint/issues/2409
|
||||
if (usedLabel["(function)"] === usedTokens[j]["(function)"]) {
|
||||
error("W038", usedTokens[j], usedLabelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// mark the label used
|
||||
_current["(labels)"][usedLabelName]["(unused)"] = false;
|
||||
|
||||
// check for modifying a const
|
||||
if (usedLabelType === "const" && usage["(modified)"]) {
|
||||
for (j = 0; j < usage["(modified)"].length; j++) {
|
||||
error("E013", usage["(modified)"][j], usedLabelName);
|
||||
}
|
||||
}
|
||||
|
||||
// check for re-assigning a function declaration
|
||||
if ((usedLabelType === "function" || usedLabelType === "class") &&
|
||||
usage["(reassigned)"]) {
|
||||
for (j = 0; j < usage["(reassigned)"].length; j++) {
|
||||
if (!usage["(reassigned)"][j].ignoreW021) {
|
||||
warning("W021", usage["(reassigned)"][j], usedLabelName, usedLabelType);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isUnstackingFunctionOuter) {
|
||||
state.funct["(isCapturing)"] = true;
|
||||
}
|
||||
|
||||
if (subScope) {
|
||||
// not exiting the global scope, so copy the usage down in case its an out of scope usage
|
||||
if (!subScope["(usages)"][usedLabelName]) {
|
||||
subScope["(usages)"][usedLabelName] = usage;
|
||||
if (isUnstackingFunctionBody) {
|
||||
subScope["(usages)"][usedLabelName]["(onlyUsedSubFunction)"] = true;
|
||||
}
|
||||
} else {
|
||||
var subScopeUsage = subScope["(usages)"][usedLabelName];
|
||||
subScopeUsage["(modified)"] = subScopeUsage["(modified)"].concat(usage["(modified)"]);
|
||||
subScopeUsage["(tokens)"] = subScopeUsage["(tokens)"].concat(usage["(tokens)"]);
|
||||
subScopeUsage["(reassigned)"] =
|
||||
subScopeUsage["(reassigned)"].concat(usage["(reassigned)"]);
|
||||
}
|
||||
} else {
|
||||
// this is exiting global scope, so we finalise everything here - we are at the end of the file
|
||||
if (typeof _current["(predefined)"][usedLabelName] === "boolean") {
|
||||
|
||||
// remove the declared token, so we know it is used
|
||||
delete declared[usedLabelName];
|
||||
|
||||
// note it as used so it can be reported
|
||||
usedPredefinedAndGlobals[usedLabelName] = marker;
|
||||
|
||||
// check for re-assigning a read-only (set to false) predefined
|
||||
if (_current["(predefined)"][usedLabelName] === false && usage["(reassigned)"]) {
|
||||
for (j = 0; j < usage["(reassigned)"].length; j++) {
|
||||
if (!usage["(reassigned)"][j].ignoreW020) {
|
||||
warning("W020", usage["(reassigned)"][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// label usage is not predefined and we have not found a declaration
|
||||
// so report as undeclared
|
||||
if (usage["(tokens)"]) {
|
||||
for (j = 0; j < usage["(tokens)"].length; j++) {
|
||||
var undefinedToken = usage["(tokens)"][j];
|
||||
// if its not a forgiven undefined (e.g. typof x)
|
||||
if (!undefinedToken.forgiveUndef) {
|
||||
// if undef is on and undef was on when the token was defined
|
||||
if (state.option.undef && !undefinedToken.ignoreUndef) {
|
||||
warning("W117", undefinedToken, usedLabelName);
|
||||
}
|
||||
if (impliedGlobals[usedLabelName]) {
|
||||
impliedGlobals[usedLabelName].line.push(undefinedToken.line);
|
||||
} else {
|
||||
impliedGlobals[usedLabelName] = {
|
||||
name: usedLabelName,
|
||||
line: [undefinedToken.line]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if exiting the global scope, we can warn about declared globals that haven't been used yet
|
||||
if (!subScope) {
|
||||
Object.keys(declared)
|
||||
.forEach(function(labelNotUsed) {
|
||||
_warnUnused(labelNotUsed, declared[labelNotUsed], "var");
|
||||
});
|
||||
}
|
||||
|
||||
// If this is not a function boundary, transfer function-scoped labels to
|
||||
// the parent block (a rough simulation of variable hoisting). Previously
|
||||
// existing labels in the parent block should take precedence so that things and stuff.
|
||||
if (subScope && !isUnstackingFunctionBody &&
|
||||
!isUnstackingFunctionParams && !isUnstackingFunctionOuter) {
|
||||
var labelNames = Object.keys(currentLabels);
|
||||
for (i = 0; i < labelNames.length; i++) {
|
||||
|
||||
var defLabelName = labelNames[i];
|
||||
var defLabel = currentLabels[defLabelName];
|
||||
|
||||
if (!defLabel["(blockscoped)"] && defLabel["(type)"] !== "exception") {
|
||||
var shadowed = subScope["(labels)"][defLabelName];
|
||||
|
||||
// Do not overwrite a label if it exists in the parent scope
|
||||
// because it is shared by adjacent blocks. Copy the `unused`
|
||||
// property so that any references found within the current block
|
||||
// are counted toward that higher-level declaration.
|
||||
if (shadowed) {
|
||||
shadowed["(unused)"] &= defLabel["(unused)"];
|
||||
|
||||
// "Hoist" the variable to the parent block, decorating the label
|
||||
// so that future references, though technically valid, can be
|
||||
// reported as "out-of-scope" in the absence of the `funcscope`
|
||||
// option.
|
||||
} else {
|
||||
defLabel["(useOutsideOfScope)"] =
|
||||
// Do not warn about out-of-scope usages in the global scope
|
||||
_currentFunctBody["(type)"] !== "global" &&
|
||||
// When a higher scope contains a binding for the label, the
|
||||
// label is a re-declaration and should not prompt "used
|
||||
// out-of-scope" warnings.
|
||||
!this.funct.has(defLabelName, { excludeCurrent: true });
|
||||
|
||||
subScope["(labels)"][defLabelName] = defLabel;
|
||||
}
|
||||
|
||||
delete currentLabels[defLabelName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_checkForUnused();
|
||||
|
||||
_scopeStack.pop();
|
||||
if (isUnstackingFunctionBody) {
|
||||
_currentFunctBody = _scopeStack[_.findLastIndex(_scopeStack, function(scope) {
|
||||
// if function or if global (which is at the bottom so it will only return true if we call back)
|
||||
return scope["(isFuncBody)"] || scope["(type)"] === "global";
|
||||
})];
|
||||
}
|
||||
|
||||
_current = subScope;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a param to the current scope
|
||||
* @param {string} labelName
|
||||
* @param {Token} token
|
||||
* @param {string} [type="param"] param type
|
||||
*/
|
||||
addParam: function(labelName, token, type) {
|
||||
type = type || "param";
|
||||
|
||||
if (type === "exception") {
|
||||
// if defined in the current function
|
||||
var previouslyDefinedLabelType = this.funct.labeltype(labelName);
|
||||
if (previouslyDefinedLabelType && previouslyDefinedLabelType !== "exception") {
|
||||
// and has not been used yet in the current function scope
|
||||
if (!state.option.node) {
|
||||
warning("W002", state.tokens.next, labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The variable was declared in the current scope
|
||||
if (_.has(_current["(labels)"], labelName)) {
|
||||
_current["(labels)"][labelName].duplicated = true;
|
||||
|
||||
// The variable was declared in an outer scope
|
||||
} else {
|
||||
// if this scope has the variable defined, it's a re-definition error
|
||||
_checkOuterShadow(labelName, token, type);
|
||||
|
||||
_current["(labels)"][labelName] = {
|
||||
"(type)" : type,
|
||||
"(token)": token,
|
||||
"(unused)": true };
|
||||
|
||||
_current["(params)"].push(labelName);
|
||||
}
|
||||
|
||||
if (_.has(_current["(usages)"], labelName)) {
|
||||
var usage = _current["(usages)"][labelName];
|
||||
// if its in a sub function it is not necessarily an error, just latedef
|
||||
if (usage["(onlyUsedSubFunction)"]) {
|
||||
_latedefWarning(type, labelName, token);
|
||||
} else {
|
||||
// this is a clear illegal usage for block scoped variables
|
||||
warning("E056", token, labelName, type);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
validateParams: function() {
|
||||
// This method only concerns errors for function parameters
|
||||
if (_currentFunctBody["(type)"] === "global") {
|
||||
return;
|
||||
}
|
||||
|
||||
var isStrict = state.isStrict();
|
||||
var currentFunctParamScope = _currentFunctBody["(parent)"];
|
||||
|
||||
if (!currentFunctParamScope["(params)"]) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentFunctParamScope["(params)"].forEach(function(labelName) {
|
||||
var label = currentFunctParamScope["(labels)"][labelName];
|
||||
|
||||
if (label && label.duplicated) {
|
||||
if (isStrict) {
|
||||
warning("E011", label["(token)"], labelName);
|
||||
} else if (state.option.shadow !== true) {
|
||||
warning("W004", label["(token)"], labelName);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getUsedOrDefinedGlobals: function() {
|
||||
// jshint proto: true
|
||||
var list = Object.keys(usedPredefinedAndGlobals);
|
||||
|
||||
// If `__proto__` is used as a global variable name, its entry in the
|
||||
// lookup table may not be enumerated by `Object.keys` (depending on the
|
||||
// environment).
|
||||
if (usedPredefinedAndGlobals.__proto__ === marker &&
|
||||
list.indexOf("__proto__") === -1) {
|
||||
list.push("__proto__");
|
||||
}
|
||||
|
||||
return list;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets an array of implied globals
|
||||
* @returns {Array.<{ name: string, line: Array.<number>}>}
|
||||
*/
|
||||
getImpliedGlobals: function() {
|
||||
// jshint proto: true
|
||||
var values = _.values(impliedGlobals);
|
||||
var hasProto = false;
|
||||
|
||||
// If `__proto__` is an implied global variable, its entry in the lookup
|
||||
// table may not be enumerated by `_.values` (depending on the
|
||||
// environment).
|
||||
if (impliedGlobals.__proto__) {
|
||||
hasProto = values.some(function(value) {
|
||||
return value.name === "__proto__";
|
||||
});
|
||||
|
||||
if (!hasProto) {
|
||||
values.push(impliedGlobals.__proto__);
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a list of unused variables
|
||||
* @returns {Array}
|
||||
*/
|
||||
getUnuseds: function() {
|
||||
return unuseds;
|
||||
},
|
||||
|
||||
has: function(labelName) {
|
||||
return Boolean(_getLabel(labelName));
|
||||
},
|
||||
|
||||
labeltype: function(labelName) {
|
||||
// returns a labels type or null if not present
|
||||
var scopeLabels = _getLabel(labelName);
|
||||
if (scopeLabels) {
|
||||
return scopeLabels[labelName]["(type)"];
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
/**
|
||||
* for the exported options, indicating a variable is used outside the file
|
||||
*/
|
||||
addExported: function(labelName) {
|
||||
var globalLabels = _scopeStack[0]["(labels)"];
|
||||
if (_.has(declared, labelName)) {
|
||||
// remove the declared token, so we know it is used
|
||||
delete declared[labelName];
|
||||
} else if (_.has(globalLabels, labelName)) {
|
||||
globalLabels[labelName]["(unused)"] = false;
|
||||
} else {
|
||||
for (var i = 1; i < _scopeStack.length; i++) {
|
||||
var scope = _scopeStack[i];
|
||||
// if `scope.(type)` is not defined, it is a block scope
|
||||
if (!scope["(type)"]) {
|
||||
if (_.has(scope["(labels)"], labelName) &&
|
||||
!scope["(labels)"][labelName]["(blockscoped)"]) {
|
||||
scope["(labels)"][labelName]["(unused)"] = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
exported[labelName] = true;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Mark an indentifier as es6 module exported
|
||||
*/
|
||||
setExported: function(labelName, token) {
|
||||
this.block.use(labelName, token);
|
||||
},
|
||||
|
||||
/**
|
||||
* adds an indentifier to the relevant current scope and creates warnings/errors as necessary
|
||||
* @param {string} labelName
|
||||
* @param {Object} opts
|
||||
* @param {String} opts.type - the type of the label e.g. "param", "var", "let, "const", "function"
|
||||
* @param {Token} opts.token - the token pointing at the declaration
|
||||
*/
|
||||
addlabel: function(labelName, opts) {
|
||||
|
||||
var type = opts.type;
|
||||
var token = opts.token;
|
||||
var isblockscoped = type === "let" || type === "const" || type === "class";
|
||||
var isexported = (isblockscoped ? _current : _currentFunctBody)["(type)"] === "global" &&
|
||||
_.has(exported, labelName);
|
||||
|
||||
// outer shadow check (inner is only on non-block scoped)
|
||||
_checkOuterShadow(labelName, token, type);
|
||||
|
||||
// if is block scoped (let or const)
|
||||
if (isblockscoped) {
|
||||
|
||||
var declaredInCurrentScope = _current["(labels)"][labelName];
|
||||
// for block scoped variables, params are seen in the current scope as the root function
|
||||
// scope, so check these too.
|
||||
if (!declaredInCurrentScope && _current === _currentFunctBody &&
|
||||
_current["(type)"] !== "global") {
|
||||
declaredInCurrentScope = !!_currentFunctBody["(parent)"]["(labels)"][labelName];
|
||||
}
|
||||
|
||||
// if its not already defined (which is an error, so ignore) and is used in TDZ
|
||||
if (!declaredInCurrentScope && _current["(usages)"][labelName]) {
|
||||
var usage = _current["(usages)"][labelName];
|
||||
// if its in a sub function it is not necessarily an error, just latedef
|
||||
if (usage["(onlyUsedSubFunction)"]) {
|
||||
_latedefWarning(type, labelName, token);
|
||||
} else {
|
||||
// this is a clear illegal usage for block scoped variables
|
||||
warning("E056", token, labelName, type);
|
||||
}
|
||||
}
|
||||
|
||||
// if this scope has the variable defined, its a re-definition error
|
||||
if (declaredInCurrentScope) {
|
||||
warning("E011", token, labelName);
|
||||
}
|
||||
else if (state.option.shadow === "outer") {
|
||||
|
||||
// if shadow is outer, for block scope we want to detect any shadowing within this function
|
||||
if (scopeManagerInst.funct.has(labelName)) {
|
||||
warning("W004", token, labelName);
|
||||
}
|
||||
}
|
||||
|
||||
scopeManagerInst.block.add(labelName, type, token, !isexported);
|
||||
|
||||
} else {
|
||||
|
||||
var declaredInCurrentFunctionScope = scopeManagerInst.funct.has(labelName);
|
||||
|
||||
// check for late definition, ignore if already declared
|
||||
if (!declaredInCurrentFunctionScope && usedSoFarInCurrentFunction(labelName)) {
|
||||
_latedefWarning(type, labelName, token);
|
||||
}
|
||||
|
||||
// defining with a var or a function when a block scope variable of the same name
|
||||
// is in scope is an error
|
||||
if (scopeManagerInst.funct.has(labelName, { onlyBlockscoped: true })) {
|
||||
warning("E011", token, labelName);
|
||||
} else if (state.option.shadow !== true) {
|
||||
// now since we didn't get any block scope variables, test for var/function
|
||||
// shadowing
|
||||
if (declaredInCurrentFunctionScope && labelName !== "__proto__") {
|
||||
|
||||
// see https://github.com/jshint/jshint/issues/2400
|
||||
if (_currentFunctBody["(type)"] !== "global") {
|
||||
warning("W004", token, labelName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scopeManagerInst.funct.add(labelName, type, token, !isexported);
|
||||
|
||||
if (_currentFunctBody["(type)"] === "global" && !state.impliedClosure()) {
|
||||
usedPredefinedAndGlobals[labelName] = marker;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
funct: {
|
||||
/**
|
||||
* Returns the label type given certain options
|
||||
* @param labelName
|
||||
* @param {Object=} options
|
||||
* @param {Boolean=} options.onlyBlockscoped - only include block scoped labels
|
||||
* @param {Boolean=} options.excludeParams - exclude the param scope
|
||||
* @param {Boolean=} options.excludeCurrent - exclude the current scope
|
||||
* @returns {String}
|
||||
*/
|
||||
labeltype: function(labelName, options) {
|
||||
var onlyBlockscoped = options && options.onlyBlockscoped;
|
||||
var excludeParams = options && options.excludeParams;
|
||||
var currentScopeIndex = _scopeStack.length - (options && options.excludeCurrent ? 2 : 1);
|
||||
for (var i = currentScopeIndex; i >= 0; i--) {
|
||||
var current = _scopeStack[i];
|
||||
if (current["(labels)"][labelName] &&
|
||||
(!onlyBlockscoped || current["(labels)"][labelName]["(blockscoped)"])) {
|
||||
return current["(labels)"][labelName]["(type)"];
|
||||
}
|
||||
var scopeCheck = excludeParams ? _scopeStack[ i - 1 ] : current;
|
||||
if (scopeCheck && scopeCheck["(type)"] === "functionparams") {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
/**
|
||||
* Returns if a break label exists in the function scope
|
||||
* @param {string} labelName
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasBreakLabel: function(labelName) {
|
||||
for (var i = _scopeStack.length - 1; i >= 0; i--) {
|
||||
var current = _scopeStack[i];
|
||||
|
||||
if (current["(breakLabels)"][labelName]) {
|
||||
return true;
|
||||
}
|
||||
if (current["(type)"] === "functionparams") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
/**
|
||||
* Returns if the label is in the current function scope
|
||||
* See scopeManager.funct.labelType for options
|
||||
*/
|
||||
has: function(labelName, options) {
|
||||
return Boolean(this.labeltype(labelName, options));
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new function scoped variable
|
||||
* see block.add for block scoped
|
||||
*/
|
||||
add: function(labelName, type, tok, unused) {
|
||||
_current["(labels)"][labelName] = {
|
||||
"(type)" : type,
|
||||
"(token)": tok,
|
||||
"(blockscoped)": false,
|
||||
"(function)": _currentFunctBody,
|
||||
"(unused)": unused };
|
||||
}
|
||||
},
|
||||
|
||||
block: {
|
||||
|
||||
/**
|
||||
* is the current block global?
|
||||
* @returns Boolean
|
||||
*/
|
||||
isGlobal: function() {
|
||||
return _current["(type)"] === "global";
|
||||
},
|
||||
|
||||
use: function(labelName, token) {
|
||||
|
||||
// if resolves to current function params, then do not store usage just resolve
|
||||
// this is because function(a) { var a; a = a; } will resolve to the param, not
|
||||
// to the unset var
|
||||
// first check the param is used
|
||||
var paramScope = _currentFunctBody["(parent)"];
|
||||
if (paramScope && paramScope["(labels)"][labelName] &&
|
||||
paramScope["(labels)"][labelName]["(type)"] === "param") {
|
||||
|
||||
// then check its not declared by a block scope variable
|
||||
if (!scopeManagerInst.funct.has(labelName,
|
||||
{ excludeParams: true, onlyBlockscoped: true })) {
|
||||
paramScope["(labels)"][labelName]["(unused)"] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (token && (state.ignored.W117 || state.option.undef === false)) {
|
||||
token.ignoreUndef = true;
|
||||
}
|
||||
|
||||
_setupUsages(labelName);
|
||||
|
||||
_current["(usages)"][labelName]["(onlyUsedSubFunction)"] = false;
|
||||
|
||||
if (token) {
|
||||
token["(function)"] = _currentFunctBody;
|
||||
_current["(usages)"][labelName]["(tokens)"].push(token);
|
||||
}
|
||||
},
|
||||
|
||||
reassign: function(labelName, token) {
|
||||
token.ignoreW020 = state.ignored.W020;
|
||||
token.ignoreW021 = state.ignored.W021;
|
||||
|
||||
this.modify(labelName, token);
|
||||
|
||||
_current["(usages)"][labelName]["(reassigned)"].push(token);
|
||||
},
|
||||
|
||||
modify: function(labelName, token) {
|
||||
|
||||
_setupUsages(labelName);
|
||||
|
||||
_current["(usages)"][labelName]["(onlyUsedSubFunction)"] = false;
|
||||
_current["(usages)"][labelName]["(modified)"].push(token);
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds a new variable
|
||||
*/
|
||||
add: function(labelName, type, tok, unused) {
|
||||
_current["(labels)"][labelName] = {
|
||||
"(type)" : type,
|
||||
"(token)": tok,
|
||||
"(blockscoped)": true,
|
||||
"(unused)": unused };
|
||||
},
|
||||
|
||||
addBreakLabel: function(labelName, opts) {
|
||||
var token = opts.token;
|
||||
if (scopeManagerInst.funct.hasBreakLabel(labelName)) {
|
||||
warning("E011", token, labelName);
|
||||
}
|
||||
else if (state.option.shadow === "outer") {
|
||||
if (scopeManagerInst.funct.has(labelName)) {
|
||||
warning("W004", token, labelName);
|
||||
} else {
|
||||
_checkOuterShadow(labelName, token);
|
||||
}
|
||||
}
|
||||
_current["(breakLabels)"][labelName] = token;
|
||||
}
|
||||
}
|
||||
};
|
||||
return scopeManagerInst;
|
||||
};
|
||||
|
||||
module.exports = scopeManager;
|
|
@ -11,34 +11,117 @@ var state = {
|
|||
*/
|
||||
isStrict: function() {
|
||||
return this.directive["use strict"] || this.inClassBody ||
|
||||
this.option.module;
|
||||
},
|
||||
|
||||
// Assumption: chronologically ES3 < ES5 < ES6/ESNext < Moz
|
||||
inMoz: function() {
|
||||
return this.option.moz && !this.option.esnext;
|
||||
this.option.module || this.option.strict === "implied";
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {object} options
|
||||
* @param {boolean} options.strict - When `true`, only consider ESNext when
|
||||
* in "esnext" code and *not* in "moz".
|
||||
* Determine if the current state warrants a warning for statements outside
|
||||
* of strict mode code.
|
||||
*
|
||||
* While emitting warnings based on function scope would be more intuitive
|
||||
* (and less noisy), JSHint observes statement-based semantics in order to
|
||||
* preserve legacy behavior.
|
||||
*
|
||||
* This method does not take the state of the parser into account, making no
|
||||
* distinction between global code and function code. Because the "missing
|
||||
* 'use strict'" warning is *also* reported at function boundaries, this
|
||||
* function interprets `strict` option values `true` and `undefined` as
|
||||
* equivalent.
|
||||
*/
|
||||
inESNext: function(strict) {
|
||||
if (strict) {
|
||||
return !this.option.moz && this.option.esnext;
|
||||
stmtMissingStrict: function() {
|
||||
if (this.option.strict === "global") {
|
||||
return true;
|
||||
}
|
||||
return this.option.moz || this.option.esnext;
|
||||
|
||||
if (this.option.strict === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.option.globalstrict) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
inES5: function() {
|
||||
return !this.option.es3;
|
||||
allowsGlobalUsd: function() {
|
||||
return this.option.strict === "global" || this.option.globalstrict ||
|
||||
this.option.module || this.impliedClosure();
|
||||
},
|
||||
|
||||
inES3: function() {
|
||||
return this.option.es3;
|
||||
/**
|
||||
* Determine if the current configuration describes an environment that is
|
||||
* wrapped in an immediately-invoked function expression prior to evaluation.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
impliedClosure: function() {
|
||||
return this.option.node || this.option.phantom || this.option.browserify;
|
||||
},
|
||||
|
||||
// Assumption: chronologically ES3 < ES5 < ES6 < Moz
|
||||
|
||||
inMoz: function() {
|
||||
return this.option.moz;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {boolean} strict - When `true`, only consider ES6 when in
|
||||
* "esversion: 6" code.
|
||||
*/
|
||||
inES6: function(strict) {
|
||||
if (strict) {
|
||||
return this.esVersion === 6;
|
||||
}
|
||||
return this.option.moz || this.esVersion >= 6;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {boolean} strict - When `true`, return `true` only when
|
||||
* esVersion is exactly 5
|
||||
*/
|
||||
inES5: function(strict) {
|
||||
if (strict) {
|
||||
return (!this.esVersion || this.esVersion === 5) && !this.option.moz;
|
||||
}
|
||||
return !this.esVersion || this.esVersion >= 5 || this.option.moz;
|
||||
},
|
||||
|
||||
/**
|
||||
* Determine the current version of the input language by inspecting the
|
||||
* value of all ECMAScript-version-related options. This logic is necessary
|
||||
* to ensure compatibility with deprecated options `es3`, `es5`, and
|
||||
* `esnext`, and it may be drastically simplified when those options are
|
||||
* removed.
|
||||
*
|
||||
* @returns {string|null} - the name of any incompatible option detected,
|
||||
* `null` otherwise
|
||||
*/
|
||||
inferEsVersion: function() {
|
||||
var badOpt = null;
|
||||
|
||||
if (this.option.esversion) {
|
||||
if (this.option.es3) {
|
||||
badOpt = "es3";
|
||||
} else if (this.option.es5) {
|
||||
badOpt = "es5";
|
||||
} else if (this.option.esnext) {
|
||||
badOpt = "esnext";
|
||||
}
|
||||
|
||||
if (badOpt) {
|
||||
return badOpt;
|
||||
}
|
||||
|
||||
this.esVersion = this.option.esversion;
|
||||
} else if (this.option.es3) {
|
||||
this.esVersion = 3;
|
||||
} else if (this.option.esnext) {
|
||||
this.esVersion = 6;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
reset: function() {
|
||||
this.tokens = {
|
||||
|
@ -48,6 +131,8 @@ var state = {
|
|||
};
|
||||
|
||||
this.option = {};
|
||||
this.esVersion = 5;
|
||||
this.funct = null;
|
||||
this.ignored = {};
|
||||
this.directive = {};
|
||||
this.jsonMode = false;
|
||||
|
@ -59,9 +144,6 @@ var state = {
|
|||
this.forinifcheckneeded = false;
|
||||
this.nameStack = new NameStack();
|
||||
this.inClassBody = false;
|
||||
|
||||
// Blank out non-multi-line-commented lines when ignoring linter errors
|
||||
this.ignoreLinterErrors = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,13 +13,14 @@ exports.register = function(linter) {
|
|||
linter.warn("W103", {
|
||||
line: data.line,
|
||||
char: data.char,
|
||||
data: [ data.name ]
|
||||
data: [ data.name, "6" ]
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Check for properties named __iterator__. This is a special property
|
||||
// available only in browsers with JavaScript 1.7 implementation.
|
||||
// available only in browsers with JavaScript 1.7 implementation, but
|
||||
// it is deprecated for ES6
|
||||
|
||||
linter.on("Identifier", function style_scanIterator(data) {
|
||||
if (linter.getOption("iterator")) {
|
||||
|
@ -27,7 +28,7 @@ exports.register = function(linter) {
|
|||
}
|
||||
|
||||
if (data.name === "__iterator__") {
|
||||
linter.warn("W104", {
|
||||
linter.warn("W103", {
|
||||
line: data.line,
|
||||
char: data.char,
|
||||
data: [ data.name ]
|
||||
|
@ -46,7 +47,7 @@ exports.register = function(linter) {
|
|||
if (data.name.replace(/^_+|_+$/g, "").indexOf("_") > -1 && !data.name.match(/^[A-Z0-9_]*$/)) {
|
||||
linter.warn("W106", {
|
||||
line: data.line,
|
||||
char: data.from,
|
||||
char: data.char,
|
||||
data: [ data.name ]
|
||||
});
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ exports.browser = {
|
|||
close : false,
|
||||
closed : false,
|
||||
Comment : false,
|
||||
CompositionEvent : false,
|
||||
CustomEvent : false,
|
||||
DOMParser : false,
|
||||
defaultStatus : false,
|
||||
|
@ -84,6 +85,8 @@ exports.browser = {
|
|||
Event : false,
|
||||
event : false,
|
||||
fetch : false,
|
||||
File : false,
|
||||
FileList : false,
|
||||
FileReader : false,
|
||||
FormData : false,
|
||||
focus : false,
|
||||
|
@ -97,6 +100,7 @@ exports.browser = {
|
|||
HTMLBRElement : false,
|
||||
HTMLButtonElement : false,
|
||||
HTMLCanvasElement : false,
|
||||
HTMLCollection : false,
|
||||
HTMLDirectoryElement : false,
|
||||
HTMLDivElement : false,
|
||||
HTMLDListElement : false,
|
||||
|
@ -176,6 +180,7 @@ exports.browser = {
|
|||
opener : false,
|
||||
Option : false,
|
||||
parent : false,
|
||||
performance : false,
|
||||
print : false,
|
||||
Range : false,
|
||||
requestAnimationFrame : false,
|
||||
|
@ -365,6 +370,7 @@ exports.browser = {
|
|||
WebGLUniformLocation : false,
|
||||
WebSocket : false,
|
||||
window : false,
|
||||
Window : false,
|
||||
Worker : false,
|
||||
XDomainRequest : false,
|
||||
XMLHttpRequest : false,
|
||||
|
@ -465,6 +471,7 @@ exports.qunit = {
|
|||
module : false,
|
||||
notDeepEqual : false,
|
||||
notEqual : false,
|
||||
notOk : false,
|
||||
notPropEqual : false,
|
||||
notStrictEqual : false,
|
||||
ok : false,
|
||||
|
@ -670,6 +677,8 @@ exports.yui = {
|
|||
};
|
||||
|
||||
exports.mocha = {
|
||||
// Global (for config etc.)
|
||||
mocha : false,
|
||||
// BDD
|
||||
describe : false,
|
||||
xdescribe : false,
|
||||
|
@ -711,5 +720,6 @@ exports.jasmine = {
|
|||
afterAll : false,
|
||||
fail : false,
|
||||
fdescribe : false,
|
||||
fit : false
|
||||
fit : false,
|
||||
pending : false
|
||||
};
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
"joi": "6.10.1",
|
||||
"joi-to-json-schema": "2.0.5",
|
||||
"js-yaml": "3.4.6",
|
||||
"jshint": "2.8.0",
|
||||
"jshint": "2.9.2",
|
||||
"lodash": "3.10.1",
|
||||
"marked": "0.3.5",
|
||||
"media-typer": "0.3.0",
|
||||
|
|
Loading…
Reference in New Issue