init
This commit is contained in:
+58
@@ -0,0 +1,58 @@
|
||||
amdefine is released under two licenses: new BSD, and MIT. You may pick the
|
||||
license that best suits your development needs. The text of both licenses are
|
||||
provided below.
|
||||
|
||||
|
||||
The "New" BSD License:
|
||||
----------------------
|
||||
|
||||
Copyright (c) 2011-2016, The Dojo Foundation
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of the Dojo Foundation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
MIT License
|
||||
-----------
|
||||
|
||||
Copyright (c) 2011-2016, The Dojo Foundation
|
||||
|
||||
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.
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
# amdefine
|
||||
|
||||
A module that can be used to implement AMD's define() in Node. This allows you
|
||||
to code to the AMD API and have the module work in node programs without
|
||||
requiring those other programs to use AMD.
|
||||
|
||||
## Usage
|
||||
|
||||
**1)** Update your package.json to indicate amdefine as a dependency:
|
||||
|
||||
```javascript
|
||||
"dependencies": {
|
||||
"amdefine": ">=0.1.0"
|
||||
}
|
||||
```
|
||||
|
||||
Then run `npm install` to get amdefine into your project.
|
||||
|
||||
**2)** At the top of each module that uses define(), place this code:
|
||||
|
||||
```javascript
|
||||
if (typeof define !== 'function') { var define = require('amdefine')(module) }
|
||||
```
|
||||
|
||||
**Only use these snippets** when loading amdefine. If you preserve the basic structure,
|
||||
with the braces, it will be stripped out when using the [RequireJS optimizer](#optimizer).
|
||||
|
||||
You can add spaces, line breaks and even require amdefine with a local path, but
|
||||
keep the rest of the structure to get the stripping behavior.
|
||||
|
||||
As you may know, because `if` statements in JavaScript don't have their own scope, the var
|
||||
declaration in the above snippet is made whether the `if` expression is truthy or not. If
|
||||
RequireJS is loaded then the declaration is superfluous because `define` is already already
|
||||
declared in the same scope in RequireJS. Fortunately JavaScript handles multiple `var`
|
||||
declarations of the same variable in the same scope gracefully.
|
||||
|
||||
If you want to deliver amdefine.js with your code rather than specifying it as a dependency
|
||||
with npm, then just download the latest release and refer to it using a relative path:
|
||||
|
||||
[Latest Version](https://github.com/jrburke/amdefine/raw/latest/amdefine.js)
|
||||
|
||||
### amdefine/intercept
|
||||
|
||||
Consider this very experimental.
|
||||
|
||||
Instead of pasting the piece of text for the amdefine setup of a `define`
|
||||
variable in each module you create or consume, you can use `amdefine/intercept`
|
||||
instead. It will automatically insert the above snippet in each .js file loaded
|
||||
by Node.
|
||||
|
||||
**Warning**: you should only use this if you are creating an application that
|
||||
is consuming AMD style defined()'d modules that are distributed via npm and want
|
||||
to run that code in Node.
|
||||
|
||||
For library code where you are not sure if it will be used by others in Node or
|
||||
in the browser, then explicitly depending on amdefine and placing the code
|
||||
snippet above is suggested path, instead of using `amdefine/intercept`. The
|
||||
intercept module affects all .js files loaded in the Node app, and it is
|
||||
inconsiderate to modify global state like that unless you are also controlling
|
||||
the top level app.
|
||||
|
||||
#### Why distribute AMD-style modules via npm?
|
||||
|
||||
npm has a lot of weaknesses for front-end use (installed layout is not great,
|
||||
should have better support for the `baseUrl + moduleID + '.js' style of loading,
|
||||
single file JS installs), but some people want a JS package manager and are
|
||||
willing to live with those constraints. If that is you, but still want to author
|
||||
in AMD style modules to get dynamic require([]), better direct source usage and
|
||||
powerful loader plugin support in the browser, then this tool can help.
|
||||
|
||||
#### amdefine/intercept usage
|
||||
|
||||
Just require it in your top level app module (for example index.js, server.js):
|
||||
|
||||
```javascript
|
||||
require('amdefine/intercept');
|
||||
```
|
||||
|
||||
The module does not return a value, so no need to assign the result to a local
|
||||
variable.
|
||||
|
||||
Then just require() code as you normally would with Node's require(). Any .js
|
||||
loaded after the intercept require will have the amdefine check injected in
|
||||
the .js source as it is loaded. It does not modify the source on disk, just
|
||||
prepends some content to the text of the module as it is loaded by Node.
|
||||
|
||||
#### How amdefine/intercept works
|
||||
|
||||
It overrides the `Module._extensions['.js']` in Node to automatically prepend
|
||||
the amdefine snippet above. So, it will affect any .js file loaded by your
|
||||
app.
|
||||
|
||||
## define() usage
|
||||
|
||||
It is best if you use the anonymous forms of define() in your module:
|
||||
|
||||
```javascript
|
||||
define(function (require) {
|
||||
var dependency = require('dependency');
|
||||
});
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```javascript
|
||||
define(['dependency'], function (dependency) {
|
||||
|
||||
});
|
||||
```
|
||||
|
||||
## RequireJS optimizer integration. <a name="optimizer"></name>
|
||||
|
||||
Version 1.0.3 of the [RequireJS optimizer](http://requirejs.org/docs/optimization.html)
|
||||
will have support for stripping the `if (typeof define !== 'function')` check
|
||||
mentioned above, so you can include this snippet for code that runs in the
|
||||
browser, but avoid taking the cost of the if() statement once the code is
|
||||
optimized for deployment.
|
||||
|
||||
## Node 0.4 Support
|
||||
|
||||
If you want to support Node 0.4, then add `require` as the second parameter to amdefine:
|
||||
|
||||
```javascript
|
||||
//Only if you want Node 0.4. If using 0.5 or later, use the above snippet.
|
||||
if (typeof define !== 'function') { var define = require('amdefine')(module, require) }
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
### Synchronous vs Asynchronous
|
||||
|
||||
amdefine creates a define() function that is callable by your code. It will
|
||||
execute and trace dependencies and call the factory function *synchronously*,
|
||||
to keep the behavior in line with Node's synchronous dependency tracing.
|
||||
|
||||
The exception: calling AMD's callback-style require() from inside a factory
|
||||
function. The require callback is called on process.nextTick():
|
||||
|
||||
```javascript
|
||||
define(function (require) {
|
||||
require(['a'], function(a) {
|
||||
//'a' is loaded synchronously, but
|
||||
//this callback is called on process.nextTick().
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### Loader Plugins
|
||||
|
||||
Loader plugins are supported as long as they call their load() callbacks
|
||||
synchronously. So ones that do network requests will not work. However plugins
|
||||
like [text](http://requirejs.org/docs/api.html#text) can load text files locally.
|
||||
|
||||
The plugin API's `load.fromText()` is **not supported** in amdefine, so this means
|
||||
transpiler plugins like the [CoffeeScript loader plugin](https://github.com/jrburke/require-cs)
|
||||
will not work. This may be fixable, but it is a bit complex, and I do not have
|
||||
enough node-fu to figure it out yet. See the source for amdefine.js if you want
|
||||
to get an idea of the issues involved.
|
||||
|
||||
## Tests
|
||||
|
||||
To run the tests, cd to **tests** and run:
|
||||
|
||||
```
|
||||
node all.js
|
||||
node all-intercept.js
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
New BSD and MIT. Check the LICENSE file for all the details.
|
||||
+301
@@ -0,0 +1,301 @@
|
||||
/** vim: et:ts=4:sw=4:sts=4
|
||||
* @license amdefine 1.0.1 Copyright (c) 2011-2016, The Dojo Foundation All Rights Reserved.
|
||||
* Available via the MIT or new BSD license.
|
||||
* see: http://github.com/jrburke/amdefine for details
|
||||
*/
|
||||
|
||||
/*jslint node: true */
|
||||
/*global module, process */
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Creates a define for node.
|
||||
* @param {Object} module the "module" object that is defined by Node for the
|
||||
* current module.
|
||||
* @param {Function} [requireFn]. Node's require function for the current module.
|
||||
* It only needs to be passed in Node versions before 0.5, when module.require
|
||||
* did not exist.
|
||||
* @returns {Function} a define function that is usable for the current node
|
||||
* module.
|
||||
*/
|
||||
function amdefine(module, requireFn) {
|
||||
'use strict';
|
||||
var defineCache = {},
|
||||
loaderCache = {},
|
||||
alreadyCalled = false,
|
||||
path = require('path'),
|
||||
makeRequire, stringRequire;
|
||||
|
||||
/**
|
||||
* Trims the . and .. from an array of path segments.
|
||||
* It will keep a leading path segment if a .. will become
|
||||
* the first path segment, to help with module name lookups,
|
||||
* which act like paths, but can be remapped. But the end result,
|
||||
* all paths that use this function should look normalized.
|
||||
* NOTE: this method MODIFIES the input array.
|
||||
* @param {Array} ary the array of path segments.
|
||||
*/
|
||||
function trimDots(ary) {
|
||||
var i, part;
|
||||
for (i = 0; ary[i]; i+= 1) {
|
||||
part = ary[i];
|
||||
if (part === '.') {
|
||||
ary.splice(i, 1);
|
||||
i -= 1;
|
||||
} else if (part === '..') {
|
||||
if (i === 1 && (ary[2] === '..' || ary[0] === '..')) {
|
||||
//End of the line. Keep at least one non-dot
|
||||
//path segment at the front so it can be mapped
|
||||
//correctly to disk. Otherwise, there is likely
|
||||
//no path mapping for a path starting with '..'.
|
||||
//This can still fail, but catches the most reasonable
|
||||
//uses of ..
|
||||
break;
|
||||
} else if (i > 0) {
|
||||
ary.splice(i - 1, 2);
|
||||
i -= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function normalize(name, baseName) {
|
||||
var baseParts;
|
||||
|
||||
//Adjust any relative paths.
|
||||
if (name && name.charAt(0) === '.') {
|
||||
//If have a base name, try to normalize against it,
|
||||
//otherwise, assume it is a top-level require that will
|
||||
//be relative to baseUrl in the end.
|
||||
if (baseName) {
|
||||
baseParts = baseName.split('/');
|
||||
baseParts = baseParts.slice(0, baseParts.length - 1);
|
||||
baseParts = baseParts.concat(name.split('/'));
|
||||
trimDots(baseParts);
|
||||
name = baseParts.join('/');
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the normalize() function passed to a loader plugin's
|
||||
* normalize method.
|
||||
*/
|
||||
function makeNormalize(relName) {
|
||||
return function (name) {
|
||||
return normalize(name, relName);
|
||||
};
|
||||
}
|
||||
|
||||
function makeLoad(id) {
|
||||
function load(value) {
|
||||
loaderCache[id] = value;
|
||||
}
|
||||
|
||||
load.fromText = function (id, text) {
|
||||
//This one is difficult because the text can/probably uses
|
||||
//define, and any relative paths and requires should be relative
|
||||
//to that id was it would be found on disk. But this would require
|
||||
//bootstrapping a module/require fairly deeply from node core.
|
||||
//Not sure how best to go about that yet.
|
||||
throw new Error('amdefine does not implement load.fromText');
|
||||
};
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
makeRequire = function (systemRequire, exports, module, relId) {
|
||||
function amdRequire(deps, callback) {
|
||||
if (typeof deps === 'string') {
|
||||
//Synchronous, single module require('')
|
||||
return stringRequire(systemRequire, exports, module, deps, relId);
|
||||
} else {
|
||||
//Array of dependencies with a callback.
|
||||
|
||||
//Convert the dependencies to modules.
|
||||
deps = deps.map(function (depName) {
|
||||
return stringRequire(systemRequire, exports, module, depName, relId);
|
||||
});
|
||||
|
||||
//Wait for next tick to call back the require call.
|
||||
if (callback) {
|
||||
process.nextTick(function () {
|
||||
callback.apply(null, deps);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
amdRequire.toUrl = function (filePath) {
|
||||
if (filePath.indexOf('.') === 0) {
|
||||
return normalize(filePath, path.dirname(module.filename));
|
||||
} else {
|
||||
return filePath;
|
||||
}
|
||||
};
|
||||
|
||||
return amdRequire;
|
||||
};
|
||||
|
||||
//Favor explicit value, passed in if the module wants to support Node 0.4.
|
||||
requireFn = requireFn || function req() {
|
||||
return module.require.apply(module, arguments);
|
||||
};
|
||||
|
||||
function runFactory(id, deps, factory) {
|
||||
var r, e, m, result;
|
||||
|
||||
if (id) {
|
||||
e = loaderCache[id] = {};
|
||||
m = {
|
||||
id: id,
|
||||
uri: __filename,
|
||||
exports: e
|
||||
};
|
||||
r = makeRequire(requireFn, e, m, id);
|
||||
} else {
|
||||
//Only support one define call per file
|
||||
if (alreadyCalled) {
|
||||
throw new Error('amdefine with no module ID cannot be called more than once per file.');
|
||||
}
|
||||
alreadyCalled = true;
|
||||
|
||||
//Use the real variables from node
|
||||
//Use module.exports for exports, since
|
||||
//the exports in here is amdefine exports.
|
||||
e = module.exports;
|
||||
m = module;
|
||||
r = makeRequire(requireFn, e, m, module.id);
|
||||
}
|
||||
|
||||
//If there are dependencies, they are strings, so need
|
||||
//to convert them to dependency values.
|
||||
if (deps) {
|
||||
deps = deps.map(function (depName) {
|
||||
return r(depName);
|
||||
});
|
||||
}
|
||||
|
||||
//Call the factory with the right dependencies.
|
||||
if (typeof factory === 'function') {
|
||||
result = factory.apply(m.exports, deps);
|
||||
} else {
|
||||
result = factory;
|
||||
}
|
||||
|
||||
if (result !== undefined) {
|
||||
m.exports = result;
|
||||
if (id) {
|
||||
loaderCache[id] = m.exports;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stringRequire = function (systemRequire, exports, module, id, relId) {
|
||||
//Split the ID by a ! so that
|
||||
var index = id.indexOf('!'),
|
||||
originalId = id,
|
||||
prefix, plugin;
|
||||
|
||||
if (index === -1) {
|
||||
id = normalize(id, relId);
|
||||
|
||||
//Straight module lookup. If it is one of the special dependencies,
|
||||
//deal with it, otherwise, delegate to node.
|
||||
if (id === 'require') {
|
||||
return makeRequire(systemRequire, exports, module, relId);
|
||||
} else if (id === 'exports') {
|
||||
return exports;
|
||||
} else if (id === 'module') {
|
||||
return module;
|
||||
} else if (loaderCache.hasOwnProperty(id)) {
|
||||
return loaderCache[id];
|
||||
} else if (defineCache[id]) {
|
||||
runFactory.apply(null, defineCache[id]);
|
||||
return loaderCache[id];
|
||||
} else {
|
||||
if(systemRequire) {
|
||||
return systemRequire(originalId);
|
||||
} else {
|
||||
throw new Error('No module with ID: ' + id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//There is a plugin in play.
|
||||
prefix = id.substring(0, index);
|
||||
id = id.substring(index + 1, id.length);
|
||||
|
||||
plugin = stringRequire(systemRequire, exports, module, prefix, relId);
|
||||
|
||||
if (plugin.normalize) {
|
||||
id = plugin.normalize(id, makeNormalize(relId));
|
||||
} else {
|
||||
//Normalize the ID normally.
|
||||
id = normalize(id, relId);
|
||||
}
|
||||
|
||||
if (loaderCache[id]) {
|
||||
return loaderCache[id];
|
||||
} else {
|
||||
plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {});
|
||||
|
||||
return loaderCache[id];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Create a define function specific to the module asking for amdefine.
|
||||
function define(id, deps, factory) {
|
||||
if (Array.isArray(id)) {
|
||||
factory = deps;
|
||||
deps = id;
|
||||
id = undefined;
|
||||
} else if (typeof id !== 'string') {
|
||||
factory = id;
|
||||
id = deps = undefined;
|
||||
}
|
||||
|
||||
if (deps && !Array.isArray(deps)) {
|
||||
factory = deps;
|
||||
deps = undefined;
|
||||
}
|
||||
|
||||
if (!deps) {
|
||||
deps = ['require', 'exports', 'module'];
|
||||
}
|
||||
|
||||
//Set up properties for this module. If an ID, then use
|
||||
//internal cache. If no ID, then use the external variables
|
||||
//for this node module.
|
||||
if (id) {
|
||||
//Put the module in deep freeze until there is a
|
||||
//require call for it.
|
||||
defineCache[id] = [id, deps, factory];
|
||||
} else {
|
||||
runFactory(id, deps, factory);
|
||||
}
|
||||
}
|
||||
|
||||
//define.require, which has access to all the values in the
|
||||
//cache. Useful for AMD modules that all have IDs in the file,
|
||||
//but need to finally export a value to node based on one of those
|
||||
//IDs.
|
||||
define.require = function (id) {
|
||||
if (loaderCache[id]) {
|
||||
return loaderCache[id];
|
||||
}
|
||||
|
||||
if (defineCache[id]) {
|
||||
runFactory.apply(null, defineCache[id]);
|
||||
return loaderCache[id];
|
||||
}
|
||||
};
|
||||
|
||||
define.amd = {};
|
||||
|
||||
return define;
|
||||
}
|
||||
|
||||
module.exports = amdefine;
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*jshint node: true */
|
||||
var inserted,
|
||||
Module = require('module'),
|
||||
fs = require('fs'),
|
||||
existingExtFn = Module._extensions['.js'],
|
||||
amdefineRegExp = /amdefine\.js/;
|
||||
|
||||
inserted = "if (typeof define !== 'function') {var define = require('amdefine')(module)}";
|
||||
|
||||
//From the node/lib/module.js source:
|
||||
function stripBOM(content) {
|
||||
// Remove byte order marker. This catches EF BB BF (the UTF-8 BOM)
|
||||
// because the buffer-to-string conversion in `fs.readFileSync()`
|
||||
// translates it to FEFF, the UTF-16 BOM.
|
||||
if (content.charCodeAt(0) === 0xFEFF) {
|
||||
content = content.slice(1);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
//Also adapted from the node/lib/module.js source:
|
||||
function intercept(module, filename) {
|
||||
var content = stripBOM(fs.readFileSync(filename, 'utf8'));
|
||||
|
||||
if (!amdefineRegExp.test(module.id)) {
|
||||
content = inserted + content;
|
||||
}
|
||||
|
||||
module._compile(content, filename);
|
||||
}
|
||||
|
||||
intercept._id = 'amdefine/intercept';
|
||||
|
||||
if (!existingExtFn._id || existingExtFn._id !== intercept._id) {
|
||||
Module._extensions['.js'] = intercept;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "amdefine",
|
||||
"description": "Provide AMD's define() API for declaring modules in the AMD format",
|
||||
"version": "1.0.1",
|
||||
"homepage": "http://github.com/jrburke/amdefine",
|
||||
"author": "James Burke <jrburke@gmail.com> (http://github.com/jrburke)",
|
||||
"license": "BSD-3-Clause OR MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jrburke/amdefine.git"
|
||||
},
|
||||
"main": "./amdefine.js",
|
||||
"engines": {
|
||||
"node": ">=0.4.2"
|
||||
}
|
||||
}
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
const x = module.exports;
|
||||
const ESC = '\u001B[';
|
||||
const OSC = '\u001B]';
|
||||
const BEL = '\u0007';
|
||||
const SEP = ';';
|
||||
const isTerminalApp = process.env.TERM_PROGRAM === 'Apple_Terminal';
|
||||
|
||||
x.cursorTo = (x, y) => {
|
||||
if (typeof x !== 'number') {
|
||||
throw new TypeError('The `x` argument is required');
|
||||
}
|
||||
|
||||
if (typeof y !== 'number') {
|
||||
return ESC + (x + 1) + 'G';
|
||||
}
|
||||
|
||||
return ESC + (y + 1) + ';' + (x + 1) + 'H';
|
||||
};
|
||||
|
||||
x.cursorMove = (x, y) => {
|
||||
if (typeof x !== 'number') {
|
||||
throw new TypeError('The `x` argument is required');
|
||||
}
|
||||
|
||||
let ret = '';
|
||||
|
||||
if (x < 0) {
|
||||
ret += ESC + (-x) + 'D';
|
||||
} else if (x > 0) {
|
||||
ret += ESC + x + 'C';
|
||||
}
|
||||
|
||||
if (y < 0) {
|
||||
ret += ESC + (-y) + 'A';
|
||||
} else if (y > 0) {
|
||||
ret += ESC + y + 'B';
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
x.cursorUp = count => ESC + (typeof count === 'number' ? count : 1) + 'A';
|
||||
x.cursorDown = count => ESC + (typeof count === 'number' ? count : 1) + 'B';
|
||||
x.cursorForward = count => ESC + (typeof count === 'number' ? count : 1) + 'C';
|
||||
x.cursorBackward = count => ESC + (typeof count === 'number' ? count : 1) + 'D';
|
||||
|
||||
x.cursorLeft = ESC + 'G';
|
||||
x.cursorSavePosition = ESC + (isTerminalApp ? '7' : 's');
|
||||
x.cursorRestorePosition = ESC + (isTerminalApp ? '8' : 'u');
|
||||
x.cursorGetPosition = ESC + '6n';
|
||||
x.cursorNextLine = ESC + 'E';
|
||||
x.cursorPrevLine = ESC + 'F';
|
||||
x.cursorHide = ESC + '?25l';
|
||||
x.cursorShow = ESC + '?25h';
|
||||
|
||||
x.eraseLines = count => {
|
||||
let clear = '';
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
clear += x.eraseLine + (i < count - 1 ? x.cursorUp() : '');
|
||||
}
|
||||
|
||||
if (count) {
|
||||
clear += x.cursorLeft;
|
||||
}
|
||||
|
||||
return clear;
|
||||
};
|
||||
|
||||
x.eraseEndLine = ESC + 'K';
|
||||
x.eraseStartLine = ESC + '1K';
|
||||
x.eraseLine = ESC + '2K';
|
||||
x.eraseDown = ESC + 'J';
|
||||
x.eraseUp = ESC + '1J';
|
||||
x.eraseScreen = ESC + '2J';
|
||||
x.scrollUp = ESC + 'S';
|
||||
x.scrollDown = ESC + 'T';
|
||||
|
||||
x.clearScreen = '\u001Bc';
|
||||
|
||||
x.clearTerminal = process.platform === 'win32' ?
|
||||
`${x.eraseScreen}${ESC}0f` :
|
||||
// 1. Erases the screen (Only done in case `2` is not supported)
|
||||
// 2. Erases the whole screen including scrollback buffer
|
||||
// 3. Moves cursor to the top-left position
|
||||
// More info: https://www.real-world-systems.com/docs/ANSIcode.html
|
||||
`${x.eraseScreen}${ESC}3J${ESC}H`;
|
||||
|
||||
x.beep = BEL;
|
||||
|
||||
x.link = (text, url) => {
|
||||
return [
|
||||
OSC,
|
||||
'8',
|
||||
SEP,
|
||||
SEP,
|
||||
url,
|
||||
BEL,
|
||||
text,
|
||||
OSC,
|
||||
'8',
|
||||
SEP,
|
||||
SEP,
|
||||
BEL
|
||||
].join('');
|
||||
};
|
||||
|
||||
x.image = (buf, opts) => {
|
||||
opts = opts || {};
|
||||
|
||||
let ret = OSC + '1337;File=inline=1';
|
||||
|
||||
if (opts.width) {
|
||||
ret += `;width=${opts.width}`;
|
||||
}
|
||||
|
||||
if (opts.height) {
|
||||
ret += `;height=${opts.height}`;
|
||||
}
|
||||
|
||||
if (opts.preserveAspectRatio === false) {
|
||||
ret += ';preserveAspectRatio=0';
|
||||
}
|
||||
|
||||
return ret + ':' + buf.toString('base64') + BEL;
|
||||
};
|
||||
|
||||
x.iTerm = {};
|
||||
|
||||
x.iTerm.setCwd = cwd => OSC + '50;CurrentDir=' + (cwd || process.cwd()) + BEL;
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "ansi-escapes",
|
||||
"version": "3.2.0",
|
||||
"description": "ANSI escape codes for manipulating the terminal",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/ansi-escapes",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"tty",
|
||||
"escape",
|
||||
"escapes",
|
||||
"formatting",
|
||||
"shell",
|
||||
"xterm",
|
||||
"log",
|
||||
"logging",
|
||||
"command-line",
|
||||
"text",
|
||||
"vt100",
|
||||
"sequence",
|
||||
"control",
|
||||
"code",
|
||||
"codes",
|
||||
"cursor",
|
||||
"iterm",
|
||||
"iterm2"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"xo": "*"
|
||||
}
|
||||
}
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
# ansi-escapes [](https://travis-ci.org/sindresorhus/ansi-escapes)
|
||||
|
||||
> [ANSI escape codes](http://www.termsys.demon.co.uk/vtansi.htm) for manipulating the terminal
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install ansi-escapes
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const ansiEscapes = require('ansi-escapes');
|
||||
|
||||
// Moves the cursor two rows up and to the left
|
||||
process.stdout.write(ansiEscapes.cursorUp(2) + ansiEscapes.cursorLeft);
|
||||
//=> '\u001B[2A\u001B[1000D'
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### cursorTo(x, [y])
|
||||
|
||||
Set the absolute position of the cursor. `x0` `y0` is the top left of the screen.
|
||||
|
||||
### cursorMove(x, [y])
|
||||
|
||||
Set the position of the cursor relative to its current position.
|
||||
|
||||
### cursorUp(count)
|
||||
|
||||
Move cursor up a specific amount of rows. Default is `1`.
|
||||
|
||||
### cursorDown(count)
|
||||
|
||||
Move cursor down a specific amount of rows. Default is `1`.
|
||||
|
||||
### cursorForward(count)
|
||||
|
||||
Move cursor forward a specific amount of rows. Default is `1`.
|
||||
|
||||
### cursorBackward(count)
|
||||
|
||||
Move cursor backward a specific amount of rows. Default is `1`.
|
||||
|
||||
### cursorLeft
|
||||
|
||||
Move cursor to the left side.
|
||||
|
||||
### cursorSavePosition
|
||||
|
||||
Save cursor position.
|
||||
|
||||
### cursorRestorePosition
|
||||
|
||||
Restore saved cursor position.
|
||||
|
||||
### cursorGetPosition
|
||||
|
||||
Get cursor position.
|
||||
|
||||
### cursorNextLine
|
||||
|
||||
Move cursor to the next line.
|
||||
|
||||
### cursorPrevLine
|
||||
|
||||
Move cursor to the previous line.
|
||||
|
||||
### cursorHide
|
||||
|
||||
Hide cursor.
|
||||
|
||||
### cursorShow
|
||||
|
||||
Show cursor.
|
||||
|
||||
### eraseLines(count)
|
||||
|
||||
Erase from the current cursor position up the specified amount of rows.
|
||||
|
||||
### eraseEndLine
|
||||
|
||||
Erase from the current cursor position to the end of the current line.
|
||||
|
||||
### eraseStartLine
|
||||
|
||||
Erase from the current cursor position to the start of the current line.
|
||||
|
||||
### eraseLine
|
||||
|
||||
Erase the entire current line.
|
||||
|
||||
### eraseDown
|
||||
|
||||
Erase the screen from the current line down to the bottom of the screen.
|
||||
|
||||
### eraseUp
|
||||
|
||||
Erase the screen from the current line up to the top of the screen.
|
||||
|
||||
### eraseScreen
|
||||
|
||||
Erase the screen and move the cursor the top left position.
|
||||
|
||||
### scrollUp
|
||||
|
||||
Scroll display up one line.
|
||||
|
||||
### scrollDown
|
||||
|
||||
Scroll display down one line.
|
||||
|
||||
### clearScreen
|
||||
|
||||
Clear the terminal screen. (Viewport)
|
||||
|
||||
### clearTerminal
|
||||
|
||||
Clear the whole terminal, including scrollback buffer. (Not just the visible part of it)
|
||||
|
||||
### beep
|
||||
|
||||
Output a beeping sound.
|
||||
|
||||
### link(text, url)
|
||||
|
||||
Create a clickable link.
|
||||
|
||||
[Supported terminals.](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda) Use [`supports-hyperlinks`](https://github.com/jamestalmage/supports-hyperlinks) to detect link support.
|
||||
|
||||
### image(input, [options])
|
||||
|
||||
Display an image.
|
||||
|
||||
*Currently only supported on iTerm2 >=3*
|
||||
|
||||
See [term-img](https://github.com/sindresorhus/term-img) for a higher-level module.
|
||||
|
||||
#### input
|
||||
|
||||
Type: `Buffer`
|
||||
|
||||
Buffer of an image. Usually read in with `fs.readFile()`.
|
||||
|
||||
#### options
|
||||
|
||||
##### width
|
||||
##### height
|
||||
|
||||
Type: `string` `number`
|
||||
|
||||
The width and height are given as a number followed by a unit, or the word "auto".
|
||||
|
||||
- `N`: N character cells.
|
||||
- `Npx`: N pixels.
|
||||
- `N%`: N percent of the session's width or height.
|
||||
- `auto`: The image's inherent size will be used to determine an appropriate dimension.
|
||||
|
||||
##### preserveAspectRatio
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `true`
|
||||
|
||||
### iTerm.setCwd([path])
|
||||
|
||||
Type: `string`<br>
|
||||
Default: `process.cwd()`
|
||||
|
||||
[Inform iTerm2](https://www.iterm2.com/documentation-escape-codes.html) of the current directory to help semantic history and enable [Cmd-clicking relative paths](https://coderwall.com/p/b7e82q/quickly-open-files-in-iterm-with-cmd-click).
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
ansi-html [](http://badge.fury.io/js/ansi-html) [](https://app.travis-ci.com/mahdyar/ansi-html-community)
|
||||
=========
|
||||
An elegant lib that converts the chalked (ANSI) text to HTML.
|
||||
|
||||
# Coverage
|
||||
- All styles of [chalk](https://github.com/sindresorhus/chalk) (100%) and [colors](https://github.com/Marak/colors.js).
|
||||
- There are over **150** randomized test cases under `test`.
|
||||
|
||||
# Installation
|
||||
```
|
||||
$ npm install ansi-html-community
|
||||
```
|
||||
|
||||
# Usage
|
||||
```javascript
|
||||
var ansiHTML = require('ansi-html-community');
|
||||
var str = ansiHTML('[ANSI_TEXT]');
|
||||
```
|
||||
|
||||
e.g.:
|
||||
```javascript
|
||||
var chalk = require('chalk');
|
||||
|
||||
var str = chalk.bold.red('foo') + ' bar';
|
||||
console.log('[ANSI]', str)
|
||||
console.log('[HTML]', ansiHTML(str));
|
||||
```
|
||||
|
||||
See complete examples under `test` / `examples` directory.
|
||||
|
||||
# Set Colors
|
||||
```javascript
|
||||
ansiHTML.setColors({
|
||||
reset: ['555', '666'], // FOREGROUND-COLOR or [FOREGROUND-COLOR] or [, BACKGROUND-COLOR] or [FOREGROUND-COLOR, BACKGROUND-COLOR]
|
||||
black: 'aaa', // String
|
||||
red: 'bbb',
|
||||
green: 'ccc',
|
||||
yellow: 'ddd',
|
||||
blue: 'eee',
|
||||
magenta: 'fff',
|
||||
cyan: '999',
|
||||
lightgrey: '888',
|
||||
darkgrey: '777'
|
||||
});
|
||||
```
|
||||
|
||||
# Reset
|
||||
```javascript
|
||||
ansiHTML.reset();
|
||||
```
|
||||
|
||||
# Exposed Tags
|
||||
```javascript
|
||||
var openTags = ansiHTML.tags.open;
|
||||
var closeTags = ansiHTML.tags.close;
|
||||
```
|
||||
|
||||
# Test
|
||||
```
|
||||
$ npm install -l
|
||||
$ npm test
|
||||
```
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var ansiHTML = require('../')
|
||||
var pkg = require('../package.json')
|
||||
var l = console.log
|
||||
var w = console.warn
|
||||
|
||||
var stdoutFlushed = true
|
||||
var readingStdin = false
|
||||
|
||||
function logLine (line) {
|
||||
if (!line) {
|
||||
return
|
||||
}
|
||||
line = ansiHTML(line)
|
||||
try {
|
||||
stdoutFlushed = process.stdout.write(line)
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
function safeExit (code) {
|
||||
l('')
|
||||
process.exit(code)
|
||||
}
|
||||
|
||||
function processStdin (finish) {
|
||||
readingStdin = true
|
||||
var chunks = ''
|
||||
process.stdin.resume()
|
||||
process.stdin.setEncoding('utf-8')
|
||||
process.stdin.on('data', function (chunk) {
|
||||
var lines = chunk.split(/[\r\n]+/g).filter(function (line) {
|
||||
return line
|
||||
})
|
||||
var length = lines.length
|
||||
if (length === 1) {
|
||||
chunks += lines[0]
|
||||
return
|
||||
}
|
||||
if (length > 1) {
|
||||
logLine(chunks + (chunks ? '\n' : '') + lines[0] + '\n')
|
||||
}
|
||||
chunks = lines.pop()
|
||||
length -= 1
|
||||
for (var i = 1; i < length; i++) {
|
||||
logLine(lines[i] + '\n')
|
||||
}
|
||||
})
|
||||
process.stdin.on('end', function () {
|
||||
if (chunks) {
|
||||
logLine(chunks)
|
||||
}
|
||||
finish()
|
||||
})
|
||||
}
|
||||
|
||||
function stdoutDrain (code) {
|
||||
process.stdout.on('drain', function () {
|
||||
safeExit(code)
|
||||
})
|
||||
if (stdoutFlushed) {
|
||||
safeExit(code)
|
||||
}
|
||||
}
|
||||
|
||||
function startup (args) {
|
||||
if (args.indexOf('-h') > 0 || args.indexOf('--help') > 0) {
|
||||
l(pkg.name + '@' + pkg.version)
|
||||
l('Usage:')
|
||||
l(' ansi-html [options]')
|
||||
l(' ... | ansi-html [options]')
|
||||
l('Options:')
|
||||
l(' -h, --help print help information')
|
||||
return
|
||||
}
|
||||
|
||||
process.stdout.on('error', function (err) {
|
||||
if (err.code === 'EPIPE') {
|
||||
stdoutDrain(0)
|
||||
} else {
|
||||
w('stdout error:', err)
|
||||
stdoutDrain(1)
|
||||
}
|
||||
})
|
||||
|
||||
processStdin(function () {
|
||||
safeExit(0)
|
||||
})
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
startup(process.argv)
|
||||
}
|
||||
|
||||
process.on('SIGINT', function () {
|
||||
if (!readingStdin) {
|
||||
safeExit(1)
|
||||
}
|
||||
})
|
||||
process.on('SIGQUIT', function () { safeExit(1) })
|
||||
process.on('SIGTERM', function () { safeExit(1) })
|
||||
process.on('SIGHUP', function () { safeExit(1) })
|
||||
+176
@@ -0,0 +1,176 @@
|
||||
'use strict'
|
||||
|
||||
module.exports = ansiHTML
|
||||
|
||||
// Reference to https://github.com/sindresorhus/ansi-regex
|
||||
var _regANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/
|
||||
|
||||
var _defColors = {
|
||||
reset: ['fff', '000'], // [FOREGROUD_COLOR, BACKGROUND_COLOR]
|
||||
black: '000',
|
||||
red: 'ff0000',
|
||||
green: '209805',
|
||||
yellow: 'e8bf03',
|
||||
blue: '0000ff',
|
||||
magenta: 'ff00ff',
|
||||
cyan: '00ffee',
|
||||
lightgrey: 'f0f0f0',
|
||||
darkgrey: '888'
|
||||
}
|
||||
var _styles = {
|
||||
30: 'black',
|
||||
31: 'red',
|
||||
32: 'green',
|
||||
33: 'yellow',
|
||||
34: 'blue',
|
||||
35: 'magenta',
|
||||
36: 'cyan',
|
||||
37: 'lightgrey'
|
||||
}
|
||||
var _openTags = {
|
||||
'1': 'font-weight:bold', // bold
|
||||
'2': 'opacity:0.5', // dim
|
||||
'3': '<i>', // italic
|
||||
'4': '<u>', // underscore
|
||||
'8': 'display:none', // hidden
|
||||
'9': '<del>' // delete
|
||||
}
|
||||
var _closeTags = {
|
||||
'23': '</i>', // reset italic
|
||||
'24': '</u>', // reset underscore
|
||||
'29': '</del>' // reset delete
|
||||
}
|
||||
|
||||
;[0, 21, 22, 27, 28, 39, 49].forEach(function (n) {
|
||||
_closeTags[n] = '</span>'
|
||||
})
|
||||
|
||||
/**
|
||||
* Converts text with ANSI color codes to HTML markup.
|
||||
* @param {String} text
|
||||
* @returns {*}
|
||||
*/
|
||||
function ansiHTML (text) {
|
||||
// Returns the text if the string has no ANSI escape code.
|
||||
if (!_regANSI.test(text)) {
|
||||
return text
|
||||
}
|
||||
|
||||
// Cache opened sequence.
|
||||
var ansiCodes = []
|
||||
// Replace with markup.
|
||||
var ret = text.replace(/\033\[(\d+)m/g, function (match, seq) {
|
||||
var ot = _openTags[seq]
|
||||
if (ot) {
|
||||
// If current sequence has been opened, close it.
|
||||
if (!!~ansiCodes.indexOf(seq)) { // eslint-disable-line no-extra-boolean-cast
|
||||
ansiCodes.pop()
|
||||
return '</span>'
|
||||
}
|
||||
// Open tag.
|
||||
ansiCodes.push(seq)
|
||||
return ot[0] === '<' ? ot : '<span style="' + ot + ';">'
|
||||
}
|
||||
|
||||
var ct = _closeTags[seq]
|
||||
if (ct) {
|
||||
// Pop sequence
|
||||
ansiCodes.pop()
|
||||
return ct
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
// Make sure tags are closed.
|
||||
var l = ansiCodes.length
|
||||
;(l > 0) && (ret += Array(l + 1).join('</span>'))
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize colors.
|
||||
* @param {Object} colors reference to _defColors
|
||||
*/
|
||||
ansiHTML.setColors = function (colors) {
|
||||
if (typeof colors !== 'object') {
|
||||
throw new Error('`colors` parameter must be an Object.')
|
||||
}
|
||||
|
||||
var _finalColors = {}
|
||||
for (var key in _defColors) {
|
||||
var hex = colors.hasOwnProperty(key) ? colors[key] : null
|
||||
if (!hex) {
|
||||
_finalColors[key] = _defColors[key]
|
||||
continue
|
||||
}
|
||||
if ('reset' === key) {
|
||||
if (typeof hex === 'string') {
|
||||
hex = [hex]
|
||||
}
|
||||
if (!Array.isArray(hex) || hex.length === 0 || hex.some(function (h) {
|
||||
return typeof h !== 'string'
|
||||
})) {
|
||||
throw new Error('The value of `' + key + '` property must be an Array and each item could only be a hex string, e.g.: FF0000')
|
||||
}
|
||||
var defHexColor = _defColors[key]
|
||||
if (!hex[0]) {
|
||||
hex[0] = defHexColor[0]
|
||||
}
|
||||
if (hex.length === 1 || !hex[1]) {
|
||||
hex = [hex[0]]
|
||||
hex.push(defHexColor[1])
|
||||
}
|
||||
|
||||
hex = hex.slice(0, 2)
|
||||
} else if (typeof hex !== 'string') {
|
||||
throw new Error('The value of `' + key + '` property must be a hex string, e.g.: FF0000')
|
||||
}
|
||||
_finalColors[key] = hex
|
||||
}
|
||||
_setTags(_finalColors)
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset colors.
|
||||
*/
|
||||
ansiHTML.reset = function () {
|
||||
_setTags(_defColors)
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose tags, including open and close.
|
||||
* @type {Object}
|
||||
*/
|
||||
ansiHTML.tags = {}
|
||||
|
||||
if (Object.defineProperty) {
|
||||
Object.defineProperty(ansiHTML.tags, 'open', {
|
||||
get: function () { return _openTags }
|
||||
})
|
||||
Object.defineProperty(ansiHTML.tags, 'close', {
|
||||
get: function () { return _closeTags }
|
||||
})
|
||||
} else {
|
||||
ansiHTML.tags.open = _openTags
|
||||
ansiHTML.tags.close = _closeTags
|
||||
}
|
||||
|
||||
function _setTags (colors) {
|
||||
// reset all
|
||||
_openTags['0'] = 'font-weight:normal;opacity:1;color:#' + colors.reset[0] + ';background:#' + colors.reset[1]
|
||||
// inverse
|
||||
_openTags['7'] = 'color:#' + colors.reset[1] + ';background:#' + colors.reset[0]
|
||||
// dark grey
|
||||
_openTags['90'] = 'color:#' + colors.darkgrey
|
||||
|
||||
for (var code in _styles) {
|
||||
var color = _styles[code]
|
||||
var oriColor = colors[color] || '000'
|
||||
_openTags[code] = 'color:#' + oriColor
|
||||
code = parseInt(code)
|
||||
_openTags[(code + 10).toString()] = 'background:#' + oriColor
|
||||
}
|
||||
}
|
||||
|
||||
ansiHTML.reset()
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
{
|
||||
"name": "ansi-html-community",
|
||||
"version": "0.0.8",
|
||||
"description": "An elegant lib that converts the chalked (ANSI) text to HTML. (Community)",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "./node_modules/.bin/mocha -R spec -t 5000"
|
||||
},
|
||||
"bin": {
|
||||
"ansi-html": "./bin/ansi-html"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/mahdyar/ansi-html-community.git"
|
||||
},
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"ansi html",
|
||||
"chalk html"
|
||||
],
|
||||
"author": {
|
||||
"name": "mahdyar"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"bugs": {
|
||||
"url": "https://github.com/mahdyar/ansi-html-community/issues"
|
||||
},
|
||||
"engines": [
|
||||
"node >= 0.8.0"
|
||||
],
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^1.21.4",
|
||||
"chai": "^1.9.1",
|
||||
"chalk": "^1.1.3",
|
||||
"lodash": "^2.4.2"
|
||||
},
|
||||
"readmeFilename": "README.md",
|
||||
"homepage": "https://github.com/mahdyar/ansi-html-community",
|
||||
"standard": {
|
||||
"ignore": [],
|
||||
"globals": [
|
||||
"describe",
|
||||
"it",
|
||||
"before",
|
||||
"after"
|
||||
]
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
declare namespace ansiRegex {
|
||||
interface Options {
|
||||
/**
|
||||
Match only the first ANSI escape.
|
||||
|
||||
@default false
|
||||
*/
|
||||
onlyFirst: boolean;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Regular expression for matching ANSI escape codes.
|
||||
|
||||
@example
|
||||
```
|
||||
import ansiRegex = require('ansi-regex');
|
||||
|
||||
ansiRegex().test('\u001B[4mcake\u001B[0m');
|
||||
//=> true
|
||||
|
||||
ansiRegex().test('cake');
|
||||
//=> false
|
||||
|
||||
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
|
||||
//=> ['\u001B[4m', '\u001B[0m']
|
||||
|
||||
'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
|
||||
//=> ['\u001B[4m']
|
||||
|
||||
'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
|
||||
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
|
||||
```
|
||||
*/
|
||||
declare function ansiRegex(options?: ansiRegex.Options): RegExp;
|
||||
|
||||
export = ansiRegex;
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = ({onlyFirst = false} = {}) => {
|
||||
const pattern = [
|
||||
'[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)',
|
||||
'(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))'
|
||||
].join('|');
|
||||
|
||||
return new RegExp(pattern, onlyFirst ? undefined : 'g');
|
||||
};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "ansi-regex",
|
||||
"version": "5.0.1",
|
||||
"description": "Regular expression for matching ANSI escape codes",
|
||||
"license": "MIT",
|
||||
"repository": "chalk/ansi-regex",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd",
|
||||
"view-supported": "node fixtures/view-codes.js"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"styles",
|
||||
"color",
|
||||
"colour",
|
||||
"colors",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"tty",
|
||||
"escape",
|
||||
"formatting",
|
||||
"rgb",
|
||||
"256",
|
||||
"shell",
|
||||
"xterm",
|
||||
"command-line",
|
||||
"text",
|
||||
"regex",
|
||||
"regexp",
|
||||
"re",
|
||||
"match",
|
||||
"test",
|
||||
"find",
|
||||
"pattern"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^2.4.0",
|
||||
"tsd": "^0.9.0",
|
||||
"xo": "^0.25.3"
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
# ansi-regex
|
||||
|
||||
> Regular expression for matching [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code)
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install ansi-regex
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const ansiRegex = require('ansi-regex');
|
||||
|
||||
ansiRegex().test('\u001B[4mcake\u001B[0m');
|
||||
//=> true
|
||||
|
||||
ansiRegex().test('cake');
|
||||
//=> false
|
||||
|
||||
'\u001B[4mcake\u001B[0m'.match(ansiRegex());
|
||||
//=> ['\u001B[4m', '\u001B[0m']
|
||||
|
||||
'\u001B[4mcake\u001B[0m'.match(ansiRegex({onlyFirst: true}));
|
||||
//=> ['\u001B[4m']
|
||||
|
||||
'\u001B]8;;https://github.com\u0007click\u001B]8;;\u0007'.match(ansiRegex());
|
||||
//=> ['\u001B]8;;https://github.com\u0007', '\u001B]8;;\u0007']
|
||||
```
|
||||
|
||||
|
||||
## API
|
||||
|
||||
### ansiRegex(options?)
|
||||
|
||||
Returns a regex for matching ANSI escape codes.
|
||||
|
||||
#### options
|
||||
|
||||
Type: `object`
|
||||
|
||||
##### onlyFirst
|
||||
|
||||
Type: `boolean`<br>
|
||||
Default: `false` *(Matches any ANSI escape codes in a string)*
|
||||
|
||||
Match only the first ANSI escape.
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### Why do you test for codes not in the ECMA 48 standard?
|
||||
|
||||
Some of the codes we run as a test are codes that we acquired finding various lists of non-standard or manufacturer specific codes. We test for both standard and non-standard codes, as most of them follow the same or similar format and can be safely matched in strings without the risk of removing actual string content. There are a few non-standard control codes that do not follow the traditional format (i.e. they end in numbers) thus forcing us to exclude them from the test because we cannot reliably match them.
|
||||
|
||||
On the historical side, those ECMA standards were established in the early 90's whereas the VT100, for example, was designed in the mid/late 70's. At that point in time, control codes were still pretty ungoverned and engineers used them for a multitude of things, namely to activate hardware ports that may have been proprietary. Somewhere else you see a similar 'anarchy' of codes is in the x86 architecture for processors; there are a ton of "interrupts" that can mean different things on certain brands of processors, most of which have been phased out.
|
||||
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
||||
- [Josh Junon](https://github.com/qix-)
|
||||
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
<b>
|
||||
<a href="https://tidelift.com/subscription/pkg/npm-ansi-regex?utm_source=npm-ansi-regex&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
|
||||
</b>
|
||||
<br>
|
||||
<sub>
|
||||
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
|
||||
</sub>
|
||||
</div>
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
'use strict';
|
||||
const colorConvert = require('color-convert');
|
||||
|
||||
const wrapAnsi16 = (fn, offset) => function () {
|
||||
const code = fn.apply(colorConvert, arguments);
|
||||
return `\u001B[${code + offset}m`;
|
||||
};
|
||||
|
||||
const wrapAnsi256 = (fn, offset) => function () {
|
||||
const code = fn.apply(colorConvert, arguments);
|
||||
return `\u001B[${38 + offset};5;${code}m`;
|
||||
};
|
||||
|
||||
const wrapAnsi16m = (fn, offset) => function () {
|
||||
const rgb = fn.apply(colorConvert, arguments);
|
||||
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
|
||||
};
|
||||
|
||||
function assembleStyles() {
|
||||
const codes = new Map();
|
||||
const styles = {
|
||||
modifier: {
|
||||
reset: [0, 0],
|
||||
// 21 isn't widely supported and 22 does the same thing
|
||||
bold: [1, 22],
|
||||
dim: [2, 22],
|
||||
italic: [3, 23],
|
||||
underline: [4, 24],
|
||||
inverse: [7, 27],
|
||||
hidden: [8, 28],
|
||||
strikethrough: [9, 29]
|
||||
},
|
||||
color: {
|
||||
black: [30, 39],
|
||||
red: [31, 39],
|
||||
green: [32, 39],
|
||||
yellow: [33, 39],
|
||||
blue: [34, 39],
|
||||
magenta: [35, 39],
|
||||
cyan: [36, 39],
|
||||
white: [37, 39],
|
||||
gray: [90, 39],
|
||||
|
||||
// Bright color
|
||||
redBright: [91, 39],
|
||||
greenBright: [92, 39],
|
||||
yellowBright: [93, 39],
|
||||
blueBright: [94, 39],
|
||||
magentaBright: [95, 39],
|
||||
cyanBright: [96, 39],
|
||||
whiteBright: [97, 39]
|
||||
},
|
||||
bgColor: {
|
||||
bgBlack: [40, 49],
|
||||
bgRed: [41, 49],
|
||||
bgGreen: [42, 49],
|
||||
bgYellow: [43, 49],
|
||||
bgBlue: [44, 49],
|
||||
bgMagenta: [45, 49],
|
||||
bgCyan: [46, 49],
|
||||
bgWhite: [47, 49],
|
||||
|
||||
// Bright color
|
||||
bgBlackBright: [100, 49],
|
||||
bgRedBright: [101, 49],
|
||||
bgGreenBright: [102, 49],
|
||||
bgYellowBright: [103, 49],
|
||||
bgBlueBright: [104, 49],
|
||||
bgMagentaBright: [105, 49],
|
||||
bgCyanBright: [106, 49],
|
||||
bgWhiteBright: [107, 49]
|
||||
}
|
||||
};
|
||||
|
||||
// Fix humans
|
||||
styles.color.grey = styles.color.gray;
|
||||
|
||||
for (const groupName of Object.keys(styles)) {
|
||||
const group = styles[groupName];
|
||||
|
||||
for (const styleName of Object.keys(group)) {
|
||||
const style = group[styleName];
|
||||
|
||||
styles[styleName] = {
|
||||
open: `\u001B[${style[0]}m`,
|
||||
close: `\u001B[${style[1]}m`
|
||||
};
|
||||
|
||||
group[styleName] = styles[styleName];
|
||||
|
||||
codes.set(style[0], style[1]);
|
||||
}
|
||||
|
||||
Object.defineProperty(styles, groupName, {
|
||||
value: group,
|
||||
enumerable: false
|
||||
});
|
||||
|
||||
Object.defineProperty(styles, 'codes', {
|
||||
value: codes,
|
||||
enumerable: false
|
||||
});
|
||||
}
|
||||
|
||||
const ansi2ansi = n => n;
|
||||
const rgb2rgb = (r, g, b) => [r, g, b];
|
||||
|
||||
styles.color.close = '\u001B[39m';
|
||||
styles.bgColor.close = '\u001B[49m';
|
||||
|
||||
styles.color.ansi = {
|
||||
ansi: wrapAnsi16(ansi2ansi, 0)
|
||||
};
|
||||
styles.color.ansi256 = {
|
||||
ansi256: wrapAnsi256(ansi2ansi, 0)
|
||||
};
|
||||
styles.color.ansi16m = {
|
||||
rgb: wrapAnsi16m(rgb2rgb, 0)
|
||||
};
|
||||
|
||||
styles.bgColor.ansi = {
|
||||
ansi: wrapAnsi16(ansi2ansi, 10)
|
||||
};
|
||||
styles.bgColor.ansi256 = {
|
||||
ansi256: wrapAnsi256(ansi2ansi, 10)
|
||||
};
|
||||
styles.bgColor.ansi16m = {
|
||||
rgb: wrapAnsi16m(rgb2rgb, 10)
|
||||
};
|
||||
|
||||
for (let key of Object.keys(colorConvert)) {
|
||||
if (typeof colorConvert[key] !== 'object') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const suite = colorConvert[key];
|
||||
|
||||
if (key === 'ansi16') {
|
||||
key = 'ansi';
|
||||
}
|
||||
|
||||
if ('ansi16' in suite) {
|
||||
styles.color.ansi[key] = wrapAnsi16(suite.ansi16, 0);
|
||||
styles.bgColor.ansi[key] = wrapAnsi16(suite.ansi16, 10);
|
||||
}
|
||||
|
||||
if ('ansi256' in suite) {
|
||||
styles.color.ansi256[key] = wrapAnsi256(suite.ansi256, 0);
|
||||
styles.bgColor.ansi256[key] = wrapAnsi256(suite.ansi256, 10);
|
||||
}
|
||||
|
||||
if ('rgb' in suite) {
|
||||
styles.color.ansi16m[key] = wrapAnsi16m(suite.rgb, 0);
|
||||
styles.bgColor.ansi16m[key] = wrapAnsi16m(suite.rgb, 10);
|
||||
}
|
||||
}
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
// Make the export immutable
|
||||
Object.defineProperty(module, 'exports', {
|
||||
enumerable: true,
|
||||
get: assembleStyles
|
||||
});
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"name": "ansi-styles",
|
||||
"version": "3.2.1",
|
||||
"description": "ANSI escape codes for styling strings in the terminal",
|
||||
"license": "MIT",
|
||||
"repository": "chalk/ansi-styles",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava",
|
||||
"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
|
||||
},
|
||||
"files": [
|
||||
"index.js"
|
||||
],
|
||||
"keywords": [
|
||||
"ansi",
|
||||
"styles",
|
||||
"color",
|
||||
"colour",
|
||||
"colors",
|
||||
"terminal",
|
||||
"console",
|
||||
"cli",
|
||||
"string",
|
||||
"tty",
|
||||
"escape",
|
||||
"formatting",
|
||||
"rgb",
|
||||
"256",
|
||||
"shell",
|
||||
"xterm",
|
||||
"log",
|
||||
"logging",
|
||||
"command-line",
|
||||
"text"
|
||||
],
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ava": "*",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"svg-term-cli": "^2.1.1",
|
||||
"xo": "*"
|
||||
},
|
||||
"ava": {
|
||||
"require": "babel-polyfill"
|
||||
}
|
||||
}
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
# ansi-styles [](https://travis-ci.org/chalk/ansi-styles)
|
||||
|
||||
> [ANSI escape codes](http://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
|
||||
|
||||
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
|
||||
|
||||
<img src="https://cdn.rawgit.com/chalk/ansi-styles/8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install ansi-styles
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const style = require('ansi-styles');
|
||||
|
||||
console.log(`${style.green.open}Hello world!${style.green.close}`);
|
||||
|
||||
|
||||
// Color conversion between 16/256/truecolor
|
||||
// NOTE: If conversion goes to 16 colors or 256 colors, the original color
|
||||
// may be degraded to fit that color palette. This means terminals
|
||||
// that do not support 16 million colors will best-match the
|
||||
// original color.
|
||||
console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
|
||||
console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
|
||||
console.log(style.color.ansi16m.hex('#ABCDEF') + 'Hello world!' + style.color.close);
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
Each style has an `open` and `close` property.
|
||||
|
||||
|
||||
## Styles
|
||||
|
||||
### Modifiers
|
||||
|
||||
- `reset`
|
||||
- `bold`
|
||||
- `dim`
|
||||
- `italic` *(Not widely supported)*
|
||||
- `underline`
|
||||
- `inverse`
|
||||
- `hidden`
|
||||
- `strikethrough` *(Not widely supported)*
|
||||
|
||||
### Colors
|
||||
|
||||
- `black`
|
||||
- `red`
|
||||
- `green`
|
||||
- `yellow`
|
||||
- `blue`
|
||||
- `magenta`
|
||||
- `cyan`
|
||||
- `white`
|
||||
- `gray` ("bright black")
|
||||
- `redBright`
|
||||
- `greenBright`
|
||||
- `yellowBright`
|
||||
- `blueBright`
|
||||
- `magentaBright`
|
||||
- `cyanBright`
|
||||
- `whiteBright`
|
||||
|
||||
### Background colors
|
||||
|
||||
- `bgBlack`
|
||||
- `bgRed`
|
||||
- `bgGreen`
|
||||
- `bgYellow`
|
||||
- `bgBlue`
|
||||
- `bgMagenta`
|
||||
- `bgCyan`
|
||||
- `bgWhite`
|
||||
- `bgBlackBright`
|
||||
- `bgRedBright`
|
||||
- `bgGreenBright`
|
||||
- `bgYellowBright`
|
||||
- `bgBlueBright`
|
||||
- `bgMagentaBright`
|
||||
- `bgCyanBright`
|
||||
- `bgWhiteBright`
|
||||
|
||||
|
||||
## Advanced usage
|
||||
|
||||
By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
|
||||
|
||||
- `style.modifier`
|
||||
- `style.color`
|
||||
- `style.bgColor`
|
||||
|
||||
###### Example
|
||||
|
||||
```js
|
||||
console.log(style.color.green.open);
|
||||
```
|
||||
|
||||
Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
|
||||
|
||||
###### Example
|
||||
|
||||
```js
|
||||
console.log(style.codes.get(36));
|
||||
//=> 39
|
||||
```
|
||||
|
||||
|
||||
## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
|
||||
|
||||
`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
|
||||
|
||||
To use these, call the associated conversion function with the intended output, for example:
|
||||
|
||||
```js
|
||||
style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
|
||||
style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
|
||||
|
||||
style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
|
||||
style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
|
||||
|
||||
style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
|
||||
style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
|
||||
```
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
|
||||
|
||||
|
||||
## Maintainers
|
||||
|
||||
- [Sindre Sorhus](https://github.com/sindresorhus)
|
||||
- [Josh Junon](https://github.com/qix-)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"node":true,
|
||||
"strict":true
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
.git*
|
||||
test/
|
||||
test-browser/
|
||||
build/
|
||||
.travis.yml
|
||||
*.swp
|
||||
Makefile
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (C) 2014-2016 Kevin Beaty
|
||||
|
||||
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.
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
## Any Promise
|
||||
|
||||
[](http://travis-ci.org/kevinbeaty/any-promise)
|
||||
|
||||
Let your library support any ES 2015 (ES6) compatible `Promise` and leave the choice to application authors. The application can *optionally* register its preferred `Promise` implementation and it will be exported when requiring `any-promise` from library code.
|
||||
|
||||
If no preference is registered, defaults to the global `Promise` for newer Node.js versions. The browser version defaults to the window `Promise`, so polyfill or register as necessary.
|
||||
|
||||
### Usage with global Promise:
|
||||
|
||||
Assuming the global `Promise` is the desired implementation:
|
||||
|
||||
```bash
|
||||
# Install any libraries depending on any-promise
|
||||
$ npm install mz
|
||||
```
|
||||
|
||||
The installed libraries will use global Promise by default.
|
||||
|
||||
```js
|
||||
// in library
|
||||
var Promise = require('any-promise') // the global Promise
|
||||
|
||||
function promiseReturningFunction(){
|
||||
return new Promise(function(resolve, reject){...})
|
||||
}
|
||||
```
|
||||
|
||||
### Usage with registration:
|
||||
|
||||
Assuming `bluebird` is the desired Promise implementation:
|
||||
|
||||
```bash
|
||||
# Install preferred promise library
|
||||
$ npm install bluebird
|
||||
# Install any-promise to allow registration
|
||||
$ npm install any-promise
|
||||
# Install any libraries you would like to use depending on any-promise
|
||||
$ npm install mz
|
||||
```
|
||||
|
||||
Register your preference in the application entry point before any other `require` of packages that load `any-promise`:
|
||||
|
||||
```javascript
|
||||
// top of application index.js or other entry point
|
||||
require('any-promise/register/bluebird')
|
||||
|
||||
// -or- Equivalent to above, but allows customization of Promise library
|
||||
require('any-promise/register')('bluebird', {Promise: require('bluebird')})
|
||||
```
|
||||
|
||||
Now that the implementation is registered, you can use any package depending on `any-promise`:
|
||||
|
||||
|
||||
```javascript
|
||||
var fsp = require('mz/fs') // mz/fs will use registered bluebird promises
|
||||
var Promise = require('any-promise') // the registered bluebird promise
|
||||
```
|
||||
|
||||
It is safe to call `register` multiple times, but it must always be with the same implementation.
|
||||
|
||||
Again, registration is *optional*. It should only be called by the application user if overriding the global `Promise` implementation is desired.
|
||||
|
||||
### Optional Application Registration
|
||||
|
||||
As an application author, you can *optionally* register a preferred `Promise` implementation on application startup (before any call to `require('any-promise')`:
|
||||
|
||||
You must register your preference before any call to `require('any-promise')` (by you or required packages), and only one implementation can be registered. Typically, this registration would occur at the top of the application entry point.
|
||||
|
||||
|
||||
#### Registration shortcuts
|
||||
|
||||
If you are using a known `Promise` implementation, you can register your preference with a shortcut:
|
||||
|
||||
|
||||
```js
|
||||
require('any-promise/register/bluebird')
|
||||
// -or-
|
||||
import 'any-promise/register/q';
|
||||
```
|
||||
|
||||
Shortcut registration is the preferred registration method as it works in the browser and Node.js. It is also convenient for using with `import` and many test runners, that offer a `--require` flag:
|
||||
|
||||
```
|
||||
$ ava --require=any-promise/register/bluebird test.js
|
||||
```
|
||||
|
||||
Current known implementations include `bluebird`, `q`, `when`, `rsvp`, `es6-promise`, `promise`, `native-promise-only`, `pinkie`, `vow` and `lie`. If you are not using a known implementation, you can use another registration method described below.
|
||||
|
||||
|
||||
#### Basic Registration
|
||||
|
||||
As an alternative to registration shortcuts, you can call the `register` function with the preferred `Promise` implementation. The benefit of this approach is that a `Promise` library can be required by name without being a known implementation. This approach does NOT work in the browser. To use `any-promise` in the browser use either registration shortcuts or specify the `Promise` constructor using advanced registration (see below).
|
||||
|
||||
```javascript
|
||||
require('any-promise/register')('when')
|
||||
// -or- require('any-promise/register')('any other ES6 compatible library (known or otherwise)')
|
||||
```
|
||||
|
||||
This registration method will try to detect the `Promise` constructor from requiring the specified implementation. If you would like to specify your own constructor, see advanced registration.
|
||||
|
||||
|
||||
#### Advanced Registration
|
||||
|
||||
To use the browser version, you should either install a polyfill or explicitly register the `Promise` constructor:
|
||||
|
||||
```javascript
|
||||
require('any-promise/register')('bluebird', {Promise: require('bluebird')})
|
||||
```
|
||||
|
||||
This could also be used for registering a custom `Promise` implementation or subclass.
|
||||
|
||||
Your preference will be registered globally, allowing a single registration even if multiple versions of `any-promise` are installed in the NPM dependency tree or are using multiple bundled JavaScript files in the browser. You can bypass this global registration in options:
|
||||
|
||||
|
||||
```javascript
|
||||
require('../register')('es6-promise', {Promise: require('es6-promise').Promise, global: false})
|
||||
```
|
||||
|
||||
### Library Usage
|
||||
|
||||
To use any `Promise` constructor, simply require it:
|
||||
|
||||
```javascript
|
||||
var Promise = require('any-promise');
|
||||
|
||||
return Promise
|
||||
.all([xf, f, init, coll])
|
||||
.then(fn);
|
||||
|
||||
|
||||
return new Promise(function(resolve, reject){
|
||||
try {
|
||||
resolve(item);
|
||||
} catch(e){
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
Except noted below, libraries using `any-promise` should only use [documented](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) functions as there is no guarantee which implementation will be chosen by the application author. Libraries should never call `register`, only the application user should call if desired.
|
||||
|
||||
|
||||
#### Advanced Library Usage
|
||||
|
||||
If your library needs to branch code based on the registered implementation, you can retrieve it using `var impl = require('any-promise/implementation')`, where `impl` will be the package name (`"bluebird"`, `"when"`, etc.) if registered, `"global.Promise"` if using the global version on Node.js, or `"window.Promise"` if using the browser version. You should always include a default case, as there is no guarantee what package may be registered.
|
||||
|
||||
|
||||
### Support for old Node.js versions
|
||||
|
||||
Node.js versions prior to `v0.12` may have contained buggy versions of the global `Promise`. For this reason, the global `Promise` is not loaded automatically for these old versions. If using `any-promise` in Node.js versions versions `<= v0.12`, the user should register a desired implementation.
|
||||
|
||||
If an implementation is not registered, `any-promise` will attempt to discover an installed `Promise` implementation. If no implementation can be found, an error will be thrown on `require('any-promise')`. While the auto-discovery usually avoids errors, it is non-deterministic. It is recommended that the user always register a preferred implementation for older Node.js versions.
|
||||
|
||||
This auto-discovery is only available for Node.jS versions prior to `v0.12`. Any newer versions will always default to the global `Promise` implementation.
|
||||
|
||||
### Related
|
||||
|
||||
- [any-observable](https://github.com/sindresorhus/any-observable) - `any-promise` for Observables.
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
declare var implementation: string;
|
||||
|
||||
export = implementation;
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./register')().implementation
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
declare class Promise <R> implements Promise.Thenable <R> {
|
||||
/**
|
||||
* If you call resolve in the body of the callback passed to the constructor,
|
||||
* your promise is fulfilled with result object passed to resolve.
|
||||
* If you call reject your promise is rejected with the object passed to resolve.
|
||||
* For consistency and debugging (eg stack traces), obj should be an instanceof Error.
|
||||
* Any errors thrown in the constructor callback will be implicitly passed to reject().
|
||||
*/
|
||||
constructor (callback: (resolve : (value?: R | Promise.Thenable<R>) => void, reject: (error?: any) => void) => void);
|
||||
|
||||
/**
|
||||
* onFulfilled is called when/if "promise" resolves. onRejected is called when/if "promise" rejects.
|
||||
* Both are optional, if either/both are omitted the next onFulfilled/onRejected in the chain is called.
|
||||
* Both callbacks have a single parameter , the fulfillment value or rejection reason.
|
||||
* "then" returns a new promise equivalent to the value you return from onFulfilled/onRejected after being passed through Promise.resolve.
|
||||
* If an error is thrown in the callback, the returned promise rejects with that error.
|
||||
*
|
||||
* @param onFulfilled called when/if "promise" resolves
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
then <U> (onFulfilled?: (value: R) => U | Promise.Thenable<U>, onRejected?: (error: any) => U | Promise.Thenable<U>): Promise<U>;
|
||||
then <U> (onFulfilled?: (value: R) => U | Promise.Thenable<U>, onRejected?: (error: any) => void): Promise<U>;
|
||||
|
||||
/**
|
||||
* Sugar for promise.then(undefined, onRejected)
|
||||
*
|
||||
* @param onRejected called when/if "promise" rejects
|
||||
*/
|
||||
catch <U> (onRejected?: (error: any) => U | Promise.Thenable<U>): Promise<U>;
|
||||
|
||||
/**
|
||||
* Make a new promise from the thenable.
|
||||
* A thenable is promise-like in as far as it has a "then" method.
|
||||
*/
|
||||
static resolve (): Promise<void>;
|
||||
static resolve <R> (value: R | Promise.Thenable<R>): Promise<R>;
|
||||
|
||||
/**
|
||||
* Make a promise that rejects to obj. For consistency and debugging (eg stack traces), obj should be an instanceof Error
|
||||
*/
|
||||
static reject <R> (error: any): Promise<R>;
|
||||
|
||||
/**
|
||||
* Make a promise that fulfills when every item in the array fulfills, and rejects if (and when) any item rejects.
|
||||
* the array passed to all can be a mixture of promise-like objects and other objects.
|
||||
* The fulfillment value is an array (in order) of fulfillment values. The rejection value is the first rejection value.
|
||||
*/
|
||||
static all <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>, T6 | Promise.Thenable<T6>, T7 | Promise.Thenable<T7>, T8 | Promise.Thenable<T8>, T9 | Promise.Thenable<T9>, T10 | Promise.Thenable<T10>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10]>;
|
||||
static all <T1, T2, T3, T4, T5, T6, T7, T8, T9> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>, T6 | Promise.Thenable<T6>, T7 | Promise.Thenable<T7>, T8 | Promise.Thenable<T8>, T9 | Promise.Thenable<T9>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8, T9]>;
|
||||
static all <T1, T2, T3, T4, T5, T6, T7, T8> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>, T6 | Promise.Thenable<T6>, T7 | Promise.Thenable<T7>, T8 | Promise.Thenable<T8>]): Promise<[T1, T2, T3, T4, T5, T6, T7, T8]>;
|
||||
static all <T1, T2, T3, T4, T5, T6, T7> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>, T6 | Promise.Thenable<T6>, T7 | Promise.Thenable<T7>]): Promise<[T1, T2, T3, T4, T5, T6, T7]>;
|
||||
static all <T1, T2, T3, T4, T5, T6> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>, T6 | Promise.Thenable<T6>]): Promise<[T1, T2, T3, T4, T5, T6]>;
|
||||
static all <T1, T2, T3, T4, T5> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>, T5 | Promise.Thenable<T5>]): Promise<[T1, T2, T3, T4, T5]>;
|
||||
static all <T1, T2, T3, T4> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>, T4 | Promise.Thenable <T4>]): Promise<[T1, T2, T3, T4]>;
|
||||
static all <T1, T2, T3> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>, T3 | Promise.Thenable<T3>]): Promise<[T1, T2, T3]>;
|
||||
static all <T1, T2> (values: [T1 | Promise.Thenable<T1>, T2 | Promise.Thenable<T2>]): Promise<[T1, T2]>;
|
||||
static all <T1> (values: [T1 | Promise.Thenable<T1>]): Promise<[T1]>;
|
||||
static all <TAll> (values: Array<TAll | Promise.Thenable<TAll>>): Promise<TAll[]>;
|
||||
|
||||
/**
|
||||
* Make a Promise that fulfills when any item fulfills, and rejects if any item rejects.
|
||||
*/
|
||||
static race <R> (promises: (R | Promise.Thenable<R>)[]): Promise<R>;
|
||||
}
|
||||
|
||||
declare namespace Promise {
|
||||
export interface Thenable <R> {
|
||||
then <U> (onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => U | Thenable<U>): Thenable<U>;
|
||||
then <U> (onFulfilled?: (value: R) => U | Thenable<U>, onRejected?: (error: any) => void): Thenable<U>;
|
||||
}
|
||||
}
|
||||
|
||||
export = Promise;
|
||||
+1
@@ -0,0 +1 @@
|
||||
module.exports = require('./register')().Promise
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
"use strict"
|
||||
// global key for user preferred registration
|
||||
var REGISTRATION_KEY = '@@any-promise/REGISTRATION',
|
||||
// Prior registration (preferred or detected)
|
||||
registered = null
|
||||
|
||||
/**
|
||||
* Registers the given implementation. An implementation must
|
||||
* be registered prior to any call to `require("any-promise")`,
|
||||
* typically on application load.
|
||||
*
|
||||
* If called with no arguments, will return registration in
|
||||
* following priority:
|
||||
*
|
||||
* For Node.js:
|
||||
*
|
||||
* 1. Previous registration
|
||||
* 2. global.Promise if node.js version >= 0.12
|
||||
* 3. Auto detected promise based on first sucessful require of
|
||||
* known promise libraries. Note this is a last resort, as the
|
||||
* loaded library is non-deterministic. node.js >= 0.12 will
|
||||
* always use global.Promise over this priority list.
|
||||
* 4. Throws error.
|
||||
*
|
||||
* For Browser:
|
||||
*
|
||||
* 1. Previous registration
|
||||
* 2. window.Promise
|
||||
* 3. Throws error.
|
||||
*
|
||||
* Options:
|
||||
*
|
||||
* Promise: Desired Promise constructor
|
||||
* global: Boolean - Should the registration be cached in a global variable to
|
||||
* allow cross dependency/bundle registration? (default true)
|
||||
*/
|
||||
module.exports = function(root, loadImplementation){
|
||||
return function register(implementation, opts){
|
||||
implementation = implementation || null
|
||||
opts = opts || {}
|
||||
// global registration unless explicitly {global: false} in options (default true)
|
||||
var registerGlobal = opts.global !== false;
|
||||
|
||||
// load any previous global registration
|
||||
if(registered === null && registerGlobal){
|
||||
registered = root[REGISTRATION_KEY] || null
|
||||
}
|
||||
|
||||
if(registered !== null
|
||||
&& implementation !== null
|
||||
&& registered.implementation !== implementation){
|
||||
// Throw error if attempting to redefine implementation
|
||||
throw new Error('any-promise already defined as "'+registered.implementation+
|
||||
'". You can only register an implementation before the first '+
|
||||
' call to require("any-promise") and an implementation cannot be changed')
|
||||
}
|
||||
|
||||
if(registered === null){
|
||||
// use provided implementation
|
||||
if(implementation !== null && typeof opts.Promise !== 'undefined'){
|
||||
registered = {
|
||||
Promise: opts.Promise,
|
||||
implementation: implementation
|
||||
}
|
||||
} else {
|
||||
// require implementation if implementation is specified but not provided
|
||||
registered = loadImplementation(implementation)
|
||||
}
|
||||
|
||||
if(registerGlobal){
|
||||
// register preference globally in case multiple installations
|
||||
root[REGISTRATION_KEY] = registered
|
||||
}
|
||||
}
|
||||
|
||||
return registered
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
"use strict";
|
||||
try {
|
||||
module.exports = require('./register')().Promise || null
|
||||
} catch(e) {
|
||||
module.exports = null
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"name": "any-promise",
|
||||
"version": "1.3.0",
|
||||
"description": "Resolve any installed ES6 compatible promise",
|
||||
"main": "index.js",
|
||||
"typings": "index.d.ts",
|
||||
"browser": {
|
||||
"./register.js": "./register-shim.js"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "ava"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kevinbeaty/any-promise"
|
||||
},
|
||||
"keywords": [
|
||||
"promise",
|
||||
"es6"
|
||||
],
|
||||
"author": "Kevin Beaty",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/kevinbeaty/any-promise/issues"
|
||||
},
|
||||
"homepage": "http://github.com/kevinbeaty/any-promise",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"ava": "^0.14.0",
|
||||
"bluebird": "^3.0.0",
|
||||
"es6-promise": "^3.0.0",
|
||||
"is-promise": "^2.0.0",
|
||||
"lie": "^3.0.0",
|
||||
"mocha": "^2.0.0",
|
||||
"native-promise-only": "^0.8.0",
|
||||
"phantomjs-prebuilt": "^2.0.0",
|
||||
"pinkie": "^2.0.0",
|
||||
"promise": "^7.0.0",
|
||||
"q": "^1.0.0",
|
||||
"rsvp": "^3.0.0",
|
||||
"vow": "^0.4.0",
|
||||
"when": "^3.0.0",
|
||||
"zuul": "^3.0.0"
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
"use strict";
|
||||
module.exports = require('./loader')(window, loadImplementation)
|
||||
|
||||
/**
|
||||
* Browser specific loadImplementation. Always uses `window.Promise`
|
||||
*
|
||||
* To register a custom implementation, must register with `Promise` option.
|
||||
*/
|
||||
function loadImplementation(){
|
||||
if(typeof window.Promise === 'undefined'){
|
||||
throw new Error("any-promise browser requires a polyfill or explicit registration"+
|
||||
" e.g: require('any-promise/register/bluebird')")
|
||||
}
|
||||
return {
|
||||
Promise: window.Promise,
|
||||
implementation: 'window.Promise'
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
import Promise = require('./index');
|
||||
|
||||
declare function register (module?: string, options?: register.Options): register.Register;
|
||||
|
||||
declare namespace register {
|
||||
export interface Register {
|
||||
Promise: typeof Promise;
|
||||
implementation: string;
|
||||
}
|
||||
|
||||
export interface Options {
|
||||
Promise?: typeof Promise;
|
||||
global?: boolean
|
||||
}
|
||||
}
|
||||
|
||||
export = register;
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
"use strict"
|
||||
module.exports = require('./loader')(global, loadImplementation);
|
||||
|
||||
/**
|
||||
* Node.js version of loadImplementation.
|
||||
*
|
||||
* Requires the given implementation and returns the registration
|
||||
* containing {Promise, implementation}
|
||||
*
|
||||
* If implementation is undefined or global.Promise, loads it
|
||||
* Otherwise uses require
|
||||
*/
|
||||
function loadImplementation(implementation){
|
||||
var impl = null
|
||||
|
||||
if(shouldPreferGlobalPromise(implementation)){
|
||||
// if no implementation or env specified use global.Promise
|
||||
impl = {
|
||||
Promise: global.Promise,
|
||||
implementation: 'global.Promise'
|
||||
}
|
||||
} else if(implementation){
|
||||
// if implementation specified, require it
|
||||
var lib = require(implementation)
|
||||
impl = {
|
||||
Promise: lib.Promise || lib,
|
||||
implementation: implementation
|
||||
}
|
||||
} else {
|
||||
// try to auto detect implementation. This is non-deterministic
|
||||
// and should prefer other branches, but this is our last chance
|
||||
// to load something without throwing error
|
||||
impl = tryAutoDetect()
|
||||
}
|
||||
|
||||
if(impl === null){
|
||||
throw new Error('Cannot find any-promise implementation nor'+
|
||||
' global.Promise. You must install polyfill or call'+
|
||||
' require("any-promise/register") with your preferred'+
|
||||
' implementation, e.g. require("any-promise/register/bluebird")'+
|
||||
' on application load prior to any require("any-promise").')
|
||||
}
|
||||
|
||||
return impl
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the global.Promise should be preferred if an implementation
|
||||
* has not been registered.
|
||||
*/
|
||||
function shouldPreferGlobalPromise(implementation){
|
||||
if(implementation){
|
||||
return implementation === 'global.Promise'
|
||||
} else if(typeof global.Promise !== 'undefined'){
|
||||
// Load global promise if implementation not specified
|
||||
// Versions < 0.11 did not have global Promise
|
||||
// Do not use for version < 0.12 as version 0.11 contained buggy versions
|
||||
var version = (/v(\d+)\.(\d+)\.(\d+)/).exec(process.version)
|
||||
return !(version && +version[1] == 0 && +version[2] < 12)
|
||||
}
|
||||
|
||||
// do not have global.Promise or another implementation was specified
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for common libs as last resort there is no guarantee that
|
||||
* this will return a desired implementation or even be deterministic.
|
||||
* The priority is also nearly arbitrary. We are only doing this
|
||||
* for older versions of Node.js <0.12 that do not have a reasonable
|
||||
* global.Promise implementation and we the user has not registered
|
||||
* the preference. This preserves the behavior of any-promise <= 0.1
|
||||
* and may be deprecated or removed in the future
|
||||
*/
|
||||
function tryAutoDetect(){
|
||||
var libs = [
|
||||
"es6-promise",
|
||||
"promise",
|
||||
"native-promise-only",
|
||||
"bluebird",
|
||||
"rsvp",
|
||||
"when",
|
||||
"q",
|
||||
"pinkie",
|
||||
"lie",
|
||||
"vow"]
|
||||
var i = 0, len = libs.length
|
||||
for(; i < len; i++){
|
||||
try {
|
||||
return loadImplementation(libs[i])
|
||||
} catch(e){}
|
||||
}
|
||||
return null
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('bluebird', {Promise: require('bluebird')})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('es6-promise', {Promise: require('es6-promise').Promise})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('lie', {Promise: require('lie')})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('native-promise-only', {Promise: require('native-promise-only')})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('pinkie', {Promise: require('pinkie')})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('promise', {Promise: require('promise')})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('q', {Promise: require('q').Promise})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('rsvp', {Promise: require('rsvp').Promise})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('vow', {Promise: require('vow').Promise})
|
||||
+1
@@ -0,0 +1 @@
|
||||
export {}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
'use strict';
|
||||
require('../register')('when', {Promise: require('when').Promise})
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
The ISC License
|
||||
|
||||
Copyright (c) 2019 Elan Shanker, Paul Miller (https://paulmillr.com)
|
||||
|
||||
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.
|
||||
+87
@@ -0,0 +1,87 @@
|
||||
anymatch [](https://travis-ci.org/micromatch/anymatch) [](https://coveralls.io/r/micromatch/anymatch?branch=master)
|
||||
======
|
||||
Javascript module to match a string against a regular expression, glob, string,
|
||||
or function that takes the string as an argument and returns a truthy or falsy
|
||||
value. The matcher can also be an array of any or all of these. Useful for
|
||||
allowing a very flexible user-defined config to define things like file paths.
|
||||
|
||||
__Note: This module has Bash-parity, please be aware that Windows-style backslashes are not supported as separators. See https://github.com/micromatch/micromatch#backslashes for more information.__
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
```sh
|
||||
npm install anymatch
|
||||
```
|
||||
|
||||
#### anymatch(matchers, testString, [returnIndex], [options])
|
||||
* __matchers__: (_Array|String|RegExp|Function_)
|
||||
String to be directly matched, string with glob patterns, regular expression
|
||||
test, function that takes the testString as an argument and returns a truthy
|
||||
value if it should be matched, or an array of any number and mix of these types.
|
||||
* __testString__: (_String|Array_) The string to test against the matchers. If
|
||||
passed as an array, the first element of the array will be used as the
|
||||
`testString` for non-function matchers, while the entire array will be applied
|
||||
as the arguments for function matchers.
|
||||
* __options__: (_Object_ [optional]_) Any of the [picomatch](https://github.com/micromatch/picomatch#options) options.
|
||||
* __returnIndex__: (_Boolean [optional]_) If true, return the array index of
|
||||
the first matcher that that testString matched, or -1 if no match, instead of a
|
||||
boolean result.
|
||||
|
||||
```js
|
||||
const anymatch = require('anymatch');
|
||||
|
||||
const matchers = [ 'path/to/file.js', 'path/anyjs/**/*.js', /foo.js$/, string => string.includes('bar') && string.length > 10 ] ;
|
||||
|
||||
anymatch(matchers, 'path/to/file.js'); // true
|
||||
anymatch(matchers, 'path/anyjs/baz.js'); // true
|
||||
anymatch(matchers, 'path/to/foo.js'); // true
|
||||
anymatch(matchers, 'path/to/bar.js'); // true
|
||||
anymatch(matchers, 'bar.js'); // false
|
||||
|
||||
// returnIndex = true
|
||||
anymatch(matchers, 'foo.js', {returnIndex: true}); // 2
|
||||
anymatch(matchers, 'path/anyjs/foo.js', {returnIndex: true}); // 1
|
||||
|
||||
// any picomatc
|
||||
|
||||
// using globs to match directories and their children
|
||||
anymatch('node_modules', 'node_modules'); // true
|
||||
anymatch('node_modules', 'node_modules/somelib/index.js'); // false
|
||||
anymatch('node_modules/**', 'node_modules/somelib/index.js'); // true
|
||||
anymatch('node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // false
|
||||
anymatch('**/node_modules/**', '/absolute/path/to/node_modules/somelib/index.js'); // true
|
||||
|
||||
const matcher = anymatch(matchers);
|
||||
['foo.js', 'bar.js'].filter(matcher); // [ 'foo.js' ]
|
||||
anymatch master* ❯
|
||||
|
||||
```
|
||||
|
||||
#### anymatch(matchers)
|
||||
You can also pass in only your matcher(s) to get a curried function that has
|
||||
already been bound to the provided matching criteria. This can be used as an
|
||||
`Array#filter` callback.
|
||||
|
||||
```js
|
||||
var matcher = anymatch(matchers);
|
||||
|
||||
matcher('path/to/file.js'); // true
|
||||
matcher('path/anyjs/baz.js', true); // 1
|
||||
|
||||
['foo.js', 'bar.js'].filter(matcher); // ['foo.js']
|
||||
```
|
||||
|
||||
Changelog
|
||||
----------
|
||||
[See release notes page on GitHub](https://github.com/micromatch/anymatch/releases)
|
||||
|
||||
- **v3.0:** Removed `startIndex` and `endIndex` arguments. Node 8.x-only.
|
||||
- **v2.0:** [micromatch](https://github.com/jonschlinkert/micromatch) moves away from minimatch-parity and inline with Bash. This includes handling backslashes differently (see https://github.com/micromatch/micromatch#backslashes for more information).
|
||||
- **v1.2:** anymatch uses [micromatch](https://github.com/jonschlinkert/micromatch)
|
||||
for glob pattern matching. Issues with glob pattern matching should be
|
||||
reported directly to the [micromatch issue tracker](https://github.com/jonschlinkert/micromatch/issues).
|
||||
|
||||
License
|
||||
-------
|
||||
[ISC](https://raw.github.com/micromatch/anymatch/master/LICENSE)
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
type AnymatchFn = (testString: string) => boolean;
|
||||
type AnymatchPattern = string|RegExp|AnymatchFn;
|
||||
type AnymatchMatcher = AnymatchPattern|AnymatchPattern[]
|
||||
type AnymatchTester = {
|
||||
(testString: string|any[], returnIndex: true): number;
|
||||
(testString: string|any[]): boolean;
|
||||
}
|
||||
|
||||
type PicomatchOptions = {dot: boolean};
|
||||
|
||||
declare const anymatch: {
|
||||
(matchers: AnymatchMatcher): AnymatchTester;
|
||||
(matchers: AnymatchMatcher, testString: string|any[], returnIndex: true | PicomatchOptions): number;
|
||||
(matchers: AnymatchMatcher, testString: string|any[]): boolean;
|
||||
}
|
||||
|
||||
export {AnymatchMatcher as Matcher}
|
||||
export {AnymatchTester as Tester}
|
||||
export default anymatch
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
|
||||
const picomatch = require('picomatch');
|
||||
const normalizePath = require('normalize-path');
|
||||
|
||||
/**
|
||||
* @typedef {(testString: string) => boolean} AnymatchFn
|
||||
* @typedef {string|RegExp|AnymatchFn} AnymatchPattern
|
||||
* @typedef {AnymatchPattern|AnymatchPattern[]} AnymatchMatcher
|
||||
*/
|
||||
const BANG = '!';
|
||||
const DEFAULT_OPTIONS = {returnIndex: false};
|
||||
const arrify = (item) => Array.isArray(item) ? item : [item];
|
||||
|
||||
/**
|
||||
* @param {AnymatchPattern} matcher
|
||||
* @param {object} options
|
||||
* @returns {AnymatchFn}
|
||||
*/
|
||||
const createPattern = (matcher, options) => {
|
||||
if (typeof matcher === 'function') {
|
||||
return matcher;
|
||||
}
|
||||
if (typeof matcher === 'string') {
|
||||
const glob = picomatch(matcher, options);
|
||||
return (string) => matcher === string || glob(string);
|
||||
}
|
||||
if (matcher instanceof RegExp) {
|
||||
return (string) => matcher.test(string);
|
||||
}
|
||||
return (string) => false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Array<Function>} patterns
|
||||
* @param {Array<Function>} negPatterns
|
||||
* @param {String|Array} args
|
||||
* @param {Boolean} returnIndex
|
||||
* @returns {boolean|number}
|
||||
*/
|
||||
const matchPatterns = (patterns, negPatterns, args, returnIndex) => {
|
||||
const isList = Array.isArray(args);
|
||||
const _path = isList ? args[0] : args;
|
||||
if (!isList && typeof _path !== 'string') {
|
||||
throw new TypeError('anymatch: second argument must be a string: got ' +
|
||||
Object.prototype.toString.call(_path))
|
||||
}
|
||||
const path = normalizePath(_path);
|
||||
|
||||
for (let index = 0; index < negPatterns.length; index++) {
|
||||
const nglob = negPatterns[index];
|
||||
if (nglob(path)) {
|
||||
return returnIndex ? -1 : false;
|
||||
}
|
||||
}
|
||||
|
||||
const applied = isList && [path].concat(args.slice(1));
|
||||
for (let index = 0; index < patterns.length; index++) {
|
||||
const pattern = patterns[index];
|
||||
if (isList ? pattern(...applied) : pattern(path)) {
|
||||
return returnIndex ? index : true;
|
||||
}
|
||||
}
|
||||
|
||||
return returnIndex ? -1 : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {AnymatchMatcher} matchers
|
||||
* @param {Array|string} testString
|
||||
* @param {object} options
|
||||
* @returns {boolean|number|Function}
|
||||
*/
|
||||
const anymatch = (matchers, testString, options = DEFAULT_OPTIONS) => {
|
||||
if (matchers == null) {
|
||||
throw new TypeError('anymatch: specify first argument');
|
||||
}
|
||||
const opts = typeof options === 'boolean' ? {returnIndex: options} : options;
|
||||
const returnIndex = opts.returnIndex || false;
|
||||
|
||||
// Early cache for matchers.
|
||||
const mtchers = arrify(matchers);
|
||||
const negatedGlobs = mtchers
|
||||
.filter(item => typeof item === 'string' && item.charAt(0) === BANG)
|
||||
.map(item => item.slice(1))
|
||||
.map(item => picomatch(item, opts));
|
||||
const patterns = mtchers
|
||||
.filter(item => typeof item !== 'string' || (typeof item === 'string' && item.charAt(0) !== BANG))
|
||||
.map(matcher => createPattern(matcher, opts));
|
||||
|
||||
if (testString == null) {
|
||||
return (testString, ri = false) => {
|
||||
const returnIndex = typeof ri === 'boolean' ? ri : false;
|
||||
return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return matchPatterns(patterns, negatedGlobs, testString, returnIndex);
|
||||
};
|
||||
|
||||
anymatch.default = anymatch;
|
||||
module.exports = anymatch;
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"name": "anymatch",
|
||||
"version": "3.1.2",
|
||||
"description": "Matches strings against configurable strings, globs, regular expressions, and/or functions",
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"dependencies": {
|
||||
"normalize-path": "^3.0.0",
|
||||
"picomatch": "^2.0.4"
|
||||
},
|
||||
"author": {
|
||||
"name": "Elan Shanker",
|
||||
"url": "https://github.com/es128"
|
||||
},
|
||||
"license": "ISC",
|
||||
"homepage": "https://github.com/micromatch/anymatch",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/micromatch/anymatch"
|
||||
},
|
||||
"keywords": [
|
||||
"match",
|
||||
"any",
|
||||
"string",
|
||||
"file",
|
||||
"fs",
|
||||
"list",
|
||||
"glob",
|
||||
"regex",
|
||||
"regexp",
|
||||
"regular",
|
||||
"expression",
|
||||
"function"
|
||||
],
|
||||
"scripts": {
|
||||
"test": "nyc mocha",
|
||||
"mocha": "mocha"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "^6.1.3",
|
||||
"nyc": "^14.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8"
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Feross Aboukhadijeh
|
||||
|
||||
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.
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
# arch [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
|
||||
|
||||
[travis-image]: https://img.shields.io/travis/feross/arch/master.svg
|
||||
[travis-url]: https://travis-ci.org/feross/arch
|
||||
[npm-image]: https://img.shields.io/npm/v/arch.svg
|
||||
[npm-url]: https://npmjs.org/package/arch
|
||||
[downloads-image]: https://img.shields.io/npm/dm/arch.svg
|
||||
[downloads-url]: https://npmjs.org/package/arch
|
||||
[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
|
||||
[standard-url]: https://standardjs.com
|
||||
|
||||
### Better `os.arch()` for node and the browser -- detect OS architecture
|
||||
|
||||
[](https://saucelabs.com/u/arch2)
|
||||
|
||||
This module is used by [WebTorrent Desktop](http://webtorrent.io/desktop) to
|
||||
determine if the user is on a 32-bit vs. 64-bit operating system to offer the
|
||||
right app installer.
|
||||
|
||||
In Node.js, the `os.arch()` method (and `process.arch` property) returns a string
|
||||
identifying the operating system CPU architecture **for which the Node.js binary
|
||||
was compiled**.
|
||||
|
||||
This is not the same as the **operating system CPU architecture**. For example,
|
||||
you can run Node.js 32-bit on a 64-bit OS. In that situation, `os.arch()` will
|
||||
return a misleading 'x86' (32-bit) value, instead of 'x64' (64-bit).
|
||||
|
||||
Use this package to get the actual operating system CPU architecture.
|
||||
|
||||
**BONUS: This package works in the browser too.**
|
||||
|
||||
## install
|
||||
|
||||
```
|
||||
npm install arch
|
||||
```
|
||||
|
||||
## usage
|
||||
|
||||
```js
|
||||
var arch = require('arch')
|
||||
console.log(arch()) // always returns 'x64' or 'x86'
|
||||
```
|
||||
|
||||
In the browser, there is no spec that defines where this information lives, so we
|
||||
check all known locations including `navigator.userAgent`, `navigator.platform`,
|
||||
and `navigator.cpuClass` to make a best guess.
|
||||
|
||||
If there is no *affirmative indication* that the architecture is 64-bit, then
|
||||
32-bit will be assumed. This makes this package perfect for determining what
|
||||
installer executable to offer to desktop app users. If there is ambiguity, then
|
||||
the user will get the 32-bit installer, which will work fine even for a user with
|
||||
a 64-bit OS.
|
||||
|
||||
For reference, `x64` means 64-bit and `x86` means 32-bit.
|
||||
|
||||
Here is some history behind these naming conventions:
|
||||
|
||||
- https://en.wikipedia.org/wiki/X86
|
||||
- https://en.wikipedia.org/wiki/IA-32
|
||||
- https://en.wikipedia.org/wiki/X86-64
|
||||
|
||||
## Node.js proposal - `os.sysarch()`
|
||||
|
||||
Note: There is
|
||||
[a proposal](https://github.com/nodejs/node-v0.x-archive/issues/2862#issuecomment-103942051)
|
||||
to add this functionality to Node.js as `os.sysarch()`.
|
||||
|
||||
## license
|
||||
|
||||
MIT. Copyright (c) [Feross Aboukhadijeh](http://feross.org).
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
module.exports = function arch () {
|
||||
/**
|
||||
* User agent strings that indicate a 64-bit OS.
|
||||
* See: http://stackoverflow.com/a/13709431/292185
|
||||
*/
|
||||
var userAgent = navigator.userAgent
|
||||
if ([
|
||||
'x86_64',
|
||||
'x86-64',
|
||||
'Win64',
|
||||
'x64;',
|
||||
'amd64',
|
||||
'AMD64',
|
||||
'WOW64',
|
||||
'x64_64'
|
||||
].some(function (str) {
|
||||
return userAgent.indexOf(str) > -1
|
||||
})) {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
/**
|
||||
* Platform strings that indicate a 64-bit OS.
|
||||
* See: http://stackoverflow.com/a/19883965/292185
|
||||
*/
|
||||
var platform = navigator.platform
|
||||
if (platform === 'MacIntel' || platform === 'Linux x86_64') {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
/**
|
||||
* CPU class strings that indicate a 64-bit OS.
|
||||
* See: http://stackoverflow.com/a/6267019/292185
|
||||
*/
|
||||
if (navigator.cpuClass === 'x64') {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
/**
|
||||
* If none of the above, assume the architecture is 32-bit.
|
||||
*/
|
||||
return 'x86'
|
||||
}
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
|
||||
declare function arch(): 'x64' | 'x86';
|
||||
|
||||
export = arch;
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*! arch. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
|
||||
var cp = require('child_process')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
|
||||
/**
|
||||
* Returns the operating system's CPU architecture. This is different than
|
||||
* `process.arch` or `os.arch()` which returns the architecture the Node.js (or
|
||||
* Electron) binary was compiled for.
|
||||
*/
|
||||
module.exports = function arch () {
|
||||
/**
|
||||
* The running binary is 64-bit, so the OS is clearly 64-bit.
|
||||
*/
|
||||
if (process.arch === 'x64') {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
/**
|
||||
* All recent versions of Mac OS are 64-bit.
|
||||
*/
|
||||
if (process.platform === 'darwin') {
|
||||
return 'x64'
|
||||
}
|
||||
|
||||
/**
|
||||
* On Windows, the most reliable way to detect a 64-bit OS from within a 32-bit
|
||||
* app is based on the presence of a WOW64 file: %SystemRoot%\SysNative.
|
||||
* See: https://twitter.com/feross/status/776949077208510464
|
||||
*/
|
||||
if (process.platform === 'win32') {
|
||||
var useEnv = false
|
||||
try {
|
||||
useEnv = !!(process.env.SYSTEMROOT && fs.statSync(process.env.SYSTEMROOT))
|
||||
} catch (err) {}
|
||||
|
||||
var sysRoot = useEnv ? process.env.SYSTEMROOT : 'C:\\Windows'
|
||||
|
||||
// If %SystemRoot%\SysNative exists, we are in a WOW64 FS Redirected application.
|
||||
var isWOW64 = false
|
||||
try {
|
||||
isWOW64 = !!fs.statSync(path.join(sysRoot, 'sysnative'))
|
||||
} catch (err) {}
|
||||
|
||||
return isWOW64 ? 'x64' : 'x86'
|
||||
}
|
||||
|
||||
/**
|
||||
* On Linux, use the `getconf` command to get the architecture.
|
||||
*/
|
||||
if (process.platform === 'linux') {
|
||||
var output = cp.execSync('getconf LONG_BIT', { encoding: 'utf8' })
|
||||
return output === '64\n' ? 'x64' : 'x86'
|
||||
}
|
||||
|
||||
/**
|
||||
* If none of the above, assume the architecture is 32-bit.
|
||||
*/
|
||||
return 'x86'
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
{
|
||||
"name": "arch",
|
||||
"description": "Better `os.arch()` for node and the browser -- detect OS architecture",
|
||||
"version": "2.2.0",
|
||||
"author": {
|
||||
"name": "Feross Aboukhadijeh",
|
||||
"email": "feross@feross.org",
|
||||
"url": "https://feross.org"
|
||||
},
|
||||
"browser": "browser.js",
|
||||
"types": "./index.d.ts",
|
||||
"bugs": {
|
||||
"url": "https://github.com/feross/arch/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"airtap": "^3.0.0",
|
||||
"standard": "*",
|
||||
"tape": "^5.0.0"
|
||||
},
|
||||
"homepage": "https://github.com/feross/arch",
|
||||
"keywords": [
|
||||
"browser",
|
||||
"browserify",
|
||||
"arch",
|
||||
"cpu info",
|
||||
"cpus",
|
||||
"architecture",
|
||||
"navigator.platform",
|
||||
"x64",
|
||||
"x86",
|
||||
"64 bit",
|
||||
"32 bit"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/feross/arch.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "standard && npm run test-node && npm run test-browser",
|
||||
"test-browser": "airtap -- test/*.js",
|
||||
"test-browser-local": "airtap --local -- test/*.js",
|
||||
"test-node": "tape test/*.js"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/feross"
|
||||
},
|
||||
{
|
||||
"type": "patreon",
|
||||
"url": "https://www.patreon.com/feross"
|
||||
},
|
||||
{
|
||||
"type": "consulting",
|
||||
"url": "https://feross.org/support"
|
||||
}
|
||||
]
|
||||
}
|
||||
+216
@@ -0,0 +1,216 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
|
||||
## [2.0.1] - 2020-08-29
|
||||
### Fixed
|
||||
- Fix issue with `process.argv` when used with interpreters (`coffee`, `ts-node`, etc.), #150.
|
||||
|
||||
|
||||
## [2.0.0] - 2020-08-14
|
||||
### Changed
|
||||
- Full rewrite. Now port from python 3.9.0 & more precise following.
|
||||
See [doc](./doc) for difference and migration info.
|
||||
- node.js 10+ required
|
||||
- Removed most of local docs in favour of original ones.
|
||||
|
||||
|
||||
## [1.0.10] - 2018-02-15
|
||||
### Fixed
|
||||
- Use .concat instead of + for arrays, #122.
|
||||
|
||||
|
||||
## [1.0.9] - 2016-09-29
|
||||
### Changed
|
||||
- Rerelease after 1.0.8 - deps cleanup.
|
||||
|
||||
|
||||
## [1.0.8] - 2016-09-29
|
||||
### Changed
|
||||
- Maintenance (deps bump, fix node 6.5+ tests, coverage report).
|
||||
|
||||
|
||||
## [1.0.7] - 2016-03-17
|
||||
### Changed
|
||||
- Teach `addArgument` to accept string arg names. #97, @tomxtobin.
|
||||
|
||||
|
||||
## [1.0.6] - 2016-02-06
|
||||
### Changed
|
||||
- Maintenance: moved to eslint & updated CS.
|
||||
|
||||
|
||||
## [1.0.5] - 2016-02-05
|
||||
### Changed
|
||||
- Removed lodash dependency to significantly reduce install size.
|
||||
Thanks to @mourner.
|
||||
|
||||
|
||||
## [1.0.4] - 2016-01-17
|
||||
### Changed
|
||||
- Maintenance: lodash update to 4.0.0.
|
||||
|
||||
|
||||
## [1.0.3] - 2015-10-27
|
||||
### Fixed
|
||||
- Fix parse `=` in args: `--examplepath="C:\myfolder\env=x64"`. #84, @CatWithApple.
|
||||
|
||||
|
||||
## [1.0.2] - 2015-03-22
|
||||
### Changed
|
||||
- Relaxed lodash version dependency.
|
||||
|
||||
|
||||
## [1.0.1] - 2015-02-20
|
||||
### Changed
|
||||
- Changed dependencies to be compatible with ancient nodejs.
|
||||
|
||||
|
||||
## [1.0.0] - 2015-02-19
|
||||
### Changed
|
||||
- Maintenance release.
|
||||
- Replaced `underscore` with `lodash`.
|
||||
- Bumped version to 1.0.0 to better reflect semver meaning.
|
||||
- HISTORY.md -> CHANGELOG.md
|
||||
|
||||
|
||||
## [0.1.16] - 2013-12-01
|
||||
### Changed
|
||||
- Maintenance release. Updated dependencies and docs.
|
||||
|
||||
|
||||
## [0.1.15] - 2013-05-13
|
||||
### Fixed
|
||||
- Fixed #55, @trebor89
|
||||
|
||||
|
||||
## [0.1.14] - 2013-05-12
|
||||
### Fixed
|
||||
- Fixed #62, @maxtaco
|
||||
|
||||
|
||||
## [0.1.13] - 2013-04-08
|
||||
### Changed
|
||||
- Added `.npmignore` to reduce package size
|
||||
|
||||
|
||||
## [0.1.12] - 2013-02-10
|
||||
### Fixed
|
||||
- Fixed conflictHandler (#46), @hpaulj
|
||||
|
||||
|
||||
## [0.1.11] - 2013-02-07
|
||||
### Added
|
||||
- Added 70+ tests (ported from python), @hpaulj
|
||||
- Added conflictHandler, @applepicke
|
||||
- Added fromfilePrefixChar, @hpaulj
|
||||
|
||||
### Fixed
|
||||
- Multiple bugfixes, @hpaulj
|
||||
|
||||
|
||||
## [0.1.10] - 2012-12-30
|
||||
### Added
|
||||
- Added [mutual exclusion](http://docs.python.org/dev/library/argparse.html#mutual-exclusion)
|
||||
support, thanks to @hpaulj
|
||||
|
||||
### Fixed
|
||||
- Fixed options check for `storeConst` & `appendConst` actions, thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.9] - 2012-12-27
|
||||
### Fixed
|
||||
- Fixed option dest interferens with other options (issue #23), thanks to @hpaulj
|
||||
- Fixed default value behavior with `*` positionals, thanks to @hpaulj
|
||||
- Improve `getDefault()` behavior, thanks to @hpaulj
|
||||
- Improve negative argument parsing, thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.8] - 2012-12-01
|
||||
### Fixed
|
||||
- Fixed parser parents (issue #19), thanks to @hpaulj
|
||||
- Fixed negative argument parse (issue #20), thanks to @hpaulj
|
||||
|
||||
|
||||
## [0.1.7] - 2012-10-14
|
||||
### Fixed
|
||||
- Fixed 'choices' argument parse (issue #16)
|
||||
- Fixed stderr output (issue #15)
|
||||
|
||||
|
||||
## [0.1.6] - 2012-09-09
|
||||
### Fixed
|
||||
- Fixed check for conflict of options (thanks to @tomxtobin)
|
||||
|
||||
|
||||
## [0.1.5] - 2012-09-03
|
||||
### Fixed
|
||||
- Fix parser #setDefaults method (thanks to @tomxtobin)
|
||||
|
||||
|
||||
## [0.1.4] - 2012-07-30
|
||||
### Fixed
|
||||
- Fixed pseudo-argument support (thanks to @CGamesPlay)
|
||||
- Fixed addHelp default (should be true), if not set (thanks to @benblank)
|
||||
|
||||
|
||||
## [0.1.3] - 2012-06-27
|
||||
### Fixed
|
||||
- Fixed formatter api name: Formatter -> HelpFormatter
|
||||
|
||||
|
||||
## [0.1.2] - 2012-05-29
|
||||
### Fixed
|
||||
- Removed excess whitespace in help
|
||||
- Fixed error reporting, when parcer with subcommands
|
||||
called with empty arguments
|
||||
|
||||
### Added
|
||||
- Added basic tests
|
||||
|
||||
|
||||
## [0.1.1] - 2012-05-23
|
||||
### Fixed
|
||||
- Fixed line wrapping in help formatter
|
||||
- Added better error reporting on invalid arguments
|
||||
|
||||
|
||||
## [0.1.0] - 2012-05-16
|
||||
### Added
|
||||
- First release.
|
||||
|
||||
|
||||
[2.0.1]: https://github.com/nodeca/argparse/compare/2.0.0...2.0.1
|
||||
[2.0.0]: https://github.com/nodeca/argparse/compare/1.0.10...2.0.0
|
||||
[1.0.10]: https://github.com/nodeca/argparse/compare/1.0.9...1.0.10
|
||||
[1.0.9]: https://github.com/nodeca/argparse/compare/1.0.8...1.0.9
|
||||
[1.0.8]: https://github.com/nodeca/argparse/compare/1.0.7...1.0.8
|
||||
[1.0.7]: https://github.com/nodeca/argparse/compare/1.0.6...1.0.7
|
||||
[1.0.6]: https://github.com/nodeca/argparse/compare/1.0.5...1.0.6
|
||||
[1.0.5]: https://github.com/nodeca/argparse/compare/1.0.4...1.0.5
|
||||
[1.0.4]: https://github.com/nodeca/argparse/compare/1.0.3...1.0.4
|
||||
[1.0.3]: https://github.com/nodeca/argparse/compare/1.0.2...1.0.3
|
||||
[1.0.2]: https://github.com/nodeca/argparse/compare/1.0.1...1.0.2
|
||||
[1.0.1]: https://github.com/nodeca/argparse/compare/1.0.0...1.0.1
|
||||
[1.0.0]: https://github.com/nodeca/argparse/compare/0.1.16...1.0.0
|
||||
[0.1.16]: https://github.com/nodeca/argparse/compare/0.1.15...0.1.16
|
||||
[0.1.15]: https://github.com/nodeca/argparse/compare/0.1.14...0.1.15
|
||||
[0.1.14]: https://github.com/nodeca/argparse/compare/0.1.13...0.1.14
|
||||
[0.1.13]: https://github.com/nodeca/argparse/compare/0.1.12...0.1.13
|
||||
[0.1.12]: https://github.com/nodeca/argparse/compare/0.1.11...0.1.12
|
||||
[0.1.11]: https://github.com/nodeca/argparse/compare/0.1.10...0.1.11
|
||||
[0.1.10]: https://github.com/nodeca/argparse/compare/0.1.9...0.1.10
|
||||
[0.1.9]: https://github.com/nodeca/argparse/compare/0.1.8...0.1.9
|
||||
[0.1.8]: https://github.com/nodeca/argparse/compare/0.1.7...0.1.8
|
||||
[0.1.7]: https://github.com/nodeca/argparse/compare/0.1.6...0.1.7
|
||||
[0.1.6]: https://github.com/nodeca/argparse/compare/0.1.5...0.1.6
|
||||
[0.1.5]: https://github.com/nodeca/argparse/compare/0.1.4...0.1.5
|
||||
[0.1.4]: https://github.com/nodeca/argparse/compare/0.1.3...0.1.4
|
||||
[0.1.3]: https://github.com/nodeca/argparse/compare/0.1.2...0.1.3
|
||||
[0.1.2]: https://github.com/nodeca/argparse/compare/0.1.1...0.1.2
|
||||
[0.1.1]: https://github.com/nodeca/argparse/compare/0.1.0...0.1.1
|
||||
[0.1.0]: https://github.com/nodeca/argparse/releases/tag/0.1.0
|
||||
+254
@@ -0,0 +1,254 @@
|
||||
A. HISTORY OF THE SOFTWARE
|
||||
==========================
|
||||
|
||||
Python was created in the early 1990s by Guido van Rossum at Stichting
|
||||
Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
|
||||
as a successor of a language called ABC. Guido remains Python's
|
||||
principal author, although it includes many contributions from others.
|
||||
|
||||
In 1995, Guido continued his work on Python at the Corporation for
|
||||
National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
|
||||
in Reston, Virginia where he released several versions of the
|
||||
software.
|
||||
|
||||
In May 2000, Guido and the Python core development team moved to
|
||||
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
|
||||
year, the PythonLabs team moved to Digital Creations, which became
|
||||
Zope Corporation. In 2001, the Python Software Foundation (PSF, see
|
||||
https://www.python.org/psf/) was formed, a non-profit organization
|
||||
created specifically to own Python-related Intellectual Property.
|
||||
Zope Corporation was a sponsoring member of the PSF.
|
||||
|
||||
All Python releases are Open Source (see http://www.opensource.org for
|
||||
the Open Source Definition). Historically, most, but not all, Python
|
||||
releases have also been GPL-compatible; the table below summarizes
|
||||
the various releases.
|
||||
|
||||
Release Derived Year Owner GPL-
|
||||
from compatible? (1)
|
||||
|
||||
0.9.0 thru 1.2 1991-1995 CWI yes
|
||||
1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
|
||||
1.6 1.5.2 2000 CNRI no
|
||||
2.0 1.6 2000 BeOpen.com no
|
||||
1.6.1 1.6 2001 CNRI yes (2)
|
||||
2.1 2.0+1.6.1 2001 PSF no
|
||||
2.0.1 2.0+1.6.1 2001 PSF yes
|
||||
2.1.1 2.1+2.0.1 2001 PSF yes
|
||||
2.1.2 2.1.1 2002 PSF yes
|
||||
2.1.3 2.1.2 2002 PSF yes
|
||||
2.2 and above 2.1.1 2001-now PSF yes
|
||||
|
||||
Footnotes:
|
||||
|
||||
(1) GPL-compatible doesn't mean that we're distributing Python under
|
||||
the GPL. All Python licenses, unlike the GPL, let you distribute
|
||||
a modified version without making your changes open source. The
|
||||
GPL-compatible licenses make it possible to combine Python with
|
||||
other software that is released under the GPL; the others don't.
|
||||
|
||||
(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
|
||||
because its license has a choice of law clause. According to
|
||||
CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
|
||||
is "not incompatible" with the GPL.
|
||||
|
||||
Thanks to the many outside volunteers who have worked under Guido's
|
||||
direction to make these releases possible.
|
||||
|
||||
|
||||
B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
|
||||
===============================================================
|
||||
|
||||
PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
|
||||
--------------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Python Software Foundation
|
||||
("PSF"), and the Individual or Organization ("Licensee") accessing and
|
||||
otherwise using this software ("Python") in source or binary form and
|
||||
its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, PSF hereby
|
||||
grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
|
||||
analyze, test, perform and/or display publicly, prepare derivative works,
|
||||
distribute, and otherwise use Python alone or in any derivative version,
|
||||
provided, however, that PSF's License Agreement and PSF's notice of copyright,
|
||||
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
|
||||
All Rights Reserved" are retained in Python alone or in any derivative version
|
||||
prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python.
|
||||
|
||||
4. PSF is making Python available to Licensee on an "AS IS"
|
||||
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. Nothing in this License Agreement shall be deemed to create any
|
||||
relationship of agency, partnership, or joint venture between PSF and
|
||||
Licensee. This License Agreement does not grant permission to use PSF
|
||||
trademarks or trade name in a trademark sense to endorse or promote
|
||||
products or services of Licensee, or any third party.
|
||||
|
||||
8. By copying, installing or otherwise using Python, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
|
||||
-------------------------------------------
|
||||
|
||||
BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
|
||||
|
||||
1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
|
||||
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
|
||||
Individual or Organization ("Licensee") accessing and otherwise using
|
||||
this software in source or binary form and its associated
|
||||
documentation ("the Software").
|
||||
|
||||
2. Subject to the terms and conditions of this BeOpen Python License
|
||||
Agreement, BeOpen hereby grants Licensee a non-exclusive,
|
||||
royalty-free, world-wide license to reproduce, analyze, test, perform
|
||||
and/or display publicly, prepare derivative works, distribute, and
|
||||
otherwise use the Software alone or in any derivative version,
|
||||
provided, however, that the BeOpen Python License is retained in the
|
||||
Software, alone or in any derivative version prepared by Licensee.
|
||||
|
||||
3. BeOpen is making the Software available to Licensee on an "AS IS"
|
||||
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
|
||||
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
|
||||
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
|
||||
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
5. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
6. This License Agreement shall be governed by and interpreted in all
|
||||
respects by the law of the State of California, excluding conflict of
|
||||
law provisions. Nothing in this License Agreement shall be deemed to
|
||||
create any relationship of agency, partnership, or joint venture
|
||||
between BeOpen and Licensee. This License Agreement does not grant
|
||||
permission to use BeOpen trademarks or trade names in a trademark
|
||||
sense to endorse or promote products or services of Licensee, or any
|
||||
third party. As an exception, the "BeOpen Python" logos available at
|
||||
http://www.pythonlabs.com/logos.html may be used according to the
|
||||
permissions granted on that web page.
|
||||
|
||||
7. By copying, installing or otherwise using the software, Licensee
|
||||
agrees to be bound by the terms and conditions of this License
|
||||
Agreement.
|
||||
|
||||
|
||||
CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
|
||||
---------------------------------------
|
||||
|
||||
1. This LICENSE AGREEMENT is between the Corporation for National
|
||||
Research Initiatives, having an office at 1895 Preston White Drive,
|
||||
Reston, VA 20191 ("CNRI"), and the Individual or Organization
|
||||
("Licensee") accessing and otherwise using Python 1.6.1 software in
|
||||
source or binary form and its associated documentation.
|
||||
|
||||
2. Subject to the terms and conditions of this License Agreement, CNRI
|
||||
hereby grants Licensee a nonexclusive, royalty-free, world-wide
|
||||
license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python 1.6.1
|
||||
alone or in any derivative version, provided, however, that CNRI's
|
||||
License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
|
||||
1995-2001 Corporation for National Research Initiatives; All Rights
|
||||
Reserved" are retained in Python 1.6.1 alone or in any derivative
|
||||
version prepared by Licensee. Alternately, in lieu of CNRI's License
|
||||
Agreement, Licensee may substitute the following text (omitting the
|
||||
quotes): "Python 1.6.1 is made available subject to the terms and
|
||||
conditions in CNRI's License Agreement. This Agreement together with
|
||||
Python 1.6.1 may be located on the Internet using the following
|
||||
unique, persistent identifier (known as a handle): 1895.22/1013. This
|
||||
Agreement may also be obtained from a proxy server on the Internet
|
||||
using the following URL: http://hdl.handle.net/1895.22/1013".
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python 1.6.1 or any part thereof, and wants to make
|
||||
the derivative work available to others as provided herein, then
|
||||
Licensee hereby agrees to include in any such work a brief summary of
|
||||
the changes made to Python 1.6.1.
|
||||
|
||||
4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
|
||||
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
|
||||
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
|
||||
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
|
||||
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
|
||||
INFRINGE ANY THIRD PARTY RIGHTS.
|
||||
|
||||
5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
|
||||
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
|
||||
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
|
||||
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
|
||||
|
||||
6. This License Agreement will automatically terminate upon a material
|
||||
breach of its terms and conditions.
|
||||
|
||||
7. This License Agreement shall be governed by the federal
|
||||
intellectual property law of the United States, including without
|
||||
limitation the federal copyright law, and, to the extent such
|
||||
U.S. federal law does not apply, by the law of the Commonwealth of
|
||||
Virginia, excluding Virginia's conflict of law provisions.
|
||||
Notwithstanding the foregoing, with regard to derivative works based
|
||||
on Python 1.6.1 that incorporate non-separable material that was
|
||||
previously distributed under the GNU General Public License (GPL), the
|
||||
law of the Commonwealth of Virginia shall govern this License
|
||||
Agreement only as to issues arising under or with respect to
|
||||
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
|
||||
License Agreement shall be deemed to create any relationship of
|
||||
agency, partnership, or joint venture between CNRI and Licensee. This
|
||||
License Agreement does not grant permission to use CNRI trademarks or
|
||||
trade name in a trademark sense to endorse or promote products or
|
||||
services of Licensee, or any third party.
|
||||
|
||||
8. By clicking on the "ACCEPT" button where indicated, or by copying,
|
||||
installing or otherwise using Python 1.6.1, Licensee agrees to be
|
||||
bound by the terms and conditions of this License Agreement.
|
||||
|
||||
ACCEPT
|
||||
|
||||
|
||||
CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
|
||||
--------------------------------------------------
|
||||
|
||||
Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
|
||||
The Netherlands. All rights reserved.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and its
|
||||
documentation for any purpose and without fee is hereby granted,
|
||||
provided that the above copyright notice appear in all copies and that
|
||||
both that copyright notice and this permission notice appear in
|
||||
supporting documentation, and that the name of Stichting Mathematisch
|
||||
Centrum or CWI not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
|
||||
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
|
||||
FOR ANY SPECIAL, 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.
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
argparse
|
||||
========
|
||||
|
||||
[](http://travis-ci.org/nodeca/argparse)
|
||||
[](https://www.npmjs.org/package/argparse)
|
||||
|
||||
CLI arguments parser for node.js, with [sub-commands](https://docs.python.org/3.9/library/argparse.html#sub-commands) support. Port of python's [argparse](http://docs.python.org/dev/library/argparse.html) (version [3.9.0](https://github.com/python/cpython/blob/v3.9.0rc1/Lib/argparse.py)).
|
||||
|
||||
**Difference with original.**
|
||||
|
||||
- JS has no keyword arguments support.
|
||||
- Pass options instead: `new ArgumentParser({ description: 'example', add_help: true })`.
|
||||
- JS has no python's types `int`, `float`, ...
|
||||
- Use string-typed names: `.add_argument('-b', { type: 'int', help: 'help' })`.
|
||||
- `%r` format specifier uses `require('util').inspect()`.
|
||||
|
||||
More details in [doc](./doc).
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
`test.js` file:
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
const { ArgumentParser } = require('argparse');
|
||||
const { version } = require('./package.json');
|
||||
|
||||
const parser = new ArgumentParser({
|
||||
description: 'Argparse example'
|
||||
});
|
||||
|
||||
parser.add_argument('-v', '--version', { action: 'version', version });
|
||||
parser.add_argument('-f', '--foo', { help: 'foo bar' });
|
||||
parser.add_argument('-b', '--bar', { help: 'bar foo' });
|
||||
parser.add_argument('--baz', { help: 'baz bar' });
|
||||
|
||||
console.dir(parser.parse_args());
|
||||
```
|
||||
|
||||
Display help:
|
||||
|
||||
```
|
||||
$ ./test.js -h
|
||||
usage: test.js [-h] [-v] [-f FOO] [-b BAR] [--baz BAZ]
|
||||
|
||||
Argparse example
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
-v, --version show program's version number and exit
|
||||
-f FOO, --foo FOO foo bar
|
||||
-b BAR, --bar BAR bar foo
|
||||
--baz BAZ baz bar
|
||||
```
|
||||
|
||||
Parse arguments:
|
||||
|
||||
```
|
||||
$ ./test.js -f=3 --bar=4 --baz 5
|
||||
{ foo: '3', bar: '4', baz: '5' }
|
||||
```
|
||||
|
||||
|
||||
API docs
|
||||
--------
|
||||
|
||||
Since this is a port with minimal divergence, there's no separate documentation.
|
||||
Use original one instead, with notes about difference.
|
||||
|
||||
1. [Original doc](https://docs.python.org/3.9/library/argparse.html).
|
||||
2. [Original tutorial](https://docs.python.org/3.9/howto/argparse.html).
|
||||
3. [Difference with python](./doc).
|
||||
|
||||
|
||||
argparse for enterprise
|
||||
-----------------------
|
||||
|
||||
Available as part of the Tidelift Subscription
|
||||
|
||||
The maintainers of argparse and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-argparse?utm_source=npm-argparse&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
||||
+3707
File diff suppressed because it is too large
Load Diff
+67
@@ -0,0 +1,67 @@
|
||||
// Limited implementation of python % string operator, supports only %s and %r for now
|
||||
// (other formats are not used here, but may appear in custom templates)
|
||||
|
||||
'use strict'
|
||||
|
||||
const { inspect } = require('util')
|
||||
|
||||
|
||||
module.exports = function sub(pattern, ...values) {
|
||||
let regex = /%(?:(%)|(-)?(\*)?(?:\((\w+)\))?([A-Za-z]))/g
|
||||
|
||||
let result = pattern.replace(regex, function (_, is_literal, is_left_align, is_padded, name, format) {
|
||||
if (is_literal) return '%'
|
||||
|
||||
let padded_count = 0
|
||||
if (is_padded) {
|
||||
if (values.length === 0) throw new TypeError('not enough arguments for format string')
|
||||
padded_count = values.shift()
|
||||
if (!Number.isInteger(padded_count)) throw new TypeError('* wants int')
|
||||
}
|
||||
|
||||
let str
|
||||
if (name !== undefined) {
|
||||
let dict = values[0]
|
||||
if (typeof dict !== 'object' || dict === null) throw new TypeError('format requires a mapping')
|
||||
if (!(name in dict)) throw new TypeError(`no such key: '${name}'`)
|
||||
str = dict[name]
|
||||
} else {
|
||||
if (values.length === 0) throw new TypeError('not enough arguments for format string')
|
||||
str = values.shift()
|
||||
}
|
||||
|
||||
switch (format) {
|
||||
case 's':
|
||||
str = String(str)
|
||||
break
|
||||
case 'r':
|
||||
str = inspect(str)
|
||||
break
|
||||
case 'd':
|
||||
case 'i':
|
||||
if (typeof str !== 'number') {
|
||||
throw new TypeError(`%${format} format: a number is required, not ${typeof str}`)
|
||||
}
|
||||
str = String(str.toFixed(0))
|
||||
break
|
||||
default:
|
||||
throw new TypeError(`unsupported format character '${format}'`)
|
||||
}
|
||||
|
||||
if (padded_count > 0) {
|
||||
return is_left_align ? str.padEnd(padded_count) : str.padStart(padded_count)
|
||||
} else {
|
||||
return str
|
||||
}
|
||||
})
|
||||
|
||||
if (values.length) {
|
||||
if (values.length === 1 && typeof values[0] === 'object' && values[0] !== null) {
|
||||
// mapping
|
||||
} else {
|
||||
throw new TypeError('not all arguments converted during string formatting')
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
// Partial port of python's argparse module, version 3.9.0 (only wrap and fill functions):
|
||||
// https://github.com/python/cpython/blob/v3.9.0b4/Lib/textwrap.py
|
||||
|
||||
'use strict'
|
||||
|
||||
/*
|
||||
* Text wrapping and filling.
|
||||
*/
|
||||
|
||||
// Copyright (C) 1999-2001 Gregory P. Ward.
|
||||
// Copyright (C) 2002, 2003 Python Software Foundation.
|
||||
// Copyright (C) 2020 argparse.js authors
|
||||
// Originally written by Greg Ward <gward@python.net>
|
||||
|
||||
// Hardcode the recognized whitespace characters to the US-ASCII
|
||||
// whitespace characters. The main reason for doing this is that
|
||||
// some Unicode spaces (like \u00a0) are non-breaking whitespaces.
|
||||
//
|
||||
// This less funky little regex just split on recognized spaces. E.g.
|
||||
// "Hello there -- you goof-ball, use the -b option!"
|
||||
// splits into
|
||||
// Hello/ /there/ /--/ /you/ /goof-ball,/ /use/ /the/ /-b/ /option!/
|
||||
const wordsep_simple_re = /([\t\n\x0b\x0c\r ]+)/
|
||||
|
||||
class TextWrapper {
|
||||
/*
|
||||
* Object for wrapping/filling text. The public interface consists of
|
||||
* the wrap() and fill() methods; the other methods are just there for
|
||||
* subclasses to override in order to tweak the default behaviour.
|
||||
* If you want to completely replace the main wrapping algorithm,
|
||||
* you'll probably have to override _wrap_chunks().
|
||||
*
|
||||
* Several instance attributes control various aspects of wrapping:
|
||||
* width (default: 70)
|
||||
* the maximum width of wrapped lines (unless break_long_words
|
||||
* is false)
|
||||
* initial_indent (default: "")
|
||||
* string that will be prepended to the first line of wrapped
|
||||
* output. Counts towards the line's width.
|
||||
* subsequent_indent (default: "")
|
||||
* string that will be prepended to all lines save the first
|
||||
* of wrapped output; also counts towards each line's width.
|
||||
* expand_tabs (default: true)
|
||||
* Expand tabs in input text to spaces before further processing.
|
||||
* Each tab will become 0 .. 'tabsize' spaces, depending on its position
|
||||
* in its line. If false, each tab is treated as a single character.
|
||||
* tabsize (default: 8)
|
||||
* Expand tabs in input text to 0 .. 'tabsize' spaces, unless
|
||||
* 'expand_tabs' is false.
|
||||
* replace_whitespace (default: true)
|
||||
* Replace all whitespace characters in the input text by spaces
|
||||
* after tab expansion. Note that if expand_tabs is false and
|
||||
* replace_whitespace is true, every tab will be converted to a
|
||||
* single space!
|
||||
* fix_sentence_endings (default: false)
|
||||
* Ensure that sentence-ending punctuation is always followed
|
||||
* by two spaces. Off by default because the algorithm is
|
||||
* (unavoidably) imperfect.
|
||||
* break_long_words (default: true)
|
||||
* Break words longer than 'width'. If false, those words will not
|
||||
* be broken, and some lines might be longer than 'width'.
|
||||
* break_on_hyphens (default: true)
|
||||
* Allow breaking hyphenated words. If true, wrapping will occur
|
||||
* preferably on whitespaces and right after hyphens part of
|
||||
* compound words.
|
||||
* drop_whitespace (default: true)
|
||||
* Drop leading and trailing whitespace from lines.
|
||||
* max_lines (default: None)
|
||||
* Truncate wrapped lines.
|
||||
* placeholder (default: ' [...]')
|
||||
* Append to the last line of truncated text.
|
||||
*/
|
||||
|
||||
constructor(options = {}) {
|
||||
let {
|
||||
width = 70,
|
||||
initial_indent = '',
|
||||
subsequent_indent = '',
|
||||
expand_tabs = true,
|
||||
replace_whitespace = true,
|
||||
fix_sentence_endings = false,
|
||||
break_long_words = true,
|
||||
drop_whitespace = true,
|
||||
break_on_hyphens = true,
|
||||
tabsize = 8,
|
||||
max_lines = undefined,
|
||||
placeholder=' [...]'
|
||||
} = options
|
||||
|
||||
this.width = width
|
||||
this.initial_indent = initial_indent
|
||||
this.subsequent_indent = subsequent_indent
|
||||
this.expand_tabs = expand_tabs
|
||||
this.replace_whitespace = replace_whitespace
|
||||
this.fix_sentence_endings = fix_sentence_endings
|
||||
this.break_long_words = break_long_words
|
||||
this.drop_whitespace = drop_whitespace
|
||||
this.break_on_hyphens = break_on_hyphens
|
||||
this.tabsize = tabsize
|
||||
this.max_lines = max_lines
|
||||
this.placeholder = placeholder
|
||||
}
|
||||
|
||||
|
||||
// -- Private methods -----------------------------------------------
|
||||
// (possibly useful for subclasses to override)
|
||||
|
||||
_munge_whitespace(text) {
|
||||
/*
|
||||
* _munge_whitespace(text : string) -> string
|
||||
*
|
||||
* Munge whitespace in text: expand tabs and convert all other
|
||||
* whitespace characters to spaces. Eg. " foo\\tbar\\n\\nbaz"
|
||||
* becomes " foo bar baz".
|
||||
*/
|
||||
if (this.expand_tabs) {
|
||||
text = text.replace(/\t/g, ' '.repeat(this.tabsize)) // not strictly correct in js
|
||||
}
|
||||
if (this.replace_whitespace) {
|
||||
text = text.replace(/[\t\n\x0b\x0c\r]/g, ' ')
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
_split(text) {
|
||||
/*
|
||||
* _split(text : string) -> [string]
|
||||
*
|
||||
* Split the text to wrap into indivisible chunks. Chunks are
|
||||
* not quite the same as words; see _wrap_chunks() for full
|
||||
* details. As an example, the text
|
||||
* Look, goof-ball -- use the -b option!
|
||||
* breaks into the following chunks:
|
||||
* 'Look,', ' ', 'goof-', 'ball', ' ', '--', ' ',
|
||||
* 'use', ' ', 'the', ' ', '-b', ' ', 'option!'
|
||||
* if break_on_hyphens is True, or in:
|
||||
* 'Look,', ' ', 'goof-ball', ' ', '--', ' ',
|
||||
* 'use', ' ', 'the', ' ', '-b', ' ', option!'
|
||||
* otherwise.
|
||||
*/
|
||||
let chunks = text.split(wordsep_simple_re)
|
||||
chunks = chunks.filter(Boolean)
|
||||
return chunks
|
||||
}
|
||||
|
||||
_handle_long_word(reversed_chunks, cur_line, cur_len, width) {
|
||||
/*
|
||||
* _handle_long_word(chunks : [string],
|
||||
* cur_line : [string],
|
||||
* cur_len : int, width : int)
|
||||
*
|
||||
* Handle a chunk of text (most likely a word, not whitespace) that
|
||||
* is too long to fit in any line.
|
||||
*/
|
||||
// Figure out when indent is larger than the specified width, and make
|
||||
// sure at least one character is stripped off on every pass
|
||||
let space_left
|
||||
if (width < 1) {
|
||||
space_left = 1
|
||||
} else {
|
||||
space_left = width - cur_len
|
||||
}
|
||||
|
||||
// If we're allowed to break long words, then do so: put as much
|
||||
// of the next chunk onto the current line as will fit.
|
||||
if (this.break_long_words) {
|
||||
cur_line.push(reversed_chunks[reversed_chunks.length - 1].slice(0, space_left))
|
||||
reversed_chunks[reversed_chunks.length - 1] = reversed_chunks[reversed_chunks.length - 1].slice(space_left)
|
||||
|
||||
// Otherwise, we have to preserve the long word intact. Only add
|
||||
// it to the current line if there's nothing already there --
|
||||
// that minimizes how much we violate the width constraint.
|
||||
} else if (!cur_line) {
|
||||
cur_line.push(...reversed_chunks.pop())
|
||||
}
|
||||
|
||||
// If we're not allowed to break long words, and there's already
|
||||
// text on the current line, do nothing. Next time through the
|
||||
// main loop of _wrap_chunks(), we'll wind up here again, but
|
||||
// cur_len will be zero, so the next line will be entirely
|
||||
// devoted to the long word that we can't handle right now.
|
||||
}
|
||||
|
||||
_wrap_chunks(chunks) {
|
||||
/*
|
||||
* _wrap_chunks(chunks : [string]) -> [string]
|
||||
*
|
||||
* Wrap a sequence of text chunks and return a list of lines of
|
||||
* length 'self.width' or less. (If 'break_long_words' is false,
|
||||
* some lines may be longer than this.) Chunks correspond roughly
|
||||
* to words and the whitespace between them: each chunk is
|
||||
* indivisible (modulo 'break_long_words'), but a line break can
|
||||
* come between any two chunks. Chunks should not have internal
|
||||
* whitespace; ie. a chunk is either all whitespace or a "word".
|
||||
* Whitespace chunks will be removed from the beginning and end of
|
||||
* lines, but apart from that whitespace is preserved.
|
||||
*/
|
||||
let lines = []
|
||||
let indent
|
||||
if (this.width <= 0) {
|
||||
throw Error(`invalid width ${this.width} (must be > 0)`)
|
||||
}
|
||||
if (this.max_lines !== undefined) {
|
||||
if (this.max_lines > 1) {
|
||||
indent = this.subsequent_indent
|
||||
} else {
|
||||
indent = this.initial_indent
|
||||
}
|
||||
if (indent.length + this.placeholder.trimStart().length > this.width) {
|
||||
throw Error('placeholder too large for max width')
|
||||
}
|
||||
}
|
||||
|
||||
// Arrange in reverse order so items can be efficiently popped
|
||||
// from a stack of chucks.
|
||||
chunks = chunks.reverse()
|
||||
|
||||
while (chunks.length > 0) {
|
||||
|
||||
// Start the list of chunks that will make up the current line.
|
||||
// cur_len is just the length of all the chunks in cur_line.
|
||||
let cur_line = []
|
||||
let cur_len = 0
|
||||
|
||||
// Figure out which static string will prefix this line.
|
||||
let indent
|
||||
if (lines) {
|
||||
indent = this.subsequent_indent
|
||||
} else {
|
||||
indent = this.initial_indent
|
||||
}
|
||||
|
||||
// Maximum width for this line.
|
||||
let width = this.width - indent.length
|
||||
|
||||
// First chunk on line is whitespace -- drop it, unless this
|
||||
// is the very beginning of the text (ie. no lines started yet).
|
||||
if (this.drop_whitespace && chunks[chunks.length - 1].trim() === '' && lines.length > 0) {
|
||||
chunks.pop()
|
||||
}
|
||||
|
||||
while (chunks.length > 0) {
|
||||
let l = chunks[chunks.length - 1].length
|
||||
|
||||
// Can at least squeeze this chunk onto the current line.
|
||||
if (cur_len + l <= width) {
|
||||
cur_line.push(chunks.pop())
|
||||
cur_len += l
|
||||
|
||||
// Nope, this line is full.
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// The current line is full, and the next chunk is too big to
|
||||
// fit on *any* line (not just this one).
|
||||
if (chunks.length && chunks[chunks.length - 1].length > width) {
|
||||
this._handle_long_word(chunks, cur_line, cur_len, width)
|
||||
cur_len = cur_line.map(l => l.length).reduce((a, b) => a + b, 0)
|
||||
}
|
||||
|
||||
// If the last chunk on this line is all whitespace, drop it.
|
||||
if (this.drop_whitespace && cur_line.length > 0 && cur_line[cur_line.length - 1].trim() === '') {
|
||||
cur_len -= cur_line[cur_line.length - 1].length
|
||||
cur_line.pop()
|
||||
}
|
||||
|
||||
if (cur_line) {
|
||||
if (this.max_lines === undefined ||
|
||||
lines.length + 1 < this.max_lines ||
|
||||
(chunks.length === 0 ||
|
||||
this.drop_whitespace &&
|
||||
chunks.length === 1 &&
|
||||
!chunks[0].trim()) && cur_len <= width) {
|
||||
// Convert current line back to a string and store it in
|
||||
// list of all lines (return value).
|
||||
lines.push(indent + cur_line.join(''))
|
||||
} else {
|
||||
let had_break = false
|
||||
while (cur_line) {
|
||||
if (cur_line[cur_line.length - 1].trim() &&
|
||||
cur_len + this.placeholder.length <= width) {
|
||||
cur_line.push(this.placeholder)
|
||||
lines.push(indent + cur_line.join(''))
|
||||
had_break = true
|
||||
break
|
||||
}
|
||||
cur_len -= cur_line[-1].length
|
||||
cur_line.pop()
|
||||
}
|
||||
if (!had_break) {
|
||||
if (lines) {
|
||||
let prev_line = lines[lines.length - 1].trimEnd()
|
||||
if (prev_line.length + this.placeholder.length <=
|
||||
this.width) {
|
||||
lines[lines.length - 1] = prev_line + this.placeholder
|
||||
break
|
||||
}
|
||||
}
|
||||
lines.push(indent + this.placeholder.lstrip())
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lines
|
||||
}
|
||||
|
||||
_split_chunks(text) {
|
||||
text = this._munge_whitespace(text)
|
||||
return this._split(text)
|
||||
}
|
||||
|
||||
// -- Public interface ----------------------------------------------
|
||||
|
||||
wrap(text) {
|
||||
/*
|
||||
* wrap(text : string) -> [string]
|
||||
*
|
||||
* Reformat the single paragraph in 'text' so it fits in lines of
|
||||
* no more than 'self.width' columns, and return a list of wrapped
|
||||
* lines. Tabs in 'text' are expanded with string.expandtabs(),
|
||||
* and all other whitespace characters (including newline) are
|
||||
* converted to space.
|
||||
*/
|
||||
let chunks = this._split_chunks(text)
|
||||
// not implemented in js
|
||||
//if (this.fix_sentence_endings) {
|
||||
// this._fix_sentence_endings(chunks)
|
||||
//}
|
||||
return this._wrap_chunks(chunks)
|
||||
}
|
||||
|
||||
fill(text) {
|
||||
/*
|
||||
* fill(text : string) -> string
|
||||
*
|
||||
* Reformat the single paragraph in 'text' to fit in lines of no
|
||||
* more than 'self.width' columns, and return a new string
|
||||
* containing the entire wrapped paragraph.
|
||||
*/
|
||||
return this.wrap(text).join('\n')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -- Convenience interface ---------------------------------------------
|
||||
|
||||
function wrap(text, options = {}) {
|
||||
/*
|
||||
* Wrap a single paragraph of text, returning a list of wrapped lines.
|
||||
*
|
||||
* Reformat the single paragraph in 'text' so it fits in lines of no
|
||||
* more than 'width' columns, and return a list of wrapped lines. By
|
||||
* default, tabs in 'text' are expanded with string.expandtabs(), and
|
||||
* all other whitespace characters (including newline) are converted to
|
||||
* space. See TextWrapper class for available keyword args to customize
|
||||
* wrapping behaviour.
|
||||
*/
|
||||
let { width = 70, ...kwargs } = options
|
||||
let w = new TextWrapper(Object.assign({ width }, kwargs))
|
||||
return w.wrap(text)
|
||||
}
|
||||
|
||||
function fill(text, options = {}) {
|
||||
/*
|
||||
* Fill a single paragraph of text, returning a new string.
|
||||
*
|
||||
* Reformat the single paragraph in 'text' to fit in lines of no more
|
||||
* than 'width' columns, and return a new string containing the entire
|
||||
* wrapped paragraph. As with wrap(), tabs are expanded and other
|
||||
* whitespace characters converted to space. See TextWrapper class for
|
||||
* available keyword args to customize wrapping behaviour.
|
||||
*/
|
||||
let { width = 70, ...kwargs } = options
|
||||
let w = new TextWrapper(Object.assign({ width }, kwargs))
|
||||
return w.fill(text)
|
||||
}
|
||||
|
||||
// -- Loosely related functionality -------------------------------------
|
||||
|
||||
let _whitespace_only_re = /^[ \t]+$/mg
|
||||
let _leading_whitespace_re = /(^[ \t]*)(?:[^ \t\n])/mg
|
||||
|
||||
function dedent(text) {
|
||||
/*
|
||||
* Remove any common leading whitespace from every line in `text`.
|
||||
*
|
||||
* This can be used to make triple-quoted strings line up with the left
|
||||
* edge of the display, while still presenting them in the source code
|
||||
* in indented form.
|
||||
*
|
||||
* Note that tabs and spaces are both treated as whitespace, but they
|
||||
* are not equal: the lines " hello" and "\\thello" are
|
||||
* considered to have no common leading whitespace.
|
||||
*
|
||||
* Entirely blank lines are normalized to a newline character.
|
||||
*/
|
||||
// Look for the longest leading string of spaces and tabs common to
|
||||
// all lines.
|
||||
let margin = undefined
|
||||
text = text.replace(_whitespace_only_re, '')
|
||||
let indents = text.match(_leading_whitespace_re) || []
|
||||
for (let indent of indents) {
|
||||
indent = indent.slice(0, -1)
|
||||
|
||||
if (margin === undefined) {
|
||||
margin = indent
|
||||
|
||||
// Current line more deeply indented than previous winner:
|
||||
// no change (previous winner is still on top).
|
||||
} else if (indent.startsWith(margin)) {
|
||||
// pass
|
||||
|
||||
// Current line consistent with and no deeper than previous winner:
|
||||
// it's the new winner.
|
||||
} else if (margin.startsWith(indent)) {
|
||||
margin = indent
|
||||
|
||||
// Find the largest common whitespace between current line and previous
|
||||
// winner.
|
||||
} else {
|
||||
for (let i = 0; i < margin.length && i < indent.length; i++) {
|
||||
if (margin[i] !== indent[i]) {
|
||||
margin = margin.slice(0, i)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (margin) {
|
||||
text = text.replace(new RegExp('^' + margin, 'mg'), '')
|
||||
}
|
||||
return text
|
||||
}
|
||||
|
||||
module.exports = { wrap, fill, dedent }
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "argparse",
|
||||
"description": "CLI arguments parser. Native port of python's argparse.",
|
||||
"version": "2.0.1",
|
||||
"keywords": [
|
||||
"cli",
|
||||
"parser",
|
||||
"argparse",
|
||||
"option",
|
||||
"args"
|
||||
],
|
||||
"main": "argparse.js",
|
||||
"files": [
|
||||
"argparse.js",
|
||||
"lib/"
|
||||
],
|
||||
"license": "Python-2.0",
|
||||
"repository": "nodeca/argparse",
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"test": "npm run lint && nyc mocha",
|
||||
"coverage": "npm run test && nyc report --reporter html"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "^7.11.0",
|
||||
"@babel/plugin-syntax-class-properties": "^7.10.4",
|
||||
"eslint": "^7.5.0",
|
||||
"mocha": "^8.0.1",
|
||||
"nyc": "^15.1.0"
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Blake Embrey (hello@blakeembrey.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.
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
# Array Flatten
|
||||
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![NPM downloads][downloads-image]][downloads-url]
|
||||
[![Build status][travis-image]][travis-url]
|
||||
[![Test coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
> Flatten nested arrays.
|
||||
|
||||
## Installation
|
||||
|
||||
```
|
||||
npm install array-flatten --save
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```javascript
|
||||
var flatten = require('array-flatten')
|
||||
|
||||
flatten([1, [2, [3, [4, [5], 6], 7], 8], 9])
|
||||
//=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
flatten.depth([1, [2, [3, [4, [5], 6], 7], 8], 9], 2)
|
||||
//=> [1, 2, 3, [4, [5], 6], 7, 8, 9]
|
||||
|
||||
(function () {
|
||||
flatten.from(arguments) //=> [1, 2, 3]
|
||||
})(1, [2, 3])
|
||||
```
|
||||
|
||||
### Methods
|
||||
|
||||
* **flatten(array)** Flatten a nested array structure
|
||||
* **flatten.from(arrayish)** Flatten an array-like structure (E.g. arguments)
|
||||
* **flatten.depth(array, depth)** Flatten a nested array structure with a specific depth
|
||||
* **flatten.fromDepth(arrayish, depth)** Flatten an array-like structure with a specific depth
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/array-flatten.svg?style=flat
|
||||
[npm-url]: https://npmjs.org/package/array-flatten
|
||||
[downloads-image]: https://img.shields.io/npm/dm/array-flatten.svg?style=flat
|
||||
[downloads-url]: https://npmjs.org/package/array-flatten
|
||||
[travis-image]: https://img.shields.io/travis/blakeembrey/array-flatten.svg?style=flat
|
||||
[travis-url]: https://travis-ci.org/blakeembrey/array-flatten
|
||||
[coveralls-image]: https://img.shields.io/coveralls/blakeembrey/array-flatten.svg?style=flat
|
||||
[coveralls-url]: https://coveralls.io/r/blakeembrey/array-flatten?branch=master
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
declare function flatten <T> (array: flatten.NestedArray<T>): T[];
|
||||
|
||||
declare namespace flatten {
|
||||
export interface NestedArray <T> extends ReadonlyArray<T | NestedArray<T>> {}
|
||||
|
||||
export interface NestedList <T> {
|
||||
[index: number]: T | NestedList<T>;
|
||||
length: number;
|
||||
}
|
||||
|
||||
export function from <T> (array: NestedList<T>): T[];
|
||||
export function depth <T> (array: NestedArray<T>, depth: number): NestedArray<T>;
|
||||
export function depthFrom <T> (array: NestedList<T>, depth: number): NestedArray<T>;
|
||||
}
|
||||
|
||||
export = flatten;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Expose `arrayFlatten`.
|
||||
*/
|
||||
module.exports = flatten
|
||||
module.exports.from = flattenFrom
|
||||
module.exports.depth = flattenDepth
|
||||
module.exports.fromDepth = flattenFromDepth
|
||||
|
||||
/**
|
||||
* Flatten an array.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @return {Array}
|
||||
*/
|
||||
function flatten (array) {
|
||||
if (!Array.isArray(array)) {
|
||||
throw new TypeError('Expected value to be an array')
|
||||
}
|
||||
|
||||
return flattenFrom(array)
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array-like structure.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @return {Array}
|
||||
*/
|
||||
function flattenFrom (array) {
|
||||
return flattenDown(array, [])
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array-like structure with depth.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @param {number} depth
|
||||
* @return {Array}
|
||||
*/
|
||||
function flattenDepth (array, depth) {
|
||||
if (!Array.isArray(array)) {
|
||||
throw new TypeError('Expected value to be an array')
|
||||
}
|
||||
|
||||
return flattenFromDepth(array, depth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array-like structure with depth.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @param {number} depth
|
||||
* @return {Array}
|
||||
*/
|
||||
function flattenFromDepth (array, depth) {
|
||||
if (typeof depth !== 'number') {
|
||||
throw new TypeError('Expected the depth to be a number')
|
||||
}
|
||||
|
||||
return flattenDownDepth(array, [], depth)
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array indefinitely.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @param {Array} result
|
||||
* @return {Array}
|
||||
*/
|
||||
function flattenDown (array, result) {
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var value = array[i]
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
flattenDown(value, result)
|
||||
} else {
|
||||
result.push(value)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten an array with depth.
|
||||
*
|
||||
* @param {Array} array
|
||||
* @param {Array} result
|
||||
* @param {number} depth
|
||||
* @return {Array}
|
||||
*/
|
||||
function flattenDownDepth (array, result, depth) {
|
||||
depth--
|
||||
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var value = array[i]
|
||||
|
||||
if (depth > -1 && Array.isArray(value)) {
|
||||
flattenDownDepth(value, result, depth)
|
||||
} else {
|
||||
result.push(value)
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"name": "array-flatten",
|
||||
"version": "2.1.2",
|
||||
"description": "Flatten nested arrays",
|
||||
"main": "array-flatten.js",
|
||||
"typings": "array-flatten.d.ts",
|
||||
"files": [
|
||||
"array-flatten.js",
|
||||
"array-flatten.d.ts",
|
||||
"LICENSE"
|
||||
],
|
||||
"scripts": {
|
||||
"lint": "standard",
|
||||
"test-spec": "mocha -R spec --bail",
|
||||
"test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- -R spec --bail",
|
||||
"test": "npm run lint && npm run test-cov",
|
||||
"benchmark": "node benchmark"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/blakeembrey/array-flatten.git"
|
||||
},
|
||||
"keywords": [
|
||||
"array",
|
||||
"flatten",
|
||||
"arguments",
|
||||
"depth",
|
||||
"fast",
|
||||
"for"
|
||||
],
|
||||
"author": {
|
||||
"name": "Blake Embrey",
|
||||
"email": "hello@blakeembrey.com",
|
||||
"url": "http://blakeembrey.me"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/blakeembrey/array-flatten/issues"
|
||||
},
|
||||
"homepage": "https://github.com/blakeembrey/array-flatten",
|
||||
"devDependencies": {
|
||||
"benchmarked": "^2.0.0",
|
||||
"istanbul": "^0.4.0",
|
||||
"mocha": "^3.1.2",
|
||||
"standard": "^10.0.0"
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
Create an array of unique values, in order, from the input arrays.
|
||||
|
||||
@example
|
||||
```
|
||||
import arrayUnion = require('array-union');
|
||||
|
||||
arrayUnion([1, 1, 2, 3], [2, 3]);
|
||||
//=> [1, 2, 3]
|
||||
|
||||
arrayUnion(['foo', 'foo', 'bar']);
|
||||
//=> ['foo', 'bar']
|
||||
|
||||
arrayUnion(['🐱', '🦄', '🐻'], ['🦄', '🌈']);
|
||||
//=> ['🐱', '🦄', '🐻', '🌈']
|
||||
|
||||
arrayUnion(['🐱', '🦄'], ['🐻', '🦄'], ['🐶', '🌈', '🌈']);
|
||||
//=> ['🐱', '🦄', '🐻', '🐶', '🌈']
|
||||
```
|
||||
*/
|
||||
declare function arrayUnion<ArgumentsType extends readonly unknown[]>(
|
||||
...arguments: readonly ArgumentsType[]
|
||||
): ArgumentsType;
|
||||
|
||||
export = arrayUnion;
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = (...arguments_) => {
|
||||
return [...new Set([].concat(...arguments_))];
|
||||
};
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
MIT License
|
||||
|
||||
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.
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "array-union",
|
||||
"version": "2.1.0",
|
||||
"description": "Create an array of unique values, in order, from the input arrays",
|
||||
"license": "MIT",
|
||||
"repository": "sindresorhus/array-union",
|
||||
"author": {
|
||||
"name": "Sindre Sorhus",
|
||||
"email": "sindresorhus@gmail.com",
|
||||
"url": "sindresorhus.com"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "xo && ava && tsd"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts"
|
||||
],
|
||||
"keywords": [
|
||||
"array",
|
||||
"set",
|
||||
"uniq",
|
||||
"unique",
|
||||
"duplicate",
|
||||
"remove",
|
||||
"union",
|
||||
"combine",
|
||||
"merge"
|
||||
],
|
||||
"devDependencies": {
|
||||
"ava": "^1.4.1",
|
||||
"tsd": "^0.7.2",
|
||||
"xo": "^0.24.0"
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
# array-union [](https://travis-ci.org/sindresorhus/array-union)
|
||||
|
||||
> Create an array of unique values, in order, from the input arrays
|
||||
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
$ npm install array-union
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```js
|
||||
const arrayUnion = require('array-union');
|
||||
|
||||
arrayUnion([1, 1, 2, 3], [2, 3]);
|
||||
//=> [1, 2, 3]
|
||||
|
||||
arrayUnion(['foo', 'foo', 'bar']);
|
||||
//=> ['foo', 'bar']
|
||||
|
||||
arrayUnion(['🐱', '🦄', '🐻'], ['🦄', '🌈']);
|
||||
//=> ['🐱', '🦄', '🐻', '🌈']
|
||||
|
||||
arrayUnion(['🐱', '🦄'], ['🐻', '🦄'], ['🐶', '🌈', '🌈']);
|
||||
//=> ['🐱', '🦄', '🐻', '🐶', '🌈']
|
||||
```
|
||||
|
||||
|
||||
## License
|
||||
|
||||
MIT © [Sindre Sorhus](https://sindresorhus.com)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# History
|
||||
----
|
||||
|
||||
## 1.8.0 / 2017-08-16
|
||||
|
||||
- validator support return promise.
|
||||
|
||||
## 1.7.0 / 2017-06/09
|
||||
|
||||
- add es
|
||||
- support string patter
|
||||
|
||||
## 1.6.0 / 2016-03-30
|
||||
|
||||
- support defaultField
|
||||
|
||||
## 1.5.0 / 2016-02-02
|
||||
|
||||
- support deep merge with default messages
|
||||
- support rule message of any type(exp: jsx)
|
||||
|
||||
## 1.4.0 / 2015-01-12
|
||||
|
||||
- fix first option.
|
||||
- add firstFields option.
|
||||
- see tests/validator.spec.js
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-present yiminghe
|
||||
|
||||
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.
|
||||
+365
@@ -0,0 +1,365 @@
|
||||
# async-validator
|
||||
---
|
||||
|
||||
Validate form asynchronous. A variation of https://github.com/freeformsystems/async-validate
|
||||
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![build status][travis-image]][travis-url]
|
||||
[![Test coverage][coveralls-image]][coveralls-url]
|
||||
[![gemnasium deps][gemnasium-image]][gemnasium-url]
|
||||
[![node version][node-image]][node-url]
|
||||
[![npm download][download-image]][download-url]
|
||||
|
||||
[npm-image]: http://img.shields.io/npm/v/async-validator.svg?style=flat-square
|
||||
[npm-url]: http://npmjs.org/package/async-validator
|
||||
[travis-image]: https://img.shields.io/travis/yiminghe/async-validator.svg?style=flat-square
|
||||
[travis-url]: https://travis-ci.org/yiminghe/async-validator
|
||||
[coveralls-image]: https://img.shields.io/coveralls/yiminghe/async-validator.svg?style=flat-square
|
||||
[coveralls-url]: https://coveralls.io/r/yiminghe/async-validator?branch=master
|
||||
[gemnasium-image]: http://img.shields.io/gemnasium/yiminghe/async-validator.svg?style=flat-square
|
||||
[gemnasium-url]: https://gemnasium.com/yiminghe/async-validator
|
||||
[node-image]: https://img.shields.io/badge/node.js-%3E=4.0.0-green.svg?style=flat-square
|
||||
[node-url]: http://nodejs.org/download/
|
||||
[download-image]: https://img.shields.io/npm/dm/async-validator.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/async-validator
|
||||
|
||||
|
||||
## API
|
||||
|
||||
The following is modified from earlier version of [async-validate](https://github.com/freeformsystems/async-validate).
|
||||
|
||||
### Usage
|
||||
|
||||
Basic usage involves defining a descriptor, assigning it to a schema and passing the object to be validated and a callback function to the `validate` method of the schema:
|
||||
|
||||
```javascript
|
||||
var schema = require('async-validator');
|
||||
var descriptor = {
|
||||
name: {type: "string", required: true}
|
||||
}
|
||||
var validator = new schema(descriptor);
|
||||
validator.validate({name: "muji"}, (errors, fields) => {
|
||||
if(errors) {
|
||||
// validation failed, errors is an array of all errors
|
||||
// fields is an object keyed by field name with an array of
|
||||
// errors per field
|
||||
return handleErrors(errors, fields);
|
||||
}
|
||||
// validation passed
|
||||
});
|
||||
```
|
||||
|
||||
### Validate
|
||||
|
||||
```javascript
|
||||
function(source, [options], callback)
|
||||
```
|
||||
|
||||
* `source`: The object to validate (required).
|
||||
* `options`: An object describing processing options for the validation (optional).
|
||||
* `callback`: A callback function to invoke when validation completes (required).
|
||||
|
||||
### Options
|
||||
|
||||
* `first`: Boolean, Invoke `callback` when the first validation rule generates an error,
|
||||
no more validation rules are processed.
|
||||
If your validation involves multiple asynchronous calls (for example, database queries) and you only need the first error use this option.
|
||||
|
||||
* `firstFields`: Boolean|String[], Invoke `callback` when the first validation rule of the specified field generates an error,
|
||||
no more validation rules of the same field are processed. `true` means all fields.
|
||||
|
||||
### Rules
|
||||
|
||||
Rules may be functions that perform validation.
|
||||
|
||||
```javascript
|
||||
function(rule, value, callback, source, options)
|
||||
```
|
||||
|
||||
* `rule`: The validation rule in the source descriptor that corresponds to the field name being validated. It is always assigned a `field` property with the name of the field being validated.
|
||||
* `value`: The value of the source object property being validated.
|
||||
* `callback`: A callback function to invoke once validation is complete. It expects to be passed an array of `Error` instances to indicate validation failure.
|
||||
* `source`: The source object that was passed to the `validate` method.
|
||||
* `options`: Additional options.
|
||||
* `options.messages`: The object containing validation error messages, will be deep merged with defaultMessages.
|
||||
|
||||
The options passed to `validate` are passed on to the validation functions so that you may reference transient data (such as model references) in validation functions. However, some option names are reserved; if you use these properties of the options object they are overwritten. The reserved properties are `messages`, `exception` and `error`.
|
||||
|
||||
```javascript
|
||||
var schema = require('async-validator');
|
||||
var descriptor = {
|
||||
name(rule, value, callback, source, options) {
|
||||
var errors = [];
|
||||
if(!/^[a-z0-9]+$/.test(value)) {
|
||||
errors.push(
|
||||
new Error(
|
||||
util.format("%s must be lowercase alphanumeric characters",
|
||||
rule.field)));
|
||||
}
|
||||
callback(errors);
|
||||
}
|
||||
}
|
||||
var validator = new schema(descriptor);
|
||||
validator.validate({name: "Firstname"}, (errors, fields) => {
|
||||
if(errors) {
|
||||
return handleErrors(errors, fields);
|
||||
}
|
||||
// validation passed
|
||||
});
|
||||
```
|
||||
|
||||
It is often useful to test against multiple validation rules for a single field, to do so make the rule an array of objects, for example:
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
email: [
|
||||
{type: "string", required: true, pattern: schema.pattern.email},
|
||||
{validator(rule, value, callback, source, options) {
|
||||
var errors = [];
|
||||
// test if email address already exists in a database
|
||||
// and add a validation error to the errors array if it does
|
||||
callback(errors);
|
||||
}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Type
|
||||
|
||||
Indicates the `type` of validator to use. Recognised type values are:
|
||||
|
||||
* `string`: Must be of type `string`. `This is the default type.`
|
||||
* `number`: Must be of type `number`.
|
||||
* `boolean`: Must be of type `boolean`.
|
||||
* `method`: Must be of type `function`.
|
||||
* `regexp`: Must be an instance of `RegExp` or a string that does not generate an exception when creating a new `RegExp`.
|
||||
* `integer`: Must be of type `number` and an integer.
|
||||
* `float`: Must be of type `number` and a floating point number.
|
||||
* `array`: Must be an array as determined by `Array.isArray`.
|
||||
* `object`: Must be of type `object` and not `Array.isArray`.
|
||||
* `enum`: Value must exist in the `enum`.
|
||||
* `date`: Value must be valid as determined by `Date`
|
||||
* `url`: Must be of type `url`.
|
||||
* `hex`: Must be of type `hex`.
|
||||
* `email`: Must be of type `email`.
|
||||
|
||||
#### Required
|
||||
|
||||
The `required` rule property indicates that the field must exist on the source object being validated.
|
||||
|
||||
#### Pattern
|
||||
|
||||
The `pattern` rule property indicates a regular expression that the value must match to pass validation.
|
||||
|
||||
#### Range
|
||||
|
||||
A range is defined using the `min` and `max` properties. For `string` and `array` types comparison is performed against the `length`, for `number` types the number must not be less than `min` nor greater than `max`.
|
||||
|
||||
#### Length
|
||||
|
||||
To validate an exact length of a field specify the `len` property. For `string` and `array` types comparison is performed on the `length` property, for the `number` type this property indicates an exact match for the `number`, ie, it may only be strictly equal to `len`.
|
||||
|
||||
If the `len` property is combined with the `min` and `max` range properties, `len` takes precedence.
|
||||
|
||||
#### Enumerable
|
||||
|
||||
To validate a value from a list of possible values use the `enum` type with a `enum` property listing the valid values for the field, for example:
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
role: {type: "enum", enum: ['admin', 'user', 'guest']}
|
||||
}
|
||||
```
|
||||
|
||||
#### Whitespace
|
||||
|
||||
It is typical to treat required fields that only contain whitespace as errors. To add an additional test for a string that consists solely of whitespace add a `whitespace` property to a rule with a value of `true`. The rule must be a `string` type.
|
||||
|
||||
You may wish to sanitize user input instead of testing for whitespace, see [transform](#transform) for an example that would allow you to strip whitespace.
|
||||
|
||||
|
||||
#### Deep Rules
|
||||
|
||||
If you need to validate deep object properties you may do so for validation rules that are of the `object` or `array` type by assigning nested rules to a `fields` property of the rule.
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
address: {
|
||||
type: "object", required: true,
|
||||
fields: {
|
||||
street: {type: "string", required: true},
|
||||
city: {type: "string", required: true},
|
||||
zip: {type: "string", required: true, len: 8, message: "invalid zip"}
|
||||
}
|
||||
},
|
||||
name: {type: "string", required: true}
|
||||
}
|
||||
var validator = new schema(descriptor);
|
||||
validator.validate({ address: {} }, (errors, fields) => {
|
||||
// errors for street, address.city, address.zip and address.name
|
||||
});
|
||||
```
|
||||
|
||||
Note that if you do not specify the `required` property on the parent rule it is perfectly valid for the field not to be declared on the source object and the deep validation rules will not be executed as there is nothing to validate against.
|
||||
|
||||
Deep rule validation creates a schema for the nested rules so you can also specify the `options` passed to the `schema.validate()` method.
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
address: {
|
||||
type: "object", required: true, options: {single: true, first: true},
|
||||
fields: {
|
||||
street: {type: "string", required: true},
|
||||
city: {type: "string", required: true},
|
||||
zip: {type: "string", required: true, len: 8, message: "invalid zip"}
|
||||
}
|
||||
},
|
||||
name: {type: "string", required: true}
|
||||
}
|
||||
var validator = new schema(descriptor);
|
||||
validator.validate({ address: {} }, (errors, fields) => {
|
||||
// now only errors for street and name
|
||||
});
|
||||
```
|
||||
|
||||
The parent rule is also validated so if you have a set of rules such as:
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
roles: {
|
||||
type: "array", required: true, len: 3,
|
||||
fields: {
|
||||
0: {type: "string", required: true},
|
||||
1: {type: "string", required: true},
|
||||
2: {type: "string", required: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And supply a source object of `{roles: ["admin", "user"]}` then two errors will be created. One for the array length mismatch and one for the missing required array entry at index 2.
|
||||
|
||||
#### defaultField
|
||||
|
||||
The `defaultField` property can be used with the `array` or `object` type for validating all values of the container.
|
||||
It may be an `object` or `array` containing validation rules. For example:
|
||||
|
||||
```javascript
|
||||
var descriptor = {
|
||||
urls: {
|
||||
type: "array", required: true,
|
||||
defaultField: {type: "url"}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Note that `defaultField` is expanded to `fields`, see [deep rules](#deep-rules).
|
||||
|
||||
#### Transform
|
||||
|
||||
Sometimes it is necessary to transform a value before validation, possibly to coerce the value or to sanitize it in some way. To do this add a `transform` function to the validation rule. The property is transformed prior to validation and re-assigned to the source object to mutate the value of the property in place.
|
||||
|
||||
```javascript
|
||||
var schema = require('async-validator');
|
||||
var sanitize = require('validator').sanitize;
|
||||
var descriptor = {
|
||||
name: {
|
||||
type: "string",
|
||||
required: true, pattern: /^[a-z]+$/,
|
||||
transform(value) {
|
||||
return sanitize(value).trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
var validator = new schema(descriptor);
|
||||
var source = {name: " user "};
|
||||
validator.validate(source, (errors, fields) => {
|
||||
assert.equal(source.name, "user");
|
||||
});
|
||||
```
|
||||
|
||||
Without the `transform` function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.
|
||||
|
||||
|
||||
### Messages
|
||||
|
||||
Depending upon your application requirements, you may need i18n support or you may prefer different validation error messages.
|
||||
|
||||
The easiest way to achieve this is to assign a `message` to a rule:
|
||||
|
||||
```javascript
|
||||
{name:{type: "string", required: true, message: "Name is required"}}
|
||||
```
|
||||
|
||||
Message can be any type, such as jsx format.
|
||||
|
||||
```javascript
|
||||
{name:{type: "string", required: true, message: <b>Name is required</b>}}
|
||||
```
|
||||
|
||||
Potentially you may require the same schema validation rules for different languages, in which case duplicating the schema rules for each language does not make sense.
|
||||
|
||||
In this scenario you could just provide your own messages for the language and assign it to the schema:
|
||||
|
||||
```javascript
|
||||
var schema = require('async-validator');
|
||||
var cn = {
|
||||
required: '%s 必填',
|
||||
};
|
||||
var descriptor = {name:{type: "string", required: true}};
|
||||
var validator = new schema(descriptor);
|
||||
// deep merge with defaultMessages
|
||||
validator.messages(cn);
|
||||
...
|
||||
```
|
||||
|
||||
If you are defining your own validation functions it is better practice to assign the message strings to a messages object and then access the messages via the `options.messages` property within the validation function.
|
||||
|
||||
### validator
|
||||
|
||||
you can custom validate function for specified field:
|
||||
|
||||
```js
|
||||
const fields = {
|
||||
asyncField:{
|
||||
validator(rule,value,callback){
|
||||
ajax({
|
||||
url:'xx',
|
||||
value:value
|
||||
}).then(function(data){
|
||||
callback();
|
||||
},function(error){
|
||||
callback(new Error(error))
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
promiseField:{
|
||||
validator(rule, value){
|
||||
return ajax({
|
||||
url:'xx',
|
||||
value:value
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Test Case
|
||||
|
||||
```
|
||||
npm test
|
||||
npm run chrome-test
|
||||
```
|
||||
|
||||
## Coverage
|
||||
|
||||
```
|
||||
npm run coverage
|
||||
```
|
||||
|
||||
open coverage/ dir
|
||||
|
||||
## License
|
||||
|
||||
Everything is [MIT](http://en.wikipedia.org/wiki/MIT_License).
|
||||
+262
@@ -0,0 +1,262 @@
|
||||
import _extends from 'babel-runtime/helpers/extends';
|
||||
import _typeof from 'babel-runtime/helpers/typeof';
|
||||
import { format, complementError, asyncMap, warning, deepMerge } from './util';
|
||||
import validators from './validator/';
|
||||
import { messages as defaultMessages, newMessages } from './messages';
|
||||
|
||||
/**
|
||||
* Encapsulates a validation schema.
|
||||
*
|
||||
* @param descriptor An object declaring validation rules
|
||||
* for this schema.
|
||||
*/
|
||||
function Schema(descriptor) {
|
||||
this.rules = null;
|
||||
this._messages = defaultMessages;
|
||||
this.define(descriptor);
|
||||
}
|
||||
|
||||
Schema.prototype = {
|
||||
messages: function messages(_messages) {
|
||||
if (_messages) {
|
||||
this._messages = deepMerge(newMessages(), _messages);
|
||||
}
|
||||
return this._messages;
|
||||
},
|
||||
define: function define(rules) {
|
||||
if (!rules) {
|
||||
throw new Error('Cannot configure a schema with no rules');
|
||||
}
|
||||
if ((typeof rules === 'undefined' ? 'undefined' : _typeof(rules)) !== 'object' || Array.isArray(rules)) {
|
||||
throw new Error('Rules must be an object');
|
||||
}
|
||||
this.rules = {};
|
||||
var z = void 0;
|
||||
var item = void 0;
|
||||
for (z in rules) {
|
||||
if (rules.hasOwnProperty(z)) {
|
||||
item = rules[z];
|
||||
this.rules[z] = Array.isArray(item) ? item : [item];
|
||||
}
|
||||
}
|
||||
},
|
||||
validate: function validate(source_) {
|
||||
var _this = this;
|
||||
|
||||
var o = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
||||
var oc = arguments[2];
|
||||
|
||||
var source = source_;
|
||||
var options = o;
|
||||
var callback = oc;
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
}
|
||||
if (!this.rules || Object.keys(this.rules).length === 0) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
function complete(results) {
|
||||
var i = void 0;
|
||||
var field = void 0;
|
||||
var errors = [];
|
||||
var fields = {};
|
||||
|
||||
function add(e) {
|
||||
if (Array.isArray(e)) {
|
||||
errors = errors.concat.apply(errors, e);
|
||||
} else {
|
||||
errors.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < results.length; i++) {
|
||||
add(results[i]);
|
||||
}
|
||||
if (!errors.length) {
|
||||
errors = null;
|
||||
fields = null;
|
||||
} else {
|
||||
for (i = 0; i < errors.length; i++) {
|
||||
field = errors[i].field;
|
||||
fields[field] = fields[field] || [];
|
||||
fields[field].push(errors[i]);
|
||||
}
|
||||
}
|
||||
callback(errors, fields);
|
||||
}
|
||||
|
||||
if (options.messages) {
|
||||
var messages = this.messages();
|
||||
if (messages === defaultMessages) {
|
||||
messages = newMessages();
|
||||
}
|
||||
deepMerge(messages, options.messages);
|
||||
options.messages = messages;
|
||||
} else {
|
||||
options.messages = this.messages();
|
||||
}
|
||||
var arr = void 0;
|
||||
var value = void 0;
|
||||
var series = {};
|
||||
var keys = options.keys || Object.keys(this.rules);
|
||||
keys.forEach(function (z) {
|
||||
arr = _this.rules[z];
|
||||
value = source[z];
|
||||
arr.forEach(function (r) {
|
||||
var rule = r;
|
||||
if (typeof rule.transform === 'function') {
|
||||
if (source === source_) {
|
||||
source = _extends({}, source);
|
||||
}
|
||||
value = source[z] = rule.transform(value);
|
||||
}
|
||||
if (typeof rule === 'function') {
|
||||
rule = {
|
||||
validator: rule
|
||||
};
|
||||
} else {
|
||||
rule = _extends({}, rule);
|
||||
}
|
||||
rule.validator = _this.getValidationMethod(rule);
|
||||
rule.field = z;
|
||||
rule.fullField = rule.fullField || z;
|
||||
rule.type = _this.getType(rule);
|
||||
if (!rule.validator) {
|
||||
return;
|
||||
}
|
||||
series[z] = series[z] || [];
|
||||
series[z].push({
|
||||
rule: rule,
|
||||
value: value,
|
||||
source: source,
|
||||
field: z
|
||||
});
|
||||
});
|
||||
});
|
||||
var errorFields = {};
|
||||
asyncMap(series, options, function (data, doIt) {
|
||||
var rule = data.rule;
|
||||
var deep = (rule.type === 'object' || rule.type === 'array') && (_typeof(rule.fields) === 'object' || _typeof(rule.defaultField) === 'object');
|
||||
deep = deep && (rule.required || !rule.required && data.value);
|
||||
rule.field = data.field;
|
||||
function addFullfield(key, schema) {
|
||||
return _extends({}, schema, {
|
||||
fullField: rule.fullField + '.' + key
|
||||
});
|
||||
}
|
||||
|
||||
function cb() {
|
||||
var e = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
|
||||
|
||||
var errors = e;
|
||||
if (!Array.isArray(errors)) {
|
||||
errors = [errors];
|
||||
}
|
||||
if (errors.length) {
|
||||
warning('async-validator:', errors);
|
||||
}
|
||||
if (errors.length && rule.message) {
|
||||
errors = [].concat(rule.message);
|
||||
}
|
||||
|
||||
errors = errors.map(complementError(rule));
|
||||
|
||||
if (options.first && errors.length) {
|
||||
errorFields[rule.field] = 1;
|
||||
return doIt(errors);
|
||||
}
|
||||
if (!deep) {
|
||||
doIt(errors);
|
||||
} else {
|
||||
// if rule is required but the target object
|
||||
// does not exist fail at the rule level and don't
|
||||
// go deeper
|
||||
if (rule.required && !data.value) {
|
||||
if (rule.message) {
|
||||
errors = [].concat(rule.message).map(complementError(rule));
|
||||
} else if (options.error) {
|
||||
errors = [options.error(rule, format(options.messages.required, rule.field))];
|
||||
} else {
|
||||
errors = [];
|
||||
}
|
||||
return doIt(errors);
|
||||
}
|
||||
|
||||
var fieldsSchema = {};
|
||||
if (rule.defaultField) {
|
||||
for (var k in data.value) {
|
||||
if (data.value.hasOwnProperty(k)) {
|
||||
fieldsSchema[k] = rule.defaultField;
|
||||
}
|
||||
}
|
||||
}
|
||||
fieldsSchema = _extends({}, fieldsSchema, data.rule.fields);
|
||||
for (var f in fieldsSchema) {
|
||||
if (fieldsSchema.hasOwnProperty(f)) {
|
||||
var fieldSchema = Array.isArray(fieldsSchema[f]) ? fieldsSchema[f] : [fieldsSchema[f]];
|
||||
fieldsSchema[f] = fieldSchema.map(addFullfield.bind(null, f));
|
||||
}
|
||||
}
|
||||
var schema = new Schema(fieldsSchema);
|
||||
schema.messages(options.messages);
|
||||
if (data.rule.options) {
|
||||
data.rule.options.messages = options.messages;
|
||||
data.rule.options.error = options.error;
|
||||
}
|
||||
schema.validate(data.value, data.rule.options || options, function (errs) {
|
||||
doIt(errs && errs.length ? errors.concat(errs) : errs);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var res = rule.validator(rule, data.value, cb, data.source, options);
|
||||
if (res && res.then) {
|
||||
res.then(function () {
|
||||
return cb();
|
||||
}, function (e) {
|
||||
return cb(e);
|
||||
});
|
||||
}
|
||||
}, function (results) {
|
||||
complete(results);
|
||||
});
|
||||
},
|
||||
getType: function getType(rule) {
|
||||
if (rule.type === undefined && rule.pattern instanceof RegExp) {
|
||||
rule.type = 'pattern';
|
||||
}
|
||||
if (typeof rule.validator !== 'function' && rule.type && !validators.hasOwnProperty(rule.type)) {
|
||||
throw new Error(format('Unknown rule type %s', rule.type));
|
||||
}
|
||||
return rule.type || 'string';
|
||||
},
|
||||
getValidationMethod: function getValidationMethod(rule) {
|
||||
if (typeof rule.validator === 'function') {
|
||||
return rule.validator;
|
||||
}
|
||||
var keys = Object.keys(rule);
|
||||
var messageIndex = keys.indexOf('message');
|
||||
if (messageIndex !== -1) {
|
||||
keys.splice(messageIndex, 1);
|
||||
}
|
||||
if (keys.length === 1 && keys[0] === 'required') {
|
||||
return validators.required;
|
||||
}
|
||||
return validators[this.getType(rule)] || false;
|
||||
}
|
||||
};
|
||||
|
||||
Schema.register = function register(type, validator) {
|
||||
if (typeof validator !== 'function') {
|
||||
throw new Error('Cannot register a validator by type, validator is not a function');
|
||||
}
|
||||
validators[type] = validator;
|
||||
};
|
||||
|
||||
Schema.messages = defaultMessages;
|
||||
|
||||
export default Schema;
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
export function newMessages() {
|
||||
return {
|
||||
'default': 'Validation error on field %s',
|
||||
required: '%s is required',
|
||||
'enum': '%s must be one of %s',
|
||||
whitespace: '%s cannot be empty',
|
||||
date: {
|
||||
format: '%s date %s is invalid for format %s',
|
||||
parse: '%s date could not be parsed, %s is invalid ',
|
||||
invalid: '%s date %s is invalid'
|
||||
},
|
||||
types: {
|
||||
string: '%s is not a %s',
|
||||
method: '%s is not a %s (function)',
|
||||
array: '%s is not an %s',
|
||||
object: '%s is not an %s',
|
||||
number: '%s is not a %s',
|
||||
date: '%s is not a %s',
|
||||
boolean: '%s is not a %s',
|
||||
integer: '%s is not an %s',
|
||||
float: '%s is not a %s',
|
||||
regexp: '%s is not a valid %s',
|
||||
email: '%s is not a valid %s',
|
||||
url: '%s is not a valid %s',
|
||||
hex: '%s is not a valid %s'
|
||||
},
|
||||
string: {
|
||||
len: '%s must be exactly %s characters',
|
||||
min: '%s must be at least %s characters',
|
||||
max: '%s cannot be longer than %s characters',
|
||||
range: '%s must be between %s and %s characters'
|
||||
},
|
||||
number: {
|
||||
len: '%s must equal %s',
|
||||
min: '%s cannot be less than %s',
|
||||
max: '%s cannot be greater than %s',
|
||||
range: '%s must be between %s and %s'
|
||||
},
|
||||
array: {
|
||||
len: '%s must be exactly %s in length',
|
||||
min: '%s cannot be less than %s in length',
|
||||
max: '%s cannot be greater than %s in length',
|
||||
range: '%s must be between %s and %s in length'
|
||||
},
|
||||
pattern: {
|
||||
mismatch: '%s value %s does not match pattern %s'
|
||||
},
|
||||
clone: function clone() {
|
||||
var cloned = JSON.parse(JSON.stringify(this));
|
||||
cloned.clone = this.clone;
|
||||
return cloned;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export var messages = newMessages();
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import * as util from '../util';
|
||||
var ENUM = 'enum';
|
||||
|
||||
/**
|
||||
* Rule for validating a value exists in an enumerable list.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function enumerable(rule, value, source, errors, options) {
|
||||
rule[ENUM] = Array.isArray(rule[ENUM]) ? rule[ENUM] : [];
|
||||
if (rule[ENUM].indexOf(value) === -1) {
|
||||
errors.push(util.format(options.messages[ENUM], rule.fullField, rule[ENUM].join(', ')));
|
||||
}
|
||||
}
|
||||
|
||||
export default enumerable;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import required from './required';
|
||||
import whitespace from './whitespace';
|
||||
import type from './type';
|
||||
import range from './range';
|
||||
import enumRule from './enum';
|
||||
import pattern from './pattern';
|
||||
|
||||
export default {
|
||||
required: required,
|
||||
whitespace: whitespace,
|
||||
type: type,
|
||||
range: range,
|
||||
'enum': enumRule,
|
||||
pattern: pattern
|
||||
};
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import * as util from '../util';
|
||||
|
||||
/**
|
||||
* Rule for validating a regular expression pattern.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function pattern(rule, value, source, errors, options) {
|
||||
if (rule.pattern) {
|
||||
if (rule.pattern instanceof RegExp) {
|
||||
// if a RegExp instance is passed, reset `lastIndex` in case its `global`
|
||||
// flag is accidentally set to `true`, which in a validation scenario
|
||||
// is not necessary and the result might be misleading
|
||||
rule.pattern.lastIndex = 0;
|
||||
if (!rule.pattern.test(value)) {
|
||||
errors.push(util.format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));
|
||||
}
|
||||
} else if (typeof rule.pattern === 'string') {
|
||||
var _pattern = new RegExp(rule.pattern);
|
||||
if (!_pattern.test(value)) {
|
||||
errors.push(util.format(options.messages.pattern.mismatch, rule.fullField, value, rule.pattern));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default pattern;
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
import * as util from '../util';
|
||||
|
||||
/**
|
||||
* Rule for validating minimum and maximum allowed values.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function range(rule, value, source, errors, options) {
|
||||
var len = typeof rule.len === 'number';
|
||||
var min = typeof rule.min === 'number';
|
||||
var max = typeof rule.max === 'number';
|
||||
// 正则匹配码点范围从U+010000一直到U+10FFFF的文字(补充平面Supplementary Plane)
|
||||
var spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
||||
var val = value;
|
||||
var key = null;
|
||||
var num = typeof value === 'number';
|
||||
var str = typeof value === 'string';
|
||||
var arr = Array.isArray(value);
|
||||
if (num) {
|
||||
key = 'number';
|
||||
} else if (str) {
|
||||
key = 'string';
|
||||
} else if (arr) {
|
||||
key = 'array';
|
||||
}
|
||||
// if the value is not of a supported type for range validation
|
||||
// the validation rule rule should use the
|
||||
// type property to also test for a particular type
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
if (arr) {
|
||||
val = value.length;
|
||||
}
|
||||
if (str) {
|
||||
// 处理码点大于U+010000的文字length属性不准确的bug,如"𠮷𠮷𠮷".lenght !== 3
|
||||
val = value.replace(spRegexp, '_').length;
|
||||
}
|
||||
if (len) {
|
||||
if (val !== rule.len) {
|
||||
errors.push(util.format(options.messages[key].len, rule.fullField, rule.len));
|
||||
}
|
||||
} else if (min && !max && val < rule.min) {
|
||||
errors.push(util.format(options.messages[key].min, rule.fullField, rule.min));
|
||||
} else if (max && !min && val > rule.max) {
|
||||
errors.push(util.format(options.messages[key].max, rule.fullField, rule.max));
|
||||
} else if (min && max && (val < rule.min || val > rule.max)) {
|
||||
errors.push(util.format(options.messages[key].range, rule.fullField, rule.min, rule.max));
|
||||
}
|
||||
}
|
||||
|
||||
export default range;
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import * as util from '../util';
|
||||
|
||||
/**
|
||||
* Rule for validating required fields.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function required(rule, value, source, errors, options, type) {
|
||||
if (rule.required && (!source.hasOwnProperty(rule.field) || util.isEmptyValue(value, type || rule.type))) {
|
||||
errors.push(util.format(options.messages.required, rule.fullField));
|
||||
}
|
||||
}
|
||||
|
||||
export default required;
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
import _typeof from 'babel-runtime/helpers/typeof';
|
||||
import * as util from '../util';
|
||||
import required from './required';
|
||||
|
||||
/* eslint max-len:0 */
|
||||
|
||||
var pattern = {
|
||||
// http://emailregex.com/
|
||||
email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
||||
url: new RegExp('^(?!mailto:)(?:(?:http|https|ftp)://|//)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$', 'i'),
|
||||
hex: /^#?([a-f0-9]{6}|[a-f0-9]{3})$/i
|
||||
};
|
||||
|
||||
var types = {
|
||||
integer: function integer(value) {
|
||||
return types.number(value) && parseInt(value, 10) === value;
|
||||
},
|
||||
float: function float(value) {
|
||||
return types.number(value) && !types.integer(value);
|
||||
},
|
||||
array: function array(value) {
|
||||
return Array.isArray(value);
|
||||
},
|
||||
regexp: function regexp(value) {
|
||||
if (value instanceof RegExp) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
return !!new RegExp(value);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
date: function date(value) {
|
||||
return typeof value.getTime === 'function' && typeof value.getMonth === 'function' && typeof value.getYear === 'function';
|
||||
},
|
||||
number: function number(value) {
|
||||
if (isNaN(value)) {
|
||||
return false;
|
||||
}
|
||||
return typeof value === 'number';
|
||||
},
|
||||
object: function object(value) {
|
||||
return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && !types.array(value);
|
||||
},
|
||||
method: function method(value) {
|
||||
return typeof value === 'function';
|
||||
},
|
||||
email: function email(value) {
|
||||
return typeof value === 'string' && !!value.match(pattern.email) && value.length < 255;
|
||||
},
|
||||
url: function url(value) {
|
||||
return typeof value === 'string' && !!value.match(pattern.url);
|
||||
},
|
||||
hex: function hex(value) {
|
||||
return typeof value === 'string' && !!value.match(pattern.hex);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Rule for validating the type of a value.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function type(rule, value, source, errors, options) {
|
||||
if (rule.required && value === undefined) {
|
||||
required(rule, value, source, errors, options);
|
||||
return;
|
||||
}
|
||||
var custom = ['integer', 'float', 'array', 'regexp', 'object', 'method', 'email', 'number', 'date', 'url', 'hex'];
|
||||
var ruleType = rule.type;
|
||||
if (custom.indexOf(ruleType) > -1) {
|
||||
if (!types[ruleType](value)) {
|
||||
errors.push(util.format(options.messages.types[ruleType], rule.fullField, rule.type));
|
||||
}
|
||||
// straight typeof check
|
||||
} else if (ruleType && (typeof value === 'undefined' ? 'undefined' : _typeof(value)) !== rule.type) {
|
||||
errors.push(util.format(options.messages.types[ruleType], rule.fullField, rule.type));
|
||||
}
|
||||
}
|
||||
|
||||
export default type;
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
import * as util from '../util';
|
||||
|
||||
/**
|
||||
* Rule for validating whitespace.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param source The source object being validated.
|
||||
* @param errors An array of errors that this rule may add
|
||||
* validation errors to.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function whitespace(rule, value, source, errors, options) {
|
||||
if (/^\s+$/.test(value) || value === '') {
|
||||
errors.push(util.format(options.messages.whitespace, rule.fullField));
|
||||
}
|
||||
}
|
||||
|
||||
export default whitespace;
|
||||
+188
@@ -0,0 +1,188 @@
|
||||
import _extends from 'babel-runtime/helpers/extends';
|
||||
import _typeof from 'babel-runtime/helpers/typeof';
|
||||
var formatRegExp = /%[sdj%]/g;
|
||||
|
||||
export var warning = function warning() {};
|
||||
|
||||
// don't print warning message when in production env or node runtime
|
||||
if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined' && typeof document !== 'undefined') {
|
||||
warning = function warning(type, errors) {
|
||||
if (typeof console !== 'undefined' && console.warn) {
|
||||
if (errors.every(function (e) {
|
||||
return typeof e === 'string';
|
||||
})) {
|
||||
console.warn(type, errors);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function format() {
|
||||
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
|
||||
args[_key] = arguments[_key];
|
||||
}
|
||||
|
||||
var i = 1;
|
||||
var f = args[0];
|
||||
var len = args.length;
|
||||
if (typeof f === 'function') {
|
||||
return f.apply(null, args.slice(1));
|
||||
}
|
||||
if (typeof f === 'string') {
|
||||
var str = String(f).replace(formatRegExp, function (x) {
|
||||
if (x === '%%') {
|
||||
return '%';
|
||||
}
|
||||
if (i >= len) {
|
||||
return x;
|
||||
}
|
||||
switch (x) {
|
||||
case '%s':
|
||||
return String(args[i++]);
|
||||
case '%d':
|
||||
return Number(args[i++]);
|
||||
case '%j':
|
||||
try {
|
||||
return JSON.stringify(args[i++]);
|
||||
} catch (_) {
|
||||
return '[Circular]';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return x;
|
||||
}
|
||||
});
|
||||
for (var arg = args[i]; i < len; arg = args[++i]) {
|
||||
str += ' ' + arg;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
function isNativeStringType(type) {
|
||||
return type === 'string' || type === 'url' || type === 'hex' || type === 'email' || type === 'pattern';
|
||||
}
|
||||
|
||||
export function isEmptyValue(value, type) {
|
||||
if (value === undefined || value === null) {
|
||||
return true;
|
||||
}
|
||||
if (type === 'array' && Array.isArray(value) && !value.length) {
|
||||
return true;
|
||||
}
|
||||
if (isNativeStringType(type) && typeof value === 'string' && !value) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isEmptyObject(obj) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
|
||||
function asyncParallelArray(arr, func, callback) {
|
||||
var results = [];
|
||||
var total = 0;
|
||||
var arrLength = arr.length;
|
||||
|
||||
function count(errors) {
|
||||
results.push.apply(results, errors);
|
||||
total++;
|
||||
if (total === arrLength) {
|
||||
callback(results);
|
||||
}
|
||||
}
|
||||
|
||||
arr.forEach(function (a) {
|
||||
func(a, count);
|
||||
});
|
||||
}
|
||||
|
||||
function asyncSerialArray(arr, func, callback) {
|
||||
var index = 0;
|
||||
var arrLength = arr.length;
|
||||
|
||||
function next(errors) {
|
||||
if (errors && errors.length) {
|
||||
callback(errors);
|
||||
return;
|
||||
}
|
||||
var original = index;
|
||||
index = index + 1;
|
||||
if (original < arrLength) {
|
||||
func(arr[original], next);
|
||||
} else {
|
||||
callback([]);
|
||||
}
|
||||
}
|
||||
|
||||
next([]);
|
||||
}
|
||||
|
||||
function flattenObjArr(objArr) {
|
||||
var ret = [];
|
||||
Object.keys(objArr).forEach(function (k) {
|
||||
ret.push.apply(ret, objArr[k]);
|
||||
});
|
||||
return ret;
|
||||
}
|
||||
|
||||
export function asyncMap(objArr, option, func, callback) {
|
||||
if (option.first) {
|
||||
var flattenArr = flattenObjArr(objArr);
|
||||
return asyncSerialArray(flattenArr, func, callback);
|
||||
}
|
||||
var firstFields = option.firstFields || [];
|
||||
if (firstFields === true) {
|
||||
firstFields = Object.keys(objArr);
|
||||
}
|
||||
var objArrKeys = Object.keys(objArr);
|
||||
var objArrLength = objArrKeys.length;
|
||||
var total = 0;
|
||||
var results = [];
|
||||
var next = function next(errors) {
|
||||
results.push.apply(results, errors);
|
||||
total++;
|
||||
if (total === objArrLength) {
|
||||
callback(results);
|
||||
}
|
||||
};
|
||||
objArrKeys.forEach(function (key) {
|
||||
var arr = objArr[key];
|
||||
if (firstFields.indexOf(key) !== -1) {
|
||||
asyncSerialArray(arr, func, next);
|
||||
} else {
|
||||
asyncParallelArray(arr, func, next);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function complementError(rule) {
|
||||
return function (oe) {
|
||||
if (oe && oe.message) {
|
||||
oe.field = oe.field || rule.fullField;
|
||||
return oe;
|
||||
}
|
||||
return {
|
||||
message: oe,
|
||||
field: oe.field || rule.fullField
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function deepMerge(target, source) {
|
||||
if (source) {
|
||||
for (var s in source) {
|
||||
if (source.hasOwnProperty(s)) {
|
||||
var value = source[s];
|
||||
if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && _typeof(target[s]) === 'object') {
|
||||
target[s] = _extends({}, target[s], value);
|
||||
} else {
|
||||
target[s] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import rules from '../rule/';
|
||||
import { isEmptyValue } from '../util';
|
||||
/**
|
||||
* Validates an array.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param callback The callback function.
|
||||
* @param source The source object being validated.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function array(rule, value, callback, source, options) {
|
||||
var errors = [];
|
||||
var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
|
||||
if (validate) {
|
||||
if (isEmptyValue(value, 'array') && !rule.required) {
|
||||
return callback();
|
||||
}
|
||||
rules.required(rule, value, source, errors, options, 'array');
|
||||
if (!isEmptyValue(value, 'array')) {
|
||||
rules.type(rule, value, source, errors, options);
|
||||
rules.range(rule, value, source, errors, options);
|
||||
}
|
||||
}
|
||||
callback(errors);
|
||||
}
|
||||
|
||||
export default array;
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import { isEmptyValue } from '../util';
|
||||
import rules from '../rule/';
|
||||
|
||||
/**
|
||||
* Validates a boolean.
|
||||
*
|
||||
* @param rule The validation rule.
|
||||
* @param value The value of the field on the source object.
|
||||
* @param callback The callback function.
|
||||
* @param source The source object being validated.
|
||||
* @param options The validation options.
|
||||
* @param options.messages The validation messages.
|
||||
*/
|
||||
function boolean(rule, value, callback, source, options) {
|
||||
var errors = [];
|
||||
var validate = rule.required || !rule.required && source.hasOwnProperty(rule.field);
|
||||
if (validate) {
|
||||
if (isEmptyValue(value) && !rule.required) {
|
||||
return callback();
|
||||
}
|
||||
rules.required(rule, value, source, errors, options);
|
||||
if (value !== undefined) {
|
||||
rules.type(rule, value, source, errors, options);
|
||||
}
|
||||
}
|
||||
callback(errors);
|
||||
}
|
||||
|
||||
export default boolean;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user