diff --git a/.eslintignore b/.eslintignore index a16c9d3d..3cdf3bf6 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,3 @@ -node_modules/* -rhino/* templates/default/static/scripts/* test/fixtures/* test/lib/* diff --git a/.gitignore b/.gitignore index d7422917..124599bd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,21 +1,7 @@ # Development-related files .tern-port coverage/ -node_modules/.bin -node_modules/eslint -node_modules/gulp* -node_modules/istanbul - -# Node.js-only modules -node_modules/requizzle - -# Unused files from committed modules -node_modules/bluebird/README.md -node_modules/bluebird/changelog.md -node_modules/bluebird/js/browser/* -node_modules/espree/README.md -node_modules/espree/bin -node_modules/espree/test +/node_modules/ # User-specific files conf.json diff --git a/.npmignore b/.npmignore index aaa8ad0a..d8b16456 100644 --- a/.npmignore +++ b/.npmignore @@ -4,11 +4,4 @@ .gitignore .travis.yml gulpfile.js - -# scripts for launching JSDoc with Mozilla Rhino -/jsdoc* -!/jsdoc.js - -# Rhino and test directories -rhino/ test/ diff --git a/LICENSE.md b/LICENSE.md index 55a84793..2e1c851b 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -145,19 +145,6 @@ Copyright (c) 2011-2015 by the Espree contributors. The source code for Esprima is available at: https://github.com/eslint/espree -## events ## - -Portions of the events source code are incorporated into the following files: - -+ `rhino/events.js` - -events is distributed under the MIT license, which is reproduced above. - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. - -The source code for events is available at: -https://github.com/Gozala/events - ## github-flavored-markdown ## github-flavored-markdown is distributed under the BSD 3-clause license: @@ -234,36 +221,6 @@ Copyright (c) 2012 Michael Kourlas. The source code for js2xmlparser is available at: https://github.com/michaelkourlas/node-js2xmlparser -## Node.js ## - -Portions of the Node.js source code are incorporated into the following files: - -- `rhino/fs.js` -- `rhino/path.js` -- `rhino/querystring.js` -- `rhino/util.js` - -Node.js is distributed under the MIT license, which is reproduced above. - -Copyright Joyent, Inc. and other Node contributors. All rights reserved. - -The source code for Node.js is available at: -https://github.com/joyent/node - -## node-browser-builtins ## - -Portions of the node-browser-builtins source code are incorporated into the -following files: - -- `rhino/assert.js` -- `rhino/rhino-shim.js` - -node-browser-builtins is distributed under the MIT license, which is reproduced -above. - -The source code for node-browser-builtins is available at: -https://github.com/alexgorbatchev/node-browser-builtins - ## Open Sans ## Open Sans is distributed under the Apache License 2.0, which is @@ -284,46 +241,6 @@ Copyright (c) 2012-2013 Johannes Ewald. The source code for Requizzle is available at: https://github.com/hegemonic/requizzle -## Rhino ## - -Rhino is distributed under the following licenses: - -### MPL 2.0 License ### -The majority of the source code for Rhino is available under the Mozilla Public -License (MPL) 2.0, which is included in this distribution. - -### License for portions of the Rhino debugger ### -Additionally, some files are available under the BSD 3-clause license: - -> Copyright 1997, 1998 Sun Microsystems, Inc. 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 Sun Microsystems 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. - -### Source Code ### -The source code for Rhino is available at: -https://github.com/jsdoc3/rhino - ## TaffyDB ## TaffyDB is distributed under a modified BSD license: diff --git a/README.md b/README.md index 0728999d..d008a4d7 100644 --- a/README.md +++ b/README.md @@ -9,17 +9,8 @@ Want to contribute to JSDoc? Please read `CONTRIBUTING.md`. Installation and Usage ---------------------- -You can run JSDoc on either Node.js or Mozilla Rhino. - -### Node.js - -Native support for Node.js is available in JSDoc 3.3.0 and later. JSDoc -supports Node.js 0.10 and later. - -#### Installing JSDoc for Node.js - -You can install JSDoc in your project's `node_modules` folder, or you can -install it globally. +JSDoc supports Node.js 0.10 and later. You can install JSDoc in your project's +`node_modules` folder, or you can install it globally. To install the latest version available on NPM: @@ -29,8 +20,6 @@ To install the latest development version: npm install git+https://github.com/jsdoc3/jsdoc.git -#### Running JSDoc with Node.js - If you installed JSDoc locally, the JSDoc command-line tool is available in `./node_modules/.bin`. To generate documentation for the file `yourJavaScriptFile.js`: @@ -46,47 +35,6 @@ can use the `--destination` (`-d`) option to specify another directory. Run `jsdoc --help` for a complete list of command-line options. -### Mozilla Rhino - -All versions of JSDoc 3 run on a customized version of Mozilla Rhino, which -requires Java. You can run JSDoc 3 on Java 1.6 and later. - -#### Installing JSDoc for Mozilla Rhino - -To install JSDoc, download a .zip file for the -[latest development version](https://github.com/jsdoc3/jsdoc/archive/master.zip) -or a [previous release](https://github.com/jsdoc3/jsdoc/tags). - -You can also use git to clone the -[JSDoc repository](https://github.com/jsdoc3/jsdoc): - - git clone git+https://github.com/jsdoc3/jsdoc.git - -The JSDoc repository includes a -[customized version of Mozilla Rhino](https://github.com/jsdoc3/rhino). Make -sure your Java classpath does not include any other versions of Rhino. (On OS X, -you may need to remove the file `~/Library/Java/Extensions/js.jar`.) - -**Note**: In JSDoc 3.3.0 and later, if you need to run JSDoc on Mozilla Rhino, -do not install JSDoc with npm. Use one of the methods described above. - -#### Running JSDoc with Mozilla Rhino - -On OS X, Linux, and other POSIX systems, to generate documentation for the file -`yourJavaScriptFile.js`: - - ./jsdoc yourJavaScriptFile.js - -Or on Windows: - - jsdoc yourJavaScriptFile.js - -By default, the generated documentation is saved in a directory named `out`. You -can use the `--destination` (`-d`) option to specify another directory. - -Run `jsdoc --help` for a complete list of command-line options. - - Templates and Build Tools ------------------------- diff --git a/cli.js b/cli.js index 3d866f57..c028be3d 100644 --- a/cli.js +++ b/cli.js @@ -6,10 +6,7 @@ * A few critical notes for anyone who works on this module: * * + The module should really export an instance of `cli`, and `props` should be properties of a - * `cli` instance. However, Rhino interpreted `this` as a reference to `global` within the - * prototype's methods, so we couldn't do that. - * + On Rhino, for unknown reasons, the `jsdoc/fs` and `jsdoc/path` modules can fail in some cases - * when they are required by this module. You may need to use `fs` and `path` instead. + * `cli` instance. * * @private */ diff --git a/gulpfile.js b/gulpfile.js index 179a9493..b4800b4a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -31,16 +31,7 @@ var options = { 'test/specs/**/*.js' ], nodeBin: path.resolve(__dirname, './jsdoc.js'), - nodePath: process.execPath, - rhinoBin: (function() { - var filepath = path.resolve(__dirname, './jsdoc'); - - if (os.platform().indexOf('win') === 0) { - filepath += '.cmd'; - } - - return filepath; - })() + nodePath: process.execPath }; gulp.task('bump', function() { @@ -63,20 +54,9 @@ gulp.task('lint', function() { .pipe(eslint.failOnError()); }); -gulp.task('test-node', function(cb) { +gulp.task('test', function(cb) { var cmd = util.format('%s "%s" -T', options.nodePath, options.nodeBin); exec(cmd, execCb.bind(null, cb)); }); -gulp.task('test-rhino', function(cb) { - var cmd = util.format('"%s" -T -q "parser=rhino"', options.rhinoBin); - exec(cmd, execCb.bind(null, cb)); -}); - -gulp.task('test-rhino-jsparser', function(cb) { - var cmd = util.format('"%s" -T -q "parser=js"', options.rhinoBin); - exec(cmd, execCb.bind(null, cb)); -}); - -gulp.task('test', ['test-node', 'test-rhino', 'test-rhino-jsparser']); gulp.task('default', ['lint', 'test']); diff --git a/jsdoc b/jsdoc deleted file mode 100755 index 53c9c8f5..00000000 --- a/jsdoc +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -SOURCE="$0" -while [ -h "$SOURCE" ] ; do - NEXTSOURCE="$(readlink "$SOURCE")" - echo $NEXTSOURCE | grep -q -e "^/" - if [ $? = 0 ]; then - SOURCE="$NEXTSOURCE" - else - SOURCE="$(dirname $SOURCE)/$NEXTSOURCE" - fi -done -# Get a Windows path under MinGW or Cygwin -BASEPATH="$( cd -P "$( dirname "$SOURCE" )" && (pwd -W 2>/dev/null || cygpath -w $(pwd) 2>/dev/null || pwd))" -if [ "${BASEPATH%${BASEPATH#?}}" != "/" ] ; then - BASEPATH="$( echo "$BASEPATH" | sed -e 's@\\@/@g' )" -fi - -if test "$1" = "--debug" -then - CMD="org.mozilla.javascript.tools.debugger.Main -debug -opt -1" -else - CMD="org.mozilla.javascript.tools.shell.Main" -fi - -if test "$1" = "-T" -then - cd -P "$(dirname "$SOURCE")" - java -classpath "${BASEPATH}/rhino/js.jar" ${CMD} -opt -1 -modules "${BASEPATH}/lib" -modules "${BASEPATH}/node_modules" -modules "${BASEPATH}/rhino" -modules "${BASEPATH}" "${BASEPATH}/jsdoc.js" "$@" - -else - java -classpath "${BASEPATH}/rhino/js.jar" ${CMD} -modules "${BASEPATH}/lib" -modules "${BASEPATH}/node_modules" -modules "${BASEPATH}/rhino" -modules "${BASEPATH}" "${BASEPATH}/jsdoc.js" "$@" -fi diff --git a/jsdoc.cmd b/jsdoc.cmd deleted file mode 100644 index 20156cd8..00000000 --- a/jsdoc.cmd +++ /dev/null @@ -1,26 +0,0 @@ -@ECHO OFF - -SETLOCAL - -REM jsdoc.js expects paths without a trailing slash -SET _BASEPATH=%~dp0 -SET _BASEPATH=%_BASEPATH:~0,-1% - -REM we need the ability to resolve paths relative to the user's working -REM directory prior to launching JSDoc -SET PWD=%cd% - -IF [%1]==[--debug] ( - SET CMD=org.mozilla.javascript.tools.debugger.Main -debug -opt -1 -) ELSE ( - SET CMD=org.mozilla.javascript.tools.shell.Main -) -SET ARGS=%* - -IF [%1]==[-T] ( - java -classpath "%_BASEPATH%/rhino/js.jar" %CMD% -opt -1 -modules "%_BASEPATH%/lib" -modules "%_BASEPATH%/node_modules" -modules "%_BASEPATH%/rhino" -modules "%_BASEPATH%" "%_BASEPATH%/jsdoc.js" %ARGS% --nocolor -) ELSE ( - java -classpath "%_BASEPATH%/rhino/js.jar" %CMD% -modules "%_BASEPATH%/lib" -modules "%_BASEPATH%/node_modules" -modules "%_BASEPATH%/rhino" -modules "%_BASEPATH%" "%_BASEPATH%/jsdoc.js" %ARGS% -) - -ENDLOCAL diff --git a/jsdoc.js b/jsdoc.js index 49897b86..414c226f 100755 --- a/jsdoc.js +++ b/jsdoc.js @@ -45,16 +45,7 @@ */ global.env = (function() { 'use strict'; - - // This bit of joy is here because Rhino treats `./lib/jsdoc/env` and `jsdoc/env` as separate - // modules. In contrast, Node.js errors out on `jsdoc/env` because we don't patch `require()` - // until after this file is loaded. - if (require('./lib/jsdoc/util/runtime').isRhino()) { - return require('jsdoc/env'); - } - else { - return require('./lib/jsdoc/env'); - } + return require('./lib/jsdoc/env'); })(); /** @@ -67,14 +58,7 @@ global.env = (function() { */ global.app = (function() { 'use strict'; - - // See comment in `global.env` to find out why we jump through this hoop. - if (require('./lib/jsdoc/util/runtime').isRhino()) { - return require('jsdoc/app'); - } - else { - return require('./lib/jsdoc/app'); - } + return require('./lib/jsdoc/app'); })(); (function() { @@ -102,8 +86,7 @@ global.app = (function() { if (env.opts.debug) { /** * Recursively print an object's properties to stdout. This method is safe to use with - * objects that contain circular references. In addition, on Mozilla Rhino, this method is - * safe to use with native Java objects. + * objects that contain circular references. * * This method is available only when JSDoc is run with the `--debug` option. * @@ -117,21 +100,5 @@ global.app = (function() { }; } - // On Rhino, we use a try/catch block so we can log the Java exception (if available) - if ( runtime.isRhino() ) { - try { - cli.runCommand(cb); - } - catch (e) { - if (e.rhinoException) { - logger.fatal( e.rhinoException.printStackTrace() ); - } else { - console.trace(e); - cli.exit(1); - } - } - } - else { - cli.runCommand(cb); - } + cli.runCommand(cb); })(); diff --git a/lib/jsdoc/opts/args.js b/lib/jsdoc/opts/args.js index cf4c45f5..6daa8542 100644 --- a/lib/jsdoc/opts/args.js +++ b/lib/jsdoc/opts/args.js @@ -24,7 +24,7 @@ function parseQuery(str) { argParser.addOption('a', 'access', true, 'Only display symbols with the given access: "public", "protected", "private" or "undefined", or "all" for all access levels. Default: all except "private"', true); argParser.addOption('c', 'configure', true, 'The path to the configuration file. Default: path/to/jsdoc/conf.json'); argParser.addOption('d', 'destination', true, 'The path to the output folder. Use "console" to dump data to the console. Default: ./out/'); -argParser.addOption('', 'debug', false, 'Log information for debugging JSDoc. On Rhino, launches the debugger when passed as the first option.'); +argParser.addOption('', 'debug', false, 'Log information for debugging JSDoc.'); argParser.addOption('e', 'encoding', true, 'Assume this encoding when reading all source files. Default: utf8'); argParser.addOption('h', 'help', false, 'Print this message and quit.'); argParser.addOption('', 'match', true, 'When running tests, only use specs whose names contain .', true); diff --git a/lib/jsdoc/path.js b/lib/jsdoc/path.js index c7c15f7f..42a27adf 100644 --- a/lib/jsdoc/path.js +++ b/lib/jsdoc/path.js @@ -95,7 +95,7 @@ exports.commonPrefix = function(paths) { * @param {string} filepath - The path to the requested resource. May be an absolute path; a path * relative to the JSDoc directory; or a path relative to the current working directory. * @param {string} [filename] - The filename of the requested resource. - * @return {string} The fully qualified path (or, on Rhino, a URI) to the requested resource. + * @return {string} The fully qualified path to the requested resource. * Includes the filename if one was provided. */ exports.getResourcePath = function(filepath, filename) { diff --git a/lib/jsdoc/plugins.js b/lib/jsdoc/plugins.js index 6147342c..57b7d4ef 100644 --- a/lib/jsdoc/plugins.js +++ b/lib/jsdoc/plugins.js @@ -33,17 +33,6 @@ exports.installPlugins = function(plugins, parser) { plugin.defineTags(dictionary); } - // ...add a Rhino node visitor (deprecated in JSDoc 3.3) - if (plugin.nodeVisitor) { - if ( !parser.addNodeVisitor ) { - logger.error('Unable to add the Rhino node visitor from %s, because JSDoc ' + - 'is not using the Rhino JavaScript parser.', plugins[i]); - } - else { - parser.addNodeVisitor(plugin.nodeVisitor); - } - } - // ...add a Mozilla Parser API node visitor if (plugin.astNodeVisitor) { parser.addAstNodeVisitor(plugin.astNodeVisitor); diff --git a/lib/jsdoc/src/astbuilder.js b/lib/jsdoc/src/astbuilder.js index deededa9..0d763e69 100644 --- a/lib/jsdoc/src/astbuilder.js +++ b/lib/jsdoc/src/astbuilder.js @@ -12,7 +12,6 @@ var jsdoc = { }; var Syntax = jsdoc.src.syntax.Syntax; -// TODO: should set e.stopPropagation == true for consistency with Rhino, right? var VISITOR_CONTINUE = true; var VISITOR_STOP = false; diff --git a/lib/jsdoc/src/parser.js b/lib/jsdoc/src/parser.js index 6fd17df0..6e4f7817 100644 --- a/lib/jsdoc/src/parser.js +++ b/lib/jsdoc/src/parser.js @@ -27,8 +27,7 @@ var Syntax = jsdoc.src.syntax.Syntax; // TODO: docs var PARSERS = exports.PARSERS = { - js: 'jsdoc/src/parser', - rhino: 'rhino/jsdoc/src/parser' + js: 'jsdoc/src/parser' }; /* eslint-disable no-script-url */ // Prefix for JavaScript strings that were provided in lieu of a filename. @@ -62,7 +61,7 @@ exports.createParser = function(type) { if (!type) { /* istanbul ignore next */ - type = jsdoc.util.runtime.isRhino() ? 'rhino' : 'js'; + type = 'js'; } if (hasOwnProp.call(PARSERS, type)) { diff --git a/lib/jsdoc/src/syntax.js b/lib/jsdoc/src/syntax.js index 5bf36ce6..3e0d9d1b 100644 --- a/lib/jsdoc/src/syntax.js +++ b/lib/jsdoc/src/syntax.js @@ -52,7 +52,7 @@ exports.Syntax = { JSXSpreadAttribute: 'JSXSpreadAttribute', JSXText: 'JSXText', LabeledStatement: 'LabeledStatement', - LetStatement: 'LetStatement', // TODO: update Rhino to use VariableDeclaration + LetStatement: 'LetStatement', Literal: 'Literal', LogicalExpression: 'LogicalExpression', MemberExpression: 'MemberExpression', diff --git a/lib/jsdoc/src/walker.js b/lib/jsdoc/src/walker.js index 816bcb86..d871810d 100644 --- a/lib/jsdoc/src/walker.js +++ b/lib/jsdoc/src/walker.js @@ -582,7 +582,6 @@ Walker.prototype._recurse = function(filename, ast) { }; // TODO: docs -// TODO: skip the AST root node to be consistent with Rhino? Walker.prototype.recurse = function(ast, visitor, filename) { var shouldContinue; var state = this._recurse(filename, ast); diff --git a/lib/jsdoc/util/runtime.js b/lib/jsdoc/util/runtime.js index 7bbb101d..60e0da16 100644 --- a/lib/jsdoc/util/runtime.js +++ b/lib/jsdoc/util/runtime.js @@ -10,25 +10,19 @@ var env = require('jsdoc/env'); var os = require('os'); -// These strings represent directory names; do not modify them! -/** @private */ -var RHINO = exports.RHINO = 'rhino'; +// This string represents a directory name; do not modify it! /** @private */ var NODE = exports.NODE = 'node'; /** * The JavaScript runtime that is executing JSDoc: * - * + `module:jsdoc/util/runtime~RHINO`: Mozilla Rhino. * + `module:jsdoc/util/runtime~NODE`: Node.js. * * @private */ var runtime = (function() { - if (global.Packages && typeof global.Packages === 'object' && - Object.prototype.toString.call(global.Packages) === '[object JavaPackage]') { - return RHINO; - } else if (require && require.main && module) { + if (require && require.main && module) { return NODE; } else { // unknown runtime @@ -36,14 +30,6 @@ var runtime = (function() { } })(); -/** - * Check whether Mozilla Rhino is running JSDoc. - * @return {boolean} Set to `true` if the current runtime is Mozilla Rhino. - */ -exports.isRhino = function() { - return runtime === RHINO; -}; - /** * Check whether Node.js is running JSDoc. * @return {boolean} Set to `true` if the current runtime is Node.js. @@ -52,18 +38,6 @@ exports.isNode = function() { return runtime === NODE; }; -function initializeRhino(args) { - // the JSDoc dirname is the main module URI, minus the filename, converted to a path - var uriParts = require.main.uri.split('/'); - uriParts.pop(); - - env.dirname = String( new java.io.File(new java.net.URI(uriParts.join('/'))) ); - env.pwd = String( java.lang.System.getenv().get('PWD') ); - env.args = args; - - require(env.dirname + '/rhino/rhino-shim.js'); -} - function initializeNode(args) { var fs = require('fs'); var path = require('path'); @@ -83,9 +57,6 @@ function initializeNode(args) { exports.initialize = function(args) { switch (runtime) { - case RHINO: - initializeRhino(args); - break; case NODE: initializeNode(args); break; diff --git a/node_modules/async/LICENSE b/node_modules/async/LICENSE deleted file mode 100644 index 8f296985..00000000 --- a/node_modules/async/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2010-2014 Caolan McMahon - -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. diff --git a/node_modules/async/lib/async.js b/node_modules/async/lib/async.js deleted file mode 100644 index f3cfb807..00000000 --- a/node_modules/async/lib/async.js +++ /dev/null @@ -1,1216 +0,0 @@ -/*! - * async - * https://github.com/caolan/async - * - * Copyright 2010-2014 Caolan McMahon - * Released under the MIT license - */ -(function () { - - var async = {}; - function noop() {} - function identity(v) { - return v; - } - function toBool(v) { - return !!v; - } - function notId(v) { - return !v; - } - - // global on the server, window in the browser - var previous_async; - - // Establish the root object, `window` (`self`) in the browser, `global` - // on the server, or `this` in some virtual machines. We use `self` - // instead of `window` for `WebWorker` support. - var root = typeof self === 'object' && self.self === self && self || - typeof global === 'object' && global.global === global && global || - this; - - if (root != null) { - previous_async = root.async; - } - - async.noConflict = function () { - root.async = previous_async; - return async; - }; - - function only_once(fn) { - return function() { - if (fn === null) throw new Error("Callback was already called."); - fn.apply(this, arguments); - fn = null; - }; - } - - function _once(fn) { - return function() { - if (fn === null) return; - fn.apply(this, arguments); - fn = null; - }; - } - - //// cross-browser compatiblity functions //// - - var _toString = Object.prototype.toString; - - var _isArray = Array.isArray || function (obj) { - return _toString.call(obj) === '[object Array]'; - }; - - function _isArrayLike(arr) { - return _isArray(arr) || ( - // has a positive integer length property - typeof arr.length === "number" && - arr.length >= 0 && - arr.length % 1 === 0 - ); - } - - function _each(coll, iterator) { - return _isArrayLike(coll) ? - _arrayEach(coll, iterator) : - _forEachOf(coll, iterator); - } - - function _arrayEach(arr, iterator) { - var index = -1, - length = arr.length; - - while (++index < length) { - iterator(arr[index], index, arr); - } - } - - function _map(arr, iterator) { - var index = -1, - length = arr.length, - result = Array(length); - - while (++index < length) { - result[index] = iterator(arr[index], index, arr); - } - return result; - } - - function _range(count) { - return _map(Array(count), function (v, i) { return i; }); - } - - function _reduce(arr, iterator, memo) { - _arrayEach(arr, function (x, i, a) { - memo = iterator(memo, x, i, a); - }); - return memo; - } - - function _forEachOf(object, iterator) { - _arrayEach(_keys(object), function (key) { - iterator(object[key], key); - }); - } - - function _indexOf(arr, item) { - for (var i = 0; i < arr.length; i++) { - if (arr[i] === item) return i; - } - return -1; - } - - var _keys = Object.keys || function (obj) { - var keys = []; - for (var k in obj) { - if (obj.hasOwnProperty(k)) { - keys.push(k); - } - } - return keys; - }; - - function _keyIterator(coll) { - var i = -1; - var len; - var keys; - if (_isArrayLike(coll)) { - len = coll.length; - return function next() { - i++; - return i < len ? i : null; - }; - } else { - keys = _keys(coll); - len = keys.length; - return function next() { - i++; - return i < len ? keys[i] : null; - }; - } - } - - // Similar to ES6's rest param (http://ariya.ofilabs.com/2013/03/es6-and-rest-parameter.html) - // This accumulates the arguments passed into an array, after a given index. - // From underscore.js (https://github.com/jashkenas/underscore/pull/2140). - function _restParam(func, startIndex) { - startIndex = startIndex == null ? func.length - 1 : +startIndex; - return function() { - var length = Math.max(arguments.length - startIndex, 0); - var rest = Array(length); - for (var index = 0; index < length; index++) { - rest[index] = arguments[index + startIndex]; - } - switch (startIndex) { - case 0: return func.call(this, rest); - case 1: return func.call(this, arguments[0], rest); - case 2: return func.call(this, arguments[0], arguments[1], rest); - } - // Currently unused but handle cases outside of the switch statement: - // var args = Array(startIndex + 1); - // for (index = 0; index < startIndex; index++) { - // args[index] = arguments[index]; - // } - // args[startIndex] = rest; - // return func.apply(this, args); - }; - } - - function _withoutIndex(iterator) { - return function (value, index, callback) { - return iterator(value, callback); - }; - } - - //// exported async module functions //// - - //// nextTick implementation with browser-compatible fallback //// - - // capture the global reference to guard against fakeTimer mocks - var _setImmediate = typeof setImmediate === 'function' && setImmediate; - - var _delay = _setImmediate ? function(fn) { - // not a direct alias for IE10 compatibility - _setImmediate(fn); - } : function(fn) { - setTimeout(fn, 0); - }; - - if (typeof process === 'object' && typeof process.nextTick === 'function') { - async.nextTick = process.nextTick; - } else { - async.nextTick = _delay; - } - async.setImmediate = _setImmediate ? _delay : async.nextTick; - - - async.forEach = - async.each = function (arr, iterator, callback) { - return async.eachOf(arr, _withoutIndex(iterator), callback); - }; - - async.forEachSeries = - async.eachSeries = function (arr, iterator, callback) { - return async.eachOfSeries(arr, _withoutIndex(iterator), callback); - }; - - - async.forEachLimit = - async.eachLimit = function (arr, limit, iterator, callback) { - return _eachOfLimit(limit)(arr, _withoutIndex(iterator), callback); - }; - - async.forEachOf = - async.eachOf = function (object, iterator, callback) { - callback = _once(callback || noop); - object = object || []; - var size = _isArrayLike(object) ? object.length : _keys(object).length; - var completed = 0; - if (!size) { - return callback(null); - } - _each(object, function (value, key) { - iterator(object[key], key, only_once(done)); - }); - function done(err) { - if (err) { - callback(err); - } - else { - completed += 1; - if (completed >= size) { - callback(null); - } - } - } - }; - - async.forEachOfSeries = - async.eachOfSeries = function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - var key = nextKey(); - function iterate() { - var sync = true; - if (key === null) { - return callback(null); - } - iterator(obj[key], key, only_once(function (err) { - if (err) { - callback(err); - } - else { - key = nextKey(); - if (key === null) { - return callback(null); - } else { - if (sync) { - async.nextTick(iterate); - } else { - iterate(); - } - } - } - })); - sync = false; - } - iterate(); - }; - - - - async.forEachOfLimit = - async.eachOfLimit = function (obj, limit, iterator, callback) { - _eachOfLimit(limit)(obj, iterator, callback); - }; - - function _eachOfLimit(limit) { - - return function (obj, iterator, callback) { - callback = _once(callback || noop); - obj = obj || []; - var nextKey = _keyIterator(obj); - if (limit <= 0) { - return callback(null); - } - var done = false; - var running = 0; - var errored = false; - - (function replenish () { - if (done && running <= 0) { - return callback(null); - } - - while (running < limit && !errored) { - var key = nextKey(); - if (key === null) { - done = true; - if (running <= 0) { - callback(null); - } - return; - } - running += 1; - iterator(obj[key], key, only_once(function (err) { - running -= 1; - if (err) { - callback(err); - errored = true; - } - else { - replenish(); - } - })); - } - })(); - }; - } - - - function doParallel(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOf, obj, iterator, callback); - }; - } - function doParallelLimit(fn) { - return function (obj, limit, iterator, callback) { - return fn(_eachOfLimit(limit), obj, iterator, callback); - }; - } - function doSeries(fn) { - return function (obj, iterator, callback) { - return fn(async.eachOfSeries, obj, iterator, callback); - }; - } - - function _asyncMap(eachfn, arr, iterator, callback) { - callback = _once(callback || noop); - var results = []; - eachfn(arr, function (value, index, callback) { - iterator(value, function (err, v) { - results[index] = v; - callback(err); - }); - }, function (err) { - callback(err, results); - }); - } - - async.map = doParallel(_asyncMap); - async.mapSeries = doSeries(_asyncMap); - async.mapLimit = doParallelLimit(_asyncMap); - - // reduce only has a series version, as doing reduce in parallel won't - // work in many situations. - async.inject = - async.foldl = - async.reduce = function (arr, memo, iterator, callback) { - async.eachOfSeries(arr, function (x, i, callback) { - iterator(memo, x, function (err, v) { - memo = v; - callback(err); - }); - }, function (err) { - callback(err || null, memo); - }); - }; - - async.foldr = - async.reduceRight = function (arr, memo, iterator, callback) { - var reversed = _map(arr, identity).reverse(); - async.reduce(reversed, memo, iterator, callback); - }; - - function _filter(eachfn, arr, iterator, callback) { - var results = []; - eachfn(arr, function (x, index, callback) { - iterator(x, function (v) { - if (v) { - results.push({index: index, value: x}); - } - callback(); - }); - }, function () { - callback(_map(results.sort(function (a, b) { - return a.index - b.index; - }), function (x) { - return x.value; - })); - }); - } - - async.select = - async.filter = doParallel(_filter); - - async.selectLimit = - async.filterLimit = doParallelLimit(_filter); - - async.selectSeries = - async.filterSeries = doSeries(_filter); - - function _reject(eachfn, arr, iterator, callback) { - _filter(eachfn, arr, function(value, cb) { - iterator(value, function(v) { - cb(!v); - }); - }, callback); - } - async.reject = doParallel(_reject); - async.rejectLimit = doParallelLimit(_reject); - async.rejectSeries = doSeries(_reject); - - function _createTester(eachfn, check, getResult) { - return function(arr, limit, iterator, cb) { - function done() { - if (cb) cb(getResult(false, void 0)); - } - function iteratee(x, _, callback) { - if (!cb) return callback(); - iterator(x, function (v) { - if (cb && check(v)) { - cb(getResult(true, x)); - cb = iterator = false; - } - callback(); - }); - } - if (arguments.length > 3) { - eachfn(arr, limit, iteratee, done); - } else { - cb = iterator; - iterator = limit; - eachfn(arr, iteratee, done); - } - }; - } - - async.any = - async.some = _createTester(async.eachOf, toBool, identity); - - async.someLimit = _createTester(async.eachOfLimit, toBool, identity); - - async.all = - async.every = _createTester(async.eachOf, notId, notId); - - async.everyLimit = _createTester(async.eachOfLimit, notId, notId); - - function _findGetResult(v, x) { - return x; - } - async.detect = _createTester(async.eachOf, identity, _findGetResult); - async.detectSeries = _createTester(async.eachOfSeries, identity, _findGetResult); - - async.sortBy = function (arr, iterator, callback) { - async.map(arr, function (x, callback) { - iterator(x, function (err, criteria) { - if (err) { - callback(err); - } - else { - callback(null, {value: x, criteria: criteria}); - } - }); - }, function (err, results) { - if (err) { - return callback(err); - } - else { - callback(null, _map(results.sort(comparator), function (x) { - return x.value; - })); - } - - }); - - function comparator(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - } - }; - - async.auto = function (tasks, callback) { - callback = _once(callback || noop); - var keys = _keys(tasks); - var remainingTasks = keys.length; - if (!remainingTasks) { - return callback(null); - } - - var results = {}; - - var listeners = []; - function addListener(fn) { - listeners.unshift(fn); - } - function removeListener(fn) { - var idx = _indexOf(listeners, fn); - if (idx >= 0) listeners.splice(idx, 1); - } - function taskComplete() { - remainingTasks--; - _arrayEach(listeners.slice(0), function (fn) { - fn(); - }); - } - - addListener(function () { - if (!remainingTasks) { - callback(null, results); - } - }); - - _arrayEach(keys, function (k) { - var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; - var taskCallback = _restParam(function(err, args) { - if (args.length <= 1) { - args = args[0]; - } - if (err) { - var safeResults = {}; - _forEachOf(results, function(val, rkey) { - safeResults[rkey] = val; - }); - safeResults[k] = args; - callback(err, safeResults); - } - else { - results[k] = args; - async.setImmediate(taskComplete); - } - }); - var requires = task.slice(0, task.length - 1); - // prevent dead-locks - var len = requires.length; - var dep; - while (len--) { - if (!(dep = tasks[requires[len]])) { - throw new Error('Has inexistant dependency'); - } - if (_isArray(dep) && _indexOf(dep, k) >= 0) { - throw new Error('Has cyclic dependencies'); - } - } - function ready() { - return _reduce(requires, function (a, x) { - return (a && results.hasOwnProperty(x)); - }, true) && !results.hasOwnProperty(k); - } - if (ready()) { - task[task.length - 1](taskCallback, results); - } - else { - addListener(listener); - } - function listener() { - if (ready()) { - removeListener(listener); - task[task.length - 1](taskCallback, results); - } - } - }); - }; - - - - async.retry = function(times, task, callback) { - var DEFAULT_TIMES = 5; - var DEFAULT_INTERVAL = 0; - - var attempts = []; - - var opts = { - times: DEFAULT_TIMES, - interval: DEFAULT_INTERVAL - }; - - function parseTimes(acc, t){ - if(typeof t === 'number'){ - acc.times = parseInt(t, 10) || DEFAULT_TIMES; - } else if(typeof t === 'object'){ - acc.times = parseInt(t.times, 10) || DEFAULT_TIMES; - acc.interval = parseInt(t.interval, 10) || DEFAULT_INTERVAL; - } else { - throw new Error('Unsupported argument type for \'times\': ' + typeof(t)); - } - } - - var length = arguments.length; - if (length < 1 || length > 3) { - throw new Error('Invalid arguments - must be either (task), (task, callback), (times, task) or (times, task, callback)'); - } else if (length <= 2 && typeof times === 'function') { - callback = task; - task = times; - } - if (typeof times !== 'function') { - parseTimes(opts, times); - } - opts.callback = callback; - opts.task = task; - - function wrappedTask(wrappedCallback, wrappedResults) { - function retryAttempt(task, finalAttempt) { - return function(seriesCallback) { - task(function(err, result){ - seriesCallback(!err || finalAttempt, {err: err, result: result}); - }, wrappedResults); - }; - } - - function retryInterval(interval){ - return function(seriesCallback){ - setTimeout(function(){ - seriesCallback(null); - }, interval); - }; - } - - while (opts.times) { - - var finalAttempt = !(opts.times-=1); - attempts.push(retryAttempt(opts.task, finalAttempt)); - if(!finalAttempt && opts.interval > 0){ - attempts.push(retryInterval(opts.interval)); - } - } - - async.series(attempts, function(done, data){ - data = data[data.length - 1]; - (wrappedCallback || opts.callback)(data.err, data.result); - }); - } - - // If a callback is passed, run this as a controll flow - return opts.callback ? wrappedTask() : wrappedTask; - }; - - async.waterfall = function (tasks, callback) { - callback = _once(callback || noop); - if (!_isArray(tasks)) { - var err = new Error('First argument to waterfall must be an array of functions'); - return callback(err); - } - if (!tasks.length) { - return callback(); - } - function wrapIterator(iterator) { - return _restParam(function (err, args) { - if (err) { - callback.apply(null, [err].concat(args)); - } - else { - var next = iterator.next(); - if (next) { - args.push(wrapIterator(next)); - } - else { - args.push(callback); - } - ensureAsync(iterator).apply(null, args); - } - }); - } - wrapIterator(async.iterator(tasks))(); - }; - - function _parallel(eachfn, tasks, callback) { - callback = callback || noop; - var results = _isArrayLike(tasks) ? [] : {}; - - eachfn(tasks, function (task, key, callback) { - task(_restParam(function (err, args) { - if (args.length <= 1) { - args = args[0]; - } - results[key] = args; - callback(err); - })); - }, function (err) { - callback(err, results); - }); - } - - async.parallel = function (tasks, callback) { - _parallel(async.eachOf, tasks, callback); - }; - - async.parallelLimit = function(tasks, limit, callback) { - _parallel(_eachOfLimit(limit), tasks, callback); - }; - - async.series = function(tasks, callback) { - _parallel(async.eachOfSeries, tasks, callback); - }; - - async.iterator = function (tasks) { - function makeCallback(index) { - function fn() { - if (tasks.length) { - tasks[index].apply(null, arguments); - } - return fn.next(); - } - fn.next = function () { - return (index < tasks.length - 1) ? makeCallback(index + 1): null; - }; - return fn; - } - return makeCallback(0); - }; - - async.apply = _restParam(function (fn, args) { - return _restParam(function (callArgs) { - return fn.apply( - null, args.concat(callArgs) - ); - }); - }); - - function _concat(eachfn, arr, fn, callback) { - var result = []; - eachfn(arr, function (x, index, cb) { - fn(x, function (err, y) { - result = result.concat(y || []); - cb(err); - }); - }, function (err) { - callback(err, result); - }); - } - async.concat = doParallel(_concat); - async.concatSeries = doSeries(_concat); - - async.whilst = function (test, iterator, callback) { - callback = callback || noop; - if (test()) { - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else if (test.apply(this, args)) { - iterator(next); - } else { - callback(null); - } - }); - iterator(next); - } else { - callback(null); - } - }; - - async.doWhilst = function (iterator, test, callback) { - var calls = 0; - return async.whilst(function() { - return ++calls <= 1 || test.apply(this, arguments); - }, iterator, callback); - }; - - async.until = function (test, iterator, callback) { - return async.whilst(function() { - return !test.apply(this, arguments); - }, iterator, callback); - }; - - async.doUntil = function (iterator, test, callback) { - return async.doWhilst(iterator, function() { - return !test.apply(this, arguments); - }, callback); - }; - - async.during = function (test, iterator, callback) { - callback = callback || noop; - - var next = _restParam(function(err, args) { - if (err) { - callback(err); - } else { - args.push(check); - test.apply(this, args); - } - }); - - var check = function(err, truth) { - if (err) { - callback(err); - } else if (truth) { - iterator(next); - } else { - callback(null); - } - }; - - test(check); - }; - - async.doDuring = function (iterator, test, callback) { - var calls = 0; - async.during(function(next) { - if (calls++ < 1) { - next(null, true); - } else { - test.apply(this, arguments); - } - }, iterator, callback); - }; - - function _queue(worker, concurrency, payload) { - if (concurrency == null) { - concurrency = 1; - } - else if(concurrency === 0) { - throw new Error('Concurrency must not be zero'); - } - function _insert(q, data, pos, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0 && q.idle()) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - callback: callback || noop - }; - - if (pos) { - q.tasks.unshift(item); - } else { - q.tasks.push(item); - } - - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - }); - async.setImmediate(q.process); - } - function _next(q, tasks) { - return function(){ - workers -= 1; - var args = arguments; - _arrayEach(tasks, function (task) { - task.callback.apply(task, args); - }); - if (q.tasks.length + workers === 0) { - q.drain(); - } - q.process(); - }; - } - - var workers = 0; - var q = { - tasks: [], - concurrency: concurrency, - payload: payload, - saturated: noop, - empty: noop, - drain: noop, - started: false, - paused: false, - push: function (data, callback) { - _insert(q, data, false, callback); - }, - kill: function () { - q.drain = noop; - q.tasks = []; - }, - unshift: function (data, callback) { - _insert(q, data, true, callback); - }, - process: function () { - if (!q.paused && workers < q.concurrency && q.tasks.length) { - while(workers < q.concurrency && q.tasks.length){ - var tasks = q.payload ? - q.tasks.splice(0, q.payload) : - q.tasks.splice(0, q.tasks.length); - - var data = _map(tasks, function (task) { - return task.data; - }); - - if (q.tasks.length === 0) { - q.empty(); - } - workers += 1; - var cb = only_once(_next(q, tasks)); - worker(data, cb); - } - } - }, - length: function () { - return q.tasks.length; - }, - running: function () { - return workers; - }, - idle: function() { - return q.tasks.length + workers === 0; - }, - pause: function () { - q.paused = true; - }, - resume: function () { - if (q.paused === false) { return; } - q.paused = false; - var resumeCount = Math.min(q.concurrency, q.tasks.length); - // Need to call q.process once per concurrent - // worker to preserve full concurrency after pause - for (var w = 1; w <= resumeCount; w++) { - async.setImmediate(q.process); - } - } - }; - return q; - } - - async.queue = function (worker, concurrency) { - var q = _queue(function (items, cb) { - worker(items[0], cb); - }, concurrency, 1); - - return q; - }; - - async.priorityQueue = function (worker, concurrency) { - - function _compareTasks(a, b){ - return a.priority - b.priority; - } - - function _binarySearch(sequence, item, compare) { - var beg = -1, - end = sequence.length - 1; - while (beg < end) { - var mid = beg + ((end - beg + 1) >>> 1); - if (compare(item, sequence[mid]) >= 0) { - beg = mid; - } else { - end = mid - 1; - } - } - return beg; - } - - function _insert(q, data, priority, callback) { - if (callback != null && typeof callback !== "function") { - throw new Error("task callback must be a function"); - } - q.started = true; - if (!_isArray(data)) { - data = [data]; - } - if(data.length === 0) { - // call drain immediately if there are no tasks - return async.setImmediate(function() { - q.drain(); - }); - } - _arrayEach(data, function(task) { - var item = { - data: task, - priority: priority, - callback: typeof callback === 'function' ? callback : noop - }; - - q.tasks.splice(_binarySearch(q.tasks, item, _compareTasks) + 1, 0, item); - - if (q.tasks.length === q.concurrency) { - q.saturated(); - } - async.setImmediate(q.process); - }); - } - - // Start with a normal queue - var q = async.queue(worker, concurrency); - - // Override push to accept second parameter representing priority - q.push = function (data, priority, callback) { - _insert(q, data, priority, callback); - }; - - // Remove unshift function - delete q.unshift; - - return q; - }; - - async.cargo = function (worker, payload) { - return _queue(worker, 1, payload); - }; - - function _console_fn(name) { - return _restParam(function (fn, args) { - fn.apply(null, args.concat([_restParam(function (err, args) { - if (typeof console !== 'undefined') { - if (err) { - if (console.error) { - console.error(err); - } - } - else if (console[name]) { - _arrayEach(args, function (x) { - console[name](x); - }); - } - } - })])); - }); - } - async.log = _console_fn('log'); - async.dir = _console_fn('dir'); - /*async.info = _console_fn('info'); - async.warn = _console_fn('warn'); - async.error = _console_fn('error');*/ - - async.memoize = function (fn, hasher) { - var memo = {}; - var queues = {}; - hasher = hasher || identity; - var memoized = _restParam(function memoized(args) { - var callback = args.pop(); - var key = hasher.apply(null, args); - if (key in memo) { - async.nextTick(function () { - callback.apply(null, memo[key]); - }); - } - else if (key in queues) { - queues[key].push(callback); - } - else { - queues[key] = [callback]; - fn.apply(null, args.concat([_restParam(function (args) { - memo[key] = args; - var q = queues[key]; - delete queues[key]; - for (var i = 0, l = q.length; i < l; i++) { - q[i].apply(null, args); - } - })])); - } - }); - memoized.memo = memo; - memoized.unmemoized = fn; - return memoized; - }; - - async.unmemoize = function (fn) { - return function () { - return (fn.unmemoized || fn).apply(null, arguments); - }; - }; - - function _times(mapper) { - return function (count, iterator, callback) { - mapper(_range(count), iterator, callback); - }; - } - - async.times = _times(async.map); - async.timesSeries = _times(async.mapSeries); - async.timesLimit = function (count, limit, iterator, callback) { - return async.mapLimit(_range(count), limit, iterator, callback); - }; - - async.seq = function (/* functions... */) { - var fns = arguments; - return _restParam(function (args) { - var that = this; - - var callback = args[args.length - 1]; - if (typeof callback == 'function') { - args.pop(); - } else { - callback = noop; - } - - async.reduce(fns, args, function (newargs, fn, cb) { - fn.apply(that, newargs.concat([_restParam(function (err, nextargs) { - cb(err, nextargs); - })])); - }, - function (err, results) { - callback.apply(that, [err].concat(results)); - }); - }); - }; - - async.compose = function (/* functions... */) { - return async.seq.apply(null, Array.prototype.reverse.call(arguments)); - }; - - - function _applyEach(eachfn) { - return _restParam(function(fns, args) { - var go = _restParam(function(args) { - var that = this; - var callback = args.pop(); - return eachfn(fns, function (fn, _, cb) { - fn.apply(that, args.concat([cb])); - }, - callback); - }); - if (args.length) { - return go.apply(this, args); - } - else { - return go; - } - }); - } - - async.applyEach = _applyEach(async.eachOf); - async.applyEachSeries = _applyEach(async.eachOfSeries); - - - async.forever = function (fn, callback) { - var done = only_once(callback || noop); - var task = ensureAsync(fn); - function next(err) { - if (err) { - return done(err); - } - task(next); - } - next(); - }; - - function ensureAsync(fn) { - return _restParam(function (args) { - var callback = args.pop(); - args.push(function () { - var innerArgs = arguments; - if (sync) { - async.setImmediate(function () { - callback.apply(null, innerArgs); - }); - } else { - callback.apply(null, innerArgs); - } - }); - var sync = true; - fn.apply(this, args); - sync = false; - }); - } - - async.ensureAsync = ensureAsync; - - async.constant = _restParam(function(values) { - var args = [null].concat(values); - return function (callback) { - return callback.apply(this, args); - }; - }); - - async.wrapSync = - async.asyncify = function asyncify(func) { - return _restParam(function (args) { - var callback = args.pop(); - var result; - try { - result = func.apply(this, args); - } catch (e) { - return callback(e); - } - // if result is Promise object - if (typeof result !== 'undefined' && typeof result.then === "function") { - result.then(function(value) { - callback(null, value); - }).catch(function(err) { - callback(err.message ? err : new Error(err)); - }); - } else { - callback(null, result); - } - }); - }; - - // Node.js - if (typeof module !== 'undefined' && module.exports) { - module.exports = async; - } - // AMD / RequireJS - else if (typeof define !== 'undefined' && define.amd) { - define([], function () { - return async; - }); - } - // included directly via - - - - -
-Please open your javascript console to see test results -
- - - - diff --git a/node_modules/taffydb/taffy.js b/node_modules/taffydb/taffy.js deleted file mode 100644 index b7ad88cd..00000000 --- a/node_modules/taffydb/taffy.js +++ /dev/null @@ -1,1973 +0,0 @@ -/* - - Software License Agreement (BSD License) - http://taffydb.com - Copyright (c) - All rights reserved. - - - Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following condition is met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - 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. - - */ - -/*jslint browser : true, continue : true, - devel : true, indent : 2, maxerr : 500, - newcap : true, nomen : true, plusplus : true, - regexp : true, sloppy : true, vars : false, - white : true -*/ - -// BUILD 193d48d, modified by mmikowski to pass jslint - -// Setup TAFFY name space to return an object with methods -var TAFFY, exports, T; -(function () { - 'use strict'; - var - typeList, makeTest, idx, typeKey, - version, TC, idpad, cmax, - API, protectJSON, each, eachin, - isIndexable, returnFilter, runFilters, - numcharsplit, orderByCol, run - ; - - - if ( ! TAFFY ){ - // TC = Counter for Taffy DBs on page, used for unique IDs - // cmax = size of charnumarray conversion cache - // idpad = zeros to pad record IDs with - version = '2.6.2'; // proposed mmikowski 2012-08-06 - TC = 1; - idpad = '000000'; - cmax = 1000; - API = {}; - - protectJSON = function ( t ) { - // **************************************** - // * - // * Takes: a variable - // * Returns: the variable if object/array or the parsed variable if JSON - // * - // **************************************** - if ( TAFFY.isArray( t ) || TAFFY.isObject( t ) ){ - return t; - } - else { - return JSON.parse( t ); - } - }; - - each = function ( a, fun, u ) { - var r, i, x, y; - // **************************************** - // * - // * Takes: - // * a = an object/value or an array of objects/values - // * f = a function - // * u = optional flag to describe how to handle undefined values - // in array of values. True: pass them to the functions, - // False: skip. Default False; - // * Purpose: Used to loop over arrays - // * - // **************************************** - if ( a && ((T.isArray( a ) && a.length === 1) || (!T.isArray( a ))) ){ - fun( (T.isArray( a )) ? a[0] : a, 0 ); - } - else { - for ( r, i, x = 0, a = (T.isArray( a )) ? a : [a], y = a.length; - x < y; x++ ) - { - i = a[x]; - if ( !T.isUndefined( i ) || (u || false) ){ - r = fun( i, x ); - if ( r === T.EXIT ){ - break; - } - - } - } - } - }; - - eachin = function ( o, fun ) { - // **************************************** - // * - // * Takes: - // * o = an object - // * f = a function - // * Purpose: Used to loop over objects - // * - // **************************************** - var x = 0, r, i; - - for ( i in o ){ - if ( o.hasOwnProperty( i ) ){ - r = fun( o[i], i, x++ ); - if ( r === T.EXIT ){ - break; - } - } - } - - }; - - API.extend = function ( m, f ) { - // **************************************** - // * - // * Takes: method name, function - // * Purpose: Add a custom method to the API - // * - // **************************************** - API[m] = function () { - return f.apply( this, arguments ); - }; - }; - - isIndexable = function ( f ) { - var i; - // Check to see if record ID - if ( T.isString( f ) && /[t][0-9]*[r][0-9]*/i.test( f ) ){ - return true; - } - // Check to see if record - if ( T.isObject( f ) && f.___id && f.___s ){ - return true; - } - - // Check to see if array of indexes - if ( T.isArray( f ) ){ - i = true; - each( f, function ( r ) { - if ( !isIndexable( r ) ){ - i = false; - - return TAFFY.EXIT; - } - }); - return i; - } - - return false; - }; - - runFilters = function ( r, filter ) { - // **************************************** - // * - // * Takes: takes a record and a collection of filters - // * Returns: true if the record matches, false otherwise - // **************************************** - var match = true; - - - each( filter, function ( mf ) { - switch ( T.typeOf( mf ) ){ - case 'function': - // run function - if ( !mf.apply( r ) ){ - match = false; - return TAFFY.EXIT; - } - break; - case 'array': - // loop array and treat like a SQL or - match = (mf.length === 1) ? (runFilters( r, mf[0] )) : - (mf.length === 2) ? (runFilters( r, mf[0] ) || - runFilters( r, mf[1] )) : - (mf.length === 3) ? (runFilters( r, mf[0] ) || - runFilters( r, mf[1] ) || runFilters( r, mf[2] )) : - (mf.length === 4) ? (runFilters( r, mf[0] ) || - runFilters( r, mf[1] ) || runFilters( r, mf[2] ) || - runFilters( r, mf[3] )) : false; - if ( mf.length > 4 ){ - each( mf, function ( f ) { - if ( runFilters( r, f ) ){ - match = true; - } - }); - } - break; - } - }); - - return match; - }; - - returnFilter = function ( f ) { - // **************************************** - // * - // * Takes: filter object - // * Returns: a filter function - // * Purpose: Take a filter object and return a function that can be used to compare - // * a TaffyDB record to see if the record matches a query - // **************************************** - var nf = []; - if ( T.isString( f ) && /[t][0-9]*[r][0-9]*/i.test( f ) ){ - f = { ___id : f }; - } - if ( T.isArray( f ) ){ - // if we are working with an array - - each( f, function ( r ) { - // loop the array and return a filter func for each value - nf.push( returnFilter( r ) ); - }); - // now build a func to loop over the filters and return true if ANY of the filters match - // This handles logical OR expressions - f = function () { - var that = this, match = false; - each( nf, function ( f ) { - if ( runFilters( that, f ) ){ - match = true; - } - }); - return match; - }; - return f; - - } - // if we are dealing with an Object - if ( T.isObject( f ) ){ - if ( T.isObject( f ) && f.___id && f.___s ){ - f = { ___id : f.___id }; - } - - // Loop over each value on the object to prep match type and match value - eachin( f, function ( v, i ) { - - // default match type to IS/Equals - if ( !T.isObject( v ) ){ - v = { - 'is' : v - }; - } - // loop over each value on the value object - if any - eachin( v, function ( mtest, s ) { - // s = match type, e.g. is, hasAll, like, etc - var c = [], looper; - - // function to loop and apply filter - looper = (s === 'hasAll') ? - function ( mtest, func ) { - func( mtest ); - } : each; - - // loop over each test - looper( mtest, function ( mtest ) { - - // su = match success - // f = match false - var su = true, f = false, matchFunc; - - - // push a function onto the filter collection to do the matching - matchFunc = function () { - - // get the value from the record - var - mvalue = this[i], - eqeq = '==', - bangeq = '!=', - eqeqeq = '===', - lt = '<', - gt = '>', - lteq = '<=', - gteq = '>=', - bangeqeq = '!==', - r - ; - - - if ( (s.indexOf( '!' ) === 0) && s !== bangeq && - s !== bangeqeq ) - { - // if the filter name starts with ! as in '!is' then reverse the match logic and remove the ! - su = false; - s = s.substring( 1, s.length ); - } - // get the match results based on the s/match type - /*jslint eqeq : true */ - r = ( - (s === 'regex') ? (mtest.test( mvalue )) : (s === 'lt' || s === lt) - ? (mvalue < mtest) : (s === 'gt' || s === gt) - ? (mvalue > mtest) : (s === 'lte' || s === lteq) - ? (mvalue <= mtest) : (s === 'gte' || s === gteq) - ? (mvalue >= mtest) : (s === 'left') - ? (mvalue.indexOf( mtest ) === 0) : (s === 'leftnocase') - ? (mvalue.toLowerCase().indexOf( mtest.toLowerCase() ) - === 0) : (s === 'right') - ? (mvalue.substring( (mvalue.length - mtest.length) ) - === mtest) : (s === 'rightnocase') - ? (mvalue.toLowerCase().substring( - (mvalue.length - mtest.length) ) === mtest.toLowerCase()) - : (s === 'like') - ? (mvalue.indexOf( mtest ) >= 0) : (s === 'likenocase') - ? (mvalue.toLowerCase().indexOf(mtest.toLowerCase()) >= 0) - : (s === eqeqeq || s === 'is') - ? (mvalue === mtest) : (s === eqeq) - ? (mvalue == mtest) : (s === bangeqeq) - ? (mvalue !== mtest) : (s === bangeq) - ? (mvalue != mtest) : (s === 'isnocase') - ? (mvalue.toLowerCase - ? mvalue.toLowerCase() === mtest.toLowerCase() - : mvalue === mtest) : (s === 'has') - ? (T.has( mvalue, mtest )) : (s === 'hasall') - ? (T.hasAll( mvalue, mtest )) : ( - s.indexOf( 'is' ) === -1 - && !TAFFY.isNull( mvalue ) - && !TAFFY.isUndefined( mvalue ) - && !TAFFY.isObject( mtest ) - && !TAFFY.isArray( mtest ) - ) - ? (mtest === mvalue[s]) - : (T[s] && T.isFunction( T[s] ) - && s.indexOf( 'is' ) === 0) - ? T[s]( mvalue ) === mtest - : (T[s] && T.isFunction( T[s] )) - ? T[s]( mvalue, mtest ) : (false) - ); - /*jslint eqeq : false */ - r = (r && !su) ? false : (!r && !su) ? true : r; - - return r; - }; - c.push( matchFunc ); - - }); - // if only one filter in the collection push it onto the filter list without the array - if ( c.length === 1 ){ - - nf.push( c[0] ); - } - else { - // else build a function to loop over all the filters and return true only if ALL match - // this is a logical AND - nf.push( function () { - var that = this, match = false; - each( c, function ( f ) { - if ( f.apply( that ) ){ - match = true; - } - }); - return match; - }); - } - }); - }); - // finally return a single function that wraps all the other functions and will run a query - // where all functions have to return true for a record to appear in a query result - f = function () { - var that = this, match = true; - // faster if less than 4 functions - match = (nf.length === 1 && !nf[0].apply( that )) ? false : - (nf.length === 2 && - (!nf[0].apply( that ) || !nf[1].apply( that ))) ? false : - (nf.length === 3 && - (!nf[0].apply( that ) || !nf[1].apply( that ) || - !nf[2].apply( that ))) ? false : - (nf.length === 4 && - (!nf[0].apply( that ) || !nf[1].apply( that ) || - !nf[2].apply( that ) || !nf[3].apply( that ))) ? false - : true; - if ( nf.length > 4 ){ - each( nf, function ( f ) { - if ( !runFilters( that, f ) ){ - match = false; - } - }); - } - return match; - }; - return f; - } - - // if function - if ( T.isFunction( f ) ){ - return f; - } - }; - - orderByCol = function ( ar, o ) { - // **************************************** - // * - // * Takes: takes an array and a sort object - // * Returns: the array sorted - // * Purpose: Accept filters such as "[col], [col2]" or "[col] desc" and sort on those columns - // * - // **************************************** - - var sortFunc = function ( a, b ) { - // function to pass to the native array.sort to sort an array - var r = 0; - - T.each( o, function ( sd ) { - // loop over the sort instructions - // get the column name - var o, col, dir, c, d; - o = sd.split( ' ' ); - col = o[0]; - - // get the direction - dir = (o.length === 1) ? "logical" : o[1]; - - - if ( dir === 'logical' ){ - // if dir is logical than grab the charnum arrays for the two values we are looking at - c = numcharsplit( a[col] ); - d = numcharsplit( b[col] ); - // loop over the charnumarrays until one value is higher than the other - T.each( (c.length <= d.length) ? c : d, function ( x, i ) { - if ( c[i] < d[i] ){ - r = -1; - return TAFFY.EXIT; - } - else if ( c[i] > d[i] ){ - r = 1; - return TAFFY.EXIT; - } - } ); - } - else if ( dir === 'logicaldesc' ){ - // if logicaldesc than grab the charnum arrays for the two values we are looking at - c = numcharsplit( a[col] ); - d = numcharsplit( b[col] ); - // loop over the charnumarrays until one value is lower than the other - T.each( (c.length <= d.length) ? c : d, function ( x, i ) { - if ( c[i] > d[i] ){ - r = -1; - return TAFFY.EXIT; - } - else if ( c[i] < d[i] ){ - r = 1; - return TAFFY.EXIT; - } - } ); - } - else if ( dir === 'asec' && a[col] < b[col] ){ - // if asec - default - check to see which is higher - r = -1; - return T.EXIT; - } - else if ( dir === 'asec' && a[col] > b[col] ){ - // if asec - default - check to see which is higher - r = 1; - return T.EXIT; - } - else if ( dir === 'desc' && a[col] > b[col] ){ - // if desc check to see which is lower - r = -1; - return T.EXIT; - - } - else if ( dir === 'desc' && a[col] < b[col] ){ - // if desc check to see which is lower - r = 1; - return T.EXIT; - - } - // if r is still 0 and we are doing a logical sort than look to see if one array is longer than the other - if ( r === 0 && dir === 'logical' && c.length < d.length ){ - r = -1; - } - else if ( r === 0 && dir === 'logical' && c.length > d.length ){ - r = 1; - } - else if ( r === 0 && dir === 'logicaldesc' && c.length > d.length ){ - r = -1; - } - else if ( r === 0 && dir === 'logicaldesc' && c.length < d.length ){ - r = 1; - } - - if ( r !== 0 ){ - return T.EXIT; - } - - - } ); - return r; - }; - // call the sort function and return the newly sorted array - return (ar && ar.push) ? ar.sort( sortFunc ) : ar; - - - }; - - // **************************************** - // * - // * Takes: a string containing numbers and letters and turn it into an array - // * Returns: return an array of numbers and letters - // * Purpose: Used for logical sorting. String Example: 12ABC results: [12,'ABC'] - // **************************************** - (function () { - // creates a cache for numchar conversions - var cache = {}, cachcounter = 0; - // creates the numcharsplit function - numcharsplit = function ( thing ) { - // if over 1000 items exist in the cache, clear it and start over - if ( cachcounter > cmax ){ - cache = {}; - cachcounter = 0; - } - - // if a cache can be found for a numchar then return its array value - return cache['_' + thing] || (function () { - // otherwise do the conversion - // make sure it is a string and setup so other variables - var nthing = String( thing ), - na = [], - rv = '_', - rt = '', - x, xx, c; - - // loop over the string char by char - for ( x = 0, xx = nthing.length; x < xx; x++ ){ - // take the char at each location - c = nthing.charCodeAt( x ); - // check to see if it is a valid number char and append it to the array. - // if last char was a string push the string to the charnum array - if ( ( c >= 48 && c <= 57 ) || c === 46 ){ - if ( rt !== 'n' ){ - rt = 'n'; - na.push( rv.toLowerCase() ); - rv = ''; - } - rv = rv + nthing.charAt( x ); - } - else { - // check to see if it is a valid string char and append to string - // if last char was a number push the whole number to the charnum array - if ( rt !== 's' ){ - rt = 's'; - na.push( parseFloat( rv ) ); - rv = ''; - } - rv = rv + nthing.charAt( x ); - } - } - // once done, push the last value to the charnum array and remove the first uneeded item - na.push( (rt === 'n') ? parseFloat( rv ) : rv.toLowerCase() ); - na.shift(); - // add to cache - cache['_' + thing] = na; - cachcounter++; - // return charnum array - return na; - }()); - }; - }()); - - // **************************************** - // * - // * Runs a query - // **************************************** - - - run = function () { - this.context( { - results : this.getDBI().query( this.context() ) - }); - - }; - - API.extend( 'filter', function () { - // **************************************** - // * - // * Takes: takes unlimited filter objects as arguments - // * Returns: method collection - // * Purpose: Take filters as objects and cache functions for later lookup when a query is run - // **************************************** - var - nc = TAFFY.mergeObj( this.context(), { run : null } ), - nq = [] - ; - each( nc.q, function ( v ) { - nq.push( v ); - }); - nc.q = nq; - // Hadnle passing of ___ID or a record on lookup. - each( arguments, function ( f ) { - nc.q.push( returnFilter( f ) ); - nc.filterRaw.push( f ); - }); - - return this.getroot( nc ); - }); - - API.extend( 'order', function ( o ) { - // **************************************** - // * - // * Purpose: takes a string and creates an array of order instructions to be used with a query - // **************************************** - - o = o.split( ',' ); - var x = [], nc; - - each( o, function ( r ) { - x.push( r.replace( /^\s*/, '' ).replace( /\s*$/, '' ) ); - }); - - nc = TAFFY.mergeObj( this.context(), {sort : null} ); - nc.order = x; - - return this.getroot( nc ); - }); - - API.extend( 'limit', function ( n ) { - // **************************************** - // * - // * Purpose: takes a limit number to limit the number of rows returned by a query. Will update the results - // * of a query - // **************************************** - var nc = TAFFY.mergeObj( this.context(), {}), - limitedresults - ; - - nc.limit = n; - - if ( nc.run && nc.sort ){ - limitedresults = []; - each( nc.results, function ( i, x ) { - if ( (x + 1) > n ){ - return TAFFY.EXIT; - } - limitedresults.push( i ); - }); - nc.results = limitedresults; - } - - return this.getroot( nc ); - }); - - API.extend( 'start', function ( n ) { - // **************************************** - // * - // * Purpose: takes a limit number to limit the number of rows returned by a query. Will update the results - // * of a query - // **************************************** - var nc = TAFFY.mergeObj( this.context(), {} ), - limitedresults - ; - - nc.start = n; - - if ( nc.run && nc.sort && !nc.limit ){ - limitedresults = []; - each( nc.results, function ( i, x ) { - if ( (x + 1) > n ){ - limitedresults.push( i ); - } - }); - nc.results = limitedresults; - } - else { - nc = TAFFY.mergeObj( this.context(), {run : null, start : n} ); - } - - return this.getroot( nc ); - }); - - API.extend( 'update', function ( arg0, arg1, arg2 ) { - // **************************************** - // * - // * Takes: a object and passes it off DBI update method for all matched records - // **************************************** - var runEvent = true, o = {}, args = arguments, that; - if ( TAFFY.isString( arg0 ) && - (arguments.length === 2 || arguments.length === 3) ) - { - o[arg0] = arg1; - if ( arguments.length === 3 ){ - runEvent = arg2; - } - } - else { - o = arg0; - if ( args.length === 2 ){ - runEvent = arg1; - } - } - - that = this; - run.call( this ); - each( this.context().results, function ( r ) { - var c = o; - if ( TAFFY.isFunction( c ) ){ - c = c.apply( TAFFY.mergeObj( r, {} ) ); - } - else { - if ( T.isFunction( c ) ){ - c = c( TAFFY.mergeObj( r, {} ) ); - } - } - if ( TAFFY.isObject( c ) ){ - that.getDBI().update( r.___id, c, runEvent ); - } - }); - if ( this.context().results.length ){ - this.context( { run : null }); - } - return this; - }); - API.extend( 'remove', function ( runEvent ) { - // **************************************** - // * - // * Purpose: removes records from the DB via the remove and removeCommit DBI methods - // **************************************** - var that = this, c = 0; - run.call( this ); - each( this.context().results, function ( r ) { - that.getDBI().remove( r.___id ); - c++; - }); - if ( this.context().results.length ){ - this.context( { - run : null - }); - that.getDBI().removeCommit( runEvent ); - } - - return c; - }); - - - API.extend( 'count', function () { - // **************************************** - // * - // * Returns: The length of a query result - // **************************************** - run.call( this ); - return this.context().results.length; - }); - - API.extend( 'callback', function ( f, delay ) { - // **************************************** - // * - // * Returns null; - // * Runs a function on return of run.call - // **************************************** - if ( f ){ - var that = this; - setTimeout( function () { - run.call( that ); - f.call( that.getroot( that.context() ) ); - }, delay || 0 ); - } - - - return null; - }); - - API.extend( 'get', function () { - // **************************************** - // * - // * Returns: An array of all matching records - // **************************************** - run.call( this ); - return this.context().results; - }); - - API.extend( 'stringify', function () { - // **************************************** - // * - // * Returns: An JSON string of all matching records - // **************************************** - return JSON.stringify( this.get() ); - }); - API.extend( 'first', function () { - // **************************************** - // * - // * Returns: The first matching record - // **************************************** - run.call( this ); - return this.context().results[0] || false; - }); - API.extend( 'last', function () { - // **************************************** - // * - // * Returns: The last matching record - // **************************************** - run.call( this ); - return this.context().results[this.context().results.length - 1] || - false; - }); - - - API.extend( 'sum', function () { - // **************************************** - // * - // * Takes: column to sum up - // * Returns: Sums the values of a column - // **************************************** - var total = 0, that = this; - run.call( that ); - each( arguments, function ( c ) { - each( that.context().results, function ( r ) { - total = total + r[c]; - }); - }); - return total; - }); - - API.extend( 'min', function ( c ) { - // **************************************** - // * - // * Takes: column to find min - // * Returns: the lowest value - // **************************************** - var lowest = null; - run.call( this ); - each( this.context().results, function ( r ) { - if ( lowest === null || r[c] < lowest ){ - lowest = r[c]; - } - }); - return lowest; - }); - - // Taffy innerJoin Extension (OCD edition) - // ======================================= - // - // How to Use - // ********** - // - // left_table.innerJoin( right_table, condition1 <,... conditionN> ) - // - // A condition can take one of 2 forms: - // - // 1. An ARRAY with 2 or 3 values: - // A column name from the left table, an optional comparison string, - // and column name from the right table. The condition passes if the test - // indicated is true. If the condition string is omitted, '===' is assumed. - // EXAMPLES: [ 'last_used_time', '>=', 'current_use_time' ], [ 'user_id','id' ] - // - // 2. A FUNCTION: - // The function receives a left table row and right table row during the - // cartesian join. If the function returns true for the rows considered, - // the merged row is included in the result set. - // EXAMPLE: function (l,r){ return l.name === r.label; } - // - // Conditions are considered in the order they are presented. Therefore the best - // performance is realized when the least expensive and highest prune-rate - // conditions are placed first, since if they return false Taffy skips any - // further condition tests. - // - // Other notes - // *********** - // - // This code passes jslint with the exception of 2 warnings about - // the '==' and '!=' lines. We can't do anything about that short of - // deleting the lines. - // - // Credits - // ******* - // - // Heavily based upon the work of Ian Toltz. - // Revisions to API by Michael Mikowski. - // Code convention per standards in http://manning.com/mikowski - (function () { - var innerJoinFunction = (function () { - var fnCompareList, fnCombineRow, fnMain; - - fnCompareList = function ( left_row, right_row, arg_list ) { - var data_lt, data_rt, op_code, error; - - if ( arg_list.length === 2 ){ - data_lt = left_row[arg_list[0]]; - op_code = '==='; - data_rt = right_row[arg_list[1]]; - } - else { - data_lt = left_row[arg_list[0]]; - op_code = arg_list[1]; - data_rt = right_row[arg_list[2]]; - } - - /*jslint eqeq : true */ - switch ( op_code ){ - case '===' : - return data_lt === data_rt; - case '!==' : - return data_lt !== data_rt; - case '<' : - return data_lt < data_rt; - case '>' : - return data_lt > data_rt; - case '<=' : - return data_lt <= data_rt; - case '>=' : - return data_lt >= data_rt; - case '==' : - return data_lt == data_rt; - case '!=' : - return data_lt != data_rt; - default : - throw String( op_code ) + ' is not supported'; - } - // 'jslint eqeq : false' here results in - // "Unreachable '/*jslint' after 'return'". - // We don't need it though, as the rule exception - // is discarded at the end of this functional scope - }; - - fnCombineRow = function ( left_row, right_row ) { - var out_map = {}, i, prefix; - - for ( i in left_row ){ - if ( left_row.hasOwnProperty( i ) ){ - out_map[i] = left_row[i]; - } - } - for ( i in right_row ){ - if ( right_row.hasOwnProperty( i ) && i !== '___id' && - i !== '___s' ) - { - prefix = !TAFFY.isUndefined( out_map[i] ) ? 'right_' : ''; - out_map[prefix + String( i ) ] = right_row[i]; - } - } - return out_map; - }; - - fnMain = function ( table ) { - var - right_table, i, - arg_list = arguments, - arg_length = arg_list.length, - result_list = [] - ; - - if ( typeof table.filter !== 'function' ){ - if ( table.TAFFY ){ right_table = table(); } - else { - throw 'TAFFY DB or result not supplied'; - } - } - else { right_table = table; } - - this.context( { - results : this.getDBI().query( this.context() ) - } ); - - TAFFY.each( this.context().results, function ( left_row ) { - right_table.each( function ( right_row ) { - var arg_data, is_ok = true; - CONDITION: - for ( i = 1; i < arg_length; i++ ){ - arg_data = arg_list[i]; - if ( typeof arg_data === 'function' ){ - is_ok = arg_data( left_row, right_row ); - } - else if ( typeof arg_data === 'object' && arg_data.length ){ - is_ok = fnCompareList( left_row, right_row, arg_data ); - } - else { - is_ok = false; - } - - if ( !is_ok ){ break CONDITION; } // short circuit - } - - if ( is_ok ){ - result_list.push( fnCombineRow( left_row, right_row ) ); - } - } ); - } ); - return TAFFY( result_list )(); - }; - - return fnMain; - }()); - - API.extend( 'join', innerJoinFunction ); - }()); - - API.extend( 'max', function ( c ) { - // **************************************** - // * - // * Takes: column to find max - // * Returns: the highest value - // **************************************** - var highest = null; - run.call( this ); - each( this.context().results, function ( r ) { - if ( highest === null || r[c] > highest ){ - highest = r[c]; - } - }); - return highest; - }); - - API.extend( 'select', function () { - // **************************************** - // * - // * Takes: columns to select values into an array - // * Returns: array of values - // * Note if more than one column is given an array of arrays is returned - // **************************************** - - var ra = [], args = arguments; - run.call( this ); - if ( arguments.length === 1 ){ - - each( this.context().results, function ( r ) { - - ra.push( r[args[0]] ); - }); - } - else { - each( this.context().results, function ( r ) { - var row = []; - each( args, function ( c ) { - row.push( r[c] ); - }); - ra.push( row ); - }); - } - return ra; - }); - API.extend( 'distinct', function () { - // **************************************** - // * - // * Takes: columns to select unique alues into an array - // * Returns: array of values - // * Note if more than one column is given an array of arrays is returned - // **************************************** - var ra = [], args = arguments; - run.call( this ); - if ( arguments.length === 1 ){ - - each( this.context().results, function ( r ) { - var v = r[args[0]], dup = false; - each( ra, function ( d ) { - if ( v === d ){ - dup = true; - return TAFFY.EXIT; - } - }); - if ( !dup ){ - ra.push( v ); - } - }); - } - else { - each( this.context().results, function ( r ) { - var row = [], dup = false; - each( args, function ( c ) { - row.push( r[c] ); - }); - each( ra, function ( d ) { - var ldup = true; - each( args, function ( c, i ) { - if ( row[i] !== d[i] ){ - ldup = false; - return TAFFY.EXIT; - } - }); - if ( ldup ){ - dup = true; - return TAFFY.EXIT; - } - }); - if ( !dup ){ - ra.push( row ); - } - }); - } - return ra; - }); - API.extend( 'supplant', function ( template, returnarray ) { - // **************************************** - // * - // * Takes: a string template formated with key to be replaced with values from the rows, flag to determine if we want array of strings - // * Returns: array of values or a string - // **************************************** - var ra = []; - run.call( this ); - each( this.context().results, function ( r ) { - // TODO: The curly braces used to be unescaped - ra.push( template.replace( /\{([^\{\}]*)\}/g, function ( a, b ) { - var v = r[b]; - return typeof v === 'string' || typeof v === 'number' ? v : a; - } ) ); - }); - return (!returnarray) ? ra.join( "" ) : ra; - }); - - - API.extend( 'each', function ( m ) { - // **************************************** - // * - // * Takes: a function - // * Purpose: loops over every matching record and applies the function - // **************************************** - run.call( this ); - each( this.context().results, m ); - return this; - }); - API.extend( 'map', function ( m ) { - // **************************************** - // * - // * Takes: a function - // * Purpose: loops over every matching record and applies the function, returing the results in an array - // **************************************** - var ra = []; - run.call( this ); - each( this.context().results, function ( r ) { - ra.push( m( r ) ); - }); - return ra; - }); - - - - T = function ( d ) { - // **************************************** - // * - // * T is the main TAFFY object - // * Takes: an array of objects or JSON - // * Returns a new TAFFYDB - // **************************************** - var TOb = [], - ID = {}, - RC = 1, - settings = { - template : false, - onInsert : false, - onUpdate : false, - onRemove : false, - onDBChange : false, - storageName : false, - forcePropertyCase : null, - cacheSize : 100, - name : '' - }, - dm = new Date(), - CacheCount = 0, - CacheClear = 0, - Cache = {}, - DBI, runIndexes, root - ; - // **************************************** - // * - // * TOb = this database - // * ID = collection of the record IDs and locations within the DB, used for fast lookups - // * RC = record counter, used for creating IDs - // * settings.template = the template to merge all new records with - // * settings.onInsert = event given a copy of the newly inserted record - // * settings.onUpdate = event given the original record, the changes, and the new record - // * settings.onRemove = event given the removed record - // * settings.forcePropertyCase = on insert force the proprty case to be lower or upper. default lower, null/undefined will leave case as is - // * dm = the modify date of the database, used for query caching - // **************************************** - - - runIndexes = function ( indexes ) { - // **************************************** - // * - // * Takes: a collection of indexes - // * Returns: collection with records matching indexed filters - // **************************************** - - var records = [], UniqueEnforce = false; - - if ( indexes.length === 0 ){ - return TOb; - } - - each( indexes, function ( f ) { - // Check to see if record ID - if ( T.isString( f ) && /[t][0-9]*[r][0-9]*/i.test( f ) && - TOb[ID[f]] ) - { - records.push( TOb[ID[f]] ); - UniqueEnforce = true; - } - // Check to see if record - if ( T.isObject( f ) && f.___id && f.___s && - TOb[ID[f.___id]] ) - { - records.push( TOb[ID[f.___id]] ); - UniqueEnforce = true; - } - // Check to see if array of indexes - if ( T.isArray( f ) ){ - each( f, function ( r ) { - each( runIndexes( r ), function ( rr ) { - records.push( rr ); - }); - - }); - } - }); - if ( UniqueEnforce && records.length > 1 ){ - records = []; - } - - return records; - }; - - DBI = { - // **************************************** - // * - // * The DBI is the internal DataBase Interface that interacts with the data - // **************************************** - dm : function ( nd ) { - // **************************************** - // * - // * Takes: an optional new modify date - // * Purpose: used to get and set the DB modify date - // **************************************** - if ( nd ){ - dm = nd; - Cache = {}; - CacheCount = 0; - CacheClear = 0; - } - if ( settings.onDBChange ){ - setTimeout( function () { - settings.onDBChange.call( TOb ); - }, 0 ); - } - if ( settings.storageName ){ - setTimeout( function () { - localStorage.setItem( 'taffy_' + settings.storageName, - JSON.stringify( TOb ) ); - }); - } - return dm; - }, - insert : function ( i, runEvent ) { - // **************************************** - // * - // * Takes: a new record to insert - // * Purpose: merge the object with the template, add an ID, insert into DB, call insert event - // **************************************** - var columns = [], - records = [], - input = protectJSON( i ) - ; - each( input, function ( v, i ) { - var nv, o; - if ( T.isArray( v ) && i === 0 ){ - each( v, function ( av ) { - - columns.push( (settings.forcePropertyCase === 'lower') - ? av.toLowerCase() - : (settings.forcePropertyCase === 'upper') - ? av.toUpperCase() : av ); - }); - return true; - } - else if ( T.isArray( v ) ){ - nv = {}; - each( v, function ( av, ai ) { - nv[columns[ai]] = av; - }); - v = nv; - - } - else if ( T.isObject( v ) && settings.forcePropertyCase ){ - o = {}; - - eachin( v, function ( av, ai ) { - o[(settings.forcePropertyCase === 'lower') ? ai.toLowerCase() - : (settings.forcePropertyCase === 'upper') - ? ai.toUpperCase() : ai] = v[ai]; - }); - v = o; - } - - RC++; - v.___id = 'T' + String( idpad + TC ).slice( -6 ) + 'R' + - String( idpad + RC ).slice( -6 ); - v.___s = true; - records.push( v.___id ); - if ( settings.template ){ - v = T.mergeObj( settings.template, v ); - } - TOb.push( v ); - - ID[v.___id] = TOb.length - 1; - if ( settings.onInsert && - (runEvent || TAFFY.isUndefined( runEvent )) ) - { - settings.onInsert.call( v ); - } - DBI.dm( new Date() ); - }); - return root( records ); - }, - sort : function ( o ) { - // **************************************** - // * - // * Purpose: Change the sort order of the DB itself and reset the ID bucket - // **************************************** - TOb = orderByCol( TOb, o.split( ',' ) ); - ID = {}; - each( TOb, function ( r, i ) { - ID[r.___id] = i; - }); - DBI.dm( new Date() ); - return true; - }, - update : function ( id, changes, runEvent ) { - // **************************************** - // * - // * Takes: the ID of record being changed and the changes - // * Purpose: Update a record and change some or all values, call the on update method - // **************************************** - - var nc = {}, or, nr, tc, hasChange; - if ( settings.forcePropertyCase ){ - eachin( changes, function ( v, p ) { - nc[(settings.forcePropertyCase === 'lower') ? p.toLowerCase() - : (settings.forcePropertyCase === 'upper') ? p.toUpperCase() - : p] = v; - }); - changes = nc; - } - - or = TOb[ID[id]]; - nr = T.mergeObj( or, changes ); - - tc = {}; - hasChange = false; - eachin( nr, function ( v, i ) { - if ( TAFFY.isUndefined( or[i] ) || or[i] !== v ){ - tc[i] = v; - hasChange = true; - } - }); - if ( hasChange ){ - if ( settings.onUpdate && - (runEvent || TAFFY.isUndefined( runEvent )) ) - { - settings.onUpdate.call( nr, TOb[ID[id]], tc ); - } - TOb[ID[id]] = nr; - DBI.dm( new Date() ); - } - }, - remove : function ( id ) { - // **************************************** - // * - // * Takes: the ID of record to be removed - // * Purpose: remove a record, changes its ___s value to false - // **************************************** - TOb[ID[id]].___s = false; - }, - removeCommit : function ( runEvent ) { - var x; - // **************************************** - // * - // * - // * Purpose: loop over all records and remove records with ___s = false, call onRemove event, clear ID - // **************************************** - for ( x = TOb.length - 1; x > -1; x-- ){ - - if ( !TOb[x].___s ){ - if ( settings.onRemove && - (runEvent || TAFFY.isUndefined( runEvent )) ) - { - settings.onRemove.call( TOb[x] ); - } - ID[TOb[x].___id] = undefined; - TOb.splice( x, 1 ); - } - } - ID = {}; - each( TOb, function ( r, i ) { - ID[r.___id] = i; - }); - DBI.dm( new Date() ); - }, - query : function ( context ) { - // **************************************** - // * - // * Takes: the context object for a query and either returns a cache result or a new query result - // **************************************** - var returnq, cid, results, indexed, limitq, ni; - - if ( settings.cacheSize ) { - cid = ''; - each( context.filterRaw, function ( r ) { - if ( T.isFunction( r ) ){ - cid = 'nocache'; - return TAFFY.EXIT; - } - }); - if ( cid === '' ){ - cid = JSON.stringify( T.mergeObj( context, - {q : false, run : false, sort : false} ) ); - } - } - // Run a new query if there are no results or the run date has been cleared - if ( !context.results || !context.run || - (context.run && DBI.dm() > context.run) ) - { - results = []; - - // check Cache - - if ( settings.cacheSize && Cache[cid] ){ - - Cache[cid].i = CacheCount++; - return Cache[cid].results; - } - else { - // if no filter, return DB - if ( context.q.length === 0 && context.index.length === 0 ){ - each( TOb, function ( r ) { - results.push( r ); - }); - returnq = results; - } - else { - // use indexes - - indexed = runIndexes( context.index ); - - // run filters - each( indexed, function ( r ) { - // Run filter to see if record matches query - if ( context.q.length === 0 || runFilters( r, context.q ) ){ - results.push( r ); - } - }); - - returnq = results; - } - } - - - } - else { - // If query exists and run has not been cleared return the cache results - returnq = context.results; - } - // If a custom order array exists and the run has been clear or the sort has been cleared - if ( context.order.length > 0 && (!context.run || !context.sort) ){ - // order the results - returnq = orderByCol( returnq, context.order ); - } - - // If a limit on the number of results exists and it is less than the returned results, limit results - if ( returnq.length && - ((context.limit && context.limit < returnq.length) || - context.start) - ) { - limitq = []; - each( returnq, function ( r, i ) { - if ( !context.start || - (context.start && (i + 1) >= context.start) ) - { - if ( context.limit ){ - ni = (context.start) ? (i + 1) - context.start : i; - if ( ni < context.limit ){ - limitq.push( r ); - } - else if ( ni > context.limit ){ - return TAFFY.EXIT; - } - } - else { - limitq.push( r ); - } - } - }); - returnq = limitq; - } - - // update cache - if ( settings.cacheSize && cid !== 'nocache' ){ - CacheClear++; - - setTimeout( function () { - var bCounter, nc; - if ( CacheClear >= settings.cacheSize * 2 ){ - CacheClear = 0; - bCounter = CacheCount - settings.cacheSize; - nc = {}; - eachin( function ( r, k ) { - if ( r.i >= bCounter ){ - nc[k] = r; - } - }); - Cache = nc; - } - }, 0 ); - - Cache[cid] = { i : CacheCount++, results : returnq }; - } - return returnq; - } - }; - - - root = function () { - var iAPI, context; - // **************************************** - // * - // * The root function that gets returned when a new DB is created - // * Takes: unlimited filter arguments and creates filters to be run when a query is called - // **************************************** - // **************************************** - // * - // * iAPI is the the method collection valiable when a query has been started by calling dbname - // * Certain methods are or are not avaliable once you have started a query such as insert -- you can only insert into root - // **************************************** - iAPI = TAFFY.mergeObj( TAFFY.mergeObj( API, { insert : undefined } ), - { getDBI : function () { return DBI; }, - getroot : function ( c ) { return root.call( c ); }, - context : function ( n ) { - // **************************************** - // * - // * The context contains all the information to manage a query including filters, limits, and sorts - // **************************************** - if ( n ){ - context = TAFFY.mergeObj( context, - n.hasOwnProperty('results') - ? TAFFY.mergeObj( n, { run : new Date(), sort: new Date() }) - : n - ); - } - return context; - }, - extend : undefined - }); - - context = (this && this.q) ? this : { - limit : false, - start : false, - q : [], - filterRaw : [], - index : [], - order : [], - results : false, - run : null, - sort : null, - settings : settings - }; - // **************************************** - // * - // * Call the query method to setup a new query - // **************************************** - each( arguments, function ( f ) { - - if ( isIndexable( f ) ){ - context.index.push( f ); - } - else { - context.q.push( returnFilter( f ) ); - } - context.filterRaw.push( f ); - }); - - - return iAPI; - }; - - // **************************************** - // * - // * If new records have been passed on creation of the DB either as JSON or as an array/object, insert them - // **************************************** - TC++; - if ( d ){ - DBI.insert( d ); - } - - - root.insert = DBI.insert; - - root.merge = function ( i, key, runEvent ) { - var - search = {}, - finalSearch = [], - obj = {} - ; - - runEvent = runEvent || false; - key = key || 'id'; - - each( i, function ( o ) { - var existingObject; - search[key] = o[key]; - finalSearch.push( o[key] ); - existingObject = root( search ).first(); - if ( existingObject ){ - DBI.update( existingObject.___id, o, runEvent ); - } - else { - DBI.insert( o, runEvent ); - } - }); - - obj[key] = finalSearch; - return root( obj ); - }; - - root.TAFFY = true; - root.sort = DBI.sort; - // **************************************** - // * - // * These are the methods that can be accessed on off the root DB function. Example dbname.insert; - // **************************************** - root.settings = function ( n ) { - // **************************************** - // * - // * Getting and setting for this DB's settings/events - // **************************************** - if ( n ){ - settings = TAFFY.mergeObj( settings, n ); - if ( n.template ){ - - root().update( n.template ); - } - } - return settings; - }; - - // **************************************** - // * - // * These are the methods that can be accessed on off the root DB function. Example dbname.insert; - // **************************************** - root.store = function ( n ) { - // **************************************** - // * - // * Setup localstorage for this DB on a given name - // * Pull data into the DB as needed - // **************************************** - var r = false, i; - if ( localStorage ){ - if ( n ){ - i = localStorage.getItem( 'taffy_' + n ); - if ( i && i.length > 0 ){ - root.insert( i ); - r = true; - } - if ( TOb.length > 0 ){ - setTimeout( function () { - localStorage.setItem( 'taffy_' + settings.storageName, - JSON.stringify( TOb ) ); - }); - } - } - root.settings( {storageName : n} ); - } - return root; - }; - - // **************************************** - // * - // * Return root on DB creation and start having fun - // **************************************** - return root; - }; - // **************************************** - // * - // * Sets the global TAFFY object - // **************************************** - TAFFY = T; - - - // **************************************** - // * - // * Create public each method - // * - // **************************************** - T.each = each; - - // **************************************** - // * - // * Create public eachin method - // * - // **************************************** - T.eachin = eachin; - // **************************************** - // * - // * Create public extend method - // * Add a custom method to the API - // * - // **************************************** - T.extend = API.extend; - - - // **************************************** - // * - // * Creates TAFFY.EXIT value that can be returned to stop an each loop - // * - // **************************************** - TAFFY.EXIT = 'TAFFYEXIT'; - - // **************************************** - // * - // * Create public utility mergeObj method - // * Return a new object where items from obj2 - // * have replaced or been added to the items in - // * obj1 - // * Purpose: Used to combine objs - // * - // **************************************** - TAFFY.mergeObj = function ( ob1, ob2 ) { - var c = {}; - eachin( ob1, function ( v, n ) { c[n] = ob1[n]; }); - eachin( ob2, function ( v, n ) { c[n] = ob2[n]; }); - return c; - }; - - - // **************************************** - // * - // * Create public utility has method - // * Returns true if a complex object, array - // * or taffy collection contains the material - // * provided in the second argument - // * Purpose: Used to comare objects - // * - // **************************************** - TAFFY.has = function ( var1, var2 ) { - - var re = true, n; - - if ( (var1.TAFFY) ){ - re = var1( var2 ); - if ( re.length > 0 ){ - return true; - } - else { - return false; - } - } - else { - - switch ( T.typeOf( var1 ) ){ - case 'object': - if ( T.isObject( var2 ) ){ - eachin( var2, function ( v, n ) { - if ( re === true && !T.isUndefined( var1[n] ) && - var1.hasOwnProperty( n ) ) - { - re = T.has( var1[n], var2[n] ); - } - else { - re = false; - return TAFFY.EXIT; - } - }); - } - else if ( T.isArray( var2 ) ){ - each( var2, function ( v, n ) { - re = T.has( var1, var2[n] ); - if ( re ){ - return TAFFY.EXIT; - } - }); - } - else if ( T.isString( var2 ) ){ - if ( !TAFFY.isUndefined( var1[var2] ) ){ - return true; - } - else { - return false; - } - } - return re; - case 'array': - if ( T.isObject( var2 ) ){ - each( var1, function ( v, i ) { - re = T.has( var1[i], var2 ); - if ( re === true ){ - return TAFFY.EXIT; - } - }); - } - else if ( T.isArray( var2 ) ){ - each( var2, function ( v2, i2 ) { - each( var1, function ( v1, i1 ) { - re = T.has( var1[i1], var2[i2] ); - if ( re === true ){ - return TAFFY.EXIT; - } - }); - if ( re === true ){ - return TAFFY.EXIT; - } - }); - } - else if ( T.isString( var2 ) || T.isNumber( var2 ) ){ - for ( n = 0; n < var1.length; n++ ){ - re = T.has( var1[n], var2 ); - if ( re ){ - return true; - } - } - } - return re; - case 'string': - if ( T.isString( var2 ) && var2 === var1 ){ - return true; - } - break; - default: - if ( T.typeOf( var1 ) === T.typeOf( var2 ) && var1 === var2 ){ - return true; - } - break; - } - } - return false; - }; - - // **************************************** - // * - // * Create public utility hasAll method - // * Returns true if a complex object, array - // * or taffy collection contains the material - // * provided in the call - for arrays it must - // * contain all the material in each array item - // * Purpose: Used to comare objects - // * - // **************************************** - TAFFY.hasAll = function ( var1, var2 ) { - - var T = TAFFY, ar; - if ( T.isArray( var2 ) ){ - ar = true; - each( var2, function ( v ) { - ar = T.has( var1, v ); - if ( ar === false ){ - return TAFFY.EXIT; - } - }); - return ar; - } - else { - return T.has( var1, var2 ); - } - }; - - - // **************************************** - // * - // * typeOf Fixed in JavaScript as public utility - // * - // **************************************** - TAFFY.typeOf = function ( v ) { - var s = typeof v; - if ( s === 'object' ){ - if ( v ){ - if ( typeof v.length === 'number' && - !(v.propertyIsEnumerable( 'length' )) ) - { - s = 'array'; - } - } - else { - s = 'null'; - } - } - return s; - }; - - // **************************************** - // * - // * Create public utility getObjectKeys method - // * Returns an array of an objects keys - // * Purpose: Used to get the keys for an object - // * - // **************************************** - TAFFY.getObjectKeys = function ( ob ) { - var kA = []; - eachin( ob, function ( n, h ) { - kA.push( h ); - }); - kA.sort(); - return kA; - }; - - // **************************************** - // * - // * Create public utility isSameArray - // * Returns an array of an objects keys - // * Purpose: Used to get the keys for an object - // * - // **************************************** - TAFFY.isSameArray = function ( ar1, ar2 ) { - return (TAFFY.isArray( ar1 ) && TAFFY.isArray( ar2 ) && - ar1.join( ',' ) === ar2.join( ',' )) ? true : false; - }; - - // **************************************** - // * - // * Create public utility isSameObject method - // * Returns true if objects contain the same - // * material or false if they do not - // * Purpose: Used to comare objects - // * - // **************************************** - TAFFY.isSameObject = function ( ob1, ob2 ) { - var T = TAFFY, rv = true; - - if ( T.isObject( ob1 ) && T.isObject( ob2 ) ){ - if ( T.isSameArray( T.getObjectKeys( ob1 ), - T.getObjectKeys( ob2 ) ) ) - { - eachin( ob1, function ( v, n ) { - if ( ! ( (T.isObject( ob1[n] ) && T.isObject( ob2[n] ) && - T.isSameObject( ob1[n], ob2[n] )) || - (T.isArray( ob1[n] ) && T.isArray( ob2[n] ) && - T.isSameArray( ob1[n], ob2[n] )) || (ob1[n] === ob2[n]) ) - ) { - rv = false; - return TAFFY.EXIT; - } - }); - } - else { - rv = false; - } - } - else { - rv = false; - } - return rv; - }; - - // **************************************** - // * - // * Create public utility is[DataType] methods - // * Return true if obj is datatype, false otherwise - // * Purpose: Used to determine if arguments are of certain data type - // * - // * mmikowski 2012-08-06 refactored to make much less "magical": - // * fewer closures and passes jslint - // * - // **************************************** - - typeList = [ - 'String', 'Number', 'Object', 'Array', - 'Boolean', 'Null', 'Function', 'Undefined' - ]; - - makeTest = function ( thisKey ) { - return function ( data ) { - return TAFFY.typeOf( data ) === thisKey.toLowerCase() ? true : false; - }; - }; - - for ( idx = 0; idx < typeList.length; idx++ ){ - typeKey = typeList[idx]; - TAFFY['is' + typeKey] = makeTest( typeKey ); - } - } -}()); - -if ( typeof(exports) === 'object' ){ - exports.taffy = TAFFY; -} - diff --git a/node_modules/tv4/LICENSE.txt b/node_modules/tv4/LICENSE.txt deleted file mode 100644 index f421228b..00000000 --- a/node_modules/tv4/LICENSE.txt +++ /dev/null @@ -1,8 +0,0 @@ -/* -Author: Geraint Luff and others -Year: 2013 - -This code is released into the "public domain" by its author(s). Anybody may use, alter and distribute the code without restriction. The author makes no guarantees, and takes no liability of any kind for use of this code. - -If you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory. -*/ \ No newline at end of file diff --git a/node_modules/tv4/README.md b/node_modules/tv4/README.md deleted file mode 100644 index 66f263f0..00000000 --- a/node_modules/tv4/README.md +++ /dev/null @@ -1,453 +0,0 @@ -# Tiny Validator (for v4 JSON Schema) - -[![Build Status](https://secure.travis-ci.org/geraintluff/tv4.png?branch=master)](http://travis-ci.org/geraintluff/tv4) [![Dependency Status](https://gemnasium.com/geraintluff/tv4.png)](https://gemnasium.com/geraintluff/tv4) [![NPM version](https://badge.fury.io/js/tv4.png)](http://badge.fury.io/js/tv4) - -Use [json-schema](http://json-schema.org/) [draft v4](http://json-schema.org/latest/json-schema-core.html) to validate simple values and complex objects using a rich [validation vocabulary](http://json-schema.org/latest/json-schema-validation.html) ([examples](http://json-schema.org/examples.html)). - -There is support for `$ref` with JSON Pointer fragment paths (```other-schema.json#/properties/myKey```). - -## Usage 1: Simple validation - -```javascript -var valid = tv4.validate(data, schema); -``` - -If validation returns ```false```, then an explanation of why validation failed can be found in ```tv4.error```. - -The error object will look something like: -```json -{ - "code": 0, - "message": "Invalid type: string", - "dataPath": "/intKey", - "schemaKey": "/properties/intKey/type" -} -``` - -The `"code"` property will refer to one of the values in `tv4.errorCodes` - in this case, `tv4.errorCodes.INVALID_TYPE`. - -To enable external schema to be referenced, you use: -```javascript -tv4.addSchema(url, schema); -``` - -If schemas are referenced (```$ref```) but not known, then validation will return ```true``` and the missing schema(s) will be listed in ```tv4.missing```. For more info see the API documentation below. - -## Usage 2: Multi-threaded validation - -Storing the error and missing schemas does not work well in multi-threaded environments, so there is an alternative syntax: - -```javascript -var result = tv4.validateResult(data, schema); -``` - -The result will look something like: -```json -{ - "valid": false, - "error": {...}, - "missing": [...] -} -``` - -## Usage 3: Multiple errors - -Normally, `tv4` stops when it encounters the first validation error. However, you can collect an array of validation errors using: - -```javascript -var result = tv4.validateMultiple(data, schema); -``` - -The result will look something like: -```json -{ - "valid": false, - "errors": [ - {...}, - ... - ], - "missing": [...] -} -``` - -## Asynchronous validation - -Support for asynchronous validation (where missing schemas are fetched) can be added by including an extra JavaScript file. Currently, the only version requires jQuery (`tv4.async-jquery.js`), but the code is very short and should be fairly easy to modify for other libraries (such as MooTools). - -Usage: - -```javascript -tv4.validate(data, schema, function (isValid, validationError) { ... }); -``` - -`validationFailure` is simply taken from `tv4.error`. - -## Options - -You can use several options to change tv4's behavior when validating objects. Pass in an object to set these options for any of the regular validation methods: - -```javascript -tv4.validate(data, schema, {checkRecursive: true}); -var result = tv4.validateResult(data, schema, {checkRecursive: true}); -var multiple = tv4.validateMultiple(data, schema, {checkRecursive: true}); -``` - -For backwards compatibility, you can also pass in two booleans to set the `checkRecursive` and `banUnknownProperties` options; this method signature is deprecated: - -```javascript -// Set checkRecursive to false (the default) and banUnknownProperties to true -tv4.validate(data, schema, false, true); -``` - -The following sections describe the validation options. - -### Cyclical JavaScript objects - -While they don't occur in proper JSON, JavaScript does support self-referencing objects. Any of the above calls support a checkRecursive option. If true, tv4 will handle self-referencing objects properly - this slows down validation slightly, but that's better than a hanging script. - -Consider this data, notice how both `a` and `b` refer to each other: - -```javascript -var a = {}; -var b = { a: a }; -a.b = b; -var aSchema = { properties: { b: { $ref: 'bSchema' }}}; -var bSchema = { properties: { a: { $ref: 'aSchema' }}}; -tv4.addSchema('aSchema', aSchema); -tv4.addSchema('bSchema', bSchema); -``` - -By default, this causes the validation methods to throw a "too much recursion" error. - -To enable support for self-referencing objects, set the checkRecursive option to `true`: - -```javascript -tv4.validate(a, aSchema, {checkRecursive: true}); -tv4.validate(a, schema, asynchronousFunction, {checkRecursive: true}); - -tv4.validateResult(a, aSchema, {checkRecursive: true}); -tv4.validateMultiple(a, aSchema, {checkRecursive: true}); -``` - -### Properties not defined in the schema - -An object's schema may include an additionalProperties setting. When additionalProperties is set to `false`, objects will fail validation if they include properties that are not defined in the schema. - -You can enforce this behavior for all object schema by setting tv4's banUnknownProperties option to `true`: - -```javascript -tv4.validate(data, schema, {banUnknownProperties: true}); -tv4.validate(data, schema, asynchronousFunction, {banUnknownProperties: true}); - -tv4.validateResult(data, schema, {banUnknownProperties: true}); -tv4.validateMultiple(data, schema, {banUnknownProperties: true}); -``` - -### Inherited properties - -By default, tv4 does not validate an object's inherited properties, which are ignored when you convert an object to JSON. This behavior differs from tv4 1.0.16 and earlier, which always validated inherited properties. - -To validate inherited properties, set tv4's checkInheritedProperties option to `true`: - -```javascript -tv4.validate(data, schema, {checkInheritedProperties: true}); -tv4.validate(data, schema, asynchronousFunction, {checkInheritedProperties: true}); - -tv4.validateResult(data, schema, {checkInheritedProperties: true}); -tv4.validateMultiple(data, schema, {checkInheritedProperties: true}); -``` - -### Non-enumerable properties - -By default, tv4 does not validate an object's own non-enumerable properties, which are ignored when you convert an object to JSON. This behavior differs from tv4 1.0.16 and earlier, which always validated an object's own non-enumerable properties. - -To validate an object's own non-enumerable properties, set tv4's checkNonEnumerableProperties option to `true`: - -```javascript -tv4.validate(data, schema, {checkNonEnumerableProperties: true}); -tv4.validate(data, schema, asynchronousFunction, {checkNonEnumerableProperties: true}); - -tv4.validateResult(data, schema, {checkNonEnumerableProperties: true}); -tv4.validateMultiple(data, schema, {checkNonEnumerableProperties: true}); -``` - -## API - -There are additional api commands available for more complex use-cases: - -##### addSchema(uri, schema) -Pre-register a schema for reference by other schema and synchronous validation. - -````js -tv4.addSchema('http://example.com/schema', { ... }); -```` - -* `uri` the uri to identify this schema. -* `schema` the schema object. - -Schemas that have their `id` property set can be added directly. - -````js -tv4.addSchema({ ... }); -```` - -##### getSchema(uri) - -Return a schema from the cache. - -* `uri` the uri of the schema (may contain a `#` fragment) - -````js -var schema = tv4.getSchema('http://example.com/schema'); -```` - -##### getSchemaMap() - -Return a shallow copy of the schema cache, mapping schema document URIs to schema objects. - -```` -var map = tv4.getSchemaMap(); - -var schema = map[uri]; -```` - -##### getSchemaUris(filter) - -Return an Array with known schema document URIs. - -* `filter` optional RegExp to filter URIs - -```` -var arr = tv4.getSchemaUris(); - -// optional filter using a RegExp -var arr = tv4.getSchemaUris(/^https?://example.com/); -```` - -##### getMissingUris(filter) - -Return an Array with schema document URIs that are used as `$ref` in known schemas but which currently have no associated schema data. - -Use this in combination with `tv4.addSchema(uri, schema)` to preload the cache for complete synchronous validation with. - -* `filter` optional RegExp to filter URIs - -```` -var arr = tv4.getMissingUris(); - -// optional filter using a RegExp -var arr = tv4.getMissingUris(/^https?://example.com/); -```` - -##### dropSchemas() - -Drop all known schema document URIs from the cache. - -```` -tv4.dropSchemas(); -```` - -##### freshApi() - -Return a new tv4 instance with no shared state. - -```` -var otherTV4 = tv4.freshApi(); -```` - -##### reset() - -Manually reset validation status from the simple `tv4.validate(data, schema)`. Although tv4 will self reset on each validation there are some implementation scenarios where this is useful. - -```` -tv4.reset(); -```` - -##### language(code) - -Select the language map used for reporting. - -* `code` is a language code, like `'en'` or `'en-gb'` - -```` -tv4.language('en-gb'); -```` - -##### addLanguage(code, map) - -Add a new language map for selection by `tv4.language(code)` - -* `code` is new language code -* `map` is an object mapping error IDs or constant names (e.g. `103` or `"NUMBER_MAXIMUM"`) to language strings. - -```` -tv4.addLanguage('fr', { ... }); - -// select for use -tv4.language('fr') -```` - -##### addFormat(format, validationFunction) - -Add a custom format validator. (There are no built-in format validators.) - -* `format` is a string, corresponding to the `"format"` value in schemas. -* `validationFunction` is a function that either returns: - * `null` (meaning no error) - * an error string (explaining the reason for failure) - -```` -tv4.addFormat('decimal-digits', function (data, schema) { - if (typeof data === 'string' && !/^[0-9]+$/.test(data)) { - return null; - } - return "must be string of decimal digits"; -}); -```` - -Alternatively, multiple formats can be added at the same time using an object: -```` -tv4.addFormat({ - 'my-format': function () {...}, - 'other-format': function () {...} -}); -```` - -## Demos - -### Basic usage -
-
-var schema = {
-	"items": {
-		"type": "boolean"
-	}
-};
-var data1 = [true, false];
-var data2 = [true, 123];
-
-alert("data 1: " + tv4.validate(data1, schema)); // true
-alert("data 2: " + tv4.validate(data2, schema)); // false
-alert("data 2 error: " + JSON.stringify(tv4.error, null, 4));
-
-
- -### Use of $ref -
-
-var schema = {
-	"type": "array",
-	"items": {"$ref": "#"}
-};
-var data1 = [[], [[]]];
-var data2 = [[], [true, []]];
-
-alert("data 1: " + tv4.validate(data1, schema)); // true
-alert("data 2: " + tv4.validate(data2, schema)); // false
-
-
- -### Missing schema -
-
-var schema = {
-	"type": "array",
-	"items": {"$ref": "http://example.com/schema" }
-};
-var data = [1, 2, 3];
-
-alert("Valid: " + tv4.validate(data, schema)); // true
-alert("Missing schemas: " + JSON.stringify(tv4.missing));
-
-
- -### Referencing remote schema -
-
-tv4.addSchema("http://example.com/schema", {
-	"definitions": {
-		"arrayItem": {"type": "boolean"}
-	}
-});
-var schema = {
-	"type": "array",
-	"items": {"$ref": "http://example.com/schema#/definitions/arrayItem" }
-};
-var data1 = [true, false, true];
-var data2 = [1, 2, 3];
-
-alert("data 1: " + tv4.validate(data1, schema)); // true
-alert("data 2: " + tv4.validate(data2, schema)); // false
-
-
- -## Supported platforms - -* Node.js -* All modern browsers -* IE >= 7 - -## Installation - -You can manually download [`tv4.js`](https://raw.github.com/geraintluff/tv4/master/tv4.js) or the minified [`tv4.min.js`](https://raw.github.com/geraintluff/tv4/master/tv4.min.js) and include it in your html to create the global `tv4` variable. - -Alternately use it as a CommonJS module: - -````js -var tv4 = require('tv4'); -```` - -#### npm - -```` -$ npm install tv4 -```` - -#### bower - -```` -$ bower install tv4 -```` - -#### component.io - -```` -$ component install geraintluff/tv4 -```` - -## Build and test - -You can rebuild and run the node and browser tests using node.js and [grunt](http://http://gruntjs.com/): - -Make sure you have the global grunt cli command: -```` -$ npm install grunt-cli -g -```` - -Clone the git repos, open a shell in the root folder and install the development dependencies: - -```` -$ npm install -```` - -Rebuild and run the tests: -```` -$ grunt -```` - -It will run a build and display one Spec-style report for the node.js and two Dot-style reports for both the plain and minified browser tests (via phantomJS). You can also use your own browser to manually run the suites by opening [`test/index.html`](http://geraintluff.github.io/tv4/test/index.html) and [`test/index-min.html`](http://geraintluff.github.io/tv4/test/index-min.html). - -## Contributing - -Pull-requests for fixes and expansions are welcome. Edit the partial files in `/source` and add your tests in a suitable suite or folder under `/test/tests` and run `grunt` to rebuild and run the test suite. Try to maintain an idiomatic coding style and add tests for any new features. It is recommend to discuss big changes in an Issue. - -## Packages using tv4 - -* [chai-json-schema](http://chaijs.com/plugins/chai-json-schema) is a [Chai Assertion Library](http://chaijs.com) plugin to assert values against json-schema. -* [grunt-tv4](http://www.github.com/Bartvds/grunt-tv4) is a plugin for [Grunt](http://http://gruntjs.com/) that uses tv4 to bulk validate json files. - -## License - -The code is available as "public domain", meaning that it is completely free to use, without any restrictions at all. Read the full license [here](http://geraintluff.github.com/tv4/LICENSE.txt). - -It's also available under an [MIT license](http://jsonary.com/LICENSE.txt). diff --git a/node_modules/tv4/lang/de.js b/node_modules/tv4/lang/de.js deleted file mode 100644 index aeb9f12f..00000000 --- a/node_modules/tv4/lang/de.js +++ /dev/null @@ -1,29 +0,0 @@ -tv4.addLanguage('de', { - INVALID_TYPE: "Ungültiger Typ: {type} (erwartet wurde: {expected})", - ENUM_MISMATCH: "Keine Übereinstimmung mit der Aufzählung (enum) für: {value}", - ANY_OF_MISSING: "Daten stimmen nicht überein mit einem der Schemas von \"anyOf\"", - ONE_OF_MISSING: "Daten stimmen nicht überein mit einem der Schemas von \"oneOf\"", - ONE_OF_MULTIPLE: "Daten sind valid in Bezug auf mehreren Schemas von \"oneOf\": index {index1} und {index2}", - NOT_PASSED: "Daten stimmen mit dem \"not\" Schema überein", - // Numeric errors - NUMBER_MULTIPLE_OF: "Wert {value} ist kein Vielfaches von {multipleOf}", - NUMBER_MINIMUM: "Wert {value} ist kleiner als das Minimum {minimum}", - NUMBER_MINIMUM_EXCLUSIVE: "Wert {value} ist gleich dem Exklusiven Minimum {minimum}", - NUMBER_MAXIMUM: "Wert {value} ist größer als das Maximum {maximum}", - NUMBER_MAXIMUM_EXCLUSIVE: "Wert {value} ist gleich dem Exklusiven Maximum {maximum}", - // String errors - STRING_LENGTH_SHORT: "Zeichenkette zu kurz ({length} chars), minimum {minimum}", - STRING_LENGTH_LONG: "Zeichenkette zu lang ({length} chars), maximum {maximum}", - STRING_PATTERN: "Zeichenkette entspricht nicht dem Muster: {pattern}", - // Object errors - OBJECT_PROPERTIES_MINIMUM: "Zu wenige Attribute definiert ({propertyCount}), minimum {minimum}", - OBJECT_PROPERTIES_MAXIMUM: "Zu viele Attribute definiert ({propertyCount}), maximum {maximum}", - OBJECT_REQUIRED: "Notwendiges Attribut fehlt: {key}", - OBJECT_ADDITIONAL_PROPERTIES: "Zusätzliche Attribute nicht erlaubt", - OBJECT_DEPENDENCY_KEY: "Abhängigkeit fehlt - Schlüssel nicht vorhanden: {missing} (wegen Schlüssel: {key})", - // Array errors - ARRAY_LENGTH_SHORT: "Array zu kurz ({length}), minimum {minimum}", - ARRAY_LENGTH_LONG: "Array zu lang ({length}), maximum {maximum}", - ARRAY_UNIQUE: "Array Einträge nicht eindeutig (Index {match1} und {match2})", - ARRAY_ADDITIONAL_ITEMS: "Zusätzliche Einträge nicht erlaubt" -}); diff --git a/node_modules/tv4/package.json b/node_modules/tv4/package.json deleted file mode 100644 index 922346c8..00000000 --- a/node_modules/tv4/package.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "tv4", - "version": "1.0.15", - "author": { - "name": "Geraint Luff" - }, - "description": "A public domain JSON Schema validator for JavaScript", - "keywords": [ - "json-schema", - "schema", - "validator", - "tv4" - ], - "maintainers": [ - { - "name": "Geraint Luff", - "email": "luffgd@gmail.com", - "url": "https://github.com/geraintluff/" - } - ], - "main": "tv4.js", - "repository": { - "type": "git", - "url": "https://github.com/geraintluff/tv4.git" - }, - "license:": [ - { - "type": "Public Domain", - "url": "http://geraintluff.github.io/tv4/LICENSE.txt" - }, - { - "type": "MIT", - "url": "http://jsonary.com/LICENSE.txt" - } - ], - "devDependencies": { - "grunt": "~0.4.1", - "grunt-contrib-clean": "~0.4.1", - "grunt-contrib-jshint": "~0.6.2", - "mocha": "~1.11.0", - "grunt-mocha": "~0.4", - "grunt-mocha-test": "~0.5.0", - "grunt-cli": "~0.1.9", - "grunt-contrib-uglify": "~0.2.2", - "grunt-contrib-copy": "~0.4.1", - "proclaim": "1.4", - "mocha-unfunk-reporter": "~0.2", - "jshint-path-reporter": "~0.1", - "grunt-concat-sourcemap": "~0.2", - "source-map-support": "~0.1", - "grunt-markdown": "~0.3.0", - "grunt-component": "~0.1.4", - "grunt-push-release": "~0.1.1", - "grunt-regex-replace": "~0.2.5" - }, - "engines": { - "node": ">= 0.8.0" - }, - "scripts": { - "test": "grunt test", - "prepublish": "grunt prepublish" - }, - "readme": "# Tiny Validator (for v4 JSON Schema)\n\n[![Build Status](https://secure.travis-ci.org/geraintluff/tv4.png?branch=master)](http://travis-ci.org/geraintluff/tv4) [![Dependency Status](https://gemnasium.com/geraintluff/tv4.png)](https://gemnasium.com/geraintluff/tv4) [![NPM version](https://badge.fury.io/js/tv4.png)](http://badge.fury.io/js/tv4)\n\nUse [json-schema](http://json-schema.org/) [draft v4](http://json-schema.org/latest/json-schema-core.html) to validate simple values and complex objects using a rich [validation vocabulary](http://json-schema.org/latest/json-schema-validation.html) ([examples](http://json-schema.org/examples.html)).\n\nThere is support for `$ref` with JSON Pointer fragment paths (```other-schema.json#/properties/myKey```).\n\n## Usage 1: Simple validation\n\n```javascript\nvar valid = tv4.validate(data, schema);\n```\n\nIf validation returns ```false```, then an explanation of why validation failed can be found in ```tv4.error```.\n\nThe error object will look something like:\n```json\n{\n \"code\": 0,\n \"message\": \"Invalid type: string\",\n \"dataPath\": \"/intKey\",\n \"schemaKey\": \"/properties/intKey/type\"\n}\n```\n\nThe `\"code\"` property will refer to one of the values in `tv4.errorCodes` - in this case, `tv4.errorCodes.INVALID_TYPE`.\n\nTo enable external schema to be referenced, you use:\n```javascript\ntv4.addSchema(url, schema);\n```\n\nIf schemas are referenced (```$ref```) but not known, then validation will return ```true``` and the missing schema(s) will be listed in ```tv4.missing```. For more info see the API documentation below.\n\n## Usage 2: Multi-threaded validation\n\nStoring the error and missing schemas does not work well in multi-threaded environments, so there is an alternative syntax:\n\n```javascript\nvar result = tv4.validateResult(data, schema);\n```\n\nThe result will look something like:\n```json\n{\n \"valid\": false,\n \"error\": {...},\n \"missing\": [...]\n}\n```\n\n## Usage 3: Multiple errors\n\nNormally, `tv4` stops when it encounters the first validation error. However, you can collect an array of validation errors using:\n\n```javascript\nvar result = tv4.validateMultiple(data, schema);\n```\n\nThe result will look something like:\n```json\n{\n \"valid\": false,\n \"errors\": [\n {...},\n ...\n ],\n \"missing\": [...]\n}\n```\n\n## Asynchronous validation\n\nSupport for asynchronous validation (where missing schemas are fetched) can be added by including an extra JavaScript file. Currently, the only version requires jQuery (`tv4.async-jquery.js`), but the code is very short and should be fairly easy to modify for other libraries (such as MooTools).\n\nUsage:\n\n```javascript\ntv4.validate(data, schema, function (isValid, validationError) { ... });\n```\n\n`validationFailure` is simply taken from `tv4.error`.\n\n## Options\n\nYou can use several options to change tv4's behavior when validating objects. Pass in an object to set these options for any of the regular validation methods:\n\n```javascript\ntv4.validate(data, schema, {checkRecursive: true});\nvar result = tv4.validateResult(data, schema, {checkRecursive: true});\nvar multiple = tv4.validateMultiple(data, schema, {checkRecursive: true});\n```\n\nFor backwards compatibility, you can also pass in two booleans to set the `checkRecursive` and `banUnknownProperties` options; this method signature is deprecated:\n\n```javascript\n// Set checkRecursive to false (the default) and banUnknownProperties to true\ntv4.validate(data, schema, false, true);\n```\n\nThe following sections describe the validation options.\n\n### Cyclical JavaScript objects\n\nWhile they don't occur in proper JSON, JavaScript does support self-referencing objects. Any of the above calls support a checkRecursive option. If true, tv4 will handle self-referencing objects properly - this slows down validation slightly, but that's better than a hanging script.\n\nConsider this data, notice how both `a` and `b` refer to each other:\n\n```javascript\nvar a = {};\nvar b = { a: a };\na.b = b;\nvar aSchema = { properties: { b: { $ref: 'bSchema' }}};\nvar bSchema = { properties: { a: { $ref: 'aSchema' }}};\ntv4.addSchema('aSchema', aSchema);\ntv4.addSchema('bSchema', bSchema);\n```\n\nBy default, this causes the validation methods to throw a \"too much recursion\" error.\n\nTo enable support for self-referencing objects, set the checkRecursive option to `true`:\n\n```javascript\ntv4.validate(a, aSchema, {checkRecursive: true});\ntv4.validate(a, schema, asynchronousFunction, {checkRecursive: true});\n\ntv4.validateResult(a, aSchema, {checkRecursive: true});\ntv4.validateMultiple(a, aSchema, {checkRecursive: true});\n```\n\n### Properties not defined in the schema\n\nAn object's schema may include an additionalProperties setting. When additionalProperties is set to `false`, objects will fail validation if they include properties that are not defined in the schema.\n\nYou can enforce this behavior for all object schema by setting tv4's banUnknownProperties option to `true`:\n\n```javascript\ntv4.validate(data, schema, {banUnknownProperties: true});\ntv4.validate(data, schema, asynchronousFunction, {banUnknownProperties: true});\n\ntv4.validateResult(data, schema, {banUnknownProperties: true});\ntv4.validateMultiple(data, schema, {banUnknownProperties: true});\n```\n\n### Inherited properties\n\nBy default, tv4 does not validate an object's inherited properties, which are ignored when you convert an object to JSON. This behavior differs from tv4 1.0.16 and earlier, which always validated inherited properties.\n\nTo validate inherited properties, set tv4's checkInheritedProperties option to `true`:\n\n```javascript\ntv4.validate(data, schema, {checkInheritedProperties: true});\ntv4.validate(data, schema, asynchronousFunction, {checkInheritedProperties: true});\n\ntv4.validateResult(data, schema, {checkInheritedProperties: true});\ntv4.validateMultiple(data, schema, {checkInheritedProperties: true});\n```\n\n### Non-enumerable properties\n\nBy default, tv4 does not validate an object's own non-enumerable properties, which are ignored when you convert an object to JSON. This behavior differs from tv4 1.0.16 and earlier, which always validated an object's own non-enumerable properties.\n\nTo validate an object's own non-enumerable properties, set tv4's checkNonEnumerableProperties option to `true`:\n\n```javascript\ntv4.validate(data, schema, {checkNonEnumerableProperties: true});\ntv4.validate(data, schema, asynchronousFunction, {checkNonEnumerableProperties: true});\n\ntv4.validateResult(data, schema, {checkNonEnumerableProperties: true});\ntv4.validateMultiple(data, schema, {checkNonEnumerableProperties: true});\n```\n\n## API\n\nThere are additional api commands available for more complex use-cases:\n\n##### addSchema(uri, schema)\nPre-register a schema for reference by other schema and synchronous validation.\n\n````js\ntv4.addSchema('http://example.com/schema', { ... });\n````\n\n* `uri` the uri to identify this schema.\n* `schema` the schema object.\n\nSchemas that have their `id` property set can be added directly.\n\n````js\ntv4.addSchema({ ... });\n````\n\n##### getSchema(uri)\n\nReturn a schema from the cache.\n\n* `uri` the uri of the schema (may contain a `#` fragment)\n\n````js\nvar schema = tv4.getSchema('http://example.com/schema');\n````\n\n##### getSchemaMap()\n\nReturn a shallow copy of the schema cache, mapping schema document URIs to schema objects.\n\n````\nvar map = tv4.getSchemaMap();\n\nvar schema = map[uri];\n````\n\n##### getSchemaUris(filter)\n\nReturn an Array with known schema document URIs.\n\n* `filter` optional RegExp to filter URIs\n\n````\nvar arr = tv4.getSchemaUris();\n\n// optional filter using a RegExp\nvar arr = tv4.getSchemaUris(/^https?://example.com/);\n````\n\n##### getMissingUris(filter)\n\nReturn an Array with schema document URIs that are used as `$ref` in known schemas but which currently have no associated schema data.\n\nUse this in combination with `tv4.addSchema(uri, schema)` to preload the cache for complete synchronous validation with.\n\n* `filter` optional RegExp to filter URIs\n\n````\nvar arr = tv4.getMissingUris();\n\n// optional filter using a RegExp\nvar arr = tv4.getMissingUris(/^https?://example.com/);\n````\n\n##### dropSchemas()\n\nDrop all known schema document URIs from the cache.\n\n````\ntv4.dropSchemas();\n````\n\n##### freshApi()\n\nReturn a new tv4 instance with no shared state.\n\n````\nvar otherTV4 = tv4.freshApi();\n````\n\n##### reset()\n\nManually reset validation status from the simple `tv4.validate(data, schema)`. Although tv4 will self reset on each validation there are some implementation scenarios where this is useful.\n\n````\ntv4.reset();\n````\n\n##### language(code)\n\nSelect the language map used for reporting.\n\n* `code` is a language code, like `'en'` or `'en-gb'`\n\n````\ntv4.language('en-gb');\n````\n\n##### addLanguage(code, map)\n\nAdd a new language map for selection by `tv4.language(code)`\n\n* `code` is new language code\n* `map` is an object mapping error IDs or constant names (e.g. `103` or `\"NUMBER_MAXIMUM\"`) to language strings.\n\n````\ntv4.addLanguage('fr', { ... });\n\n// select for use\ntv4.language('fr')\n````\n\n##### addFormat(format, validationFunction)\n\nAdd a custom format validator. (There are no built-in format validators.)\n\n* `format` is a string, corresponding to the `\"format\"` value in schemas.\n* `validationFunction` is a function that either returns:\n * `null` (meaning no error)\n * an error string (explaining the reason for failure)\n\n````\ntv4.addFormat('decimal-digits', function (data, schema) {\n\tif (typeof data === 'string' && !/^[0-9]+$/.test(data)) {\n\t\treturn null;\n\t}\n\treturn \"must be string of decimal digits\";\n});\n````\n\nAlternatively, multiple formats can be added at the same time using an object:\n````\ntv4.addFormat({\n\t'my-format': function () {...},\n\t'other-format': function () {...}\n});\n````\n\n## Demos\n\n### Basic usage\n
\n
\nvar schema = {\n\t\"items\": {\n\t\t\"type\": \"boolean\"\n\t}\n};\nvar data1 = [true, false];\nvar data2 = [true, 123];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\nalert(\"data 2 error: \" + JSON.stringify(tv4.error, null, 4));\n
\n
\n\n### Use of $ref\n
\n
\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"#\"}\n};\nvar data1 = [[], [[]]];\nvar data2 = [[], [true, []]];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\n
\n
\n\n### Missing schema\n
\n
\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"http://example.com/schema\" }\n};\nvar data = [1, 2, 3];\n\nalert(\"Valid: \" + tv4.validate(data, schema)); // true\nalert(\"Missing schemas: \" + JSON.stringify(tv4.missing));\n
\n
\n\n### Referencing remote schema\n
\n
\ntv4.addSchema(\"http://example.com/schema\", {\n\t\"definitions\": {\n\t\t\"arrayItem\": {\"type\": \"boolean\"}\n\t}\n});\nvar schema = {\n\t\"type\": \"array\",\n\t\"items\": {\"$ref\": \"http://example.com/schema#/definitions/arrayItem\" }\n};\nvar data1 = [true, false, true];\nvar data2 = [1, 2, 3];\n\nalert(\"data 1: \" + tv4.validate(data1, schema)); // true\nalert(\"data 2: \" + tv4.validate(data2, schema)); // false\n
\n
\n\n## Supported platforms\n\n* Node.js\n* All modern browsers\n* IE >= 7\n\n## Installation\n\nYou can manually download [`tv4.js`](https://raw.github.com/geraintluff/tv4/master/tv4.js) or the minified [`tv4.min.js`](https://raw.github.com/geraintluff/tv4/master/tv4.min.js) and include it in your html to create the global `tv4` variable.\n\nAlternately use it as a CommonJS module:\n\n````js\nvar tv4 = require('tv4');\n````\n\n#### npm\n\n````\n$ npm install tv4\n````\n\n#### bower\n\n````\n$ bower install tv4\n````\n\n#### component.io\n\n````\n$ component install geraintluff/tv4\n````\n\n## Build and test\n\nYou can rebuild and run the node and browser tests using node.js and [grunt](http://http://gruntjs.com/):\n\nMake sure you have the global grunt cli command:\n````\n$ npm install grunt-cli -g\n````\n\nClone the git repos, open a shell in the root folder and install the development dependencies:\n\n````\n$ npm install\n````\n\nRebuild and run the tests:\n````\n$ grunt\n````\n\nIt will run a build and display one Spec-style report for the node.js and two Dot-style reports for both the plain and minified browser tests (via phantomJS). You can also use your own browser to manually run the suites by opening [`test/index.html`](http://geraintluff.github.io/tv4/test/index.html) and [`test/index-min.html`](http://geraintluff.github.io/tv4/test/index-min.html).\n\n## Contributing\n\nPull-requests for fixes and expansions are welcome. Edit the partial files in `/source` and add your tests in a suitable suite or folder under `/test/tests` and run `grunt` to rebuild and run the test suite. Try to maintain an idiomatic coding style and add tests for any new features. It is recommend to discuss big changes in an Issue.\n\n## Packages using tv4\n\n* [chai-json-schema](http://chaijs.com/plugins/chai-json-schema) is a [Chai Assertion Library](http://chaijs.com) plugin to assert values against json-schema.\n* [grunt-tv4](http://www.github.com/Bartvds/grunt-tv4) is a plugin for [Grunt](http://http://gruntjs.com/) that uses tv4 to bulk validate json files.\n\n## License\n\nThe code is available as \"public domain\", meaning that it is completely free to use, without any restrictions at all. Read the full license [here](http://geraintluff.github.com/tv4/LICENSE.txt).\n\nIt's also available under an [MIT license](http://jsonary.com/LICENSE.txt).\n", - "readmeFilename": "README.md", - "bugs": { - "url": "https://github.com/geraintluff/tv4/issues" - }, - "homepage": "https://github.com/geraintluff/tv4", - "_id": "tv4@1.0.15", - "_shasum": "081e6823ee51d67aabe5b92ea3a00804902be155", - "_from": "https://github.com/hegemonic/tv4/tarball/own-properties", - "_resolved": "https://github.com/hegemonic/tv4/tarball/own-properties" -} diff --git a/node_modules/tv4/tv4.async-jquery.js b/node_modules/tv4/tv4.async-jquery.js deleted file mode 100644 index 761f232a..00000000 --- a/node_modules/tv4/tv4.async-jquery.js +++ /dev/null @@ -1,34 +0,0 @@ -// Provides support for asynchronous validation (fetching schemas) using jQuery -// Callback is optional third argument to tv4.validate() - if not present, synchronous operation -// callback(result, error); -if (typeof (tv4.asyncValidate) === 'undefined') { - tv4.syncValidate = tv4.validate; - tv4.validate = function (data, schema, callback, checkRecursive, banUnknownProperties) { - if (typeof (callback) === 'undefined') { - return this.syncValidate(data, schema, checkRecursive, banUnknownProperties); - } else { - return this.asyncValidate(data, schema, callback, checkRecursive, banUnknownProperties); - } - }; - tv4.asyncValidate = function (data, schema, callback, checkRecursive, banUnknownProperties) { - var $ = jQuery; - var result = tv4.validate(data, schema, checkRecursive, banUnknownProperties); - if (!tv4.missing.length) { - callback(result, tv4.error); - } else { - // Make a request for each missing schema - var missingSchemas = $.map(tv4.missing, function (schemaUri) { - return $.getJSON(schemaUri).success(function (fetchedSchema) { - tv4.addSchema(schemaUri, fetchedSchema); - }).error(function () { - // If there's an error, just use an empty schema - tv4.addSchema(schemaUri, {}); - }); - }); - // When all requests done, try again - $.when.apply($, missingSchemas).done(function () { - var result = tv4.asyncValidate(data, schema, callback, checkRecursive, banUnknownProperties); - }); - } - }; -} diff --git a/node_modules/tv4/tv4.js b/node_modules/tv4/tv4.js deleted file mode 100644 index 37a36241..00000000 --- a/node_modules/tv4/tv4.js +++ /dev/null @@ -1,1388 +0,0 @@ -/* -Author: Geraint Luff and others -Year: 2013 - -This code is released into the "public domain" by its author(s). Anybody may use, alter and distribute the code without restriction. The author makes no guarantees, and takes no liability of any kind for use of this code. - -If you find a bug or make an improvement, it would be courteous to let the author know, but it is not compulsory. -*/ -(function (global) { -'use strict'; - -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fkeys -if (!Object.keys) { - Object.keys = (function () { - var hasOwnProperty = Object.prototype.hasOwnProperty, - hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'), - dontEnums = [ - 'toString', - 'toLocaleString', - 'valueOf', - 'hasOwnProperty', - 'isPrototypeOf', - 'propertyIsEnumerable', - 'constructor' - ], - dontEnumsLength = dontEnums.length; - - return function (obj) { - if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) { - throw new TypeError('Object.keys called on non-object'); - } - - var result = []; - - for (var prop in obj) { - if (hasOwnProperty.call(obj, prop)) { - result.push(prop); - } - } - - if (hasDontEnumBug) { - for (var i=0; i < dontEnumsLength; i++) { - if (hasOwnProperty.call(obj, dontEnums[i])) { - result.push(dontEnums[i]); - } - } - } - return result; - }; - })(); -} -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create -if (!Object.create) { - Object.create = (function(){ - function F(){} - - return function(o){ - if (arguments.length !== 1) { - throw new Error('Object.create implementation only accepts one parameter.'); - } - F.prototype = o; - return new F(); - }; - })(); -} -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FisArray -if(!Array.isArray) { - Array.isArray = function (vArg) { - return Object.prototype.toString.call(vArg) === "[object Array]"; - }; -} -// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2FindexOf -if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) { - if (this === null) { - throw new TypeError(); - } - var t = Object(this); - var len = t.length >>> 0; - - if (len === 0) { - return -1; - } - var n = 0; - if (arguments.length > 1) { - n = Number(arguments[1]); - if (n !== n) { // shortcut for verifying if it's NaN - n = 0; - } else if (n !== 0 && n !== Infinity && n !== -Infinity) { - n = (n > 0 || -1) * Math.floor(Math.abs(n)); - } - } - if (n >= len) { - return -1; - } - var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0); - for (; k < len; k++) { - if (k in t && t[k] === searchElement) { - return k; - } - } - return -1; - }; -} - -// Grungey Object.isFrozen hack -if (!Object.isFrozen) { - Object.isFrozen = function (obj) { - var key = "tv4_test_frozen_key"; - while (obj.hasOwnProperty(key)) { - key += Math.random(); - } - try { - obj[key] = true; - delete obj[key]; - return false; - } catch (e) { - return true; - } - }; -} -var ValidatorContext = function ValidatorContext(parent, collectMultiple, errorMessages, options) { - this.missing = []; - this.missingMap = {}; - this.formatValidators = parent ? Object.create(parent.formatValidators) : {}; - this.schemas = parent ? Object.create(parent.schemas) : {}; - this.collectMultiple = collectMultiple; - this.errors = []; - this.handleError = collectMultiple ? this.collectError : this.returnError; - options = options || {}; - if (options.checkRecursive) { - this.checkRecursive = true; - this.scanned = []; - this.scannedFrozen = []; - this.scannedFrozenSchemas = []; - this.scannedFrozenValidationErrors = []; - this.validatedSchemasKey = 'tv4_validation_id'; - this.validationErrorsKey = 'tv4_validation_errors_id'; - } - if (options.banUnknownProperties) { - this.trackUnknownProperties = true; - this.knownPropertyPaths = {}; - this.unknownPropertyPaths = {}; - } - if (options.checkInheritedProperties) { - this.checkInheritedProperties = true; - } - if (options.checkNonEnumerableProperties) { - this.checkNonEnumerableProperties = true; - } - this.errorMessages = errorMessages; -}; -ValidatorContext.prototype.createError = function (code, messageParams, dataPath, schemaPath, subErrors) { - var messageTemplate = this.errorMessages[code] || ErrorMessagesDefault[code]; - if (typeof messageTemplate !== 'string') { - return new ValidationError(code, "Unknown error code " + code + ": " + JSON.stringify(messageParams), dataPath, schemaPath, subErrors); - } - // Adapted from Crockford's supplant() - var message = messageTemplate.replace(/\{([^{}]*)\}/g, function (whole, varName) { - var subValue = messageParams[varName]; - return typeof subValue === 'string' || typeof subValue === 'number' ? subValue : whole; - }); - return new ValidationError(code, message, dataPath, schemaPath, subErrors); -}; -ValidatorContext.prototype.returnError = function (error) { - return error; -}; -ValidatorContext.prototype.collectError = function (error) { - if (error) { - this.errors.push(error); - } - return null; -}; -ValidatorContext.prototype.prefixErrors = function (startIndex, dataPath, schemaPath) { - for (var i = startIndex; i < this.errors.length; i++) { - this.errors[i] = this.errors[i].prefixWith(dataPath, schemaPath); - } - return this; -}; -ValidatorContext.prototype.banUnknownProperties = function () { - if (this.trackUnknownProperties) { - var unknownPaths = Object.keys(this.unknownPropertyPaths); - for (var i = 0; i < unknownPaths.length; i++) { - var unknownPath = unknownPaths[i]; - var error = this.createError(ErrorCodes.UNKNOWN_PROPERTY, {path: unknownPath}, unknownPath, ""); - var result = this.handleError(error); - if (result) { - return result; - } - } - } - return null; -}; - -ValidatorContext.prototype.addFormat = function (format, validator) { - if (typeof format === 'object') { - var formatKeys = Object.keys(format); - for (var i = 0; i < formatKeys.length; i++) { - var key = formatKeys[i]; - this.addFormat(key, format[key]); - } - return this; - } - this.formatValidators[format] = validator; -}; -ValidatorContext.prototype.resolveRefs = function (schema, urlHistory) { - if (schema['$ref'] !== undefined) { - urlHistory = urlHistory || {}; - if (urlHistory[schema['$ref']]) { - return this.createError(ErrorCodes.CIRCULAR_REFERENCE, {urls: Object.keys(urlHistory).join(', ')}, '', ''); - } - urlHistory[schema['$ref']] = true; - schema = this.getSchema(schema['$ref'], urlHistory); - } - return schema; -}; -ValidatorContext.prototype.getSchema = function (url, urlHistory) { - var schema; - if (this.schemas[url] !== undefined) { - schema = this.schemas[url]; - return this.resolveRefs(schema, urlHistory); - } - var baseUrl = url; - var fragment = ""; - if (url.indexOf('#') !== -1) { - fragment = url.substring(url.indexOf("#") + 1); - baseUrl = url.substring(0, url.indexOf("#")); - } - if (typeof this.schemas[baseUrl] === 'object') { - schema = this.schemas[baseUrl]; - var pointerPath = decodeURIComponent(fragment); - if (pointerPath === "") { - return this.resolveRefs(schema, urlHistory); - } else if (pointerPath.charAt(0) !== "/") { - return undefined; - } - var parts = pointerPath.split("/").slice(1); - for (var i = 0; i < parts.length; i++) { - var component = parts[i].replace(/~1/g, "/").replace(/~0/g, "~"); - if (schema[component] === undefined) { - schema = undefined; - break; - } - schema = schema[component]; - } - if (schema !== undefined) { - return this.resolveRefs(schema, urlHistory); - } - } - if (this.missing[baseUrl] === undefined) { - this.missing.push(baseUrl); - this.missing[baseUrl] = baseUrl; - this.missingMap[baseUrl] = baseUrl; - } -}; -ValidatorContext.prototype.searchSchemas = function (schema, url) { - if (schema && typeof schema === "object") { - if (typeof schema.id === "string") { - if (isTrustedUrl(url, schema.id)) { - if (this.schemas[schema.id] === undefined) { - this.schemas[schema.id] = schema; - } - } - } - var schemaKeys = Object.keys(schema); - for (var i = 0; i < schemaKeys.length; i++) { - var key = schemaKeys[i]; - if (key !== "enum") { - if (typeof schema[key] === "object") { - this.searchSchemas(schema[key], url); - } else if (key === "$ref") { - var uri = getDocumentUri(schema[key]); - if (uri && this.schemas[uri] === undefined && this.missingMap[uri] === undefined) { - this.missingMap[uri] = uri; - } - } - } - } - } -}; -ValidatorContext.prototype.addSchema = function (url, schema) { - //overload - if (typeof url !== 'string' || typeof schema === 'undefined') { - if (typeof url === 'object' && typeof url.id === 'string') { - schema = url; - url = schema.id; - } - else { - return; - } - } - if (url = getDocumentUri(url) + "#") { - // Remove empty fragment - url = getDocumentUri(url); - } - this.schemas[url] = schema; - delete this.missingMap[url]; - normSchema(schema, url); - this.searchSchemas(schema, url); -}; - -ValidatorContext.prototype.getSchemaMap = function () { - var map = {}; - var schemaKeys = Object.keys(this.schemas); - for (var i = 0; i < schemaKeys.length; i++) { - var key = schemaKeys[i]; - map[key] = this.schemas[key]; - } - return map; -}; - -ValidatorContext.prototype.getSchemaUris = function (filterRegExp) { - var list = []; - var schemaKeys = Object.keys(this.schemas); - for (var i = 0; i < schemaKeys.length; i++) { - var key = schemaKeys[i]; - if (!filterRegExp || filterRegExp.test(key)) { - list.push(key); - } - } - return list; -}; - -ValidatorContext.prototype.getMissingUris = function (filterRegExp) { - var list = []; - var missingKeys = Object.keys(this.missingMap); - for (var i = 0; i < missingKeys.length; i++) { - var key = missingKeys[i]; - if (!filterRegExp || filterRegExp.test(key)) { - list.push(key); - } - } - return list; -}; - -ValidatorContext.prototype.dropSchemas = function () { - this.schemas = {}; - this.reset(); -}; -ValidatorContext.prototype.reset = function () { - this.missing = []; - this.missingMap = {}; - this.errors = []; -}; - -ValidatorContext.prototype.validateAll = function (data, schema, dataPathParts, schemaPathParts, dataPointerPath) { - var topLevel; - schema = this.resolveRefs(schema); - if (!schema) { - return null; - } else if (schema instanceof ValidationError) { - this.errors.push(schema); - return schema; - } - - var startErrorCount = this.errors.length; - var frozenIndex, scannedFrozenSchemaIndex = null, scannedSchemasIndex = null; - if (this.checkRecursive && (typeof data) === 'object') { - topLevel = !this.scanned.length; - if (data[this.validatedSchemasKey]) { - var schemaIndex = data[this.validatedSchemasKey].indexOf(schema); - if (schemaIndex !== -1) { - this.errors = this.errors.concat(data[this.validationErrorsKey][schemaIndex]); - return null; - } - } - if (Object.isFrozen(data)) { - frozenIndex = this.scannedFrozen.indexOf(data); - if (frozenIndex !== -1) { - var frozenSchemaIndex = this.scannedFrozenSchemas[frozenIndex].indexOf(schema); - if (frozenSchemaIndex !== -1) { - this.errors = this.errors.concat(this.scannedFrozenValidationErrors[frozenIndex][frozenSchemaIndex]); - return null; - } - } - } - this.scanned.push(data); - if (Object.isFrozen(data)) { - if (frozenIndex === -1) { - frozenIndex = this.scannedFrozen.length; - this.scannedFrozen.push(data); - this.scannedFrozenSchemas.push([]); - } - scannedFrozenSchemaIndex = this.scannedFrozenSchemas[frozenIndex].length; - this.scannedFrozenSchemas[frozenIndex][scannedFrozenSchemaIndex] = schema; - this.scannedFrozenValidationErrors[frozenIndex][scannedFrozenSchemaIndex] = []; - } else { - if (!data[this.validatedSchemasKey]) { - try { - Object.defineProperty(data, this.validatedSchemasKey, { - value: [], - configurable: true - }); - Object.defineProperty(data, this.validationErrorsKey, { - value: [], - configurable: true - }); - } catch (e) { - //IE 7/8 workaround - data[this.validatedSchemasKey] = []; - data[this.validationErrorsKey] = []; - } - } - scannedSchemasIndex = data[this.validatedSchemasKey].length; - data[this.validatedSchemasKey][scannedSchemasIndex] = schema; - data[this.validationErrorsKey][scannedSchemasIndex] = []; - } - } - - var errorCount = this.errors.length; - var error = this.validateBasic(data, schema, dataPointerPath) - || this.validateNumeric(data, schema, dataPointerPath) - || this.validateString(data, schema, dataPointerPath) - || this.validateArray(data, schema, dataPointerPath) - || this.validateObject(data, schema, dataPointerPath) - || this.validateCombinations(data, schema, dataPointerPath) - || this.validateFormat(data, schema, dataPointerPath) - || null; - - if (topLevel) { - while (this.scanned.length) { - var item = this.scanned.pop(); - delete item[this.validatedSchemasKey]; - } - this.scannedFrozen = []; - this.scannedFrozenSchemas = []; - } - - if (error || errorCount !== this.errors.length) { - while ((dataPathParts && dataPathParts.length) || (schemaPathParts && schemaPathParts.length)) { - var dataPart = (dataPathParts && dataPathParts.length) ? "" + dataPathParts.pop() : null; - var schemaPart = (schemaPathParts && schemaPathParts.length) ? "" + schemaPathParts.pop() : null; - if (error) { - error = error.prefixWith(dataPart, schemaPart); - } - this.prefixErrors(errorCount, dataPart, schemaPart); - } - } - - if (scannedFrozenSchemaIndex !== null) { - this.scannedFrozenValidationErrors[frozenIndex][scannedFrozenSchemaIndex] = this.errors.slice(startErrorCount); - } else if (scannedSchemasIndex !== null) { - data[this.validationErrorsKey][scannedSchemasIndex] = this.errors.slice(startErrorCount); - } - - return this.handleError(error); -}; -ValidatorContext.prototype.validateFormat = function (data, schema) { - if (typeof schema.format !== 'string' || !this.formatValidators[schema.format]) { - return null; - } - var errorMessage = this.formatValidators[schema.format].call(null, data, schema); - if (typeof errorMessage === 'string' || typeof errorMessage === 'number') { - return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage}).prefixWith(null, "format"); - } else if (errorMessage && typeof errorMessage === 'object') { - return this.createError(ErrorCodes.FORMAT_CUSTOM, {message: errorMessage.message || "?"}, errorMessage.dataPath || null, errorMessage.schemaPath || "/format"); - } - return null; -}; - -function recursiveCompare(A, B) { - if (A === B) { - return true; - } - if (typeof A === "object" && typeof B === "object") { - if (Array.isArray(A) !== Array.isArray(B)) { - return false; - } else if (Array.isArray(A)) { - if (A.length !== B.length) { - return false; - } - for (var i = 0; i < A.length; i++) { - if (!recursiveCompare(A[i], B[i])) { - return false; - } - } - } else { - var key; - for (key in A) { - if (B[key] === undefined && A[key] !== undefined) { - return false; - } - } - for (key in B) { - if (A[key] === undefined && B[key] !== undefined) { - return false; - } - } - for (key in A) { - if (!recursiveCompare(A[key], B[key])) { - return false; - } - } - } - return true; - } - return false; -} - -ValidatorContext.prototype.validateBasic = function validateBasic(data, schema, dataPointerPath) { - var error; - if (error = this.validateType(data, schema, dataPointerPath)) { - return error.prefixWith(null, "type"); - } - if (error = this.validateEnum(data, schema, dataPointerPath)) { - return error.prefixWith(null, "type"); - } - return null; -}; - -ValidatorContext.prototype.validateType = function validateType(data, schema) { - if (schema.type === undefined) { - return null; - } - var dataType = typeof data; - if (data === null) { - dataType = "null"; - } else if (Array.isArray(data)) { - dataType = "array"; - } - var allowedTypes = schema.type; - if (typeof allowedTypes !== "object") { - allowedTypes = [allowedTypes]; - } - - for (var i = 0; i < allowedTypes.length; i++) { - var type = allowedTypes[i]; - if (type === dataType || (type === "integer" && dataType === "number" && (data % 1 === 0))) { - return null; - } - } - return this.createError(ErrorCodes.INVALID_TYPE, {type: dataType, expected: allowedTypes.join("/")}); -}; - -ValidatorContext.prototype.validateEnum = function validateEnum(data, schema) { - if (schema["enum"] === undefined) { - return null; - } - for (var i = 0; i < schema["enum"].length; i++) { - var enumVal = schema["enum"][i]; - if (recursiveCompare(data, enumVal)) { - return null; - } - } - return this.createError(ErrorCodes.ENUM_MISMATCH, {value: (typeof JSON !== 'undefined') ? JSON.stringify(data) : data}); -}; - -ValidatorContext.prototype.validateNumeric = function validateNumeric(data, schema, dataPointerPath) { - return this.validateMultipleOf(data, schema, dataPointerPath) - || this.validateMinMax(data, schema, dataPointerPath) - || null; -}; - -ValidatorContext.prototype.validateMultipleOf = function validateMultipleOf(data, schema) { - var multipleOf = schema.multipleOf || schema.divisibleBy; - if (multipleOf === undefined) { - return null; - } - if (typeof data === "number") { - if (data % multipleOf !== 0) { - return this.createError(ErrorCodes.NUMBER_MULTIPLE_OF, {value: data, multipleOf: multipleOf}); - } - } - return null; -}; - -ValidatorContext.prototype.validateMinMax = function validateMinMax(data, schema) { - if (typeof data !== "number") { - return null; - } - if (schema.minimum !== undefined) { - if (data < schema.minimum) { - return this.createError(ErrorCodes.NUMBER_MINIMUM, {value: data, minimum: schema.minimum}).prefixWith(null, "minimum"); - } - if (schema.exclusiveMinimum && data === schema.minimum) { - return this.createError(ErrorCodes.NUMBER_MINIMUM_EXCLUSIVE, {value: data, minimum: schema.minimum}).prefixWith(null, "exclusiveMinimum"); - } - } - if (schema.maximum !== undefined) { - if (data > schema.maximum) { - return this.createError(ErrorCodes.NUMBER_MAXIMUM, {value: data, maximum: schema.maximum}).prefixWith(null, "maximum"); - } - if (schema.exclusiveMaximum && data === schema.maximum) { - return this.createError(ErrorCodes.NUMBER_MAXIMUM_EXCLUSIVE, {value: data, maximum: schema.maximum}).prefixWith(null, "exclusiveMaximum"); - } - } - return null; -}; - -ValidatorContext.prototype.validateString = function validateString(data, schema, dataPointerPath) { - return this.validateStringLength(data, schema, dataPointerPath) - || this.validateStringPattern(data, schema, dataPointerPath) - || null; -}; - -ValidatorContext.prototype.validateStringLength = function validateStringLength(data, schema) { - if (typeof data !== "string") { - return null; - } - if (schema.minLength !== undefined) { - if (data.length < schema.minLength) { - return this.createError(ErrorCodes.STRING_LENGTH_SHORT, {length: data.length, minimum: schema.minLength}).prefixWith(null, "minLength"); - } - } - if (schema.maxLength !== undefined) { - if (data.length > schema.maxLength) { - return this.createError(ErrorCodes.STRING_LENGTH_LONG, {length: data.length, maximum: schema.maxLength}).prefixWith(null, "maxLength"); - } - } - return null; -}; - -ValidatorContext.prototype.validateStringPattern = function validateStringPattern(data, schema) { - if (typeof data !== "string" || schema.pattern === undefined) { - return null; - } - var regexp = new RegExp(schema.pattern); - if (!regexp.test(data)) { - return this.createError(ErrorCodes.STRING_PATTERN, {pattern: schema.pattern}).prefixWith(null, "pattern"); - } - return null; -}; -ValidatorContext.prototype.validateArray = function validateArray(data, schema, dataPointerPath) { - if (!Array.isArray(data)) { - return null; - } - return this.validateArrayLength(data, schema, dataPointerPath) - || this.validateArrayUniqueItems(data, schema, dataPointerPath) - || this.validateArrayItems(data, schema, dataPointerPath) - || null; -}; - -ValidatorContext.prototype.validateArrayLength = function validateArrayLength(data, schema) { - var error; - if (schema.minItems !== undefined) { - if (data.length < schema.minItems) { - error = (this.createError(ErrorCodes.ARRAY_LENGTH_SHORT, {length: data.length, minimum: schema.minItems})).prefixWith(null, "minItems"); - if (this.handleError(error)) { - return error; - } - } - } - if (schema.maxItems !== undefined) { - if (data.length > schema.maxItems) { - error = (this.createError(ErrorCodes.ARRAY_LENGTH_LONG, {length: data.length, maximum: schema.maxItems})).prefixWith(null, "maxItems"); - if (this.handleError(error)) { - return error; - } - } - } - return null; -}; - -ValidatorContext.prototype.validateArrayUniqueItems = function validateArrayUniqueItems(data, schema) { - if (schema.uniqueItems) { - for (var i = 0; i < data.length; i++) { - for (var j = i + 1; j < data.length; j++) { - if (recursiveCompare(data[i], data[j])) { - var error = (this.createError(ErrorCodes.ARRAY_UNIQUE, {match1: i, match2: j})).prefixWith(null, "uniqueItems"); - if (this.handleError(error)) { - return error; - } - } - } - } - } - return null; -}; - -ValidatorContext.prototype.validateArrayItems = function validateArrayItems(data, schema, dataPointerPath) { - if (schema.items === undefined) { - return null; - } - var error, i; - if (Array.isArray(schema.items)) { - for (i = 0; i < data.length; i++) { - if (i < schema.items.length) { - if (error = this.validateAll(data[i], schema.items[i], [i], ["items", i], dataPointerPath + "/" + i)) { - return error; - } - } else if (schema.additionalItems !== undefined) { - if (typeof schema.additionalItems === "boolean") { - if (!schema.additionalItems) { - error = (this.createError(ErrorCodes.ARRAY_ADDITIONAL_ITEMS, {})).prefixWith("" + i, "additionalItems"); - if (this.handleError(error)) { - return error; - } - } - } else if (error = this.validateAll(data[i], schema.additionalItems, [i], ["additionalItems"], dataPointerPath + "/" + i)) { - return error; - } - } - } - } else { - for (i = 0; i < data.length; i++) { - if (error = this.validateAll(data[i], schema.items, [i], ["items"], dataPointerPath + "/" + i)) { - return error; - } - } - } - return null; -}; - -ValidatorContext.prototype.validateObject = function validateObject(data, schema, dataPointerPath) { - if (typeof data !== "object" || data === null || Array.isArray(data)) { - return null; - } - return this.validateObjectMinMaxProperties(data, schema, dataPointerPath) - || this.validateObjectRequiredProperties(data, schema, dataPointerPath) - || this.validateObjectProperties(data, schema, dataPointerPath) - || this.validateObjectDependencies(data, schema, dataPointerPath) - || null; -}; - -ValidatorContext.prototype.validateObjectMinMaxProperties = function validateObjectMinMaxProperties(data, schema) { - var keys = Object.keys(data); - var error; - if (schema.minProperties !== undefined) { - if (keys.length < schema.minProperties) { - error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MINIMUM, {propertyCount: keys.length, minimum: schema.minProperties}).prefixWith(null, "minProperties"); - if (this.handleError(error)) { - return error; - } - } - } - if (schema.maxProperties !== undefined) { - if (keys.length > schema.maxProperties) { - error = this.createError(ErrorCodes.OBJECT_PROPERTIES_MAXIMUM, {propertyCount: keys.length, maximum: schema.maxProperties}).prefixWith(null, "maxProperties"); - if (this.handleError(error)) { - return error; - } - } - } - return null; -}; - -ValidatorContext.prototype.validateObjectRequiredProperties = function validateObjectRequiredProperties(data, schema) { - if (schema.required !== undefined) { - for (var i = 0; i < schema.required.length; i++) { - var key = schema.required[i]; - if (data[key] === undefined) { - var error = this.createError(ErrorCodes.OBJECT_REQUIRED, {key: key}).prefixWith(key, "" + i).prefixWith(null, "required"); - if (this.handleError(error)) { - return error; - } - } - } - } - return null; -}; - -function findProperties(obj, checkInheritedProperties, checkNonEnumerableProperties) { - // Start with the object's own enumerable properties - var properties = Object.keys(obj); - if (checkInheritedProperties) { - for (var key in obj) { - if (properties.indexOf(key) === -1) { - properties.push(key); - } - } - } - // Object.getOwnPropertyNames is not available in IE 8 and below (and cannot be polyfilled) - if (checkNonEnumerableProperties && Object.getOwnPropertyNames) { - Object.getOwnPropertyNames(obj).forEach(function (name) { - if (properties.indexOf(name) === -1) { - properties.push(name); - } - }); - } - return properties; -} - -ValidatorContext.prototype.validateObjectProperties = function validateObjectProperties(data, schema, dataPointerPath) { - var error; - var dataKeys = findProperties(data, this.checkInheritedProperties, this.checkNonEnumerableProperties); - for (var i = 0; i < dataKeys.length; i++) { - var key = dataKeys[i]; - var keyPointerPath = dataPointerPath + "/" + key.replace(/~/g, '~0').replace(/\//g, '~1'); - var foundMatch = false; - if (schema.properties !== undefined && schema.properties[key] !== undefined) { - foundMatch = true; - if (error = this.validateAll(data[key], schema.properties[key], [key], ["properties", key], keyPointerPath)) { - return error; - } - } - if (schema.patternProperties !== undefined) { - var patternKeys = Object.keys(schema.patternProperties); - for (var j = 0; j < patternKeys.length; j++) { - var patternKey = patternKeys[j]; - var regexp = new RegExp(patternKey); - if (regexp.test(key)) { - foundMatch = true; - if (error = this.validateAll(data[key], schema.patternProperties[patternKey], [key], ["patternProperties", patternKey], keyPointerPath)) { - return error; - } - } - } - } - if (!foundMatch) { - if (schema.additionalProperties !== undefined) { - if (this.trackUnknownProperties) { - this.knownPropertyPaths[keyPointerPath] = true; - delete this.unknownPropertyPaths[keyPointerPath]; - } - if (typeof schema.additionalProperties === "boolean") { - if (!schema.additionalProperties) { - error = this.createError(ErrorCodes.OBJECT_ADDITIONAL_PROPERTIES, {}).prefixWith(key, "additionalProperties"); - if (this.handleError(error)) { - return error; - } - } - } else { - if (error = this.validateAll(data[key], schema.additionalProperties, [key], ["additionalProperties"], keyPointerPath)) { - return error; - } - } - } else if (this.trackUnknownProperties && !this.knownPropertyPaths[keyPointerPath]) { - this.unknownPropertyPaths[keyPointerPath] = true; - } - } else if (this.trackUnknownProperties) { - this.knownPropertyPaths[keyPointerPath] = true; - delete this.unknownPropertyPaths[keyPointerPath]; - } - } - return null; -}; - -ValidatorContext.prototype.validateObjectDependencies = function validateObjectDependencies(data, schema, dataPointerPath) { - var error; - if (schema.dependencies !== undefined) { - var depKeys = Object.keys(schema.dependencies); - for (var i = 0; i < depKeys.length; i++) { - var depKey = depKeys[i]; - if (data[depKey] !== undefined) { - var dep = schema.dependencies[depKey]; - if (typeof dep === "string") { - if (data[dep] === undefined) { - error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: dep}).prefixWith(null, depKey).prefixWith(null, "dependencies"); - if (this.handleError(error)) { - return error; - } - } - } else if (Array.isArray(dep)) { - for (var j = 0; j < dep.length; j++) { - var requiredKey = dep[j]; - if (data[requiredKey] === undefined) { - error = this.createError(ErrorCodes.OBJECT_DEPENDENCY_KEY, {key: depKey, missing: requiredKey}).prefixWith(null, "" + i).prefixWith(null, depKey).prefixWith(null, "dependencies"); - if (this.handleError(error)) { - return error; - } - } - } - } else { - if (error = this.validateAll(data, dep, [], ["dependencies", depKey], dataPointerPath)) { - return error; - } - } - } - } - } - return null; -}; - -ValidatorContext.prototype.validateCombinations = function validateCombinations(data, schema, dataPointerPath) { - return this.validateAllOf(data, schema, dataPointerPath) - || this.validateAnyOf(data, schema, dataPointerPath) - || this.validateOneOf(data, schema, dataPointerPath) - || this.validateNot(data, schema, dataPointerPath) - || null; -}; - -ValidatorContext.prototype.validateAllOf = function validateAllOf(data, schema, dataPointerPath) { - if (schema.allOf === undefined) { - return null; - } - var error; - for (var i = 0; i < schema.allOf.length; i++) { - var subSchema = schema.allOf[i]; - if (error = this.validateAll(data, subSchema, [], ["allOf", i], dataPointerPath)) { - return error; - } - } - return null; -}; - -ValidatorContext.prototype.validateAnyOf = function validateAnyOf(data, schema, dataPointerPath) { - if (schema.anyOf === undefined) { - return null; - } - var errors = []; - var startErrorCount = this.errors.length; - var oldUnknownPropertyPaths, oldKnownPropertyPaths; - if (this.trackUnknownProperties) { - oldUnknownPropertyPaths = this.unknownPropertyPaths; - oldKnownPropertyPaths = this.knownPropertyPaths; - } - var errorAtEnd = true; - for (var i = 0; i < schema.anyOf.length; i++) { - if (this.trackUnknownProperties) { - this.unknownPropertyPaths = {}; - this.knownPropertyPaths = {}; - } - var subSchema = schema.anyOf[i]; - - var errorCount = this.errors.length; - var error = this.validateAll(data, subSchema, [], ["anyOf", i], dataPointerPath); - - if (error === null && errorCount === this.errors.length) { - this.errors = this.errors.slice(0, startErrorCount); - - if (this.trackUnknownProperties) { - var knownKeys = Object.keys(this.knownPropertyPaths); - for (var j = 0; j < knownKeys.length; j++) { - var knownKey = knownKeys[j]; - oldKnownPropertyPaths[knownKey] = true; - delete oldUnknownPropertyPaths[knownKey]; - } - var unknownKeys = Object.keys(this.unknownPropertyPaths); - for (j = 0; j < unknownKeys.length; j++) { - var unknownKey = unknownKeys[j]; - if (!oldKnownPropertyPaths[unknownKey]) { - oldUnknownPropertyPaths[unknownKey] = true; - } - } - // We need to continue looping so we catch all the property definitions, but we don't want to return an error - errorAtEnd = false; - continue; - } - - return null; - } - if (error) { - errors.push(error.prefixWith(null, "" + i).prefixWith(null, "anyOf")); - } - } - if (this.trackUnknownProperties) { - this.unknownPropertyPaths = oldUnknownPropertyPaths; - this.knownPropertyPaths = oldKnownPropertyPaths; - } - if (errorAtEnd) { - errors = errors.concat(this.errors.slice(startErrorCount)); - this.errors = this.errors.slice(0, startErrorCount); - return this.createError(ErrorCodes.ANY_OF_MISSING, {}, "", "/anyOf", errors); - } -}; - -ValidatorContext.prototype.validateOneOf = function validateOneOf(data, schema, dataPointerPath) { - if (schema.oneOf === undefined) { - return null; - } - var validIndex = null; - var errors = []; - var startErrorCount = this.errors.length; - var oldUnknownPropertyPaths, oldKnownPropertyPaths; - if (this.trackUnknownProperties) { - oldUnknownPropertyPaths = this.unknownPropertyPaths; - oldKnownPropertyPaths = this.knownPropertyPaths; - } - for (var i = 0; i < schema.oneOf.length; i++) { - if (this.trackUnknownProperties) { - this.unknownPropertyPaths = {}; - this.knownPropertyPaths = {}; - } - var subSchema = schema.oneOf[i]; - - var errorCount = this.errors.length; - var error = this.validateAll(data, subSchema, [], ["oneOf", i], dataPointerPath); - - if (error === null && errorCount === this.errors.length) { - if (validIndex === null) { - validIndex = i; - } else { - this.errors = this.errors.slice(0, startErrorCount); - return this.createError(ErrorCodes.ONE_OF_MULTIPLE, {index1: validIndex, index2: i}, "", "/oneOf"); - } - if (this.trackUnknownProperties) { - var knownKeys = Object.keys(this.knownPropertyPaths); - for (var j = 0; j < knownKeys.length; j++) { - var knownKey = knownKeys[j]; - oldKnownPropertyPaths[knownKey] = true; - delete oldUnknownPropertyPaths[knownKey]; - } - var unknownKeys = Object.keys(this.unknownPropertyPaths); - for (j = 0; j < unknownKeys.length; j++) { - var unknownKey = unknownKeys[j]; - if (!oldKnownPropertyPaths[unknownKey]) { - oldUnknownPropertyPaths[unknownKey] = true; - } - } - } - } else if (error) { - errors.push(error.prefixWith(null, "" + i).prefixWith(null, "oneOf")); - } - } - if (this.trackUnknownProperties) { - this.unknownPropertyPaths = oldUnknownPropertyPaths; - this.knownPropertyPaths = oldKnownPropertyPaths; - } - if (validIndex === null) { - errors = errors.concat(this.errors.slice(startErrorCount)); - this.errors = this.errors.slice(0, startErrorCount); - return this.createError(ErrorCodes.ONE_OF_MISSING, {}, "", "/oneOf", errors); - } else { - this.errors = this.errors.slice(0, startErrorCount); - } - return null; -}; - -ValidatorContext.prototype.validateNot = function validateNot(data, schema, dataPointerPath) { - if (schema.not === undefined) { - return null; - } - var oldErrorCount = this.errors.length; - var oldUnknownPropertyPaths, oldKnownPropertyPaths; - if (this.trackUnknownProperties) { - oldUnknownPropertyPaths = this.unknownPropertyPaths; - oldKnownPropertyPaths = this.knownPropertyPaths; - this.unknownPropertyPaths = {}; - this.knownPropertyPaths = {}; - } - var error = this.validateAll(data, schema.not, null, null, dataPointerPath); - var notErrors = this.errors.slice(oldErrorCount); - this.errors = this.errors.slice(0, oldErrorCount); - if (this.trackUnknownProperties) { - this.unknownPropertyPaths = oldUnknownPropertyPaths; - this.knownPropertyPaths = oldKnownPropertyPaths; - } - if (error === null && notErrors.length === 0) { - return this.createError(ErrorCodes.NOT_PASSED, {}, "", "/not"); - } - return null; -}; - -// parseURI() and resolveUrl() are from https://gist.github.com/1088850 -// - released as public domain by author ("Yaffle") - see comments on gist - -function parseURI(url) { - var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/); - // authority = '//' + user + ':' + pass '@' + hostname + ':' port - return (m ? { - href : m[0] || '', - protocol : m[1] || '', - authority: m[2] || '', - host : m[3] || '', - hostname : m[4] || '', - port : m[5] || '', - pathname : m[6] || '', - search : m[7] || '', - hash : m[8] || '' - } : null); -} - -function resolveUrl(base, href) {// RFC 3986 - - function removeDotSegments(input) { - var output = []; - input.replace(/^(\.\.?(\/|$))+/, '') - .replace(/\/(\.(\/|$))+/g, '/') - .replace(/\/\.\.$/, '/../') - .replace(/\/?[^\/]*/g, function (p) { - if (p === '/..') { - output.pop(); - } else { - output.push(p); - } - }); - return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : ''); - } - - href = parseURI(href || ''); - base = parseURI(base || ''); - - return !href || !base ? null : (href.protocol || base.protocol) + - (href.protocol || href.authority ? href.authority : base.authority) + - removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) + - (href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) + - href.hash; -} - -function getDocumentUri(uri) { - return uri.split('#')[0]; -} -function normSchema(schema, baseUri) { - if (schema && typeof schema === "object") { - var i; - if (baseUri === undefined) { - baseUri = schema.id; - } else if (typeof schema.id === "string") { - baseUri = resolveUrl(baseUri, schema.id); - schema.id = baseUri; - } - if (Array.isArray(schema)) { - for (i = 0; i < schema.length; i++) { - normSchema(schema[i], baseUri); - } - } else if (typeof schema['$ref'] === "string") { - schema['$ref'] = resolveUrl(baseUri, schema['$ref']); - } else { - var schemaKeys = Object.keys(schema); - for (i = 0; i < schemaKeys.length; i++) { - var key = schemaKeys[i]; - if (key !== "enum") { - normSchema(schema[key], baseUri); - } - } - } - } -} - -var ErrorCodes = { - INVALID_TYPE: 0, - ENUM_MISMATCH: 1, - ANY_OF_MISSING: 10, - ONE_OF_MISSING: 11, - ONE_OF_MULTIPLE: 12, - NOT_PASSED: 13, - // Numeric errors - NUMBER_MULTIPLE_OF: 100, - NUMBER_MINIMUM: 101, - NUMBER_MINIMUM_EXCLUSIVE: 102, - NUMBER_MAXIMUM: 103, - NUMBER_MAXIMUM_EXCLUSIVE: 104, - // String errors - STRING_LENGTH_SHORT: 200, - STRING_LENGTH_LONG: 201, - STRING_PATTERN: 202, - // Object errors - OBJECT_PROPERTIES_MINIMUM: 300, - OBJECT_PROPERTIES_MAXIMUM: 301, - OBJECT_REQUIRED: 302, - OBJECT_ADDITIONAL_PROPERTIES: 303, - OBJECT_DEPENDENCY_KEY: 304, - // Array errors - ARRAY_LENGTH_SHORT: 400, - ARRAY_LENGTH_LONG: 401, - ARRAY_UNIQUE: 402, - ARRAY_ADDITIONAL_ITEMS: 403, - // Format errors - FORMAT_CUSTOM: 500, - // Schema structure - CIRCULAR_REFERENCE: 600, - // Non-standard validation options - UNKNOWN_PROPERTY: 1000 -}; -var ErrorMessagesDefault = { - INVALID_TYPE: "invalid type: {type} (expected {expected})", - ENUM_MISMATCH: "No enum match for: {value}", - ANY_OF_MISSING: "Data does not match any schemas from \"anyOf\"", - ONE_OF_MISSING: "Data does not match any schemas from \"oneOf\"", - ONE_OF_MULTIPLE: "Data is valid against more than one schema from \"oneOf\": indices {index1} and {index2}", - NOT_PASSED: "Data matches schema from \"not\"", - // Numeric errors - NUMBER_MULTIPLE_OF: "Value {value} is not a multiple of {multipleOf}", - NUMBER_MINIMUM: "Value {value} is less than minimum {minimum}", - NUMBER_MINIMUM_EXCLUSIVE: "Value {value} is equal to exclusive minimum {minimum}", - NUMBER_MAXIMUM: "Value {value} is greater than maximum {maximum}", - NUMBER_MAXIMUM_EXCLUSIVE: "Value {value} is equal to exclusive maximum {maximum}", - // String errors - STRING_LENGTH_SHORT: "String is too short ({length} chars), minimum {minimum}", - STRING_LENGTH_LONG: "String is too long ({length} chars), maximum {maximum}", - STRING_PATTERN: "String does not match pattern: {pattern}", - // Object errors - OBJECT_PROPERTIES_MINIMUM: "Too few properties defined ({propertyCount}), minimum {minimum}", - OBJECT_PROPERTIES_MAXIMUM: "Too many properties defined ({propertyCount}), maximum {maximum}", - OBJECT_REQUIRED: "Missing required property: {key}", - OBJECT_ADDITIONAL_PROPERTIES: "Additional properties not allowed", - OBJECT_DEPENDENCY_KEY: "Dependency failed - key must exist: {missing} (due to key: {key})", - // Array errors - ARRAY_LENGTH_SHORT: "Array is too short ({length}), minimum {minimum}", - ARRAY_LENGTH_LONG: "Array is too long ({length}), maximum {maximum}", - ARRAY_UNIQUE: "Array items are not unique (indices {match1} and {match2})", - ARRAY_ADDITIONAL_ITEMS: "Additional items not allowed", - // Format errors - FORMAT_CUSTOM: "Format validation failed ({message})", - // Schema structure - CIRCULAR_REFERENCE: "Circular $refs: {urls}", - // Non-standard validation options - UNKNOWN_PROPERTY: "Unknown property (not in schema)" -}; - -function ValidationError(code, message, dataPath, schemaPath, subErrors) { - Error.call(this); - if (code === undefined) { - throw new Error ("No code supplied for error: "+ message); - } - this.message = message; - this.code = code; - this.dataPath = dataPath || ""; - this.schemaPath = schemaPath || ""; - this.subErrors = subErrors || null; - - var err = new Error(this.message); - this.stack = err.stack || err.stacktrace; - if (!this.stack) { - try { - throw err; - } - catch(err) { - this.stack = err.stack || err.stacktrace; - } - } -} -ValidationError.prototype = Object.create(Error.prototype); -ValidationError.prototype.constructor = ValidationError; -ValidationError.prototype.name = 'ValidationError'; - -ValidationError.prototype.prefixWith = function (dataPrefix, schemaPrefix) { - if (dataPrefix !== null) { - dataPrefix = dataPrefix.replace(/~/g, "~0").replace(/\//g, "~1"); - this.dataPath = "/" + dataPrefix + this.dataPath; - } - if (schemaPrefix !== null) { - schemaPrefix = schemaPrefix.replace(/~/g, "~0").replace(/\//g, "~1"); - this.schemaPath = "/" + schemaPrefix + this.schemaPath; - } - if (this.subErrors !== null) { - for (var i = 0; i < this.subErrors.length; i++) { - this.subErrors[i].prefixWith(dataPrefix, schemaPrefix); - } - } - return this; -}; - -function isTrustedUrl(baseUrl, testUrl) { - if(testUrl.substring(0, baseUrl.length) === baseUrl){ - var remainder = testUrl.substring(baseUrl.length); - if ((testUrl.length > 0 && testUrl.charAt(baseUrl.length - 1) === "/") - || remainder.charAt(0) === "#" - || remainder.charAt(0) === "?") { - return true; - } - } - return false; -} - -function makeOptionsObject(opts) { - var options = {}; - // old method signatures accepted checkRecursive and banUnknownProperties - if (opts[0] !== undefined) { - options.checkRecursive = opts[0]; - } - if (opts[1] !== undefined) { - options.banUnknownProperties = opts[1]; - } - return options; -} - -var languages = {}; -function createApi(language) { - var globalContext = new ValidatorContext(); - var currentLanguage = language || 'en'; - var api = { - addFormat: function () { - globalContext.addFormat.apply(globalContext, arguments); - }, - language: function (code) { - if (!code) { - return currentLanguage; - } - if (!languages[code]) { - code = code.split('-')[0]; // fall back to base language - } - if (languages[code]) { - currentLanguage = code; - return code; // so you can tell if fall-back has happened - } - return false; - }, - addLanguage: function (code, messageMap) { - var key; - for (key in ErrorCodes) { - if (messageMap[key] && !messageMap[ErrorCodes[key]]) { - messageMap[ErrorCodes[key]] = messageMap[key]; - } - } - var rootCode = code.split('-')[0]; - if (!languages[rootCode]) { // use for base language if not yet defined - languages[code] = messageMap; - languages[rootCode] = messageMap; - } else { - languages[code] = Object.create(languages[rootCode]); - for (key in messageMap) { - if (typeof languages[rootCode][key] === 'undefined') { - languages[rootCode][key] = messageMap[key]; - } - languages[code][key] = messageMap[key]; - } - } - return this; - }, - freshApi: function (language) { - var result = createApi(); - if (language) { - result.language(language); - } - return result; - }, - validate: function (data, schema, options) { - if (typeof schema === "string") { - schema = {"$ref": schema}; - } - if (typeof options !== "object" || options === null) { - options = makeOptionsObject(Array.prototype.slice.call(arguments, 2)); - } - var context = new ValidatorContext(globalContext, false, languages[currentLanguage], options); - context.addSchema("", schema); - var error = context.validateAll(data, schema, null, null, ""); - if (!error && options.banUnknownProperties) { - error = context.banUnknownProperties(); - } - this.error = error; - this.missing = context.missing; - this.valid = (error === null); - return this.valid; - }, - validateResult: function () { - var result = {}; - this.validate.apply(result, arguments); - return result; - }, - validateMultiple: function (data, schema, options) { - if (typeof schema === "string") { - schema = {"$ref": schema}; - } - if (typeof options !== "object" || options === null) { - options = makeOptionsObject(Array.prototype.slice.call(arguments, 2)); - } - var context = new ValidatorContext(globalContext, true, languages[currentLanguage], options); - context.addSchema("", schema); - context.validateAll(data, schema, null, null, ""); - if (options.banUnknownProperties) { - context.banUnknownProperties(); - } - var result = {}; - result.errors = context.errors; - result.missing = context.missing; - result.valid = (result.errors.length === 0); - return result; - }, - addSchema: function () { - return globalContext.addSchema.apply(globalContext, arguments); - }, - getSchema: function () { - return globalContext.getSchema.apply(globalContext, arguments); - }, - getSchemaMap: function () { - return globalContext.getSchemaMap.apply(globalContext, arguments); - }, - getSchemaUris: function () { - return globalContext.getSchemaUris.apply(globalContext, arguments); - }, - getMissingUris: function () { - return globalContext.getMissingUris.apply(globalContext, arguments); - }, - dropSchemas: function () { - globalContext.dropSchemas.apply(globalContext, arguments); - }, - reset: function () { - globalContext.reset(); - this.error = null; - this.missing = []; - this.valid = true; - }, - missing: [], - error: null, - valid: true, - normSchema: normSchema, - resolveUrl: resolveUrl, - getDocumentUri: getDocumentUri, - errorCodes: ErrorCodes - }; - return api; -} - -var tv4 = createApi(); -tv4.addLanguage('en-gb', ErrorMessagesDefault); - -//legacy property -tv4.tv4 = tv4; - -if (typeof module !== 'undefined' && module.exports){ - module.exports = tv4; -} -else { - global.tv4 = tv4; -} - -})(this); diff --git a/node_modules/underscore/LICENSE b/node_modules/underscore/LICENSE deleted file mode 100644 index ad0e71bc..00000000 --- a/node_modules/underscore/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative -Reporters & Editors - -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. diff --git a/node_modules/underscore/package.json b/node_modules/underscore/package.json deleted file mode 100644 index 3b021d07..00000000 --- a/node_modules/underscore/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "underscore", - "description": "JavaScript's functional programming helper library.", - "homepage": "http://underscorejs.org", - "keywords": [ - "util", - "functional", - "server", - "client", - "browser" - ], - "author": { - "name": "Jeremy Ashkenas", - "email": "jeremy@documentcloud.org" - }, - "repository": { - "type": "git", - "url": "git://github.com/jashkenas/underscore.git" - }, - "main": "underscore.js", - "version": "1.8.3", - "devDependencies": { - "docco": "*", - "eslint": "0.6.x", - "karma": "~0.12.31", - "karma-qunit": "~0.1.4", - "qunit-cli": "~0.2.0", - "uglify-js": "2.4.x" - }, - "scripts": { - "test": "npm run test-node && npm run lint", - "lint": "eslint underscore.js test/*.js", - "test-node": "qunit-cli test/*.js", - "test-browser": "npm i karma-phantomjs-launcher && ./node_modules/karma/bin/karma start", - "build": "uglifyjs underscore.js -c \"evaluate=false\" --comments \"/ .*/\" -m --source-map underscore-min.map -o underscore-min.js", - "doc": "docco underscore.js" - }, - "license": "MIT", - "files": [ - "underscore.js", - "underscore-min.js", - "underscore-min.map", - "LICENSE" - ], - "gitHead": "e4743ab712b8ab42ad4ccb48b155034d02394e4d", - "bugs": { - "url": "https://github.com/jashkenas/underscore/issues" - }, - "_id": "underscore@1.8.3", - "_shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022", - "_from": "underscore@1.8.3", - "_npmVersion": "1.4.28", - "_npmUser": { - "name": "jashkenas", - "email": "jashkenas@gmail.com" - }, - "maintainers": [ - { - "name": "jashkenas", - "email": "jashkenas@gmail.com" - } - ], - "dist": { - "shasum": "4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022", - "tarball": "http://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/underscore/-/underscore-1.8.3.tgz" -} diff --git a/node_modules/underscore/underscore.js b/node_modules/underscore/underscore.js deleted file mode 100644 index b29332f9..00000000 --- a/node_modules/underscore/underscore.js +++ /dev/null @@ -1,1548 +0,0 @@ -// Underscore.js 1.8.3 -// http://underscorejs.org -// (c) 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -(function() { - - // Baseline setup - // -------------- - - // Establish the root object, `window` in the browser, or `exports` on the server. - var root = this; - - // Save the previous value of the `_` variable. - var previousUnderscore = root._; - - // Save bytes in the minified (but not gzipped) version: - var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; - - // Create quick reference variables for speed access to core prototypes. - var - push = ArrayProto.push, - slice = ArrayProto.slice, - toString = ObjProto.toString, - hasOwnProperty = ObjProto.hasOwnProperty; - - // All **ECMAScript 5** native function implementations that we hope to use - // are declared here. - var - nativeIsArray = Array.isArray, - nativeKeys = Object.keys, - nativeBind = FuncProto.bind, - nativeCreate = Object.create; - - // Naked function reference for surrogate-prototype-swapping. - var Ctor = function(){}; - - // Create a safe reference to the Underscore object for use below. - var _ = function(obj) { - if (obj instanceof _) return obj; - if (!(this instanceof _)) return new _(obj); - this._wrapped = obj; - }; - - // Export the Underscore object for **Node.js**, with - // backwards-compatibility for the old `require()` API. If we're in - // the browser, add `_` as a global object. - if (typeof exports !== 'undefined') { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = _; - } - exports._ = _; - } else { - root._ = _; - } - - // Current version. - _.VERSION = '1.8.3'; - - // Internal function that returns an efficient (for current engines) version - // of the passed-in callback, to be repeatedly applied in other Underscore - // functions. - var optimizeCb = function(func, context, argCount) { - if (context === void 0) return func; - switch (argCount == null ? 3 : argCount) { - case 1: return function(value) { - return func.call(context, value); - }; - case 2: return function(value, other) { - return func.call(context, value, other); - }; - case 3: return function(value, index, collection) { - return func.call(context, value, index, collection); - }; - case 4: return function(accumulator, value, index, collection) { - return func.call(context, accumulator, value, index, collection); - }; - } - return function() { - return func.apply(context, arguments); - }; - }; - - // A mostly-internal function to generate callbacks that can be applied - // to each element in a collection, returning the desired result — either - // identity, an arbitrary callback, a property matcher, or a property accessor. - var cb = function(value, context, argCount) { - if (value == null) return _.identity; - if (_.isFunction(value)) return optimizeCb(value, context, argCount); - if (_.isObject(value)) return _.matcher(value); - return _.property(value); - }; - _.iteratee = function(value, context) { - return cb(value, context, Infinity); - }; - - // An internal function for creating assigner functions. - var createAssigner = function(keysFunc, undefinedOnly) { - return function(obj) { - var length = arguments.length; - if (length < 2 || obj == null) return obj; - for (var index = 1; index < length; index++) { - var source = arguments[index], - keys = keysFunc(source), - l = keys.length; - for (var i = 0; i < l; i++) { - var key = keys[i]; - if (!undefinedOnly || obj[key] === void 0) obj[key] = source[key]; - } - } - return obj; - }; - }; - - // An internal function for creating a new object that inherits from another. - var baseCreate = function(prototype) { - if (!_.isObject(prototype)) return {}; - if (nativeCreate) return nativeCreate(prototype); - Ctor.prototype = prototype; - var result = new Ctor; - Ctor.prototype = null; - return result; - }; - - var property = function(key) { - return function(obj) { - return obj == null ? void 0 : obj[key]; - }; - }; - - // Helper for collection methods to determine whether a collection - // should be iterated as an array or as an object - // Related: http://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength - // Avoids a very nasty iOS 8 JIT bug on ARM-64. #2094 - var MAX_ARRAY_INDEX = Math.pow(2, 53) - 1; - var getLength = property('length'); - var isArrayLike = function(collection) { - var length = getLength(collection); - return typeof length == 'number' && length >= 0 && length <= MAX_ARRAY_INDEX; - }; - - // Collection Functions - // -------------------- - - // The cornerstone, an `each` implementation, aka `forEach`. - // Handles raw objects in addition to array-likes. Treats all - // sparse array-likes as if they were dense. - _.each = _.forEach = function(obj, iteratee, context) { - iteratee = optimizeCb(iteratee, context); - var i, length; - if (isArrayLike(obj)) { - for (i = 0, length = obj.length; i < length; i++) { - iteratee(obj[i], i, obj); - } - } else { - var keys = _.keys(obj); - for (i = 0, length = keys.length; i < length; i++) { - iteratee(obj[keys[i]], keys[i], obj); - } - } - return obj; - }; - - // Return the results of applying the iteratee to each element. - _.map = _.collect = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - results = Array(length); - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - results[index] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Create a reducing function iterating left or right. - function createReduce(dir) { - // Optimized iterator function as using arguments.length - // in the main function will deoptimize the, see #1991. - function iterator(obj, iteratee, memo, keys, index, length) { - for (; index >= 0 && index < length; index += dir) { - var currentKey = keys ? keys[index] : index; - memo = iteratee(memo, obj[currentKey], currentKey, obj); - } - return memo; - } - - return function(obj, iteratee, memo, context) { - iteratee = optimizeCb(iteratee, context, 4); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length, - index = dir > 0 ? 0 : length - 1; - // Determine the initial value if none is provided. - if (arguments.length < 3) { - memo = obj[keys ? keys[index] : index]; - index += dir; - } - return iterator(obj, iteratee, memo, keys, index, length); - }; - } - - // **Reduce** builds up a single result from a list of values, aka `inject`, - // or `foldl`. - _.reduce = _.foldl = _.inject = createReduce(1); - - // The right-associative version of reduce, also known as `foldr`. - _.reduceRight = _.foldr = createReduce(-1); - - // Return the first value which passes a truth test. Aliased as `detect`. - _.find = _.detect = function(obj, predicate, context) { - var key; - if (isArrayLike(obj)) { - key = _.findIndex(obj, predicate, context); - } else { - key = _.findKey(obj, predicate, context); - } - if (key !== void 0 && key !== -1) return obj[key]; - }; - - // Return all the elements that pass a truth test. - // Aliased as `select`. - _.filter = _.select = function(obj, predicate, context) { - var results = []; - predicate = cb(predicate, context); - _.each(obj, function(value, index, list) { - if (predicate(value, index, list)) results.push(value); - }); - return results; - }; - - // Return all the elements for which a truth test fails. - _.reject = function(obj, predicate, context) { - return _.filter(obj, _.negate(cb(predicate)), context); - }; - - // Determine whether all of the elements match a truth test. - // Aliased as `all`. - _.every = _.all = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (!predicate(obj[currentKey], currentKey, obj)) return false; - } - return true; - }; - - // Determine if at least one element in the object matches a truth test. - // Aliased as `any`. - _.some = _.any = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = !isArrayLike(obj) && _.keys(obj), - length = (keys || obj).length; - for (var index = 0; index < length; index++) { - var currentKey = keys ? keys[index] : index; - if (predicate(obj[currentKey], currentKey, obj)) return true; - } - return false; - }; - - // Determine if the array or object contains a given item (using `===`). - // Aliased as `includes` and `include`. - _.contains = _.includes = _.include = function(obj, item, fromIndex, guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - if (typeof fromIndex != 'number' || guard) fromIndex = 0; - return _.indexOf(obj, item, fromIndex) >= 0; - }; - - // Invoke a method (with arguments) on every item in a collection. - _.invoke = function(obj, method) { - var args = slice.call(arguments, 2); - var isFunc = _.isFunction(method); - return _.map(obj, function(value) { - var func = isFunc ? method : value[method]; - return func == null ? func : func.apply(value, args); - }); - }; - - // Convenience version of a common use case of `map`: fetching a property. - _.pluck = function(obj, key) { - return _.map(obj, _.property(key)); - }; - - // Convenience version of a common use case of `filter`: selecting only objects - // containing specific `key:value` pairs. - _.where = function(obj, attrs) { - return _.filter(obj, _.matcher(attrs)); - }; - - // Convenience version of a common use case of `find`: getting the first object - // containing specific `key:value` pairs. - _.findWhere = function(obj, attrs) { - return _.find(obj, _.matcher(attrs)); - }; - - // Return the maximum element (or element-based computation). - _.max = function(obj, iteratee, context) { - var result = -Infinity, lastComputed = -Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value > result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed > lastComputed || computed === -Infinity && result === -Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Return the minimum element (or element-based computation). - _.min = function(obj, iteratee, context) { - var result = Infinity, lastComputed = Infinity, - value, computed; - if (iteratee == null && obj != null) { - obj = isArrayLike(obj) ? obj : _.values(obj); - for (var i = 0, length = obj.length; i < length; i++) { - value = obj[i]; - if (value < result) { - result = value; - } - } - } else { - iteratee = cb(iteratee, context); - _.each(obj, function(value, index, list) { - computed = iteratee(value, index, list); - if (computed < lastComputed || computed === Infinity && result === Infinity) { - result = value; - lastComputed = computed; - } - }); - } - return result; - }; - - // Shuffle a collection, using the modern version of the - // [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). - _.shuffle = function(obj) { - var set = isArrayLike(obj) ? obj : _.values(obj); - var length = set.length; - var shuffled = Array(length); - for (var index = 0, rand; index < length; index++) { - rand = _.random(0, index); - if (rand !== index) shuffled[index] = shuffled[rand]; - shuffled[rand] = set[index]; - } - return shuffled; - }; - - // Sample **n** random values from a collection. - // If **n** is not specified, returns a single random element. - // The internal `guard` argument allows it to work with `map`. - _.sample = function(obj, n, guard) { - if (n == null || guard) { - if (!isArrayLike(obj)) obj = _.values(obj); - return obj[_.random(obj.length - 1)]; - } - return _.shuffle(obj).slice(0, Math.max(0, n)); - }; - - // Sort the object's values by a criterion produced by an iteratee. - _.sortBy = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - return _.pluck(_.map(obj, function(value, index, list) { - return { - value: value, - index: index, - criteria: iteratee(value, index, list) - }; - }).sort(function(left, right) { - var a = left.criteria; - var b = right.criteria; - if (a !== b) { - if (a > b || a === void 0) return 1; - if (a < b || b === void 0) return -1; - } - return left.index - right.index; - }), 'value'); - }; - - // An internal function used for aggregate "group by" operations. - var group = function(behavior) { - return function(obj, iteratee, context) { - var result = {}; - iteratee = cb(iteratee, context); - _.each(obj, function(value, index) { - var key = iteratee(value, index, obj); - behavior(result, value, key); - }); - return result; - }; - }; - - // Groups the object's values by a criterion. Pass either a string attribute - // to group by, or a function that returns the criterion. - _.groupBy = group(function(result, value, key) { - if (_.has(result, key)) result[key].push(value); else result[key] = [value]; - }); - - // Indexes the object's values by a criterion, similar to `groupBy`, but for - // when you know that your index values will be unique. - _.indexBy = group(function(result, value, key) { - result[key] = value; - }); - - // Counts instances of an object that group by a certain criterion. Pass - // either a string attribute to count by, or a function that returns the - // criterion. - _.countBy = group(function(result, value, key) { - if (_.has(result, key)) result[key]++; else result[key] = 1; - }); - - // Safely create a real, live array from anything iterable. - _.toArray = function(obj) { - if (!obj) return []; - if (_.isArray(obj)) return slice.call(obj); - if (isArrayLike(obj)) return _.map(obj, _.identity); - return _.values(obj); - }; - - // Return the number of elements in an object. - _.size = function(obj) { - if (obj == null) return 0; - return isArrayLike(obj) ? obj.length : _.keys(obj).length; - }; - - // Split a collection into two arrays: one whose elements all satisfy the given - // predicate, and one whose elements all do not satisfy the predicate. - _.partition = function(obj, predicate, context) { - predicate = cb(predicate, context); - var pass = [], fail = []; - _.each(obj, function(value, key, obj) { - (predicate(value, key, obj) ? pass : fail).push(value); - }); - return [pass, fail]; - }; - - // Array Functions - // --------------- - - // Get the first element of an array. Passing **n** will return the first N - // values in the array. Aliased as `head` and `take`. The **guard** check - // allows it to work with `_.map`. - _.first = _.head = _.take = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[0]; - return _.initial(array, array.length - n); - }; - - // Returns everything but the last entry of the array. Especially useful on - // the arguments object. Passing **n** will return all the values in - // the array, excluding the last N. - _.initial = function(array, n, guard) { - return slice.call(array, 0, Math.max(0, array.length - (n == null || guard ? 1 : n))); - }; - - // Get the last element of an array. Passing **n** will return the last N - // values in the array. - _.last = function(array, n, guard) { - if (array == null) return void 0; - if (n == null || guard) return array[array.length - 1]; - return _.rest(array, Math.max(0, array.length - n)); - }; - - // Returns everything but the first entry of the array. Aliased as `tail` and `drop`. - // Especially useful on the arguments object. Passing an **n** will return - // the rest N values in the array. - _.rest = _.tail = _.drop = function(array, n, guard) { - return slice.call(array, n == null || guard ? 1 : n); - }; - - // Trim out all falsy values from an array. - _.compact = function(array) { - return _.filter(array, _.identity); - }; - - // Internal implementation of a recursive `flatten` function. - var flatten = function(input, shallow, strict, startIndex) { - var output = [], idx = 0; - for (var i = startIndex || 0, length = getLength(input); i < length; i++) { - var value = input[i]; - if (isArrayLike(value) && (_.isArray(value) || _.isArguments(value))) { - //flatten current level of array or arguments object - if (!shallow) value = flatten(value, shallow, strict); - var j = 0, len = value.length; - output.length += len; - while (j < len) { - output[idx++] = value[j++]; - } - } else if (!strict) { - output[idx++] = value; - } - } - return output; - }; - - // Flatten out an array, either recursively (by default), or just one level. - _.flatten = function(array, shallow) { - return flatten(array, shallow, false); - }; - - // Return a version of the array that does not contain the specified value(s). - _.without = function(array) { - return _.difference(array, slice.call(arguments, 1)); - }; - - // Produce a duplicate-free version of the array. If the array has already - // been sorted, you have the option of using a faster algorithm. - // Aliased as `unique`. - _.uniq = _.unique = function(array, isSorted, iteratee, context) { - if (!_.isBoolean(isSorted)) { - context = iteratee; - iteratee = isSorted; - isSorted = false; - } - if (iteratee != null) iteratee = cb(iteratee, context); - var result = []; - var seen = []; - for (var i = 0, length = getLength(array); i < length; i++) { - var value = array[i], - computed = iteratee ? iteratee(value, i, array) : value; - if (isSorted) { - if (!i || seen !== computed) result.push(value); - seen = computed; - } else if (iteratee) { - if (!_.contains(seen, computed)) { - seen.push(computed); - result.push(value); - } - } else if (!_.contains(result, value)) { - result.push(value); - } - } - return result; - }; - - // Produce an array that contains the union: each distinct element from all of - // the passed-in arrays. - _.union = function() { - return _.uniq(flatten(arguments, true, true)); - }; - - // Produce an array that contains every item shared between all the - // passed-in arrays. - _.intersection = function(array) { - var result = []; - var argsLength = arguments.length; - for (var i = 0, length = getLength(array); i < length; i++) { - var item = array[i]; - if (_.contains(result, item)) continue; - for (var j = 1; j < argsLength; j++) { - if (!_.contains(arguments[j], item)) break; - } - if (j === argsLength) result.push(item); - } - return result; - }; - - // Take the difference between one array and a number of other arrays. - // Only the elements present in just the first array will remain. - _.difference = function(array) { - var rest = flatten(arguments, true, true, 1); - return _.filter(array, function(value){ - return !_.contains(rest, value); - }); - }; - - // Zip together multiple lists into a single array -- elements that share - // an index go together. - _.zip = function() { - return _.unzip(arguments); - }; - - // Complement of _.zip. Unzip accepts an array of arrays and groups - // each array's elements on shared indices - _.unzip = function(array) { - var length = array && _.max(array, getLength).length || 0; - var result = Array(length); - - for (var index = 0; index < length; index++) { - result[index] = _.pluck(array, index); - } - return result; - }; - - // Converts lists into objects. Pass either a single array of `[key, value]` - // pairs, or two parallel arrays of the same length -- one of keys, and one of - // the corresponding values. - _.object = function(list, values) { - var result = {}; - for (var i = 0, length = getLength(list); i < length; i++) { - if (values) { - result[list[i]] = values[i]; - } else { - result[list[i][0]] = list[i][1]; - } - } - return result; - }; - - // Generator function to create the findIndex and findLastIndex functions - function createPredicateIndexFinder(dir) { - return function(array, predicate, context) { - predicate = cb(predicate, context); - var length = getLength(array); - var index = dir > 0 ? 0 : length - 1; - for (; index >= 0 && index < length; index += dir) { - if (predicate(array[index], index, array)) return index; - } - return -1; - }; - } - - // Returns the first index on an array-like that passes a predicate test - _.findIndex = createPredicateIndexFinder(1); - _.findLastIndex = createPredicateIndexFinder(-1); - - // Use a comparator function to figure out the smallest index at which - // an object should be inserted so as to maintain order. Uses binary search. - _.sortedIndex = function(array, obj, iteratee, context) { - iteratee = cb(iteratee, context, 1); - var value = iteratee(obj); - var low = 0, high = getLength(array); - while (low < high) { - var mid = Math.floor((low + high) / 2); - if (iteratee(array[mid]) < value) low = mid + 1; else high = mid; - } - return low; - }; - - // Generator function to create the indexOf and lastIndexOf functions - function createIndexFinder(dir, predicateFind, sortedIndex) { - return function(array, item, idx) { - var i = 0, length = getLength(array); - if (typeof idx == 'number') { - if (dir > 0) { - i = idx >= 0 ? idx : Math.max(idx + length, i); - } else { - length = idx >= 0 ? Math.min(idx + 1, length) : idx + length + 1; - } - } else if (sortedIndex && idx && length) { - idx = sortedIndex(array, item); - return array[idx] === item ? idx : -1; - } - if (item !== item) { - idx = predicateFind(slice.call(array, i, length), _.isNaN); - return idx >= 0 ? idx + i : -1; - } - for (idx = dir > 0 ? i : length - 1; idx >= 0 && idx < length; idx += dir) { - if (array[idx] === item) return idx; - } - return -1; - }; - } - - // Return the position of the first occurrence of an item in an array, - // or -1 if the item is not included in the array. - // If the array is large and already in sort order, pass `true` - // for **isSorted** to use binary search. - _.indexOf = createIndexFinder(1, _.findIndex, _.sortedIndex); - _.lastIndexOf = createIndexFinder(-1, _.findLastIndex); - - // Generate an integer Array containing an arithmetic progression. A port of - // the native Python `range()` function. See - // [the Python documentation](http://docs.python.org/library/functions.html#range). - _.range = function(start, stop, step) { - if (stop == null) { - stop = start || 0; - start = 0; - } - step = step || 1; - - var length = Math.max(Math.ceil((stop - start) / step), 0); - var range = Array(length); - - for (var idx = 0; idx < length; idx++, start += step) { - range[idx] = start; - } - - return range; - }; - - // Function (ahem) Functions - // ------------------ - - // Determines whether to execute a function as a constructor - // or a normal function with the provided arguments - var executeBound = function(sourceFunc, boundFunc, context, callingContext, args) { - if (!(callingContext instanceof boundFunc)) return sourceFunc.apply(context, args); - var self = baseCreate(sourceFunc.prototype); - var result = sourceFunc.apply(self, args); - if (_.isObject(result)) return result; - return self; - }; - - // Create a function bound to a given object (assigning `this`, and arguments, - // optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if - // available. - _.bind = function(func, context) { - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!_.isFunction(func)) throw new TypeError('Bind must be called on a function'); - var args = slice.call(arguments, 2); - var bound = function() { - return executeBound(func, bound, context, this, args.concat(slice.call(arguments))); - }; - return bound; - }; - - // Partially apply a function by creating a version that has had some of its - // arguments pre-filled, without changing its dynamic `this` context. _ acts - // as a placeholder, allowing any combination of arguments to be pre-filled. - _.partial = function(func) { - var boundArgs = slice.call(arguments, 1); - var bound = function() { - var position = 0, length = boundArgs.length; - var args = Array(length); - for (var i = 0; i < length; i++) { - args[i] = boundArgs[i] === _ ? arguments[position++] : boundArgs[i]; - } - while (position < arguments.length) args.push(arguments[position++]); - return executeBound(func, bound, this, this, args); - }; - return bound; - }; - - // Bind a number of an object's methods to that object. Remaining arguments - // are the method names to be bound. Useful for ensuring that all callbacks - // defined on an object belong to it. - _.bindAll = function(obj) { - var i, length = arguments.length, key; - if (length <= 1) throw new Error('bindAll must be passed function names'); - for (i = 1; i < length; i++) { - key = arguments[i]; - obj[key] = _.bind(obj[key], obj); - } - return obj; - }; - - // Memoize an expensive function by storing its results. - _.memoize = function(func, hasher) { - var memoize = function(key) { - var cache = memoize.cache; - var address = '' + (hasher ? hasher.apply(this, arguments) : key); - if (!_.has(cache, address)) cache[address] = func.apply(this, arguments); - return cache[address]; - }; - memoize.cache = {}; - return memoize; - }; - - // Delays a function for the given number of milliseconds, and then calls - // it with the arguments supplied. - _.delay = function(func, wait) { - var args = slice.call(arguments, 2); - return setTimeout(function(){ - return func.apply(null, args); - }, wait); - }; - - // Defers a function, scheduling it to run after the current call stack has - // cleared. - _.defer = _.partial(_.delay, _, 1); - - // Returns a function, that, when invoked, will only be triggered at most once - // during a given window of time. Normally, the throttled function will run - // as much as it can, without ever going more than once per `wait` duration; - // but if you'd like to disable the execution on the leading edge, pass - // `{leading: false}`. To disable execution on the trailing edge, ditto. - _.throttle = function(func, wait, options) { - var context, args, result; - var timeout = null; - var previous = 0; - if (!options) options = {}; - var later = function() { - previous = options.leading === false ? 0 : _.now(); - timeout = null; - result = func.apply(context, args); - if (!timeout) context = args = null; - }; - return function() { - var now = _.now(); - if (!previous && options.leading === false) previous = now; - var remaining = wait - (now - previous); - context = this; - args = arguments; - if (remaining <= 0 || remaining > wait) { - if (timeout) { - clearTimeout(timeout); - timeout = null; - } - previous = now; - result = func.apply(context, args); - if (!timeout) context = args = null; - } else if (!timeout && options.trailing !== false) { - timeout = setTimeout(later, remaining); - } - return result; - }; - }; - - // Returns a function, that, as long as it continues to be invoked, will not - // be triggered. The function will be called after it stops being called for - // N milliseconds. If `immediate` is passed, trigger the function on the - // leading edge, instead of the trailing. - _.debounce = function(func, wait, immediate) { - var timeout, args, context, timestamp, result; - - var later = function() { - var last = _.now() - timestamp; - - if (last < wait && last >= 0) { - timeout = setTimeout(later, wait - last); - } else { - timeout = null; - if (!immediate) { - result = func.apply(context, args); - if (!timeout) context = args = null; - } - } - }; - - return function() { - context = this; - args = arguments; - timestamp = _.now(); - var callNow = immediate && !timeout; - if (!timeout) timeout = setTimeout(later, wait); - if (callNow) { - result = func.apply(context, args); - context = args = null; - } - - return result; - }; - }; - - // Returns the first function passed as an argument to the second, - // allowing you to adjust arguments, run code before and after, and - // conditionally execute the original function. - _.wrap = function(func, wrapper) { - return _.partial(wrapper, func); - }; - - // Returns a negated version of the passed-in predicate. - _.negate = function(predicate) { - return function() { - return !predicate.apply(this, arguments); - }; - }; - - // Returns a function that is the composition of a list of functions, each - // consuming the return value of the function that follows. - _.compose = function() { - var args = arguments; - var start = args.length - 1; - return function() { - var i = start; - var result = args[start].apply(this, arguments); - while (i--) result = args[i].call(this, result); - return result; - }; - }; - - // Returns a function that will only be executed on and after the Nth call. - _.after = function(times, func) { - return function() { - if (--times < 1) { - return func.apply(this, arguments); - } - }; - }; - - // Returns a function that will only be executed up to (but not including) the Nth call. - _.before = function(times, func) { - var memo; - return function() { - if (--times > 0) { - memo = func.apply(this, arguments); - } - if (times <= 1) func = null; - return memo; - }; - }; - - // Returns a function that will be executed at most one time, no matter how - // often you call it. Useful for lazy initialization. - _.once = _.partial(_.before, 2); - - // Object Functions - // ---------------- - - // Keys in IE < 9 that won't be iterated by `for key in ...` and thus missed. - var hasEnumBug = !{toString: null}.propertyIsEnumerable('toString'); - var nonEnumerableProps = ['valueOf', 'isPrototypeOf', 'toString', - 'propertyIsEnumerable', 'hasOwnProperty', 'toLocaleString']; - - function collectNonEnumProps(obj, keys) { - var nonEnumIdx = nonEnumerableProps.length; - var constructor = obj.constructor; - var proto = (_.isFunction(constructor) && constructor.prototype) || ObjProto; - - // Constructor is a special case. - var prop = 'constructor'; - if (_.has(obj, prop) && !_.contains(keys, prop)) keys.push(prop); - - while (nonEnumIdx--) { - prop = nonEnumerableProps[nonEnumIdx]; - if (prop in obj && obj[prop] !== proto[prop] && !_.contains(keys, prop)) { - keys.push(prop); - } - } - } - - // Retrieve the names of an object's own properties. - // Delegates to **ECMAScript 5**'s native `Object.keys` - _.keys = function(obj) { - if (!_.isObject(obj)) return []; - if (nativeKeys) return nativeKeys(obj); - var keys = []; - for (var key in obj) if (_.has(obj, key)) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve all the property names of an object. - _.allKeys = function(obj) { - if (!_.isObject(obj)) return []; - var keys = []; - for (var key in obj) keys.push(key); - // Ahem, IE < 9. - if (hasEnumBug) collectNonEnumProps(obj, keys); - return keys; - }; - - // Retrieve the values of an object's properties. - _.values = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var values = Array(length); - for (var i = 0; i < length; i++) { - values[i] = obj[keys[i]]; - } - return values; - }; - - // Returns the results of applying the iteratee to each element of the object - // In contrast to _.map it returns an object - _.mapObject = function(obj, iteratee, context) { - iteratee = cb(iteratee, context); - var keys = _.keys(obj), - length = keys.length, - results = {}, - currentKey; - for (var index = 0; index < length; index++) { - currentKey = keys[index]; - results[currentKey] = iteratee(obj[currentKey], currentKey, obj); - } - return results; - }; - - // Convert an object into a list of `[key, value]` pairs. - _.pairs = function(obj) { - var keys = _.keys(obj); - var length = keys.length; - var pairs = Array(length); - for (var i = 0; i < length; i++) { - pairs[i] = [keys[i], obj[keys[i]]]; - } - return pairs; - }; - - // Invert the keys and values of an object. The values must be serializable. - _.invert = function(obj) { - var result = {}; - var keys = _.keys(obj); - for (var i = 0, length = keys.length; i < length; i++) { - result[obj[keys[i]]] = keys[i]; - } - return result; - }; - - // Return a sorted list of the function names available on the object. - // Aliased as `methods` - _.functions = _.methods = function(obj) { - var names = []; - for (var key in obj) { - if (_.isFunction(obj[key])) names.push(key); - } - return names.sort(); - }; - - // Extend a given object with all the properties in passed-in object(s). - _.extend = createAssigner(_.allKeys); - - // Assigns a given object with all the own properties in the passed-in object(s) - // (https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) - _.extendOwn = _.assign = createAssigner(_.keys); - - // Returns the first key on an object that passes a predicate test - _.findKey = function(obj, predicate, context) { - predicate = cb(predicate, context); - var keys = _.keys(obj), key; - for (var i = 0, length = keys.length; i < length; i++) { - key = keys[i]; - if (predicate(obj[key], key, obj)) return key; - } - }; - - // Return a copy of the object only containing the whitelisted properties. - _.pick = function(object, oiteratee, context) { - var result = {}, obj = object, iteratee, keys; - if (obj == null) return result; - if (_.isFunction(oiteratee)) { - keys = _.allKeys(obj); - iteratee = optimizeCb(oiteratee, context); - } else { - keys = flatten(arguments, false, false, 1); - iteratee = function(value, key, obj) { return key in obj; }; - obj = Object(obj); - } - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i]; - var value = obj[key]; - if (iteratee(value, key, obj)) result[key] = value; - } - return result; - }; - - // Return a copy of the object without the blacklisted properties. - _.omit = function(obj, iteratee, context) { - if (_.isFunction(iteratee)) { - iteratee = _.negate(iteratee); - } else { - var keys = _.map(flatten(arguments, false, false, 1), String); - iteratee = function(value, key) { - return !_.contains(keys, key); - }; - } - return _.pick(obj, iteratee, context); - }; - - // Fill in a given object with default properties. - _.defaults = createAssigner(_.allKeys, true); - - // Creates an object that inherits from the given prototype object. - // If additional properties are provided then they will be added to the - // created object. - _.create = function(prototype, props) { - var result = baseCreate(prototype); - if (props) _.extendOwn(result, props); - return result; - }; - - // Create a (shallow-cloned) duplicate of an object. - _.clone = function(obj) { - if (!_.isObject(obj)) return obj; - return _.isArray(obj) ? obj.slice() : _.extend({}, obj); - }; - - // Invokes interceptor with the obj, and then returns obj. - // The primary purpose of this method is to "tap into" a method chain, in - // order to perform operations on intermediate results within the chain. - _.tap = function(obj, interceptor) { - interceptor(obj); - return obj; - }; - - // Returns whether an object has a given set of `key:value` pairs. - _.isMatch = function(object, attrs) { - var keys = _.keys(attrs), length = keys.length; - if (object == null) return !length; - var obj = Object(object); - for (var i = 0; i < length; i++) { - var key = keys[i]; - if (attrs[key] !== obj[key] || !(key in obj)) return false; - } - return true; - }; - - - // Internal recursive comparison function for `isEqual`. - var eq = function(a, b, aStack, bStack) { - // Identical objects are equal. `0 === -0`, but they aren't identical. - // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). - if (a === b) return a !== 0 || 1 / a === 1 / b; - // A strict comparison is necessary because `null == undefined`. - if (a == null || b == null) return a === b; - // Unwrap any wrapped objects. - if (a instanceof _) a = a._wrapped; - if (b instanceof _) b = b._wrapped; - // Compare `[[Class]]` names. - var className = toString.call(a); - if (className !== toString.call(b)) return false; - switch (className) { - // Strings, numbers, regular expressions, dates, and booleans are compared by value. - case '[object RegExp]': - // RegExps are coerced to strings for comparison (Note: '' + /a/i === '/a/i') - case '[object String]': - // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is - // equivalent to `new String("5")`. - return '' + a === '' + b; - case '[object Number]': - // `NaN`s are equivalent, but non-reflexive. - // Object(NaN) is equivalent to NaN - if (+a !== +a) return +b !== +b; - // An `egal` comparison is performed for other numeric values. - return +a === 0 ? 1 / +a === 1 / b : +a === +b; - case '[object Date]': - case '[object Boolean]': - // Coerce dates and booleans to numeric primitive values. Dates are compared by their - // millisecond representations. Note that invalid dates with millisecond representations - // of `NaN` are not equivalent. - return +a === +b; - } - - var areArrays = className === '[object Array]'; - if (!areArrays) { - if (typeof a != 'object' || typeof b != 'object') return false; - - // Objects with different constructors are not equivalent, but `Object`s or `Array`s - // from different frames are. - var aCtor = a.constructor, bCtor = b.constructor; - if (aCtor !== bCtor && !(_.isFunction(aCtor) && aCtor instanceof aCtor && - _.isFunction(bCtor) && bCtor instanceof bCtor) - && ('constructor' in a && 'constructor' in b)) { - return false; - } - } - // Assume equality for cyclic structures. The algorithm for detecting cyclic - // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. - - // Initializing stack of traversed objects. - // It's done here since we only need them for objects and arrays comparison. - aStack = aStack || []; - bStack = bStack || []; - var length = aStack.length; - while (length--) { - // Linear search. Performance is inversely proportional to the number of - // unique nested structures. - if (aStack[length] === a) return bStack[length] === b; - } - - // Add the first object to the stack of traversed objects. - aStack.push(a); - bStack.push(b); - - // Recursively compare objects and arrays. - if (areArrays) { - // Compare array lengths to determine if a deep comparison is necessary. - length = a.length; - if (length !== b.length) return false; - // Deep compare the contents, ignoring non-numeric properties. - while (length--) { - if (!eq(a[length], b[length], aStack, bStack)) return false; - } - } else { - // Deep compare objects. - var keys = _.keys(a), key; - length = keys.length; - // Ensure that both objects contain the same number of properties before comparing deep equality. - if (_.keys(b).length !== length) return false; - while (length--) { - // Deep compare each member - key = keys[length]; - if (!(_.has(b, key) && eq(a[key], b[key], aStack, bStack))) return false; - } - } - // Remove the first object from the stack of traversed objects. - aStack.pop(); - bStack.pop(); - return true; - }; - - // Perform a deep comparison to check if two objects are equal. - _.isEqual = function(a, b) { - return eq(a, b); - }; - - // Is a given array, string, or object empty? - // An "empty" object has no enumerable own-properties. - _.isEmpty = function(obj) { - if (obj == null) return true; - if (isArrayLike(obj) && (_.isArray(obj) || _.isString(obj) || _.isArguments(obj))) return obj.length === 0; - return _.keys(obj).length === 0; - }; - - // Is a given value a DOM element? - _.isElement = function(obj) { - return !!(obj && obj.nodeType === 1); - }; - - // Is a given value an array? - // Delegates to ECMA5's native Array.isArray - _.isArray = nativeIsArray || function(obj) { - return toString.call(obj) === '[object Array]'; - }; - - // Is a given variable an object? - _.isObject = function(obj) { - var type = typeof obj; - return type === 'function' || type === 'object' && !!obj; - }; - - // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp, isError. - _.each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp', 'Error'], function(name) { - _['is' + name] = function(obj) { - return toString.call(obj) === '[object ' + name + ']'; - }; - }); - - // Define a fallback version of the method in browsers (ahem, IE < 9), where - // there isn't any inspectable "Arguments" type. - if (!_.isArguments(arguments)) { - _.isArguments = function(obj) { - return _.has(obj, 'callee'); - }; - } - - // Optimize `isFunction` if appropriate. Work around some typeof bugs in old v8, - // IE 11 (#1621), and in Safari 8 (#1929). - if (typeof /./ != 'function' && typeof Int8Array != 'object') { - _.isFunction = function(obj) { - return typeof obj == 'function' || false; - }; - } - - // Is a given object a finite number? - _.isFinite = function(obj) { - return isFinite(obj) && !isNaN(parseFloat(obj)); - }; - - // Is the given value `NaN`? (NaN is the only number which does not equal itself). - _.isNaN = function(obj) { - return _.isNumber(obj) && obj !== +obj; - }; - - // Is a given value a boolean? - _.isBoolean = function(obj) { - return obj === true || obj === false || toString.call(obj) === '[object Boolean]'; - }; - - // Is a given value equal to null? - _.isNull = function(obj) { - return obj === null; - }; - - // Is a given variable undefined? - _.isUndefined = function(obj) { - return obj === void 0; - }; - - // Shortcut function for checking if an object has a given property directly - // on itself (in other words, not on a prototype). - _.has = function(obj, key) { - return obj != null && hasOwnProperty.call(obj, key); - }; - - // Utility Functions - // ----------------- - - // Run Underscore.js in *noConflict* mode, returning the `_` variable to its - // previous owner. Returns a reference to the Underscore object. - _.noConflict = function() { - root._ = previousUnderscore; - return this; - }; - - // Keep the identity function around for default iteratees. - _.identity = function(value) { - return value; - }; - - // Predicate-generating functions. Often useful outside of Underscore. - _.constant = function(value) { - return function() { - return value; - }; - }; - - _.noop = function(){}; - - _.property = property; - - // Generates a function for a given object that returns a given property. - _.propertyOf = function(obj) { - return obj == null ? function(){} : function(key) { - return obj[key]; - }; - }; - - // Returns a predicate for checking whether an object has a given set of - // `key:value` pairs. - _.matcher = _.matches = function(attrs) { - attrs = _.extendOwn({}, attrs); - return function(obj) { - return _.isMatch(obj, attrs); - }; - }; - - // Run a function **n** times. - _.times = function(n, iteratee, context) { - var accum = Array(Math.max(0, n)); - iteratee = optimizeCb(iteratee, context, 1); - for (var i = 0; i < n; i++) accum[i] = iteratee(i); - return accum; - }; - - // Return a random integer between min and max (inclusive). - _.random = function(min, max) { - if (max == null) { - max = min; - min = 0; - } - return min + Math.floor(Math.random() * (max - min + 1)); - }; - - // A (possibly faster) way to get the current timestamp as an integer. - _.now = Date.now || function() { - return new Date().getTime(); - }; - - // List of HTML entities for escaping. - var escapeMap = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''', - '`': '`' - }; - var unescapeMap = _.invert(escapeMap); - - // Functions for escaping and unescaping strings to/from HTML interpolation. - var createEscaper = function(map) { - var escaper = function(match) { - return map[match]; - }; - // Regexes for identifying a key that needs to be escaped - var source = '(?:' + _.keys(map).join('|') + ')'; - var testRegexp = RegExp(source); - var replaceRegexp = RegExp(source, 'g'); - return function(string) { - string = string == null ? '' : '' + string; - return testRegexp.test(string) ? string.replace(replaceRegexp, escaper) : string; - }; - }; - _.escape = createEscaper(escapeMap); - _.unescape = createEscaper(unescapeMap); - - // If the value of the named `property` is a function then invoke it with the - // `object` as context; otherwise, return it. - _.result = function(object, property, fallback) { - var value = object == null ? void 0 : object[property]; - if (value === void 0) { - value = fallback; - } - return _.isFunction(value) ? value.call(object) : value; - }; - - // Generate a unique integer id (unique within the entire client session). - // Useful for temporary DOM ids. - var idCounter = 0; - _.uniqueId = function(prefix) { - var id = ++idCounter + ''; - return prefix ? prefix + id : id; - }; - - // By default, Underscore uses ERB-style template delimiters, change the - // following template settings to use alternative delimiters. - _.templateSettings = { - evaluate : /<%([\s\S]+?)%>/g, - interpolate : /<%=([\s\S]+?)%>/g, - escape : /<%-([\s\S]+?)%>/g - }; - - // When customizing `templateSettings`, if you don't want to define an - // interpolation, evaluation or escaping regex, we need one that is - // guaranteed not to match. - var noMatch = /(.)^/; - - // Certain characters need to be escaped so that they can be put into a - // string literal. - var escapes = { - "'": "'", - '\\': '\\', - '\r': 'r', - '\n': 'n', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - var escaper = /\\|'|\r|\n|\u2028|\u2029/g; - - var escapeChar = function(match) { - return '\\' + escapes[match]; - }; - - // JavaScript micro-templating, similar to John Resig's implementation. - // Underscore templating handles arbitrary delimiters, preserves whitespace, - // and correctly escapes quotes within interpolated code. - // NB: `oldSettings` only exists for backwards compatibility. - _.template = function(text, settings, oldSettings) { - if (!settings && oldSettings) settings = oldSettings; - settings = _.defaults({}, settings, _.templateSettings); - - // Combine delimiters into one regular expression via alternation. - var matcher = RegExp([ - (settings.escape || noMatch).source, - (settings.interpolate || noMatch).source, - (settings.evaluate || noMatch).source - ].join('|') + '|$', 'g'); - - // Compile the template source, escaping string literals appropriately. - var index = 0; - var source = "__p+='"; - text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { - source += text.slice(index, offset).replace(escaper, escapeChar); - index = offset + match.length; - - if (escape) { - source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; - } else if (interpolate) { - source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; - } else if (evaluate) { - source += "';\n" + evaluate + "\n__p+='"; - } - - // Adobe VMs need the match returned to produce the correct offest. - return match; - }); - source += "';\n"; - - // If a variable is not specified, place data values in local scope. - if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; - - source = "var __t,__p='',__j=Array.prototype.join," + - "print=function(){__p+=__j.call(arguments,'');};\n" + - source + 'return __p;\n'; - - try { - var render = new Function(settings.variable || 'obj', '_', source); - } catch (e) { - e.source = source; - throw e; - } - - var template = function(data) { - return render.call(this, data, _); - }; - - // Provide the compiled source as a convenience for precompilation. - var argument = settings.variable || 'obj'; - template.source = 'function(' + argument + '){\n' + source + '}'; - - return template; - }; - - // Add a "chain" function. Start chaining a wrapped Underscore object. - _.chain = function(obj) { - var instance = _(obj); - instance._chain = true; - return instance; - }; - - // OOP - // --------------- - // If Underscore is called as a function, it returns a wrapped object that - // can be used OO-style. This wrapper holds altered versions of all the - // underscore functions. Wrapped objects may be chained. - - // Helper function to continue chaining intermediate results. - var result = function(instance, obj) { - return instance._chain ? _(obj).chain() : obj; - }; - - // Add your own custom functions to the Underscore object. - _.mixin = function(obj) { - _.each(_.functions(obj), function(name) { - var func = _[name] = obj[name]; - _.prototype[name] = function() { - var args = [this._wrapped]; - push.apply(args, arguments); - return result(this, func.apply(_, args)); - }; - }); - }; - - // Add all of the Underscore functions to the wrapper object. - _.mixin(_); - - // Add all mutator Array functions to the wrapper. - _.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - var obj = this._wrapped; - method.apply(obj, arguments); - if ((name === 'shift' || name === 'splice') && obj.length === 0) delete obj[0]; - return result(this, obj); - }; - }); - - // Add all accessor Array functions to the wrapper. - _.each(['concat', 'join', 'slice'], function(name) { - var method = ArrayProto[name]; - _.prototype[name] = function() { - return result(this, method.apply(this._wrapped, arguments)); - }; - }); - - // Extracts the result from a wrapped and chained object. - _.prototype.value = function() { - return this._wrapped; - }; - - // Provide unwrapping proxy for some methods used in engine operations - // such as arithmetic and JSON stringification. - _.prototype.valueOf = _.prototype.toJSON = _.prototype.value; - - _.prototype.toString = function() { - return '' + this._wrapped; - }; - - // AMD registration happens at the end for compatibility with AMD loaders - // that may not enforce next-turn semantics on modules. Even though general - // practice for AMD registration is to be anonymous, underscore registers - // as a named module because, like jQuery, it is a base library that is - // popular enough to be bundled in a third party lib, but not be part of - // an AMD load request. Those cases could generate an error when an - // anonymous define() is called outside of a loader request. - if (typeof define === 'function' && define.amd) { - define('underscore', [], function() { - return _; - }); - } -}.call(this)); diff --git a/node_modules/url/LICENSE b/node_modules/url/LICENSE deleted file mode 100644 index f45bc118..00000000 --- a/node_modules/url/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright Joyent, Inc. and other Node contributors. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/node_modules/url/node_modules/punycode/README.md b/node_modules/url/node_modules/punycode/README.md deleted file mode 100644 index 831e6379..00000000 --- a/node_modules/url/node_modules/punycode/README.md +++ /dev/null @@ -1,176 +0,0 @@ -# Punycode.js [![Build status](https://travis-ci.org/bestiejs/punycode.js.svg?branch=master)](https://travis-ci.org/bestiejs/punycode.js) [![Code coverage status](http://img.shields.io/coveralls/bestiejs/punycode.js/master.svg)](https://coveralls.io/r/bestiejs/punycode.js) [![Dependency status](https://gemnasium.com/bestiejs/punycode.js.svg)](https://gemnasium.com/bestiejs/punycode.js) - -A robust Punycode converter that fully complies to [RFC 3492](http://tools.ietf.org/html/rfc3492) and [RFC 5891](http://tools.ietf.org/html/rfc5891), and works on nearly all JavaScript platforms. - -This JavaScript library is the result of comparing, optimizing and documenting different open-source implementations of the Punycode algorithm: - -* [The C example code from RFC 3492](http://tools.ietf.org/html/rfc3492#appendix-C) -* [`punycode.c` by _Markus W. Scherer_ (IBM)](http://opensource.apple.com/source/ICU/ICU-400.42/icuSources/common/punycode.c) -* [`punycode.c` by _Ben Noordhuis_](https://github.com/bnoordhuis/punycode/blob/master/punycode.c) -* [JavaScript implementation by _some_](http://stackoverflow.com/questions/183485/can-anyone-recommend-a-good-free-javascript-for-punycode-to-unicode-conversion/301287#301287) -* [`punycode.js` by _Ben Noordhuis_](https://github.com/joyent/node/blob/426298c8c1c0d5b5224ac3658c41e7c2a3fe9377/lib/punycode.js) (note: [not fully compliant](https://github.com/joyent/node/issues/2072)) - -This project is [bundled](https://github.com/joyent/node/blob/master/lib/punycode.js) with [Node.js v0.6.2+](https://github.com/joyent/node/compare/975f1930b1...61e796decc). - -## Installation - -Via [npm](http://npmjs.org/) (only required for Node.js releases older than v0.6.2): - -```bash -npm install punycode -``` - -Via [Bower](http://bower.io/): - -```bash -bower install punycode -``` - -Via [Component](https://github.com/component/component): - -```bash -component install bestiejs/punycode.js -``` - -In a browser: - -```html - -``` - -In [Narwhal](http://narwhaljs.org/), [Node.js](http://nodejs.org/), and [RingoJS](http://ringojs.org/): - -```js -var punycode = require('punycode'); -``` - -In [Rhino](http://www.mozilla.org/rhino/): - -```js -load('punycode.js'); -``` - -Using an AMD loader like [RequireJS](http://requirejs.org/): - -```js -require( - { - 'paths': { - 'punycode': 'path/to/punycode' - } - }, - ['punycode'], - function(punycode) { - console.log(punycode); - } -); -``` - -## API - -### `punycode.decode(string)` - -Converts a Punycode string of ASCII symbols to a string of Unicode symbols. - -```js -// decode domain name parts -punycode.decode('maana-pta'); // 'mañana' -punycode.decode('--dqo34k'); // '☃-⌘' -``` - -### `punycode.encode(string)` - -Converts a string of Unicode symbols to a Punycode string of ASCII symbols. - -```js -// encode domain name parts -punycode.encode('mañana'); // 'maana-pta' -punycode.encode('☃-⌘'); // '--dqo34k' -``` - -### `punycode.toUnicode(input)` - -Converts a Punycode string representing a domain name or an email address to Unicode. Only the Punycoded parts of the input will be converted, i.e. it doesn’t matter if you call it on a string that has already been converted to Unicode. - -```js -// decode domain names -punycode.toUnicode('xn--maana-pta.com'); -// → 'mañana.com' -punycode.toUnicode('xn----dqo34k.com'); -// → '☃-⌘.com' - -// decode email addresses -punycode.toUnicode('джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq'); -// → 'джумла@джpумлатест.bрфa' -``` - -### `punycode.toASCII(input)` - -Converts a Unicode string representing a domain name or an email address to Punycode. Only the non-ASCII parts of the input will be converted, i.e. it doesn’t matter if you call it with a domain that's already in ASCII. - -```js -// encode domain names -punycode.toASCII('mañana.com'); -// → 'xn--maana-pta.com' -punycode.toASCII('☃-⌘.com'); -// → 'xn----dqo34k.com' - -// encode email addresses -punycode.toASCII('джумла@джpумлатест.bрфa'); -// → 'джумла@xn--p-8sbkgc5ag7bhce.xn--ba-lmcq' -``` - -### `punycode.ucs2` - -#### `punycode.ucs2.decode(string)` - -Creates an array containing the numeric code point values of each Unicode symbol in the string. While [JavaScript uses UCS-2 internally](https://mathiasbynens.be/notes/javascript-encoding), this function will convert a pair of surrogate halves (each of which UCS-2 exposes as separate characters) into a single code point, matching UTF-16. - -```js -punycode.ucs2.decode('abc'); -// → [0x61, 0x62, 0x63] -// surrogate pair for U+1D306 TETRAGRAM FOR CENTRE: -punycode.ucs2.decode('\uD834\uDF06'); -// → [0x1D306] -``` - -#### `punycode.ucs2.encode(codePoints)` - -Creates a string based on an array of numeric code point values. - -```js -punycode.ucs2.encode([0x61, 0x62, 0x63]); -// → 'abc' -punycode.ucs2.encode([0x1D306]); -// → '\uD834\uDF06' -``` - -### `punycode.version` - -A string representing the current Punycode.js version number. - -## Unit tests & code coverage - -After cloning this repository, run `npm install --dev` to install the dependencies needed for Punycode.js development and testing. You may want to install Istanbul _globally_ using `npm install istanbul -g`. - -Once that’s done, you can run the unit tests in Node using `npm test` or `node tests/tests.js`. To run the tests in Rhino, Ringo, Narwhal, PhantomJS, and web browsers as well, use `grunt test`. - -To generate the code coverage report, use `grunt cover`. - -Feel free to fork if you see possible improvements! - -## Author - -| [![twitter/mathias](https://gravatar.com/avatar/24e08a9ea84deb17ae121074d0f17125?s=70)](https://twitter.com/mathias "Follow @mathias on Twitter") | -|---| -| [Mathias Bynens](https://mathiasbynens.be/) | - -## Contributors - -| [![twitter/jdalton](https://gravatar.com/avatar/299a3d891ff1920b69c364d061007043?s=70)](https://twitter.com/jdalton "Follow @jdalton on Twitter") | -|---| -| [John-David Dalton](http://allyoucanleet.com/) | - -## License - -Punycode.js is available under the [MIT](https://mths.be/mit) license. diff --git a/node_modules/url/node_modules/punycode/package.json b/node_modules/url/node_modules/punycode/package.json deleted file mode 100644 index 6d193c2c..00000000 --- a/node_modules/url/node_modules/punycode/package.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "punycode", - "version": "1.3.2", - "description": "A robust Punycode converter that fully complies to RFC 3492 and RFC 5891, and works on nearly all JavaScript platforms.", - "homepage": "https://mths.be/punycode", - "main": "punycode.js", - "keywords": [ - "punycode", - "unicode", - "idn", - "idna", - "dns", - "url", - "domain" - ], - "license": "MIT", - "author": { - "name": "Mathias Bynens", - "url": "https://mathiasbynens.be/" - }, - "contributors": [ - { - "name": "Mathias Bynens", - "url": "https://mathiasbynens.be/" - }, - { - "name": "John-David Dalton", - "url": "http://allyoucanleet.com/" - } - ], - "repository": { - "type": "git", - "url": "https://github.com/bestiejs/punycode.js.git" - }, - "bugs": { - "url": "https://github.com/bestiejs/punycode.js/issues" - }, - "files": [ - "LICENSE-MIT.txt", - "punycode.js" - ], - "scripts": { - "test": "node tests/tests.js" - }, - "devDependencies": { - "coveralls": "^2.10.1", - "grunt": "^0.4.5", - "grunt-contrib-uglify": "^0.5.0", - "grunt-shell": "^0.7.0", - "istanbul": "^0.2.13", - "qunit-extras": "^1.2.0", - "qunitjs": "~1.11.0", - "requirejs": "^2.1.14" - }, - "gitHead": "38c8d3131a82567bfef18da09f7f4db68c84f8a3", - "_id": "punycode@1.3.2", - "_shasum": "9653a036fb7c1ee42342f2325cceefea3926c48d", - "_from": "punycode@1.3.2", - "_npmVersion": "1.4.28", - "_npmUser": { - "name": "mathias", - "email": "mathias@qiwi.be" - }, - "maintainers": [ - { - "name": "mathias", - "email": "mathias@qiwi.be" - }, - { - "name": "reconbot", - "email": "wizard@roborooter.com" - } - ], - "dist": { - "shasum": "9653a036fb7c1ee42342f2325cceefea3926c48d", - "tarball": "http://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz" -} diff --git a/node_modules/url/node_modules/punycode/punycode.js b/node_modules/url/node_modules/punycode/punycode.js deleted file mode 100644 index ac685973..00000000 --- a/node_modules/url/node_modules/punycode/punycode.js +++ /dev/null @@ -1,530 +0,0 @@ -/*! https://mths.be/punycode v1.3.2 by @mathias */ -;(function(root) { - - /** Detect free variables */ - var freeExports = typeof exports == 'object' && exports && - !exports.nodeType && exports; - var freeModule = typeof module == 'object' && module && - !module.nodeType && module; - var freeGlobal = typeof global == 'object' && global; - if ( - freeGlobal.global === freeGlobal || - freeGlobal.window === freeGlobal || - freeGlobal.self === freeGlobal - ) { - root = freeGlobal; - } - - /** - * The `punycode` object. - * @name punycode - * @type Object - */ - var punycode, - - /** Highest positive signed 32-bit float value */ - maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1 - - /** Bootstring parameters */ - base = 36, - tMin = 1, - tMax = 26, - skew = 38, - damp = 700, - initialBias = 72, - initialN = 128, // 0x80 - delimiter = '-', // '\x2D' - - /** Regular expressions */ - regexPunycode = /^xn--/, - regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars - regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators - - /** Error messages */ - errors = { - 'overflow': 'Overflow: input needs wider integers to process', - 'not-basic': 'Illegal input >= 0x80 (not a basic code point)', - 'invalid-input': 'Invalid input' - }, - - /** Convenience shortcuts */ - baseMinusTMin = base - tMin, - floor = Math.floor, - stringFromCharCode = String.fromCharCode, - - /** Temporary variable */ - key; - - /*--------------------------------------------------------------------------*/ - - /** - * A generic error utility function. - * @private - * @param {String} type The error type. - * @returns {Error} Throws a `RangeError` with the applicable error message. - */ - function error(type) { - throw RangeError(errors[type]); - } - - /** - * A generic `Array#map` utility function. - * @private - * @param {Array} array The array to iterate over. - * @param {Function} callback The function that gets called for every array - * item. - * @returns {Array} A new array of values returned by the callback function. - */ - function map(array, fn) { - var length = array.length; - var result = []; - while (length--) { - result[length] = fn(array[length]); - } - return result; - } - - /** - * A simple `Array#map`-like wrapper to work with domain name strings or email - * addresses. - * @private - * @param {String} domain The domain name or email address. - * @param {Function} callback The function that gets called for every - * character. - * @returns {Array} A new string of characters returned by the callback - * function. - */ - function mapDomain(string, fn) { - var parts = string.split('@'); - var result = ''; - if (parts.length > 1) { - // In email addresses, only the domain name should be punycoded. Leave - // the local part (i.e. everything up to `@`) intact. - result = parts[0] + '@'; - string = parts[1]; - } - // Avoid `split(regex)` for IE8 compatibility. See #17. - string = string.replace(regexSeparators, '\x2E'); - var labels = string.split('.'); - var encoded = map(labels, fn).join('.'); - return result + encoded; - } - - /** - * Creates an array containing the numeric code points of each Unicode - * character in the string. While JavaScript uses UCS-2 internally, - * this function will convert a pair of surrogate halves (each of which - * UCS-2 exposes as separate characters) into a single code point, - * matching UTF-16. - * @see `punycode.ucs2.encode` - * @see - * @memberOf punycode.ucs2 - * @name decode - * @param {String} string The Unicode input string (UCS-2). - * @returns {Array} The new array of code points. - */ - function ucs2decode(string) { - var output = [], - counter = 0, - length = string.length, - value, - extra; - while (counter < length) { - value = string.charCodeAt(counter++); - if (value >= 0xD800 && value <= 0xDBFF && counter < length) { - // high surrogate, and there is a next character - extra = string.charCodeAt(counter++); - if ((extra & 0xFC00) == 0xDC00) { // low surrogate - output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000); - } else { - // unmatched surrogate; only append this code unit, in case the next - // code unit is the high surrogate of a surrogate pair - output.push(value); - counter--; - } - } else { - output.push(value); - } - } - return output; - } - - /** - * Creates a string based on an array of numeric code points. - * @see `punycode.ucs2.decode` - * @memberOf punycode.ucs2 - * @name encode - * @param {Array} codePoints The array of numeric code points. - * @returns {String} The new Unicode string (UCS-2). - */ - function ucs2encode(array) { - return map(array, function(value) { - var output = ''; - if (value > 0xFFFF) { - value -= 0x10000; - output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800); - value = 0xDC00 | value & 0x3FF; - } - output += stringFromCharCode(value); - return output; - }).join(''); - } - - /** - * Converts a basic code point into a digit/integer. - * @see `digitToBasic()` - * @private - * @param {Number} codePoint The basic numeric code point value. - * @returns {Number} The numeric value of a basic code point (for use in - * representing integers) in the range `0` to `base - 1`, or `base` if - * the code point does not represent a value. - */ - function basicToDigit(codePoint) { - if (codePoint - 48 < 10) { - return codePoint - 22; - } - if (codePoint - 65 < 26) { - return codePoint - 65; - } - if (codePoint - 97 < 26) { - return codePoint - 97; - } - return base; - } - - /** - * Converts a digit/integer into a basic code point. - * @see `basicToDigit()` - * @private - * @param {Number} digit The numeric value of a basic code point. - * @returns {Number} The basic code point whose value (when used for - * representing integers) is `digit`, which needs to be in the range - * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is - * used; else, the lowercase form is used. The behavior is undefined - * if `flag` is non-zero and `digit` has no uppercase form. - */ - function digitToBasic(digit, flag) { - // 0..25 map to ASCII a..z or A..Z - // 26..35 map to ASCII 0..9 - return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5); - } - - /** - * Bias adaptation function as per section 3.4 of RFC 3492. - * http://tools.ietf.org/html/rfc3492#section-3.4 - * @private - */ - function adapt(delta, numPoints, firstTime) { - var k = 0; - delta = firstTime ? floor(delta / damp) : delta >> 1; - delta += floor(delta / numPoints); - for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) { - delta = floor(delta / baseMinusTMin); - } - return floor(k + (baseMinusTMin + 1) * delta / (delta + skew)); - } - - /** - * Converts a Punycode string of ASCII-only symbols to a string of Unicode - * symbols. - * @memberOf punycode - * @param {String} input The Punycode string of ASCII-only symbols. - * @returns {String} The resulting string of Unicode symbols. - */ - function decode(input) { - // Don't use UCS-2 - var output = [], - inputLength = input.length, - out, - i = 0, - n = initialN, - bias = initialBias, - basic, - j, - index, - oldi, - w, - k, - digit, - t, - /** Cached calculation results */ - baseMinusT; - - // Handle the basic code points: let `basic` be the number of input code - // points before the last delimiter, or `0` if there is none, then copy - // the first basic code points to the output. - - basic = input.lastIndexOf(delimiter); - if (basic < 0) { - basic = 0; - } - - for (j = 0; j < basic; ++j) { - // if it's not a basic code point - if (input.charCodeAt(j) >= 0x80) { - error('not-basic'); - } - output.push(input.charCodeAt(j)); - } - - // Main decoding loop: start just after the last delimiter if any basic code - // points were copied; start at the beginning otherwise. - - for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) { - - // `index` is the index of the next character to be consumed. - // Decode a generalized variable-length integer into `delta`, - // which gets added to `i`. The overflow checking is easier - // if we increase `i` as we go, then subtract off its starting - // value at the end to obtain `delta`. - for (oldi = i, w = 1, k = base; /* no condition */; k += base) { - - if (index >= inputLength) { - error('invalid-input'); - } - - digit = basicToDigit(input.charCodeAt(index++)); - - if (digit >= base || digit > floor((maxInt - i) / w)) { - error('overflow'); - } - - i += digit * w; - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - - if (digit < t) { - break; - } - - baseMinusT = base - t; - if (w > floor(maxInt / baseMinusT)) { - error('overflow'); - } - - w *= baseMinusT; - - } - - out = output.length + 1; - bias = adapt(i - oldi, out, oldi == 0); - - // `i` was supposed to wrap around from `out` to `0`, - // incrementing `n` each time, so we'll fix that now: - if (floor(i / out) > maxInt - n) { - error('overflow'); - } - - n += floor(i / out); - i %= out; - - // Insert `n` at position `i` of the output - output.splice(i++, 0, n); - - } - - return ucs2encode(output); - } - - /** - * Converts a string of Unicode symbols (e.g. a domain name label) to a - * Punycode string of ASCII-only symbols. - * @memberOf punycode - * @param {String} input The string of Unicode symbols. - * @returns {String} The resulting Punycode string of ASCII-only symbols. - */ - function encode(input) { - var n, - delta, - handledCPCount, - basicLength, - bias, - j, - m, - q, - k, - t, - currentValue, - output = [], - /** `inputLength` will hold the number of code points in `input`. */ - inputLength, - /** Cached calculation results */ - handledCPCountPlusOne, - baseMinusT, - qMinusT; - - // Convert the input in UCS-2 to Unicode - input = ucs2decode(input); - - // Cache the length - inputLength = input.length; - - // Initialize the state - n = initialN; - delta = 0; - bias = initialBias; - - // Handle the basic code points - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue < 0x80) { - output.push(stringFromCharCode(currentValue)); - } - } - - handledCPCount = basicLength = output.length; - - // `handledCPCount` is the number of code points that have been handled; - // `basicLength` is the number of basic code points. - - // Finish the basic string - if it is not empty - with a delimiter - if (basicLength) { - output.push(delimiter); - } - - // Main encoding loop: - while (handledCPCount < inputLength) { - - // All non-basic code points < n have been handled already. Find the next - // larger one: - for (m = maxInt, j = 0; j < inputLength; ++j) { - currentValue = input[j]; - if (currentValue >= n && currentValue < m) { - m = currentValue; - } - } - - // Increase `delta` enough to advance the decoder's state to , - // but guard against overflow - handledCPCountPlusOne = handledCPCount + 1; - if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) { - error('overflow'); - } - - delta += (m - n) * handledCPCountPlusOne; - n = m; - - for (j = 0; j < inputLength; ++j) { - currentValue = input[j]; - - if (currentValue < n && ++delta > maxInt) { - error('overflow'); - } - - if (currentValue == n) { - // Represent delta as a generalized variable-length integer - for (q = delta, k = base; /* no condition */; k += base) { - t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias); - if (q < t) { - break; - } - qMinusT = q - t; - baseMinusT = base - t; - output.push( - stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)) - ); - q = floor(qMinusT / baseMinusT); - } - - output.push(stringFromCharCode(digitToBasic(q, 0))); - bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength); - delta = 0; - ++handledCPCount; - } - } - - ++delta; - ++n; - - } - return output.join(''); - } - - /** - * Converts a Punycode string representing a domain name or an email address - * to Unicode. Only the Punycoded parts of the input will be converted, i.e. - * it doesn't matter if you call it on a string that has already been - * converted to Unicode. - * @memberOf punycode - * @param {String} input The Punycoded domain name or email address to - * convert to Unicode. - * @returns {String} The Unicode representation of the given Punycode - * string. - */ - function toUnicode(input) { - return mapDomain(input, function(string) { - return regexPunycode.test(string) - ? decode(string.slice(4).toLowerCase()) - : string; - }); - } - - /** - * Converts a Unicode string representing a domain name or an email address to - * Punycode. Only the non-ASCII parts of the domain name will be converted, - * i.e. it doesn't matter if you call it with a domain that's already in - * ASCII. - * @memberOf punycode - * @param {String} input The domain name or email address to convert, as a - * Unicode string. - * @returns {String} The Punycode representation of the given domain name or - * email address. - */ - function toASCII(input) { - return mapDomain(input, function(string) { - return regexNonASCII.test(string) - ? 'xn--' + encode(string) - : string; - }); - } - - /*--------------------------------------------------------------------------*/ - - /** Define the public API */ - punycode = { - /** - * A string representing the current Punycode.js version number. - * @memberOf punycode - * @type String - */ - 'version': '1.3.2', - /** - * An object of methods to convert from JavaScript's internal character - * representation (UCS-2) to Unicode code points, and back. - * @see - * @memberOf punycode - * @type Object - */ - 'ucs2': { - 'decode': ucs2decode, - 'encode': ucs2encode - }, - 'decode': decode, - 'encode': encode, - 'toASCII': toASCII, - 'toUnicode': toUnicode - }; - - /** Expose `punycode` */ - // Some AMD build optimizers, like r.js, check for specific condition patterns - // like the following: - if ( - typeof define == 'function' && - typeof define.amd == 'object' && - define.amd - ) { - define('punycode', function() { - return punycode; - }); - } else if (freeExports && freeModule) { - if (module.exports == freeExports) { // in Node.js or RingoJS v0.8.0+ - freeModule.exports = punycode; - } else { // in Narwhal or RingoJS v0.7.0- - for (key in punycode) { - punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]); - } - } - } else { // in Rhino or a web browser - root.punycode = punycode; - } - -}(this)); diff --git a/node_modules/url/package.json b/node_modules/url/package.json deleted file mode 100644 index 8fcc6d49..00000000 --- a/node_modules/url/package.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "name": "url", - "description": "The core `url` packaged standalone for use with Browserify.", - "version": "0.10.2", - "dependencies": { - "punycode": "1.3.2" - }, - "main": "./url.js", - "devDependencies": { - "assert": "1.1.1", - "mocha": "1.18.2", - "zuul": "1.16.3" - }, - "scripts": { - "test": "mocha --ui qunit test.js && zuul -- test.js", - "test-local": "zuul --local -- test.js" - }, - "repository": { - "type": "git", - "url": "https://github.com/defunctzombie/node-url.git" - }, - "gitHead": "9a64b9ab8703d1d38d1a39793bd9841224962eb4", - "bugs": { - "url": "https://github.com/defunctzombie/node-url/issues" - }, - "homepage": "https://github.com/defunctzombie/node-url", - "_id": "url@0.10.2", - "_shasum": "68621d6929ea1cad344ebf135d82fcf7eb1a7469", - "_from": "url@", - "_npmVersion": "2.1.12", - "_nodeVersion": "0.10.33", - "_npmUser": { - "name": "shtylman", - "email": "shtylman@gmail.com" - }, - "maintainers": [ - { - "name": "coolaj86", - "email": "coolaj86@gmail.com" - }, - { - "name": "shtylman", - "email": "shtylman@gmail.com" - } - ], - "dist": { - "shasum": "68621d6929ea1cad344ebf135d82fcf7eb1a7469", - "tarball": "http://registry.npmjs.org/url/-/url-0.10.2.tgz" - }, - "directories": {}, - "_resolved": "https://registry.npmjs.org/url/-/url-0.10.2.tgz" -} diff --git a/node_modules/url/url.js b/node_modules/url/url.js deleted file mode 100644 index ddc4ade0..00000000 --- a/node_modules/url/url.js +++ /dev/null @@ -1,707 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var punycode = require('punycode'); - -exports.parse = urlParse; -exports.resolve = urlResolve; -exports.resolveObject = urlResolveObject; -exports.format = urlFormat; - -exports.Url = Url; - -function Url() { - this.protocol = null; - this.slashes = null; - this.auth = null; - this.host = null; - this.port = null; - this.hostname = null; - this.hash = null; - this.search = null; - this.query = null; - this.pathname = null; - this.path = null; - this.href = null; -} - -// Reference: RFC 3986, RFC 1808, RFC 2396 - -// define these here so at least they only have to be -// compiled once on the first module load. -var protocolPattern = /^([a-z0-9.+-]+:)/i, - portPattern = /:[0-9]*$/, - - // RFC 2396: characters reserved for delimiting URLs. - // We actually just auto-escape these. - delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], - - // RFC 2396: characters not allowed for various reasons. - unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims), - - // Allowed by RFCs, but cause of XSS attacks. Always escape these. - autoEscape = ['\''].concat(unwise), - // Characters that are never ever allowed in a hostname. - // Note that any invalid chars are also handled, but these - // are the ones that are *expected* to be seen, so we fast-path - // them. - nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape), - hostEndingChars = ['/', '?', '#'], - hostnameMaxLen = 255, - hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/, - hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/, - // protocols that can allow "unsafe" and "unwise" chars. - unsafeProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that never have a hostname. - hostlessProtocol = { - 'javascript': true, - 'javascript:': true - }, - // protocols that always contain a // bit. - slashedProtocol = { - 'http': true, - 'https': true, - 'ftp': true, - 'gopher': true, - 'file': true, - 'http:': true, - 'https:': true, - 'ftp:': true, - 'gopher:': true, - 'file:': true - }, - querystring = require('querystring'); - -function urlParse(url, parseQueryString, slashesDenoteHost) { - if (url && isObject(url) && url instanceof Url) return url; - - var u = new Url; - u.parse(url, parseQueryString, slashesDenoteHost); - return u; -} - -Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { - if (!isString(url)) { - throw new TypeError("Parameter 'url' must be a string, not " + typeof url); - } - - var rest = url; - - // trim before proceeding. - // This is to support parse stuff like " http://foo.com \n" - rest = rest.trim(); - - var proto = protocolPattern.exec(rest); - if (proto) { - proto = proto[0]; - var lowerProto = proto.toLowerCase(); - this.protocol = lowerProto; - rest = rest.substr(proto.length); - } - - // figure out if it's got a host - // user@server is *always* interpreted as a hostname, and url - // resolution will treat //foo/bar as host=foo,path=bar because that's - // how the browser resolves relative URLs. - if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) { - var slashes = rest.substr(0, 2) === '//'; - if (slashes && !(proto && hostlessProtocol[proto])) { - rest = rest.substr(2); - this.slashes = true; - } - } - - if (!hostlessProtocol[proto] && - (slashes || (proto && !slashedProtocol[proto]))) { - - // there's a hostname. - // the first instance of /, ?, ;, or # ends the host. - // - // If there is an @ in the hostname, then non-host chars *are* allowed - // to the left of the last @ sign, unless some host-ending character - // comes *before* the @-sign. - // URLs are obnoxious. - // - // ex: - // http://a@b@c/ => user:a@b host:c - // http://a@b?@c => user:a host:c path:/?@c - - // v0.12 TODO(isaacs): This is not quite how Chrome does things. - // Review our test case against browsers more comprehensively. - - // find the first instance of any hostEndingChars - var hostEnd = -1; - for (var i = 0; i < hostEndingChars.length; i++) { - var hec = rest.indexOf(hostEndingChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - - // at this point, either we have an explicit point where the - // auth portion cannot go past, or the last @ char is the decider. - var auth, atSign; - if (hostEnd === -1) { - // atSign can be anywhere. - atSign = rest.lastIndexOf('@'); - } else { - // atSign must be in auth portion. - // http://a@b/c@d => host:b auth:a path:/c@d - atSign = rest.lastIndexOf('@', hostEnd); - } - - // Now we have a portion which is definitely the auth. - // Pull that off. - if (atSign !== -1) { - auth = rest.slice(0, atSign); - rest = rest.slice(atSign + 1); - this.auth = decodeURIComponent(auth); - } - - // the host is the remaining to the left of the first non-host char - hostEnd = -1; - for (var i = 0; i < nonHostChars.length; i++) { - var hec = rest.indexOf(nonHostChars[i]); - if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) - hostEnd = hec; - } - // if we still have not hit it, then the entire thing is a host. - if (hostEnd === -1) - hostEnd = rest.length; - - this.host = rest.slice(0, hostEnd); - rest = rest.slice(hostEnd); - - // pull out port. - this.parseHost(); - - // we've indicated that there is a hostname, - // so even if it's empty, it has to be present. - this.hostname = this.hostname || ''; - - // if hostname begins with [ and ends with ] - // assume that it's an IPv6 address. - var ipv6Hostname = this.hostname[0] === '[' && - this.hostname[this.hostname.length - 1] === ']'; - - // validate a little. - if (!ipv6Hostname) { - var hostparts = this.hostname.split(/\./); - for (var i = 0, l = hostparts.length; i < l; i++) { - var part = hostparts[i]; - if (!part) continue; - if (!part.match(hostnamePartPattern)) { - var newpart = ''; - for (var j = 0, k = part.length; j < k; j++) { - if (part.charCodeAt(j) > 127) { - // we replace non-ASCII char with a temporary placeholder - // we need this to make sure size of hostname is not - // broken by replacing non-ASCII by nothing - newpart += 'x'; - } else { - newpart += part[j]; - } - } - // we test again with ASCII char only - if (!newpart.match(hostnamePartPattern)) { - var validParts = hostparts.slice(0, i); - var notHost = hostparts.slice(i + 1); - var bit = part.match(hostnamePartStart); - if (bit) { - validParts.push(bit[1]); - notHost.unshift(bit[2]); - } - if (notHost.length) { - rest = '/' + notHost.join('.') + rest; - } - this.hostname = validParts.join('.'); - break; - } - } - } - } - - if (this.hostname.length > hostnameMaxLen) { - this.hostname = ''; - } else { - // hostnames are always lower case. - this.hostname = this.hostname.toLowerCase(); - } - - if (!ipv6Hostname) { - // IDNA Support: Returns a puny coded representation of "domain". - // It only converts the part of the domain name that - // has non ASCII characters. I.e. it dosent matter if - // you call it with a domain that already is in ASCII. - var domainArray = this.hostname.split('.'); - var newOut = []; - for (var i = 0; i < domainArray.length; ++i) { - var s = domainArray[i]; - newOut.push(s.match(/[^A-Za-z0-9_-]/) ? - 'xn--' + punycode.encode(s) : s); - } - this.hostname = newOut.join('.'); - } - - var p = this.port ? ':' + this.port : ''; - var h = this.hostname || ''; - this.host = h + p; - this.href += this.host; - - // strip [ and ] from the hostname - // the host field still retains them, though - if (ipv6Hostname) { - this.hostname = this.hostname.substr(1, this.hostname.length - 2); - if (rest[0] !== '/') { - rest = '/' + rest; - } - } - } - - // now rest is set to the post-host stuff. - // chop off any delim chars. - if (!unsafeProtocol[lowerProto]) { - - // First, make 100% sure that any "autoEscape" chars get - // escaped, even if encodeURIComponent doesn't think they - // need to be. - for (var i = 0, l = autoEscape.length; i < l; i++) { - var ae = autoEscape[i]; - var esc = encodeURIComponent(ae); - if (esc === ae) { - esc = escape(ae); - } - rest = rest.split(ae).join(esc); - } - } - - - // chop off from the tail first. - var hash = rest.indexOf('#'); - if (hash !== -1) { - // got a fragment string. - this.hash = rest.substr(hash); - rest = rest.slice(0, hash); - } - var qm = rest.indexOf('?'); - if (qm !== -1) { - this.search = rest.substr(qm); - this.query = rest.substr(qm + 1); - if (parseQueryString) { - this.query = querystring.parse(this.query); - } - rest = rest.slice(0, qm); - } else if (parseQueryString) { - // no query string, but parseQueryString still requested - this.search = ''; - this.query = {}; - } - if (rest) this.pathname = rest; - if (slashedProtocol[lowerProto] && - this.hostname && !this.pathname) { - this.pathname = '/'; - } - - //to support http.request - if (this.pathname || this.search) { - var p = this.pathname || ''; - var s = this.search || ''; - this.path = p + s; - } - - // finally, reconstruct the href based on what has been validated. - this.href = this.format(); - return this; -}; - -// format a parsed object into a url string -function urlFormat(obj) { - // ensure it's an object, and not a string url. - // If it's an obj, this is a no-op. - // this way, you can call url_format() on strings - // to clean up potentially wonky urls. - if (isString(obj)) obj = urlParse(obj); - if (!(obj instanceof Url)) return Url.prototype.format.call(obj); - return obj.format(); -} - -Url.prototype.format = function() { - var auth = this.auth || ''; - if (auth) { - auth = encodeURIComponent(auth); - auth = auth.replace(/%3A/i, ':'); - auth += '@'; - } - - var protocol = this.protocol || '', - pathname = this.pathname || '', - hash = this.hash || '', - host = false, - query = ''; - - if (this.host) { - host = auth + this.host; - } else if (this.hostname) { - host = auth + (this.hostname.indexOf(':') === -1 ? - this.hostname : - '[' + this.hostname + ']'); - if (this.port) { - host += ':' + this.port; - } - } - - if (this.query && - isObject(this.query) && - Object.keys(this.query).length) { - query = querystring.stringify(this.query); - } - - var search = this.search || (query && ('?' + query)) || ''; - - if (protocol && protocol.substr(-1) !== ':') protocol += ':'; - - // only the slashedProtocols get the //. Not mailto:, xmpp:, etc. - // unless they had them to begin with. - if (this.slashes || - (!protocol || slashedProtocol[protocol]) && host !== false) { - host = '//' + (host || ''); - if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname; - } else if (!host) { - host = ''; - } - - if (hash && hash.charAt(0) !== '#') hash = '#' + hash; - if (search && search.charAt(0) !== '?') search = '?' + search; - - pathname = pathname.replace(/[?#]/g, function(match) { - return encodeURIComponent(match); - }); - search = search.replace('#', '%23'); - - return protocol + host + pathname + search + hash; -}; - -function urlResolve(source, relative) { - return urlParse(source, false, true).resolve(relative); -} - -Url.prototype.resolve = function(relative) { - return this.resolveObject(urlParse(relative, false, true)).format(); -}; - -function urlResolveObject(source, relative) { - if (!source) return relative; - return urlParse(source, false, true).resolveObject(relative); -} - -Url.prototype.resolveObject = function(relative) { - if (isString(relative)) { - var rel = new Url(); - rel.parse(relative, false, true); - relative = rel; - } - - var result = new Url(); - Object.keys(this).forEach(function(k) { - result[k] = this[k]; - }, this); - - // hash is always overridden, no matter what. - // even href="" will remove it. - result.hash = relative.hash; - - // if the relative url is empty, then there's nothing left to do here. - if (relative.href === '') { - result.href = result.format(); - return result; - } - - // hrefs like //foo/bar always cut to the protocol. - if (relative.slashes && !relative.protocol) { - // take everything except the protocol from relative - Object.keys(relative).forEach(function(k) { - if (k !== 'protocol') - result[k] = relative[k]; - }); - - //urlParse appends trailing / to urls like http://www.example.com - if (slashedProtocol[result.protocol] && - result.hostname && !result.pathname) { - result.path = result.pathname = '/'; - } - - result.href = result.format(); - return result; - } - - if (relative.protocol && relative.protocol !== result.protocol) { - // if it's a known url protocol, then changing - // the protocol does weird things - // first, if it's not file:, then we MUST have a host, - // and if there was a path - // to begin with, then we MUST have a path. - // if it is file:, then the host is dropped, - // because that's known to be hostless. - // anything else is assumed to be absolute. - if (!slashedProtocol[relative.protocol]) { - Object.keys(relative).forEach(function(k) { - result[k] = relative[k]; - }); - result.href = result.format(); - return result; - } - - result.protocol = relative.protocol; - if (!relative.host && !hostlessProtocol[relative.protocol]) { - var relPath = (relative.pathname || '').split('/'); - while (relPath.length && !(relative.host = relPath.shift())); - if (!relative.host) relative.host = ''; - if (!relative.hostname) relative.hostname = ''; - if (relPath[0] !== '') relPath.unshift(''); - if (relPath.length < 2) relPath.unshift(''); - result.pathname = relPath.join('/'); - } else { - result.pathname = relative.pathname; - } - result.search = relative.search; - result.query = relative.query; - result.host = relative.host || ''; - result.auth = relative.auth; - result.hostname = relative.hostname || relative.host; - result.port = relative.port; - // to support http.request - if (result.pathname || result.search) { - var p = result.pathname || ''; - var s = result.search || ''; - result.path = p + s; - } - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; - } - - var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'), - isRelAbs = ( - relative.host || - relative.pathname && relative.pathname.charAt(0) === '/' - ), - mustEndAbs = (isRelAbs || isSourceAbs || - (result.host && relative.pathname)), - removeAllDots = mustEndAbs, - srcPath = result.pathname && result.pathname.split('/') || [], - relPath = relative.pathname && relative.pathname.split('/') || [], - psychotic = result.protocol && !slashedProtocol[result.protocol]; - - // if the url is a non-slashed url, then relative - // links like ../.. should be able - // to crawl up to the hostname, as well. This is strange. - // result.protocol has already been set by now. - // Later on, put the first path part into the host field. - if (psychotic) { - result.hostname = ''; - result.port = null; - if (result.host) { - if (srcPath[0] === '') srcPath[0] = result.host; - else srcPath.unshift(result.host); - } - result.host = ''; - if (relative.protocol) { - relative.hostname = null; - relative.port = null; - if (relative.host) { - if (relPath[0] === '') relPath[0] = relative.host; - else relPath.unshift(relative.host); - } - relative.host = null; - } - mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === ''); - } - - if (isRelAbs) { - // it's absolute. - result.host = (relative.host || relative.host === '') ? - relative.host : result.host; - result.hostname = (relative.hostname || relative.hostname === '') ? - relative.hostname : result.hostname; - result.search = relative.search; - result.query = relative.query; - srcPath = relPath; - // fall through to the dot-handling below. - } else if (relPath.length) { - // it's relative - // throw away the existing file, and take the new path instead. - if (!srcPath) srcPath = []; - srcPath.pop(); - srcPath = srcPath.concat(relPath); - result.search = relative.search; - result.query = relative.query; - } else if (!isNullOrUndefined(relative.search)) { - // just pull out the search. - // like href='?foo'. - // Put this after the other two cases because it simplifies the booleans - if (psychotic) { - result.hostname = result.host = srcPath.shift(); - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - result.search = relative.search; - result.query = relative.query; - //to support http.request - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.href = result.format(); - return result; - } - - if (!srcPath.length) { - // no path at all. easy. - // we've already handled the other stuff above. - result.pathname = null; - //to support http.request - if (result.search) { - result.path = '/' + result.search; - } else { - result.path = null; - } - result.href = result.format(); - return result; - } - - // if a url ENDs in . or .., then it must get a trailing slash. - // however, if it ends in anything else non-slashy, - // then it must NOT get a trailing slash. - var last = srcPath.slice(-1)[0]; - var hasTrailingSlash = ( - (result.host || relative.host) && (last === '.' || last === '..') || - last === ''); - - // strip single dots, resolve double dots to parent dir - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = srcPath.length; i >= 0; i--) { - last = srcPath[i]; - if (last == '.') { - srcPath.splice(i, 1); - } else if (last === '..') { - srcPath.splice(i, 1); - up++; - } else if (up) { - srcPath.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (!mustEndAbs && !removeAllDots) { - for (; up--; up) { - srcPath.unshift('..'); - } - } - - if (mustEndAbs && srcPath[0] !== '' && - (!srcPath[0] || srcPath[0].charAt(0) !== '/')) { - srcPath.unshift(''); - } - - if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) { - srcPath.push(''); - } - - var isAbsolute = srcPath[0] === '' || - (srcPath[0] && srcPath[0].charAt(0) === '/'); - - // put the host back - if (psychotic) { - result.hostname = result.host = isAbsolute ? '' : - srcPath.length ? srcPath.shift() : ''; - //occationaly the auth can get stuck only in host - //this especialy happens in cases like - //url.resolveObject('mailto:local1@domain1', 'local2@domain2') - var authInHost = result.host && result.host.indexOf('@') > 0 ? - result.host.split('@') : false; - if (authInHost) { - result.auth = authInHost.shift(); - result.host = result.hostname = authInHost.shift(); - } - } - - mustEndAbs = mustEndAbs || (result.host && srcPath.length); - - if (mustEndAbs && !isAbsolute) { - srcPath.unshift(''); - } - - if (!srcPath.length) { - result.pathname = null; - result.path = null; - } else { - result.pathname = srcPath.join('/'); - } - - //to support request.http - if (!isNull(result.pathname) || !isNull(result.search)) { - result.path = (result.pathname ? result.pathname : '') + - (result.search ? result.search : ''); - } - result.auth = relative.auth || result.auth; - result.slashes = result.slashes || relative.slashes; - result.href = result.format(); - return result; -}; - -Url.prototype.parseHost = function() { - var host = this.host; - var port = portPattern.exec(host); - if (port) { - port = port[0]; - if (port !== ':') { - this.port = port.substr(1); - } - host = host.substr(0, host.length - port.length); - } - if (host) this.hostname = host; -}; - -function isString(arg) { - return typeof arg === "string"; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isNull(arg) { - return arg === null; -} -function isNullOrUndefined(arg) { - return arg == null; -} diff --git a/node_modules/wrench/LICENSE b/node_modules/wrench/LICENSE deleted file mode 100644 index a85a94a6..00000000 --- a/node_modules/wrench/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2010 Ryan McGrath - -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. diff --git a/node_modules/wrench/lib/wrench.js b/node_modules/wrench/lib/wrench.js deleted file mode 100644 index 01f5e957..00000000 --- a/node_modules/wrench/lib/wrench.js +++ /dev/null @@ -1,531 +0,0 @@ -/* wrench.js - * - * A collection of various utility functions I've found myself in need of - * for use with Node.js (http://nodejs.org/). This includes things like: - * - * - Recursively deleting directories in Node.js (Sync, not Async) - * - Recursively copying directories in Node.js (Sync, not Async) - * - Recursively chmoding a directory structure from Node.js (Sync, not Async) - * - Other things that I'll add here as time goes on. Shhhh... - * - * ~ Ryan McGrath (ryan [at] venodesigns.net) - */ - -var fs = require("fs"), - _path = require("path"), - isWindows = !!process.platform.match(/^win/); - -/* wrench.readdirSyncRecursive("directory_path"); - * - * Recursively dives through directories and read the contents of all the - * children directories. - */ -exports.readdirSyncRecursive = function(baseDir) { - baseDir = baseDir.replace(/\/$/, ''); - - var readdirSyncRecursive = function(baseDir) { - var files = [], - curFiles, - nextDirs, - isDir = function(fname){ - return fs.existsSync(_path.join(baseDir, fname)) ? fs.statSync( _path.join(baseDir, fname) ).isDirectory() : false; - }, - prependBaseDir = function(fname){ - return _path.join(baseDir, fname); - }; - - curFiles = fs.readdirSync(baseDir); - nextDirs = curFiles.filter(isDir); - curFiles = curFiles.map(prependBaseDir); - - files = files.concat( curFiles ); - - while (nextDirs.length) { - files = files.concat( readdirSyncRecursive( _path.join(baseDir, nextDirs.shift()) ) ); - } - - return files; - }; - - // convert absolute paths to relative - var fileList = readdirSyncRecursive(baseDir).map(function(val){ - return _path.relative(baseDir, val); - }); - - return fileList; -}; - -/* wrench.readdirRecursive("directory_path", function(error, files) {}); - * - * Recursively dives through directories and read the contents of all the - * children directories. - * - * Asynchronous, so returns results/error in callback. - * Callback receives the of files in currently recursed directory. - * When no more directories are left, callback is called with null for all arguments. - * - */ -exports.readdirRecursive = function(baseDir, fn) { - baseDir = baseDir.replace(/\/$/, ''); - - var waitCount = 0; - - function readdirRecursive(curDir) { - var prependcurDir = function(fname){ - return _path.join(curDir, fname); - }; - - waitCount++; - fs.readdir(curDir, function(e, curFiles) { - if (e) { - fn(e); - return; - } - waitCount--; - - curFiles = curFiles.map(prependcurDir); - - curFiles.forEach(function(it) { - waitCount++; - - fs.stat(it, function(e, stat) { - waitCount--; - - if (e) { - fn(e); - } else { - if (stat.isDirectory()) { - readdirRecursive(it); - } - } - - if (waitCount == 0) { - fn(null, null); - } - }); - }); - - fn(null, curFiles.map(function(val) { - // convert absolute paths to relative - return _path.relative(baseDir, val); - })); - - if (waitCount == 0) { - fn(null, null); - } - }); - }; - - readdirRecursive(baseDir); -}; - - - - - -/* wrench.rmdirSyncRecursive("directory_path", failSilent); - * - * Recursively dives through directories and obliterates everything about it. This is a - * Sync-function, which blocks things until it's done. No idea why anybody would want an - * Asynchronous version. :\ - */ -exports.rmdirSyncRecursive = function(path, failSilent) { - var files; - - try { - files = fs.readdirSync(path); - } catch (err) { - - if(failSilent) return; - throw new Error(err.message); - } - - /* Loop through and delete everything in the sub-tree after checking it */ - for(var i = 0; i < files.length; i++) { - var file = _path.join(path, files[i]); - var currFile = fs.lstatSync(file); - - if(currFile.isDirectory()) { - // Recursive function back to the beginning - exports.rmdirSyncRecursive(file); - } else if(currFile.isSymbolicLink()) { - // Unlink symlinks - if (isWindows) { - fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. - } - - fs.unlinkSync(file); - } else { - // Assume it's a file - perhaps a try/catch belongs here? - if (isWindows) { - fs.chmodSync(file, 666) // Windows needs this unless joyent/node#3006 is resolved.. - } - - fs.unlinkSync(file); - } - } - - /* Now that we know everything in the sub-tree has been deleted, we can delete the main - directory. Huzzah for the shopkeep. */ - return fs.rmdirSync(path); -}; - - - -function isFileIncluded(opts, dir, filename) { - - function isMatch(filter) { - if (typeof filter === 'function') { - return filter(filename, dir) === true; - } - else { - // Maintain backwards compatibility and use just the filename - return filename.match(filter); - } - } - - if (opts.include || opts.exclude) { - if (opts.exclude) { - if (isMatch(opts.exclude)) { - return false; - } - } - - if (opts.include) { - if (isMatch(opts.include)) { - return true; - } - else { - return false; - } - } - - return true; - } - else if (opts.filter) { - var filter = opts.filter; - - if (!opts.whitelist) { - // if !opts.whitelist is false every file or directory - // which does match opts.filter will be ignored - return isMatch(filter) ? false : true; - } else { - // if opts.whitelist is true every file or directory - // which doesn't match opts.filter will be ignored - return !isMatch(filter) ? false : true; - } - } - - return true; -} - -/* wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts); - * - * Recursively dives through a directory and moves all its files to a new location. This is a - * Synchronous function, which blocks things until it's done. If you need/want to do this in - * an Asynchronous manner, look at wrench.copyDirRecursively() below. Specify forceDelete to force directory overwrite. - * - * Note: Directories should be passed to this function without a trailing slash. - */ -exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) { - opts = opts || {}; - - try { - if(fs.statSync(newDirLocation).isDirectory()) { - if(opts.forceDelete) { - exports.rmdirSyncRecursive(newDirLocation); - } else { - return new Error('You are trying to delete a directory that already exists. Specify forceDelete in the opts argument to override this. Bailing~'); - } - } - } catch(e) { } - - /* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */ - var checkDir = fs.statSync(sourceDir); - try { - fs.mkdirSync(newDirLocation, checkDir.mode); - } catch (e) { - //if the directory already exists, that's okay - if (e.code !== 'EEXIST') throw e; - } - - var files = fs.readdirSync(sourceDir); - var hasFilter = opts.filter || opts.include || opts.exclude; - var preserveFiles = opts.preserveFiles === true; - var preserveTimestamps = opts.preserveTimestamps === true; - - for(var i = 0; i < files.length; i++) { - // ignores all files or directories which match the RegExp in opts.filter - if(typeof opts !== 'undefined') { - if (hasFilter) { - if (!isFileIncluded(opts, sourceDir, files[i])) { - continue; - } - } - - if (opts.excludeHiddenUnix && /^\./.test(files[i])) continue; - } - - var currFile = fs.lstatSync(_path.join(sourceDir, files[i])); - - var fCopyFile = function(srcFile, destFile) { - if(typeof opts !== 'undefined' && opts.preserveFiles && fs.existsSync(destFile)) return; - - var contents = fs.readFileSync(srcFile); - fs.writeFileSync(destFile, contents); - var stat = fs.lstatSync(srcFile); - fs.chmodSync(destFile, stat.mode); - if (preserveTimestamps) { - fs.utimesSync(destFile, stat.atime, stat.mtime) - } - }; - - if(currFile.isDirectory()) { - /* recursion this thing right on back. */ - exports.copyDirSyncRecursive(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i]), opts); - } else if(currFile.isSymbolicLink()) { - var symlinkFull = fs.readlinkSync(_path.join(sourceDir, files[i])); - symlinkFull = _path.resolve(fs.realpathSync(sourceDir), symlinkFull); - - if (typeof opts !== 'undefined' && !opts.inflateSymlinks) { - fs.symlinkSync(symlinkFull, _path.join(newDirLocation, files[i])); - continue; - } - - var tmpCurrFile = fs.lstatSync(symlinkFull); - if (tmpCurrFile.isDirectory()) { - exports.copyDirSyncRecursive(symlinkFull, _path.join(newDirLocation, files[i]), opts); - } else { - /* At this point, we've hit a file actually worth copying... so copy it on over. */ - fCopyFile(symlinkFull, _path.join(newDirLocation, files[i])); - } - } else { - /* At this point, we've hit a file actually worth copying... so copy it on over. */ - fCopyFile(_path.join(sourceDir, files[i]), _path.join(newDirLocation, files[i])); - } - } -}; - -/* wrench.chmodSyncRecursive("directory", filemode); - * - * Recursively dives through a directory and chmods everything to the desired mode. This is a - * Synchronous function, which blocks things until it's done. - * - * Note: Directories should be passed to this function without a trailing slash. - */ -exports.chmodSyncRecursive = function(sourceDir, filemode) { - var files = fs.readdirSync(sourceDir); - - for(var i = 0; i < files.length; i++) { - var currFile = fs.lstatSync(_path.join(sourceDir, files[i])); - - if(currFile.isDirectory()) { - /* ...and recursion this thing right on back. */ - exports.chmodSyncRecursive(_path.join(sourceDir, files[i]), filemode); - } else { - /* At this point, we've hit a file actually worth copying... so copy it on over. */ - fs.chmod(_path.join(sourceDir, files[i]), filemode); - } - } - - /* Finally, chmod the parent directory */ - fs.chmod(sourceDir, filemode); -}; - - -/* wrench.chownSyncRecursive("directory", uid, gid); - * - * Recursively dives through a directory and chowns everything to the desired user and group. This is a - * Synchronous function, which blocks things until it's done. - * - * Note: Directories should be passed to this function without a trailing slash. - */ -exports.chownSyncRecursive = function(sourceDir, uid, gid) { - var files = fs.readdirSync(sourceDir); - - for(var i = 0; i < files.length; i++) { - var currFile = fs.lstatSync(_path.join(sourceDir, files[i])); - - if(currFile.isDirectory()) { - /* ...and recursion this thing right on back. */ - exports.chownSyncRecursive(_path.join(sourceDir, files[i]), uid, gid); - } else { - /* At this point, we've hit a file actually worth chowning... so own it. */ - fs.chownSync(_path.join(sourceDir, files[i]), uid, gid); - } - } - - /* Finally, chown the parent directory */ - fs.chownSync(sourceDir, uid, gid); -}; - - - -/* wrench.rmdirRecursive("directory_path", callback); - * - * Recursively dives through directories and obliterates everything about it. - */ -exports.rmdirRecursive = function rmdirRecursive(dir, failSilent, clbk){ - if(clbk === null || typeof clbk == 'undefined') - clbk = function(err) {}; - - fs.readdir(dir, function(err, files) { - if(err && typeof failSilent === 'boolean' && !failSilent) - return clbk(err); - - if(typeof failSilent === 'function') - clbk = failSilent; - - (function rmFile(err){ - if (err) return clbk(err); - - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') - return fs.rmdir(dir, clbk); - - var file = dir+'/'+filename; - fs.lstat(file, function(err, stat){ - if (err) return clbk(err); - if (stat.isDirectory()) - rmdirRecursive(file, rmFile); - else - fs.unlink(file, rmFile); - }); - })(); - }); -}; - -/* wrench.copyDirRecursive("directory_to_copy", "new_location", {forceDelete: bool}, callback); - * - * Recursively dives through a directory and moves all its files to a new - * location. Specify forceDelete to force directory overwrite. - * - * Note: Directories should be passed to this function without a trailing slash. - */ -exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, opts, clbk) { - var originalArguments = Array.prototype.slice.apply(arguments); - srcDir = _path.normalize(srcDir); - newDir = _path.normalize(newDir); - - fs.stat(newDir, function(err, newDirStat) { - if(!err) { - if(typeof opts !== 'undefined' && typeof opts !== 'function' && opts.forceDelete) - return exports.rmdirRecursive(newDir, function(err) { - copyDirRecursive.apply(this, originalArguments); - }); - else - return clbk(new Error('You are trying to delete a directory that already exists. Specify forceDelete in an options object to override this.')); - } - - if(typeof opts === 'function') - clbk = opts; - - fs.stat(srcDir, function(err, srcDirStat){ - if (err) return clbk(err); - fs.mkdir(newDir, srcDirStat.mode, function(err){ - if (err) return clbk(err); - fs.readdir(srcDir, function(err, files){ - if (err) return clbk(err); - (function copyFiles(err){ - if (err) return clbk(err); - - var filename = files.shift(); - if (filename === null || typeof filename == 'undefined') - return clbk(null); - - var file = srcDir+'/'+filename, - newFile = newDir+'/'+filename; - - fs.stat(file, function(err, fileStat){ - if (err) return clbk(err); - if (fileStat.isDirectory()) - copyDirRecursive(file, newFile, copyFiles, clbk); - else if (fileStat.isSymbolicLink()) - fs.readlink(file, function(err, link){ - if (err) return clbk(err); - fs.symlink(link, newFile, copyFiles); - }); - else - fs.readFile(file, function(err, data){ - if (err) return clbk(err); - fs.writeFile(newFile, data, copyFiles); - }); - }); - })(); - }); - }); - }); - }); -}; - -var mkdirSyncRecursive = function(path, mode) { - var self = this; - path = _path.normalize(path) - - try { - fs.mkdirSync(path, mode); - } catch(err) { - if(err.code == "ENOENT") { - var slashIdx = path.lastIndexOf(_path.sep); - - if(slashIdx > 0) { - var parentPath = path.substring(0, slashIdx); - mkdirSyncRecursive(parentPath, mode); - mkdirSyncRecursive(path, mode); - } else { - throw err; - } - } else if(err.code == "EEXIST") { - return; - } else { - throw err; - } - } -}; -exports.mkdirSyncRecursive = mkdirSyncRecursive; - -exports.LineReader = function(filename, bufferSize) { - this.bufferSize = bufferSize || 8192; - this.buffer = ""; - this.fd = fs.openSync(filename, "r"); - this.currentPosition = 0; -}; - -exports.LineReader.prototype = { - close: function() { - return fs.closeSync(this.fd); - }, - - getBufferAndSetCurrentPosition: function(position) { - var res = fs.readSync(this.fd, this.bufferSize, position, "ascii"); - - this.buffer += res[0]; - if(res[1] === 0) { - this.currentPosition = -1; - } else { - this.currentPosition = position + res[1]; - } - - return this.currentPosition; - }, - - hasNextLine: function() { - while(this.buffer.indexOf('\n') === -1) { - this.getBufferAndSetCurrentPosition(this.currentPosition); - if(this.currentPosition === -1) return false; - } - - if(this.buffer.indexOf("\n") > -1 || this.buffer.length !== 0) return true; - return false; - }, - - getNextLine: function() { - var lineEnd = this.buffer.indexOf("\n"), - result = this.buffer.substring(0, lineEnd != -1 ? lineEnd : this.buffer.length); - - this.buffer = this.buffer.substring(result.length + 1, this.buffer.length); - return result; - } -}; - -// vim: et ts=4 sw=4 diff --git a/node_modules/wrench/package.json b/node_modules/wrench/package.json deleted file mode 100644 index 7cd149cd..00000000 --- a/node_modules/wrench/package.json +++ /dev/null @@ -1,43 +0,0 @@ -{ - "name": "wrench", - "description": "Recursive filesystem (and other) operations that Node *should* have.", - "version": "1.5.8", - "author": { - "name": "Ryan McGrath", - "email": "ryan@venodesigns.net" - }, - "repository": { - "type": "git", - "url": "https://ryanmcgrath@github.com/ryanmcgrath/wrench-js.git" - }, - "bugs": { - "url": "http://github.com/ryanmcgrath/wrench-js/issues" - }, - "directories": { - "lib": "./lib/" - }, - "dependencies": {}, - "devDependencies": { - "nodeunit": ">= 0.6.4" - }, - "main": "./lib/wrench", - "engines": { - "node": ">=0.1.97" - }, - "scripts": { - "test": "nodeunit tests/runner.js" - }, - "licenses": [ - { - "type": "MIT", - "url": "http://github.com/ryanmcgrath/wrench-js/raw/master/LICENSE" - } - ], - "readme": "wrench.js - Recursive file operations in Node.js\n----------------------------------------------------------------------------\nWhile I love Node.js, I've found myself missing some functions. Things like\nrecursively deleting/chmodding a directory (or even deep copying a directory),\nor even a basic line reader, shouldn't need to be re-invented time and time again.\n\nThat said, here's my attempt at a re-usable solution, at least until something\nmore formalized gets integrated into Node.js (*hint hint*). wrench.js is fairly simple\nto use - check out the documentation/examples below:\n\nPossibly Breaking Change in v1.5.0\n-----------------------------------------------------------------------------\nIn previous versions of Wrench, we went against the OS-default behavior of not\ndeleting a directory unless the operation is forced. In 1.5.0, this has been\nchanged to be the behavior people expect there to be - if you try to copy over\na directory that already exists, you'll get an Error returned or thrown stating\nthat you need to force it.\n\nSomething like this will do the trick:\n\n``` javascript\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {\n forceDelete: true\n});\n```\n\nIf you desire the older behavior of Wrench... hit up your package.json. If you\nhappen to find bugs in the 1.5.0 release please feel free to file them on the \nGitHub issues tracker for this project, or send me a pull request and I'll get to\nit as fast as I can. Thanks!\n\n**If this breaks enough projects I will consider rolling it back. Please hit me up if this seems to be the case.**\n\nInstallation\n-----------------------------------------------------------------------------\n\n npm install wrench\n\nUsage\n-----------------------------------------------------------------------------\n``` javascript\nvar wrench = require('wrench'),\n\tutil = require('util');\n```\n\n### Synchronous operations\n``` javascript\n// Recursively create directories, sub-trees and all.\nwrench.mkdirSyncRecursive(dir, 0777);\n\n// Recursively delete the entire sub-tree of a directory, then kill the directory\nwrench.rmdirSyncRecursive('my_directory_name', failSilently);\n\n// Recursively read directories contents.\nwrench.readdirSyncRecursive('my_directory_name');\n\n// Recursively chmod the entire sub-tree of a directory\nwrench.chmodSyncRecursive('my_directory_name', 0755);\n\n// Recursively chown the entire sub-tree of a directory\nwrench.chownSyncRecursive(\"directory\", uid, gid);\n\n// Deep-copy an existing directory\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up', {\n forceDelete: bool, // Whether to overwrite existing directory or not\n excludeHiddenUnix: bool, // Whether to copy hidden Unix files or not (preceding .)\n preserveFiles: bool, // If we're overwriting something and the file already exists, keep the existing\n preserveTimestamps: bool, // Preserve the mtime and atime when copying files\n inflateSymlinks: bool, // Whether to follow symlinks or not when copying files\n filter: regexpOrFunction, // A filter to match files against; if matches, do nothing (exclude).\n whitelist: bool, // if true every file or directory which doesn't match filter will be ignored\n include: regexpOrFunction, // An include filter (either a regexp or a function)\n exclude: regexpOrFunction // An exclude filter (either a regexp or a function)\n});\n\n// Note: If a RegExp is provided then then it will be matched against the filename. If a function is\n// provided then the signature should be the following:\n// function(filename, dir) { return result; }\n\n// Read lines in from a file until you hit the end\nvar f = new wrench.LineReader('x.txt');\nwhile(f.hasNextLine()) {\n\tutil.puts(f.getNextLine());\n}\n\n// Note: You will need to close that above line reader at some point, otherwise\n// you will run into a \"too many open files\" error. f.close() or fs.closeSync(f.fd) are\n// your friends, as only you know when it is safe to close.\n```\n\n### Asynchronous operations\n``` javascript\n// Recursively read directories contents\nvar files = [];\nwrench.readdirRecursive('my_directory_name', function(error, curFiles) {\n // curFiles is what you want\n});\n\n// If you're feeling somewhat masochistic\nwrench.copyDirRecursive(srcDir, newDir, {forceDelete: bool /* See sync version */}, callbackfn);\n```\n\nQuestions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)\n", - "readmeFilename": "readme.md", - "homepage": "https://github.com/ryanmcgrath/wrench-js", - "_id": "wrench@1.5.8", - "_shasum": "7a31c97f7869246d76c5cf2f5c977a1c4c8e5ab5", - "_from": "wrench@~1.5.8", - "_resolved": "https://registry.npmjs.org/wrench/-/wrench-1.5.8.tgz" -} diff --git a/plugins/eventDumper.js b/plugins/eventDumper.js index 72ccdce0..7ae7c444 100644 --- a/plugins/eventDumper.js +++ b/plugins/eventDumper.js @@ -11,7 +11,6 @@ var env = require('jsdoc/env'); var util = require('util'); var conf = env.conf.eventDumper || {}; -var isRhino = require('jsdoc/util/runtime').isRhino(); // Dump the included parser events (defaults to all events) var events = conf.include || [ @@ -30,20 +29,6 @@ if (conf.exclude) { events = _.difference(events, conf.exclude); } -/** - * Check whether a variable appears to be a Java native object. - * - * @param {*} o - The variable to check. - * @return {boolean} Set to `true` for Java native objects and `false` in all other cases. - */ -function isJavaNativeObject(o) { - if (!isRhino) { - return false; - } - - return o && typeof o === 'object' && typeof o.getClass === 'function'; -} - /** * Replace AST node objects in events with a placeholder. * @@ -91,8 +76,7 @@ function cleanse(e) { } // never include functions that belong to the object else if (typeof e[prop] !== 'function') { - // don't call JSON.stringify() on Java native objects--Rhino will throw an exception - result[prop] = isJavaNativeObject(e[prop]) ? String(e[prop]) : e[prop]; + result[prop] = e[prop]; } }); diff --git a/rhino/MPL_2.0.txt b/rhino/MPL_2.0.txt deleted file mode 100644 index a612ad98..00000000 --- a/rhino/MPL_2.0.txt +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/rhino/assert.js b/rhino/assert.js deleted file mode 100644 index 5c762d07..00000000 --- a/rhino/assert.js +++ /dev/null @@ -1,315 +0,0 @@ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// UTILITY -var util = require('util'); -var pSlice = Array.prototype.slice; - -// 1. The assert module provides functions that throw -// AssertionError's when particular conditions are not met. The -// assert module must conform to the following interface. - -var assert = module.exports = ok; - -// 2. The AssertionError is defined in assert. -// new assert.AssertionError({ message: message, -// actual: actual, -// expected: expected }) - -assert.AssertionError = function AssertionError(options) { - this.name = 'AssertionError'; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - this.message = options.message || getMessage(this); -}; - -// assert.AssertionError instanceof Error -util.inherits(assert.AssertionError, Error); - -function replacer(key, value) { - if (util.isUndefined(value)) { - return '' + value; - } - if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) { - return value.toString(); - } - if (util.isFunction(value) || util.isRegExp(value)) { - return value.toString(); - } - return value; -} - -function truncate(s, n) { - if (util.isString(s)) { - return s.length < n ? s : s.slice(0, n); - } else { - return s; - } -} - -function getMessage(self) { - return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + - self.operator + ' ' + - truncate(JSON.stringify(self.expected, replacer), 128); -} - -// At present only the three keys mentioned above are used and -// understood by the spec. Implementations or sub modules can pass -// other keys to the AssertionError's constructor - they will be -// ignored. - -// 3. All of the following functions must throw an AssertionError -// when a corresponding condition is not met, with a message that -// may be undefined if not provided. All assertion methods provide -// both the actual and expected values to the assertion error for -// display purposes. - -function fail(actual, expected, message, operator, stackStartFunction) { - throw new assert.AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); -} - -// EXTENSION! allows for well behaved errors defined elsewhere. -assert.fail = fail; - -// 4. Pure assertion tests whether a value is truthy, as determined -// by !!guard. -// assert.ok(guard, message_opt); -// This statement is equivalent to assert.equal(true, !!guard, -// message_opt);. To test strictly for the value true, use -// assert.strictEqual(true, guard, message_opt);. - -function ok(value, message) { - if (!value) fail(value, true, message, '==', assert.ok); -} -assert.ok = ok; - -// 5. The equality assertion tests shallow, coercive equality with -// ==. -// assert.equal(actual, expected, message_opt); - -assert.equal = function equal(actual, expected, message) { - if (actual != expected) fail(actual, expected, message, '==', assert.equal); -}; - -// 6. The non-equality assertion tests for whether two objects are not equal -// with != assert.notEqual(actual, expected, message_opt); - -assert.notEqual = function notEqual(actual, expected, message) { - if (actual == expected) { - fail(actual, expected, message, '!=', assert.notEqual); - } -}; - -// 7. The equivalence assertion tests a deep equality relation. -// assert.deepEqual(actual, expected, message_opt); - -assert.deepEqual = function deepEqual(actual, expected, message) { - if (!_deepEqual(actual, expected)) { - fail(actual, expected, message, 'deepEqual', assert.deepEqual); - } -}; - -function _deepEqual(actual, expected) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - - } else if (util.isBuffer(actual) && util.isBuffer(expected)) { - if (actual.length != expected.length) return false; - - for (var i = 0; i < actual.length; i++) { - if (actual[i] !== expected[i]) return false; - } - - return true; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (util.isDate(actual) && util.isDate(expected)) { - return actual.getTime() === expected.getTime(); - - // 7.3 If the expected value is a RegExp object, the actual value is - // equivalent if it is also a RegExp object with the same source and - // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). - } else if (util.isRegExp(actual) && util.isRegExp(expected)) { - return actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase; - - // 7.4. Other pairs that do not both pass typeof value == 'object', - // equivalence is determined by ==. - } else if (!util.isObject(actual) && !util.isObject(expected)) { - return actual == expected; - - // 7.5 For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical 'prototype' property. Note: this - // accounts for both named and indexed properties on Arrays. - } else { - return objEquiv(actual, expected); - } -} - -function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; -} - -function objEquiv(a, b) { - if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) - return false; - // an identical 'prototype' property. - if (a.prototype !== b.prototype) return false; - //~~~I've managed to break Object.keys through screwy arguments passing. - // Converting to array solves the problem. - if (isArguments(a)) { - if (!isArguments(b)) { - return false; - } - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a, b); - } - try { - var ka = Object.keys(a), - kb = Object.keys(b), - key, i; - } catch (e) {//happens when one is a string literal and the other isn't - return false; - } - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length != kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] != kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!_deepEqual(a[key], b[key])) return false; - } - return true; -} - -// 8. The non-equivalence assertion tests for any deep inequality. -// assert.notDeepEqual(actual, expected, message_opt); - -assert.notDeepEqual = function notDeepEqual(actual, expected, message) { - if (_deepEqual(actual, expected)) { - fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); - } -}; - -// 9. The strict equality assertion tests strict equality, as determined by ===. -// assert.strictEqual(actual, expected, message_opt); - -assert.strictEqual = function strictEqual(actual, expected, message) { - if (actual !== expected) { - fail(actual, expected, message, '===', assert.strictEqual); - } -}; - -// 10. The strict non-equality assertion tests for strict inequality, as -// determined by !==. assert.notStrictEqual(actual, expected, message_opt); - -assert.notStrictEqual = function notStrictEqual(actual, expected, message) { - if (actual === expected) { - fail(actual, expected, message, '!==', assert.notStrictEqual); - } -}; - -function expectedException(actual, expected) { - if (!actual || !expected) { - return false; - } - - if (Object.prototype.toString.call(expected) == '[object RegExp]') { - return expected.test(actual); - } else if (actual instanceof expected) { - return true; - } else if (expected.call({}, actual) === true) { - return true; - } - - return false; -} - -function _throws(shouldThrow, block, expected, message) { - var actual; - - if (util.isString(expected)) { - message = expected; - expected = null; - } - - try { - block(); - } catch (e) { - actual = e; - } - - message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + - (message ? ' ' + message : '.'); - - if (shouldThrow && !actual) { - fail(actual, expected, 'Missing expected exception' + message); - } - - if (!shouldThrow && expectedException(actual, expected)) { - fail(actual, expected, 'Got unwanted exception' + message); - } - - if ((shouldThrow && actual && expected && - !expectedException(actual, expected)) || (!shouldThrow && actual)) { - throw actual; - } -} - -// 11. Expected to throw an error: -// assert.throws(block, Error_opt, message_opt); - -assert.throws = function(block, /*optional*/error, /*optional*/message) { - _throws.apply(this, [true].concat(pSlice.call(arguments))); -}; - -// EXTENSION! This is annoying to write outside this module. -assert.doesNotThrow = function(block, /*optional*/message) { - _throws.apply(this, [false].concat(pSlice.call(arguments))); -}; - -assert.ifError = function(err) { if (err) {throw err;}}; diff --git a/rhino/buffer.js b/rhino/buffer.js deleted file mode 100644 index 1c3c3bb3..00000000 --- a/rhino/buffer.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = require('buffer-browserify'); diff --git a/rhino/crypto.js b/rhino/crypto.js deleted file mode 100644 index 35e162b7..00000000 --- a/rhino/crypto.js +++ /dev/null @@ -1,3 +0,0 @@ -'use strict'; - -module.exports = require('crypto-browserify'); diff --git a/rhino/events.js b/rhino/events.js deleted file mode 100644 index 488025a5..00000000 --- a/rhino/events.js +++ /dev/null @@ -1,292 +0,0 @@ -/** - * Shim for Node.js `events` module. - * @see https://github.com/Gozala/events - * @license MIT - */ -'use strict'; - -function EventEmitter() { - this._events = this._events || {}; - this._maxListeners = this._maxListeners || undefined; -} -module.exports = EventEmitter; -if (!process.EventEmitter) { - process.EventEmitter = EventEmitter; -} - -// Backwards-compat with node 0.10.x -EventEmitter.EventEmitter = EventEmitter; - -EventEmitter.prototype._events = undefined; -EventEmitter.prototype._maxListeners = undefined; - -// By default EventEmitters will print a warning if more than 10 listeners are -// added to it. This is a useful default which helps finding memory leaks. -EventEmitter.defaultMaxListeners = 10; - -// Obviously not all Emitters should be limited to 10. This function allows -// that to be increased. Set to zero for unlimited. -EventEmitter.prototype.setMaxListeners = function(n) { - if (!isNumber(n) || n < 0 || isNaN(n)) - throw TypeError('n must be a positive number'); - this._maxListeners = n; - return this; -}; - -EventEmitter.prototype.emit = function(type) { - var er, handler, len, args, i, listeners; - - if (!this._events) - this._events = {}; - - // If there is no 'error' event listener then throw. - if (type === 'error') { - if (!this._events.error || - (isObject(this._events.error) && !this._events.error.length)) { - er = arguments[1]; - if (er instanceof Error) { - throw er; // Unhandled 'error' event - } else { - throw TypeError('Uncaught, unspecified "error" event.'); - } - return false; - } - } - - handler = this._events[type]; - - if (isUndefined(handler)) - return false; - - if (isFunction(handler)) { - switch (arguments.length) { - // fast cases - case 1: - handler.call(this); - break; - case 2: - handler.call(this, arguments[1]); - break; - case 3: - handler.call(this, arguments[1], arguments[2]); - break; - // slower - default: - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - handler.apply(this, args); - } - } else if (isObject(handler)) { - len = arguments.length; - args = new Array(len - 1); - for (i = 1; i < len; i++) - args[i - 1] = arguments[i]; - - listeners = handler.slice(); - len = listeners.length; - for (i = 0; i < len; i++) - listeners[i].apply(this, args); - } - - return true; -}; - -EventEmitter.prototype.addListener = function(type, listener) { - var m; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events) - this._events = {}; - - // To avoid recursion in the case that type === "newListener"! Before - // adding it to the listeners, first emit "newListener". - if (this._events.newListener) - this.emit('newListener', type, - isFunction(listener.listener) ? - listener.listener : listener); - - if (!this._events[type]) - // Optimize the case of one listener. Don't need the extra array object. - this._events[type] = listener; - else if (isObject(this._events[type])) - // If we've already got an array, just append. - this._events[type].push(listener); - else - // Adding the second element, need to change to array. - this._events[type] = [this._events[type], listener]; - - // Check for listener leak - if (isObject(this._events[type]) && !this._events[type].warned) { - var m; - if (!isUndefined(this._maxListeners)) { - m = this._maxListeners; - } else { - m = EventEmitter.defaultMaxListeners; - } - - if (m && m > 0 && this._events[type].length > m) { - this._events[type].warned = true; - console.error('(node) warning: possible EventEmitter memory ' + - 'leak detected. %d listeners added. ' + - 'Use emitter.setMaxListeners() to increase limit.', - this._events[type].length); - if (typeof console.trace === 'function') { - // not supported in IE 10 - console.trace(); - } - } - } - - return this; -}; - -EventEmitter.prototype.on = EventEmitter.prototype.addListener; - -EventEmitter.prototype.once = function(type, listener) { - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - var fired = false; - - function g() { - this.removeListener(type, g); - - if (!fired) { - fired = true; - listener.apply(this, arguments); - } - } - - g.listener = listener; - this.on(type, g); - - return this; -}; - -// emits a 'removeListener' event iff the listener was removed -EventEmitter.prototype.removeListener = function(type, listener) { - var list, position, length, i; - - if (!isFunction(listener)) - throw TypeError('listener must be a function'); - - if (!this._events || !this._events[type]) - return this; - - list = this._events[type]; - length = list.length; - position = -1; - - if (list === listener || - (isFunction(list.listener) && list.listener === listener)) { - delete this._events[type]; - if (this._events.removeListener) - this.emit('removeListener', type, listener); - - } else if (isObject(list)) { - for (i = length; i-- > 0;) { - if (list[i] === listener || - (list[i].listener && list[i].listener === listener)) { - position = i; - break; - } - } - - if (position < 0) - return this; - - if (list.length === 1) { - list.length = 0; - delete this._events[type]; - } else { - list.splice(position, 1); - } - - if (this._events.removeListener) - this.emit('removeListener', type, listener); - } - - return this; -}; - -EventEmitter.prototype.removeAllListeners = function(type) { - var key, listeners; - - if (!this._events) - return this; - - // not listening for removeListener, no need to emit - if (!this._events.removeListener) { - if (arguments.length === 0) - this._events = {}; - else if (this._events[type]) - delete this._events[type]; - return this; - } - - // emit removeListener for all listeners on all events - if (arguments.length === 0) { - for (key in this._events) { - if (key === 'removeListener') continue; - this.removeAllListeners(key); - } - this.removeAllListeners('removeListener'); - this._events = {}; - return this; - } - - listeners = this._events[type]; - - if (isFunction(listeners)) { - this.removeListener(type, listeners); - } else { - // LIFO order - while (listeners.length) - this.removeListener(type, listeners[listeners.length - 1]); - } - delete this._events[type]; - - return this; -}; - -EventEmitter.prototype.listeners = function(type) { - var ret; - if (!this._events || !this._events[type]) - ret = []; - else if (isFunction(this._events[type])) - ret = [this._events[type]]; - else - ret = this._events[type].slice(); - return ret; -}; - -EventEmitter.listenerCount = function(emitter, type) { - var ret; - if (!emitter._events || !emitter._events[type]) - ret = 0; - else if (isFunction(emitter._events[type])) - ret = 1; - else - ret = emitter._events[type].length; - return ret; -}; - -function isFunction(arg) { - return typeof arg === 'function'; -} - -function isNumber(arg) { - return typeof arg === 'number'; -} - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} - -function isUndefined(arg) { - return arg === void 0; -} \ No newline at end of file diff --git a/rhino/fs.js b/rhino/fs.js deleted file mode 100644 index 9cd3ab2d..00000000 --- a/rhino/fs.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * Partial Rhino shim for Node.js' `fs` module. - * @see http://nodejs.org/api/fs.html - */ -'use strict'; - -var env = require('jsdoc/env'); -var path = require('path'); -var util = require('util'); - -var asyncify = path._asyncify; - -function checkEncoding(enc, name) { - // we require the `encoding` parameter for Node.js compatibility; on Node.js, if you omit the - // encoding, you get a stream instead of a string - if (!enc || typeof enc === 'function') { - throw new Error(name + ' requires an encoding on Rhino!'); - } - - // Node.js wants 'utf8', but Java wants 'utf-8' - if (enc === 'utf8') { - enc = 'utf-8'; - } - - return enc; -} - -// provide an error that's consistent with Node.js -function errorFactory(filepath) { - return new Error( util.format("ENOENT, no such file or directory '%s'", filepath) ); -} - -exports.readFileSync = function readFileSync(filename, encoding) { - encoding = checkEncoding(encoding, 'fs.readFile[Sync]'); - - return readFile(filename, encoding); -}; -exports.readFile = asyncify(exports.readFileSync); - -// in node 0.8, path.exists() and path.existsSync() moved to the "fs" module -exports.existsSync = path.existsSync; -exports.exists = path.exists; - -var statSync = exports.statSync = function statSync(_path) { - var f = new java.io.File(_path); - if (!f) { - throw errorFactory(_path); - } - - return { - isFile: function isFile() { - return f.isFile(); - }, - isDirectory: function isDirectory() { - return f.isDirectory(); - }, - isSymlink: function isSymlink() { - // java.io.File resolves symlinks - return false; - } - }; -}; -exports.stat = asyncify(statSync); - -// java.io.File resolves symlinks, so we can alias `lstat` to `stat` -var lstatSync = exports.lstatSync = statSync; -exports.lstat = asyncify(lstatSync); - -var readdirSync = exports.readdirSync = function readdirSync(_path) { - var dir; - var files; - - dir = new java.io.File(_path); - if (!dir.directory) { - throw errorFactory(_path); - } - - files = dir.list() - .map(function(fileName) { - return String(fileName); - }); - - return files; -}; -exports.readdir = asyncify(readdirSync); - -// JSDoc extension to `fs` module -var toDir = exports.toDir = function toDir(_path) { - var f; - - _path = path.normalize(_path); - f = new java.io.File( path.resolve(env.pwd, _path) ); - - if ( f.isDirectory() ){ - return _path; - } else { - return path.dirname(_path); - } -}; - -var mkdirSync = exports.mkdirSync = function mkdirSync(_path) { - var dir_path = toDir(_path); - ( new java.io.File(dir_path) ).mkdir(); -}; -exports.mkdir = asyncify(mkdirSync); - -// JSDoc extension to `fs` module -exports.mkPath = function mkPath(_path) { - if ( Array.isArray(_path) ) { - _path = _path.join(''); - } - - ( new java.io.File(path.resolve(env.pwd, _path)) ).mkdirs(); -}; - -// JSDoc extension to `fs` module -exports.copyFileSync = function copyFileSync(inFile, outDir, fileName) { - if (fileName === undefined || fileName === null) { - fileName = path.basename(inFile); - } - - outDir = toDir(outDir); - - inFile = new java.io.File(inFile); - var outFile = new java.io.File(outDir + '/' + fileName); - - var bis = new java.io.BufferedInputStream(new java.io.FileInputStream(inFile), 4096); - var bos = new java.io.BufferedOutputStream(new java.io.FileOutputStream(outFile), 4096); - var theChar = bis.read(); - while (theChar !== -1) { - bos.write(theChar); - theChar = bis.read(); - } - - bos.close(); - bis.close(); -}; -exports.copyFile = asyncify(exports.copyFileSync); - -exports.writeFileSync = function writeFileSync(filename, data, encoding) { - encoding = checkEncoding(encoding, 'fs.writeFile[Sync]'); - - var out = new java.io.PrintWriter( - new java.io.OutputStreamWriter( - new java.io.FileOutputStream(filename), - encoding - ) - ); - - try { - out.write(data); - } - finally { - out.flush(); - out.close(); - } -}; -exports.writeFile = asyncify(exports.writeFileSync); - -exports.rmdirSync = function rmdirSync(_path) { - throw new Error('not implemented'); -}; -exports.rmdir = asyncify(exports.rmdirSync); - -exports.unlinkSync = function unlinkSync(_path) { - throw new Error('not implemented'); -}; -exports.unlink = asyncify(exports.unlinkSync); diff --git a/rhino/js.jar b/rhino/js.jar deleted file mode 100644 index ce8dcb3c..00000000 Binary files a/rhino/js.jar and /dev/null differ diff --git a/rhino/jsdoc/src/astbuilder.js b/rhino/jsdoc/src/astbuilder.js deleted file mode 100644 index 1d62560e..00000000 --- a/rhino/jsdoc/src/astbuilder.js +++ /dev/null @@ -1,18 +0,0 @@ -/*global Packages: true */ -/** - * Creates an Esprima-compatible AST using Rhino's JavaScript parser. - * @module rhino/jsdoc/src/astbuilder - */ -'use strict'; - -var AstBuilder = exports.AstBuilder = function() { - this._builder = new Packages.org.jsdoc.AstBuilder(); -}; - -AstBuilder.prototype.build = function(sourceCode, sourceName) { - return this._builder.build(sourceCode, sourceName); -}; - -AstBuilder.prototype.getRhinoNodes = function() { - return this._builder.getRhinoNodes(); -}; diff --git a/rhino/jsdoc/src/parser.js b/rhino/jsdoc/src/parser.js deleted file mode 100644 index 3d26552d..00000000 --- a/rhino/jsdoc/src/parser.js +++ /dev/null @@ -1,48 +0,0 @@ -// TODO: module docs -'use strict'; - -// TODO: docs -exports.createParser = require('jsdoc/src/parser').createParser; - -// TODO: docs -var Parser = exports.Parser = function() { - var astBuilder; - var visitor; - - var runtime = require('jsdoc/util/runtime'); - if ( !runtime.isRhino() ) { - throw new Error('You must run JSDoc on Mozilla Rhino to use the Rhino parser.'); - } - - astBuilder = new ( require(runtime.getModulePath('jsdoc/src/astbuilder')) ).AstBuilder(); - visitor = new ( require(runtime.getModulePath('jsdoc/src/visitor')) ).Visitor(this); - - Parser.super_.call(this, astBuilder, visitor); -}; -require('util').inherits(Parser, require('jsdoc/src/parser').Parser); - -// TODO: update docs -/** - * Adds a node visitor to use in parsing - */ -Parser.prototype.addNodeVisitor = function(visitor) { - this._visitor.addRhinoNodeVisitor(visitor); -}; - -// TODO: docs -/** - * Get the node visitors used in parsing - */ -Parser.prototype.getNodeVisitors = function() { - return this._visitor.getRhinoNodeVisitors(); -}; - -// TODO: docs -Parser.prototype._walkAst = function(ast, visitor, sourceName) { - // On Rhino, we visit the comments all at once before we walk the AST - this._visitor.visitNodeComments({ - leadingComments: ast.comments - }, this, sourceName); - - Parser.super_.prototype._walkAst.call(this, ast, visitor, sourceName); -}; diff --git a/rhino/jsdoc/src/visitor.js b/rhino/jsdoc/src/visitor.js deleted file mode 100644 index 4be5c70f..00000000 --- a/rhino/jsdoc/src/visitor.js +++ /dev/null @@ -1,69 +0,0 @@ -// TODO: module docs -'use strict'; - -// TODO: docs -var Visitor = exports.Visitor = function() { - var runtime = require('jsdoc/util/runtime'); - if ( !runtime.isRhino() ) { - throw new Error('You must run JSDoc on Mozilla Rhino to use the Rhino node visitor.'); - } - - Visitor.super_.call(this); - - // Rhino node visitors added by plugins (deprecated in JSDoc 3.3) - this._rhinoNodeVisitors = []; - // Rhino nodes retrieved from the org.jsdoc.AstBuilder instance - this._rhinoNodes = null; - - // only visit nodes, not their comments--the parser visits all the comments at once - this._visitors = [ - this.visitNode - ]; - - this.addAstNodeVisitor({ - visitNode: this._visitRhinoNode.bind(this) - }); -}; -require('util').inherits(Visitor, require('jsdoc/src/visitor').Visitor); - -// TODO: docs (deprecated) -Visitor.prototype.addRhinoNodeVisitor = function(visitor) { - this._rhinoNodeVisitors.push(visitor); -}; - -// TODO: docs (deprecated) -Visitor.prototype.removeRhinoNodeVisitor = function(visitor) { - var idx = this._rhinoNodeVisitors.indexOf(visitor); - if (idx !== -1) { - this._rhinoNodeVisitors.splice(idx, 1); - } -}; - -// TODO: docs (deprecated) -Visitor.prototype.getRhinoNodeVisitors = function() { - return this._rhinoNodeVisitors; -}; - -// TODO: docs (deprecated) -Visitor.prototype._visitRhinoNode = function(astNode, e, parser, filename) { - var rhinoNode; - var visitors = this._rhinoNodeVisitors; - - if (!visitors.length) { - return; - } - - if (!this._rhinoNodes) { - this._rhinoNodes = parser.astBuilder.getRhinoNodes(); - } - - rhinoNode = this._rhinoNodes ? this._rhinoNodes.get(astNode.nodeId) : null; - if (rhinoNode) { - for (var i = 0, l = visitors.length; i < l; i++) { - visitors[i].visitNode(rhinoNode, e, parser, filename); - if (e.stopPropagation) { - break; - } - } - } -}; diff --git a/rhino/os.js b/rhino/os.js deleted file mode 100644 index 80473b62..00000000 --- a/rhino/os.js +++ /dev/null @@ -1,14 +0,0 @@ -/*global java */ -/** - * Partial Rhino implementation of Node.js' `os` module. - * @module os - * @author Jeff Williams - * @see http://nodejs.org/api/os.html - */ -'use strict'; - -exports.EOL = String( java.lang.System.getProperty('line.separator') ); - -exports.platform = function() { - return process.platform; -}; diff --git a/rhino/path.js b/rhino/path.js deleted file mode 100644 index c4218f93..00000000 --- a/rhino/path.js +++ /dev/null @@ -1,432 +0,0 @@ -'use strict'; - -var isWindows = java.lang.System.getProperty("os.name").toLowerCase().contains("windows"); -var fileSeparator = exports.sep = String( java.lang.System.getProperty("file.separator") ); - -function noOp() {} - -// exported for the benefit of our `fs` shim -var asyncify = exports._asyncify = function(func) { - return function() { - var args = Array.prototype.slice.call(arguments); - var callback = args.pop(); - var data; - - callback = typeof callback === 'function' ? callback : noOp; - - try { - data = func.apply(this, args); - process.nextTick(function() { - callback(null, data); - }); - } - catch (e) { - process.nextTick(function() { - callback(e); - }); - } - }; -}; - -/** - * Returns everything on a path except for the last item - * e.g. if the path was 'path/to/something', the return value would be 'path/to' - */ -exports.dirname = function(_path) { - var f = new java.io.File(_path); - return String(f.getParent()); -}; - -/** - * Returns the last item on a path - */ -exports.basename = function(_path, ext) { - var f = new java.io.File(_path); - var p = f.getParentFile(); - var base = String(f.getName()); - if (p != null) { - var idx = ext ? base.indexOf(ext) : -1; - if (idx !== -1) { - base = base.substring(0, base.length - ext.length); - } - } - return base; -}; - -exports.existsSync = function(_path) { - var f = new java.io.File(_path); - - if (f.isDirectory()){ - return true; - } - if (!f.exists()){ - return false; - } - if (!f.canRead()){ - return false; - } - return true; -}; - -exports.exists = asyncify(exports.existsSync); - -//Code below taken from node - -//resolves . and .. elements in a path array with directory names there -//must be no slashes, empty elements, or device names (c:\) in the array -//(so also no leading and trailing slashes - it does not distinguish -//relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for ( var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last == '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } - - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } - - return parts; -} - -exports.extname = function(path) { - return splitPath(path)[3]; -}; - -if (isWindows) { - // Regex to split a windows path into three parts: [*, device, slash, - // tail] windows-only - var splitDeviceRe = - /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?([\s\S]*?)$/; - - // Regex to split the tail part of the above into [*, dir, basename, ext] - var splitTailRe = - /^([\s\S]*?)((?:\.{1,2}|[^\\\/]+?|)(\.[^.\/\\]*|))(?:[\\\/]*)$/; - - // Function to split a filename into [root, dir, basename, ext] - // windows version - var splitPath = function(filename) { - // Separate device+slash from tail - var result = splitDeviceRe.exec(filename), - device = (result[1] || '') + (result[2] || ''), - tail = result[3] || ''; - // Split the tail into dir, basename and extension - var result2 = splitTailRe.exec(tail), - dir = result2[1], - basename = result2[2], - ext = result2[3]; - return [device, dir, basename, ext]; - }; - - // path.resolve([from ...], to) - // windows version - exports.resolve = function() { - var resolvedDevice = '', - resolvedTail = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1; i--) { - var path; - if (i >= 0) { - path = arguments[i]; - } else if (!resolvedDevice) { - path = process.cwd(); - } else { - // Windows has the concept of drive-specific current working - // directories. If we've resolved a drive letter but not yet an - // absolute path, get cwd for that drive. We're sure the device is not - // an unc path at this points, because unc paths are always absolute. - path = process.env['=' + resolvedDevice]; - // Verify that a drive-local cwd was found and that it actually points - // to our drive. If not, default to the drive's root. - if (!path || path.substr(0, 3).toLowerCase() !== - resolvedDevice.toLowerCase() + '\\') { - path = resolvedDevice + '\\'; - } - } - - // Skip empty and invalid entries - if (typeof path !== 'string' || !path) { - continue; - } - - var result = splitDeviceRe.exec(path), - device = result[1] || '', - isUnc = device && device.charAt(1) !== ':', - isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute - tail = result[3]; - - if (device && - resolvedDevice && - device.toLowerCase() !== resolvedDevice.toLowerCase()) { - // This path points to another device so it is not applicable - continue; - } - - if (!resolvedDevice) { - resolvedDevice = device; - } - if (!resolvedAbsolute) { - resolvedTail = tail + '\\' + resolvedTail; - resolvedAbsolute = isAbsolute; - } - - if (resolvedDevice && resolvedAbsolute) { - break; - } - } - - // Replace slashes (in UNC share name) by backslashes - resolvedDevice = resolvedDevice.replace(/\//g, '\\'); - - // At this point the path should be resolved to a full absolute path, - // but handle relative paths to be safe (might happen when process.cwd() - // fails) - - // Normalize the tail path - - function f(p) { - return !!p; - } - - resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f), - !resolvedAbsolute).join('\\'); - - return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) || - '.'; - }; - - // windows version - exports.normalize = function(_path) { - var result = splitDeviceRe.exec(_path), - device = result[1] || '', - isUnc = device && device.charAt(1) !== ':', - isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute - tail = result[3], - trailingSlash = /[\\\/]$/.test(tail); - - // Normalize the tail path - tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) { - return !!p; - }), !isAbsolute).join('\\'); - - if (!tail && !isAbsolute) { - tail = '.'; - } - if (tail && trailingSlash) { - tail += '\\'; - } - - return device + (isAbsolute ? '\\' : '') + tail; - }; - - //windows version - exports.join = function() { - function f(p) { - return p && typeof p === 'string'; - } - - var _paths = Array.prototype.slice.call(arguments, 0).filter(f); - var joined = _paths.join('\\'); - - // Make sure that the joined path doesn't start with two slashes - // - it will be mistaken for an unc path by normalize() - - // unless the _paths[0] also starts with two slashes - if (/^[\\\/]{2}/.test(joined) && !/^[\\\/]{2}/.test(_paths[0])) { - joined = joined.slice(1); - } - - return exports.normalize(joined); - }; - - // path.relative(from, to) - // it will solve the relative path from 'from' to 'to', for instance: - // from = 'C:\\orandea\\test\\aaa' - // to = 'C:\\orandea\\impl\\bbb' - // The output of the function should be: '..\\..\\impl\\bbb' - // windows version - exports.relative = function(from, to) { - from = exports.resolve(from); - to = exports.resolve(to); - - // windows is not case sensitive - var lowerFrom = from.toLowerCase(); - var lowerTo = to.toLowerCase(); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') { - break; - } - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') { - break; - } - } - - if (start > end) { - return []; - } - return arr.slice(start, end - start + 1); - } - - var toParts = trim(to.split('\\')); - - var lowerFromParts = trim(lowerFrom.split('\\')); - var lowerToParts = trim(lowerTo.split('\\')); - - var length = Math.min(lowerFromParts.length, lowerToParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (lowerFromParts[i] !== lowerToParts[i]) { - samePartsLength = i; - break; - } - } - - if (samePartsLength === 0) { - return to; - } - - var outputParts = []; - for (i = samePartsLength; i < lowerFromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('\\'); - }; -} else { - // Split a filename into [root, dir, basename, ext], unix version - // 'root' is just a slash, or nothing. - var splitPathRe = - /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; - var splitPath = function(filename) { - return splitPathRe.exec(filename).slice(1); - }; - - // path.resolve([from ...], to) - // posix version - exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; - - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); - - // Skip empty and invalid entries - if (typeof path !== 'string' || !path) { - continue; - } - - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } - - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) - - // Normalize the path - resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); - - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; - }; - - // path.normalize(_path) - // posix version - exports.normalize = function(_path) { - var isAbsolute = _path.charAt(0) === '/', - trailingSlash = _path.slice(-1) === '/'; - - // Normalize the path - _path = normalizeArray(_path.split('/').filter(function(p) { - return !!p; - }), !isAbsolute).join('/'); - - if (!_path && !isAbsolute) { - _path = '.'; - } - if (_path && trailingSlash) { - _path += '/'; - } - - return (isAbsolute ? '/' : '') + _path; - }; - - // posix version - exports.join = function() { - var _paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(_paths.filter(function(p, index) { - return p && typeof p === 'string'; - }).join('/')); - }; - - // path.relative(from, to) - // posix version - exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); - - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') { - break; - } - } - - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') { - break; - } - } - - if (start > end) { - return []; - } - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } - - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); - }; -} \ No newline at end of file diff --git a/rhino/querystring.js b/rhino/querystring.js deleted file mode 100644 index a24ec97f..00000000 --- a/rhino/querystring.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Adapted version of Node.js' `querystring` module. - * @module querystring - * @see http://nodejs.org/api/querystring.html - * @see https://github.com/joyent/node/blob/f105f2f2/lib/querystring.js - * @license MIT - */ -'use strict'; - -var QueryString = exports; - -// If obj.hasOwnProperty has been overridden, then calling -// obj.hasOwnProperty(prop) will break. -// See: https://github.com/joyent/node/issues/1707 -function hasOwnProp(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -QueryString.unescape = function(s) { - return decodeURIComponent(s); -}; - -QueryString.escape = function(str) { - return encodeURIComponent(str); -}; - -var stringifyPrimitive = function(v) { - switch (typeof v) { - case 'string': - return v; - - case 'boolean': - return v ? 'true' : 'false'; - - case 'number': - return isFinite(v) ? v : ''; - - default: - return ''; - } -}; - -QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) { - sep = sep || '&'; - eq = eq || '='; - if (obj === null) { - obj = undefined; - } - - if (typeof obj === 'object') { - return Object.keys(obj).map(function(k) { - var ks = QueryString.escape(stringifyPrimitive(k)) + eq; - if (Array.isArray(obj[k])) { - return obj[k].map(function(v) { - return ks + QueryString.escape(stringifyPrimitive(v)); - }).join(sep); - } else { - return ks + QueryString.escape(stringifyPrimitive(obj[k])); - } - }).join(sep); - - } - - if (!name) { - return ''; - } - return QueryString.escape(stringifyPrimitive(name)) + eq + - QueryString.escape(stringifyPrimitive(obj)); -}; - -// Parse a key=val string. -QueryString.parse = QueryString.decode = function(qs, sep, eq, options) { - sep = sep || '&'; - eq = eq || '='; - var obj = {}; - - if (typeof qs !== 'string' || qs.length === 0) { - return obj; - } - - var regexp = /\+/g; - qs = qs.split(sep); - - var maxKeys = 1000; - if (options && typeof options.maxKeys === 'number') { - maxKeys = options.maxKeys; - } - - var len = qs.length; - // maxKeys <= 0 means that we should not limit keys count - if (maxKeys > 0 && len > maxKeys) { - len = maxKeys; - } - - for (var i = 0; i < len; ++i) { - var x = qs[i].replace(regexp, '%20'), - idx = x.indexOf(eq), - kstr, vstr, k, v; - - if (idx >= 0) { - kstr = x.substr(0, idx); - vstr = x.substr(idx + 1); - } else { - kstr = x; - vstr = ''; - } - - k = QueryString.unescape(kstr); - v = QueryString.unescape(vstr); - - if (!hasOwnProp(obj, k)) { - obj[k] = v; - } else if (Array.isArray(obj[k])) { - obj[k].push(v); - } else { - obj[k] = [obj[k], v]; - } - } - - return obj; -}; diff --git a/rhino/rhino-shim.js b/rhino/rhino-shim.js deleted file mode 100644 index c24a733b..00000000 --- a/rhino/rhino-shim.js +++ /dev/null @@ -1,191 +0,0 @@ -/*global java, Packages, version */ -/*eslint-disable strict */ -/** - * @overview A minimal emulation of the standard features of Node.js necessary - * to get JSDoc to run. - */ - -// Set the JS version that the Rhino interpreter will use. -version(180); - -/** - * Emulate DOM timeout/interval functions. - * @see https://developer.mozilla.org/en-US/docs/DOM/window#Methods - */ -(function() { - 'use strict'; - - var timerPool = new java.util.concurrent.ScheduledThreadPoolExecutor(1); - var timers = {}; - var timerCount = 1; - var timerUnits = java.util.concurrent.TimeUnit.MILLISECONDS; - var queue = {}; - var queueActive = false; - - function getCallback(fn) { - return new java.lang.Runnable({ - run: Packages.org.mozilla.javascript.Context.call(fn) - }); - } - - global.setTimeout = function setTimeout(fn, delay) { - var timerId = timerCount++; - var callback = getCallback(fn); - timers[timerId] = timerPool.schedule(callback, delay, timerUnits); - return timerId; - }; - - global.clearTimeout = function clearTimeout(timerId) { - if (timers[timerId]) { - timerPool.remove(timers[timerId]); - delete timers[timerId]; - } - }; - - global.setInterval = function setInterval(fn, delay) { - var timerId = timerCount++; - var callback = getCallback(fn); - timers[timerId] = timerPool.scheduleAtFixedRate(callback, delay, delay, timerUnits); - return timerId; - }; - - global.clearInterval = global.clearTimeout; - - // adapted from https://github.com/alexgorbatchev/node-browser-builtins - // MIT license - global.setImmediate = (function() { - function drain() { - var key; - - var keys = Object.keys(queue); - - queueActive = false; - - for (var i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - var fn = queue[key]; - delete queue[key]; - fn(); - } - } - - return function setImmediate(fn) { - var timerId = timerCount++; - queue[timerId] = fn; - - if (!queueActive) { - queueActive = true; - global.setTimeout(drain, 0); - } - - return timerId; - }; - })(); - - global.clearImmediate = function clearImmediate(id) { - delete queue[id]; - }; -})(); - -/** - * Emulate Node.js console functions. - * @see http://nodejs.org/api/stdio.html - */ -global.console = (function() { - function println(stream, args) { - java.lang.System[stream].println( require('util').format.apply(this, args) ); - } - - return { - error: function error() { - println('err', arguments); - }, - info: function info() { - println('out', arguments); - }, - log: function log() { - println('out', arguments); - }, - trace: function trace(label) { - // this puts some extra junk at the top of the stack trace, but it's close enough - var e = new java.lang.Exception(label || 'Trace'); - e.printStackTrace(); - }, - warn: function warn() { - println('err', arguments); - } - }; -})(); - -/** - * Emulate Node.js process functions. - * @see http://nodejs.org/api/process.html - */ -global.process = { - // not quite right, but close enough - argv: ['java', 'jsdoc.js'] - .concat( Array.prototype.slice.call(arguments, 0) ), - // this depends on a hack in our version of Rhino - cwd: function cwd() { - var f = new java.io.File( java.lang.System.getProperty('user.dir') ); - return String( f.getAbsolutePath() ); - }, - env: (function() { - var javaEnv = java.lang.System.getenv(); - var key; - var keys = javaEnv.keySet().toArray(); - var result = {}; - - for (var i = 0, l = keys.length; i < l; i++) { - key = keys[i]; - result[key + ''] = javaEnv.get(key) + ''; - } - - return result; - })(), - exit: function exit(n) { - n = n || 0; - java.lang.System.exit(n); - }, - nextTick: function nextTick(callback) { - setTimeout(callback, 0); - }, - platform: (function() { - if ( String(java.lang.System.getProperty('os.name')).match(/^[Ww]in/) ) { - return 'win32'; - } - else { - // not necessarily accurate, but good enough - return 'linux'; - } - })(), - stderr: { - // Java can't reliably find the terminal width across platforms, so we hard-code a - // reasonable value - columns: 80, - write: function write(str) { - java.lang.System.err.print(str); - } - }, - stdout: { - // Java can't reliably find the terminal width across platforms, so we hard-code a - // reasonable value - columns: 80, - write: function write(str) { - java.lang.System.out.print(str); - } - } -}; - -/** - * Emulate other Node.js globals. - * @see http://nodejs.org/docs/latest/api/globals.html - */ -Object.defineProperties(global, { - '__dirname': { - get: function() { - return global.process.cwd(); - }, - enumerable: true - } -}); diff --git a/rhino/util.js b/rhino/util.js deleted file mode 100644 index 3dc33113..00000000 --- a/rhino/util.js +++ /dev/null @@ -1,532 +0,0 @@ -/** - * Adapted version of Node.js' `util` module. - * @module util - * @see http://nodejs.org/api/util.html - * @see https://github.com/joyent/node/blob/85090734/lib/util.js - * @license MIT - */ - -function hasOwnProp(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -// placate JSHint -var stylizeNoColor, stylizeWithColor, formatValue, formatPrimitive; - -/** - * Echoes the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) { - ctx.depth = arguments[2]; - } - if (arguments.length >= 4) { - ctx.colors = arguments[3]; - } - if (typeof opts === 'boolean') { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (typeof ctx.showHidden === 'undefined') { - ctx.showHidden = false; - } - if (typeof ctx.depth === 'undefined') { - ctx.depth = 2; - } - if (typeof ctx.colors === 'undefined') { - ctx.colors = false; - } - if (typeof ctx.customInspect === 'undefined') { - ctx.customInspect = true; - } - if (ctx.colors) { - ctx.stylize = stylizeWithColor; - } - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; - -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; - -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; - -stylizeWithColor = function(str, styleType) { - var style = inspect.styles[styleType]; - - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -}; - -stylizeNoColor = function(str, styleType) { - return str; -}; - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - var i, len; - - if (typeof f !== 'string') { - var objects = []; - for (i = 0, len = arguments.length; i < len; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } - - i = 1; - var args = arguments; - len = args.length; - 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': return require('jsdoc/util/dumper').dump(args[i++]); - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (x === null || typeof x !== 'object') { - str += ' ' + x; - } else { - str += ' ' + inspect(x); - } - } - return str; -}; - -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - if (process.noDeprecation === true) { - return fn; - } - - var warned = false; - function deprecated() { - if (!warned) { - if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } - - return deprecated; -}; - -exports.print = function() { - var args = Array.prototype.slice.call(arguments, 0); - for (var i = 0, len = args.length; i < len; ++i) { - process.stdout.write(String(args[i])); - } -}; - -exports.puts = function() { - var args = Array.prototype.slice.call(arguments, 0); - for (var i = 0, len = args.length; i < len; ++i) { - process.stdout.write(args[i] + '\n'); - } -}; - -exports.debug = function(x) { - process.stderr.write('DEBUG: ' + x + '\n'); -}; - -var error = exports.error = function(x) { - var args = Array.prototype.slice.call(arguments, 0); - for (var i = 0, len = args.length; i < len; ++i) { - process.stderr.write(args[i] + '\n'); - } -}; - -function arrayToHash(array) { - var hash = {}; - - array.forEach(function(val, idx) { - hash[val] = true; - }); - - return hash; -} - -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} - -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProp(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (recurseTimes === null) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (typeof name === 'undefined') { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } - - return name + ': ' + str; -} - -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProp(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} - -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) { - numLinesEst++; - } - return prev + cur.length + 1; - }, 0); - - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } - - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar) || - (typeof ar === 'object' && objectToString(ar) === '[object Array]'); -} -exports.isArray = isArray; - -function isRegExp(re) { - return typeof re === 'object' && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isDate(d) { - return typeof d === 'object' && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return typeof e === 'object' && objectToString(e) === '[object Error]'; -} -exports.isError = isError; - -formatValue = function(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && value && typeof value.inspect === 'function' && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - return String(value.inspect(recurseTimes)); - } - - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } - - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); - - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } - - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (typeof value === 'function') { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } - - var base = '', array = false, braces = ['{', '}']; - - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } - - // Make functions say that they are functions - if (typeof value === 'function') { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } - - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } - - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } - - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } - - if (keys.length === 0 && (!array || value.length === 0)) { - return braces[0] + base + braces[1]; - } - - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } - - ctx.seen.push(value); - - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } - - ctx.seen.pop(); - - return reduceToSingleString(output, base, braces); -}; - -formatPrimitive = function(ctx, value) { - switch (typeof value) { - case 'undefined': - return ctx.stylize('undefined', 'undefined'); - - case 'string': - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - - case 'number': - return ctx.stylize('' + value, 'number'); - - case 'boolean': - return ctx.stylize('' + value, 'boolean'); - } - // For some reason typeof null is "object", so special case here. - if (value === null) { - return ctx.stylize('null', 'null'); - } -}; - -exports.p = exports.deprecate(function() { - var args = Array.prototype.slice.call(arguments, 0); - for (var i = 0, len = args.length; i < len; ++i) { - error(exports.inspect(args[i])); - } -}, 'util.p: Use console.error() instead.'); - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - -exports.log = function(msg) { - exports.puts(timestamp() + ' - ' + msg.toString()); -}; - -exports.exec = function() { - throw new Error('util.exec() is not implemented on Rhino (and was deprecated in Node.js 0.2)'); -}; - -exports.pump = function() { - throw new Error('util.pump() is not implemented on Rhino (and was deprecated in Node.js 0.8'); -}; - -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = function(ctor, superCtor) { - ctor.super_ = superCtor; - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); -}; - -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || typeof add !== 'object') { - return origin; - } - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; diff --git a/test/README.md b/test/README.md index 46456226..8bd7fa9b 100644 --- a/test/README.md +++ b/test/README.md @@ -13,12 +13,6 @@ Or on OS X, Linux, and other POSIX-compliant platforms: ./jsdoc -T -If you can't get the short-form commands to work, try invoking Java directly: - - java -cp lib/js.jar org.mozilla.javascript.tools.shell.Main \ - -modules node_modules -modules rhino -modules lib -modules . \ - jsdoc.js -T - Writing Tests ------------- diff --git a/test/jasmine-jsdoc.js b/test/jasmine-jsdoc.js index 33f46a75..01480944 100644 --- a/test/jasmine-jsdoc.js +++ b/test/jasmine-jsdoc.js @@ -40,9 +40,9 @@ jasmine.getParseResults = function() { return parseResults; }; -// use the requested parser, or default to the pure JS parser (on Node.js) or Rhino (on Rhino) +// use the requested parser, or default to the pure JS parser (on Node.js) jasmine.jsParser = (function() { - var parser = jsdoc.util.runtime.isRhino() ? 'rhino' : 'js'; + var parser = 'js'; if (jsdoc.env.opts.query && jsdoc.env.opts.query.parser) { parser = jsdoc.env.opts.query.parser; diff --git a/test/spec-collection.js b/test/spec-collection.js index efafc777..99b92b3a 100644 --- a/test/spec-collection.js +++ b/test/spec-collection.js @@ -43,7 +43,7 @@ function addSpec(file, target) { function isValidSpec(file, matcher) { var result; - var skipPath = runtime.isRhino() ? runtime.NODE : runtime.RHINO; + var skipPath = runtime.NODE; // valid specs must... try { diff --git a/test/specs/documentation/arrowfunction.js b/test/specs/documentation/arrowfunction.js index bedb5f18..d46ccd98 100644 --- a/test/specs/documentation/arrowfunction.js +++ b/test/specs/documentation/arrowfunction.js @@ -1,24 +1,22 @@ 'use strict'; -if (jasmine.jsParser !== 'rhino') { - describe('arrow functions', function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/arrowfunction.js'); - var increment = docSet.getByLongname('increment')[0]; - var print = docSet.getByLongname('print')[0]; +describe('arrow functions', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/arrowfunction.js'); + var increment = docSet.getByLongname('increment')[0]; + var print = docSet.getByLongname('print')[0]; - it('should use the correct name and longname', function() { - expect(increment).toBeDefined(); - expect(increment.name).toBe('increment'); - }); - - it('should allow function parameters to be documented', function() { - expect(increment.params.length).toBe(1); - expect(increment.params[0].name).toBe('n'); - }); - - it('should support inline comments on parameters', function() { - expect(print.params.length).toBe(1); - expect(print.params[0].type.names[0]).toBe('*'); - }); + it('should use the correct name and longname', function() { + expect(increment).toBeDefined(); + expect(increment.name).toBe('increment'); }); -} + + it('should allow function parameters to be documented', function() { + expect(increment.params.length).toBe(1); + expect(increment.params[0].name).toBe('n'); + }); + + it('should support inline comments on parameters', function() { + expect(print.params.length).toBe(1); + expect(print.params[0].type.names[0]).toBe('*'); + }); +}); diff --git a/test/specs/documentation/const.js b/test/specs/documentation/const.js index 441bc49a..8ee1d667 100644 --- a/test/specs/documentation/const.js +++ b/test/specs/documentation/const.js @@ -8,14 +8,12 @@ describe('const declarations', function() { expect(myPocket.kind).toBe('constant'); }); - if (jasmine.jsParser !== 'rhino') { - describe('ES 2015 only', function() { - it('should not override kind="class" when a const is autodetected', function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/constanttag2.js'); - var foo = docSet.getByLongname('Foo')[0]; + describe('ES 2015 only', function() { + it('should not override kind="class" when a const is autodetected', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/constanttag2.js'); + var foo = docSet.getByLongname('Foo')[0]; - expect(foo.kind).toBe('class'); - }); + expect(foo.kind).toBe('class'); }); - } + }); }); diff --git a/test/specs/documentation/defaultparams.js b/test/specs/documentation/defaultparams.js index 6035c171..f13d4c70 100644 --- a/test/specs/documentation/defaultparams.js +++ b/test/specs/documentation/defaultparams.js @@ -1,55 +1,52 @@ 'use strict'; -// Rhino can't handle default parameters -if (jasmine.jsParser !== 'rhino') { - describe('default parameters', function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/defaultparams.js'); +describe('default parameters', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/defaultparams.js'); - var setActive = docSet.getByLongname('setActive')[0]; - var setBirthYear = docSet.getByLongname('setBirthYear')[0]; - var setDogName = docSet.getByLongname('setDogName')[0]; - var setFirstName = docSet.getByLongname('setFirstName')[0]; - var setLastName = docSet.getByLongname('setLastName')[0]; - var setManager = docSet.getByLongname('setManager')[0]; - var setName = docSet.getByLongname('setName')[0]; - var setPizzaToppings = docSet.getByLongname('setPizzaToppings')[0]; + var setActive = docSet.getByLongname('setActive')[0]; + var setBirthYear = docSet.getByLongname('setBirthYear')[0]; + var setDogName = docSet.getByLongname('setDogName')[0]; + var setFirstName = docSet.getByLongname('setFirstName')[0]; + var setLastName = docSet.getByLongname('setLastName')[0]; + var setManager = docSet.getByLongname('setManager')[0]; + var setName = docSet.getByLongname('setName')[0]; + var setPizzaToppings = docSet.getByLongname('setPizzaToppings')[0]; - it('should automatically add string-literal values as defaults when no default value is documented', function() { - expect(setFirstName.params[0].defaultvalue).toBe('Buster'); - }); - - it('should not automatically mark parameters with default values as optional', function() { - expect(setFirstName.params[0].optional).toBeUndefined(); - }); - - it('should not automatically mark parameters with default values as nullable', function() { - expect(setFirstName.params[0].nullable).toBeUndefined(); - }); - - it('should not override documented default values', function() { - expect(setLastName.params[0].defaultvalue).toBe('Braun'); - }); - - it('should work when some parameters have default values and others do not', function() { - expect(setName.params[0].defaultvalue).toBeUndefined(); - expect(setName.params[1].defaultvalue).toBe('Bluster'); - expect(setName.params[2].defaultvalue).toBe('Brown'); - }); - - it('should ignore empty strings', function() { - expect(setDogName.params[0].defaultvalue).toBeUndefined(); - }); - - it('should work with boolean literals', function() { - expect(setActive.params[0].defaultvalue).toBe(true); - }); - - it('should work with numeric literals', function() { - expect(setBirthYear.params[0].defaultvalue).toBe(3000); - }); - - it('should ignore non-literal default values, such as variable identifiers', function() { - expect(setPizzaToppings.params[0].defaultvalue).toBeUndefined(); - }); + it('should automatically add string-literal values as defaults when no default value is documented', function() { + expect(setFirstName.params[0].defaultvalue).toBe('Buster'); }); -} + + it('should not automatically mark parameters with default values as optional', function() { + expect(setFirstName.params[0].optional).toBeUndefined(); + }); + + it('should not automatically mark parameters with default values as nullable', function() { + expect(setFirstName.params[0].nullable).toBeUndefined(); + }); + + it('should not override documented default values', function() { + expect(setLastName.params[0].defaultvalue).toBe('Braun'); + }); + + it('should work when some parameters have default values and others do not', function() { + expect(setName.params[0].defaultvalue).toBeUndefined(); + expect(setName.params[1].defaultvalue).toBe('Bluster'); + expect(setName.params[2].defaultvalue).toBe('Brown'); + }); + + it('should ignore empty strings', function() { + expect(setDogName.params[0].defaultvalue).toBeUndefined(); + }); + + it('should work with boolean literals', function() { + expect(setActive.params[0].defaultvalue).toBe(true); + }); + + it('should work with numeric literals', function() { + expect(setBirthYear.params[0].defaultvalue).toBe(3000); + }); + + it('should ignore non-literal default values, such as variable identifiers', function() { + expect(setPizzaToppings.params[0].defaultvalue).toBeUndefined(); + }); +}); diff --git a/test/specs/documentation/getset.js b/test/specs/documentation/getset.js index 02f88b49..b858945d 100644 --- a/test/specs/documentation/getset.js +++ b/test/specs/documentation/getset.js @@ -31,29 +31,27 @@ describe('When a getter or setter is part of a class', function() { }); }); - if (jasmine.jsParser !== 'rhino') { - describe('in an ES 2015 class', function() { - var docSet2 = jasmine.getDocSetFromFile('test/fixtures/getset2.js'); - var location = docSet2.getByLongname('Employee#location'); + describe('in an ES 2015 class', function() { + var docSet2 = jasmine.getDocSetFromFile('test/fixtures/getset2.js'); + var location = docSet2.getByLongname('Employee#location'); - it('should have a doclet with the correct longname', function() { - expect(location.length).toBe(2); - }); - - it('should have a doclet with the correct name', function() { - expect(location[0].name).toBe('location'); - expect(location[1].name).toBe('location'); - }); - - it('should have a doclet with the correct kind', function() { - expect(location[0].kind).toBe('member'); - expect(location[1].kind).toBe('member'); - }); - - it('should have a doclet with the correct memberof', function() { - expect(location[0].memberof).toBe('Employee'); - expect(location[1].memberof).toBe('Employee'); - }); + it('should have a doclet with the correct longname', function() { + expect(location.length).toBe(2); }); - } + + it('should have a doclet with the correct name', function() { + expect(location[0].name).toBe('location'); + expect(location[1].name).toBe('location'); + }); + + it('should have a doclet with the correct kind', function() { + expect(location[0].kind).toBe('member'); + expect(location[1].kind).toBe('member'); + }); + + it('should have a doclet with the correct memberof', function() { + expect(location[0].memberof).toBe('Employee'); + expect(location[1].memberof).toBe('Employee'); + }); + }); }); diff --git a/test/specs/documentation/jsx.js b/test/specs/documentation/jsx.js index bf04cc5d..dadb3c3e 100644 --- a/test/specs/documentation/jsx.js +++ b/test/specs/documentation/jsx.js @@ -1,17 +1,15 @@ 'use strict'; -if (jasmine.jsParser !== 'rhino') { - describe('JSX support', function() { - it('should parse JSX files without errors', function() { - var logger = require('jsdoc/util/logger'); +describe('JSX support', function() { + it('should parse JSX files without errors', function() { + var logger = require('jsdoc/util/logger'); - function parseJsx() { - return jasmine.getDocSetFromFile('test/fixtures/jsx.js'); - } + function parseJsx() { + return jasmine.getDocSetFromFile('test/fixtures/jsx.js'); + } - spyOn(logger, 'error'); - expect(parseJsx).not.toThrow(); - expect(logger.error).not.toHaveBeenCalled(); - }); + spyOn(logger, 'error'); + expect(parseJsx).not.toThrow(); + expect(logger.error).not.toHaveBeenCalled(); }); -} +}); diff --git a/test/specs/documentation/methoddefinition.js b/test/specs/documentation/methoddefinition.js index 96b17419..396f1a4c 100644 --- a/test/specs/documentation/methoddefinition.js +++ b/test/specs/documentation/methoddefinition.js @@ -1,19 +1,17 @@ 'use strict'; -if (jasmine.jsParser !== 'rhino') { - describe('method definition inside a class declaration', function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/methoddefinition.js'); - var runMethod = docSet.getByLongname('Test#run')[0]; - var staticRunMethod = docSet.getByLongname('Test.run')[0]; +describe('method definition inside a class declaration', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/methoddefinition.js'); + var runMethod = docSet.getByLongname('Test#run')[0]; + var staticRunMethod = docSet.getByLongname('Test.run')[0]; - it('methods should have documentation comments', function() { - expect(runMethod).toBeDefined(); - expect(runMethod.description).toBe('Document me.'); - expect(runMethod.kind).toBe('function'); + it('methods should have documentation comments', function() { + expect(runMethod).toBeDefined(); + expect(runMethod.description).toBe('Document me.'); + expect(runMethod.kind).toBe('function'); - expect(staticRunMethod).toBeDefined(); - expect(staticRunMethod.description).toBe('Static document me.'); - expect(staticRunMethod.kind).toBe('function'); - }); + expect(staticRunMethod).toBeDefined(); + expect(staticRunMethod.description).toBe('Static document me.'); + expect(staticRunMethod.kind).toBe('function'); }); -} +}); diff --git a/test/specs/documentation/restparams.js b/test/specs/documentation/restparams.js index a1773676..bf30079b 100644 --- a/test/specs/documentation/restparams.js +++ b/test/specs/documentation/restparams.js @@ -1,24 +1,21 @@ 'use strict'; -// Rhino can't handle rest parameters -if (jasmine.jsParser !== 'rhino') { - describe('rest parameters', function() { - var docSet = jasmine.getDocSetFromFile('test/fixtures/restparams.js'); - var setAdmins = docSet.getByLongname('setAdmins')[0]; - var setWidgetAccess = docSet.getByLongname('setWidgetAccess')[0]; +describe('rest parameters', function() { + var docSet = jasmine.getDocSetFromFile('test/fixtures/restparams.js'); + var setAdmins = docSet.getByLongname('setAdmins')[0]; + var setWidgetAccess = docSet.getByLongname('setWidgetAccess')[0]; - it('should automatically mark standalone rest parameters as repeatable', function() { - var restParam = setAdmins.params[0]; + it('should automatically mark standalone rest parameters as repeatable', function() { + var restParam = setAdmins.params[0]; - expect(restParam.name).toBe('users'); - expect(restParam.variable).toBe(true); - }); - - it('should automatically mark rest parameters as repeatable when they are mixed with other params', function() { - var restParam = setWidgetAccess.params[1]; - - expect(restParam.name).toBe('users'); - expect(restParam.variable).toBe(true); - }); + expect(restParam.name).toBe('users'); + expect(restParam.variable).toBe(true); }); -} + + it('should automatically mark rest parameters as repeatable when they are mixed with other params', function() { + var restParam = setWidgetAccess.params[1]; + + expect(restParam.name).toBe('users'); + expect(restParam.variable).toBe(true); + }); +}); diff --git a/test/specs/jsdoc/src/parser.js b/test/specs/jsdoc/src/parser.js index 913312c6..db47f7ae 100644 --- a/test/specs/jsdoc/src/parser.js +++ b/test/specs/jsdoc/src/parser.js @@ -31,7 +31,6 @@ describe('jsdoc/src/parser', function() { describe('createParser', function() { it('should return a Parser when called without arguments', function() { - // we don't check instanceof because we get different objects on Node.js and Rhino expect(typeof jsdoc.src.parser.createParser()).toBe('object'); }); @@ -41,15 +40,6 @@ describe('jsdoc/src/parser', function() { expect(parser instanceof jsdoc.src.parser.Parser).toBe(true); }); - if (jsdoc.util.runtime.isRhino()) { - it('should create a Rhino parser with the argument "rhino"', function() { - var RhinoParser = require('rhino/jsdoc/src/parser').Parser; - var parser = jsdoc.src.parser.createParser('rhino'); - - expect(parser instanceof RhinoParser).toBe(true); - }); - } - it('should log a fatal error on bad input', function() { var parser; @@ -303,18 +293,15 @@ describe('jsdoc/src/parser', function() { expect(spy.mostRecentCall.args[0].doclets).toBe(doclets); }); - // Rhino can't parse ES6 - if (jasmine.jsParser !== 'rhino') { - it('should not throw errors when parsing files with ES6 syntax', function() { - function parse() { - var parserSrc = 'javascript:' + fs.readFileSync( - path.join(jsdoc.env.dirname, 'test/fixtures/es6.js'), 'utf8'); - parser.parse(parserSrc); - } + it('should not throw errors when parsing files with ES6 syntax', function() { + function parse() { + var parserSrc = 'javascript:' + fs.readFileSync( + path.join(jsdoc.env.dirname, 'test/fixtures/es6.js'), 'utf8'); + parser.parse(parserSrc); + } - expect(parse).not.toThrow(); - }); - } + expect(parse).not.toThrow(); + }); it('should be able to parse its own source file', function() { var parserSrc = 'javascript:' + fs.readFileSync(path.join(jsdoc.env.dirname, @@ -408,43 +395,14 @@ describe('jsdoc/src/parser', function() { } } - // Rhino fires events in a different order - if (jasmine.jsParser === 'rhino') { - it('should fire all jsdocCommentFound events, in source order, ' + - 'then all symbolFound events, in source order', function() { - parser.on('jsdocCommentFound', pushEvent); - - parser.on('symbolFound', pushEvent); - - jsdoc.src.handlers.attachTo(parser); - parser.parse('javascript:' + source); - - // make sure jsdocCommentFound events are in the correct order - events.jsdocCommentFound.slice(0).sort(sourceOrderSort) - .forEach(function(e, i) { - expect(e).toBe(events.jsdocCommentFound[i]); - }); - // make sure symbolFound events are in the correct order - events.symbolFound.slice(0).sort(sourceOrderSort).forEach(function(e, i) { - expect(e).toBe(events.symbolFound[i]); - }); - // make sure jsdocCommentFound events are all first - events.all.slice(0, events.jsdocCommentFound.length) - .forEach(function(e, i) { - expect(e).toBe(events.all[i]); - }); + it('should fire interleaved jsdocCommentFound and symbolFound events, ' + + 'in source order', function() { + jsdoc.src.handlers.attachTo(parser); + parser.parse(source); + events.all.slice(0).sort(sourceOrderSort).forEach(function(e, i) { + expect(e).toBe(events.all[i]); }); - } - else { - it('should fire interleaved jsdocCommentFound and symbolFound events, ' + - 'in source order', function() { - jsdoc.src.handlers.attachTo(parser); - parser.parse(source); - events.all.slice(0).sort(sourceOrderSort).forEach(function(e, i) { - expect(e).toBe(events.all[i]); - }); - }); - } + }); }); }); diff --git a/test/specs/jsdoc/util/runtime.js b/test/specs/jsdoc/util/runtime.js index be6587d6..c69a53a8 100644 --- a/test/specs/jsdoc/util/runtime.js +++ b/test/specs/jsdoc/util/runtime.js @@ -2,7 +2,6 @@ describe('jsdoc/util/runtime', function() { var runtime = require('jsdoc/util/runtime'); - var isRhino; var isNode; it('should exist', function() { @@ -10,54 +9,21 @@ describe('jsdoc/util/runtime', function() { expect(typeof runtime).toEqual('object'); }); - it("should export a 'RHINO' constant", function() { - expect(runtime.RHINO).toBeDefined(); - expect(typeof runtime.RHINO).toEqual('string'); - }); - it("should export a 'NODE' constant", function() { expect(runtime.NODE).toBeDefined(); expect(typeof runtime.NODE).toEqual('string'); }); - it("should export an 'isRhino' function", function() { - expect(runtime.isRhino).toBeDefined(); - expect(typeof runtime.isRhino).toEqual('function'); - }); it("should export an 'isNode' function", function() { expect(runtime.isNode).toBeDefined(); expect(typeof runtime.isNode).toEqual('function'); }); - describe('isRhino', function() { - isRhino = runtime.isRhino(); - - it('should return a boolean', function() { - expect(typeof isRhino).toEqual('boolean'); - }); - - it('should return the opposite value from isNode()', function() { - if (isNode === undefined) { - isNode = runtime.isNode(); - } - - expect(!isRhino).toBe(isNode); - }); - }); - describe('isNode', function() { isNode = runtime.isNode(); it('should return a boolean', function() { expect(typeof isNode).toEqual('boolean'); }); - - it('should return the opposite value from isRhino()', function() { - if (isRhino === undefined) { - isRhino = runtime.isRhino(); - } - - expect(!isNode).toBe(isRhino); - }); }); }); diff --git a/test/specs/rhino/fs.js b/test/specs/rhino/fs.js deleted file mode 100644 index 507aa806..00000000 --- a/test/specs/rhino/fs.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -xdescribe('rhino/fs', function() { - // TODO -}); diff --git a/test/specs/rhino/os.js b/test/specs/rhino/os.js deleted file mode 100644 index 418d9ca6..00000000 --- a/test/specs/rhino/os.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -xdescribe('rhino/os', function() { - // TODO -}); diff --git a/test/specs/rhino/path.js b/test/specs/rhino/path.js deleted file mode 100644 index 58bebd1a..00000000 --- a/test/specs/rhino/path.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -describe('rhino/path', function() { - // TODO: more tests - var path = require('path'); - - var pathChunks = [ - 'foo', - 'bar', - 'baz', - 'qux.html' - ]; - var joinedPath = path.join.apply(this, pathChunks); - - describe('basename', function() { - it('should exist', function() { - expect(path.basename).toBeDefined(); - }); - - it('should be a function', function() { - expect(typeof path.basename).toBe('function'); - }); - - it('should work correctly without an "ext" parameter', function() { - expect( path.basename(joinedPath) ).toBe( pathChunks[pathChunks.length - 1] ); - }); - - it('should work correctly with an "ext" parameter', function() { - var fn = pathChunks[pathChunks.length - 1]; - var ext = Array.prototype.slice.call( fn, fn.indexOf('.') ).join(''); - var bn = Array.prototype.slice.call( fn, 0, fn.indexOf('.') ).join(''); - - expect( path.basename(joinedPath, ext) ).toBe(bn); - }); - }); -}); diff --git a/test/specs/rhino/src/parser.js b/test/specs/rhino/src/parser.js deleted file mode 100644 index 877e9795..00000000 --- a/test/specs/rhino/src/parser.js +++ /dev/null @@ -1,185 +0,0 @@ -'use strict'; - -describe('rhino/jsdoc/src/parser', function() { - var jsdoc = { - src: { - parser: (function() { - var runtime = require('jsdoc/util/runtime'); - return require( runtime.getModulePath('jsdoc/src/parser') ); - })() - } - }; - - // don't run this spec if we're currently testing another parser - if (jasmine.jsParser !== 'rhino') { - return; - } - - it('should exist', function() { - expect(jsdoc.src.parser).toBeDefined(); - expect(typeof jsdoc.src.parser).toBe('object'); - }); - - it('should export a "Parser" constructor', function() { - expect(jsdoc.src.parser.Parser).toBeDefined(); - expect(typeof jsdoc.src.parser.Parser).toBe('function'); - }); - - describe('Parser', function() { - var parser; - - function newParser() { - parser = jsdoc.src.parser.createParser('rhino'); - } - - newParser(); - - it('should inherit from jsdoc/src/parser', function() { - var parent = require('jsdoc/src/parser').Parser; - expect(parser instanceof parent).toBe(true); - }); - - it('should have an "addNodeVisitor" method', function() { - expect(parser.addNodeVisitor).toBeDefined(); - expect(typeof parser.addNodeVisitor).toBe('function'); - }); - - it('should have a "getNodeVisitors" method', function() { - expect(parser.getNodeVisitors).toBeDefined(); - expect(typeof parser.getNodeVisitors).toBe('function'); - }); - - describe('addNodeVisitor', function() { - function visitorA() {} - function visitorB() {} - - var visitors; - - beforeEach(newParser); - - it('should work with a single Rhino node visitor', function() { - parser.addNodeVisitor(visitorA); - - visitors = parser.getNodeVisitors(); - - expect(visitors.length).toBe(1); - expect(visitors[0]).toBe(visitorA); - }); - - it('should work with multiple Rhino node visitors', function() { - parser.addNodeVisitor(visitorA); - parser.addNodeVisitor(visitorB); - - visitors = parser.getNodeVisitors(); - - expect(visitors.length).toBe(2); - expect(visitors[0]).toBe(visitorA); - expect(visitors[1]).toBe(visitorB); - }); - }); - - describe('getNodeVisitors', function() { - beforeEach(newParser); - - it('should return an empty array by default', function() { - var visitors = parser.getNodeVisitors(); - - expect( Array.isArray(visitors) ).toBe(true); - expect(visitors.length).toBe(0); - }); - - // other functionality is covered by the addNodeVisitors tests - }); - - describe('parse', function() { - /*eslint no-script-url: 0 */ - beforeEach(newParser); - - var sourceCode = ['javascript:/** foo */var foo;']; - - it('should call Rhino node visitors', function() { - var args; - - var visitor = { - visitNode: function(rhinoNode, e, visitParser, sourceName) { - if (e && e.code && !args) { - args = Array.prototype.slice.call(arguments); - } - } - }; - - require('jsdoc/src/handlers').attachTo(parser); - parser.addNodeVisitor(visitor); - parser.parse(sourceCode); - - expect(args).toBeDefined(); - expect( Array.isArray(args) ).toBe(true); - expect(args.length).toBe(4); - - // args[0]: Rhino node - expect(args[0].toSource).toBeDefined(); - expect( String(args[0].toSource()) ).toBe('foo'); - - // args[1]: JSDoc event - expect(typeof args[1]).toBe('object'); - expect(args[1].code).toBeDefined(); - expect(args[1].code.name).toBeDefined(); - expect( String(args[1].code.name) ).toBe('foo'); - - // args[2]: parser - expect(typeof args[2]).toBe('object'); - - // args[3]: current source name - expect( String(args[3]) ).toBe('[[string0]]'); - }); - - it('should reflect changes made by Rhino node visitors', function() { - var doclet; - - var visitor = { - visitNode: function(rhinoNode, e, visitParser, sourceName) { - if (e && e.code && e.code.name === 'foo') { - e.code.name = 'bar'; - } - } - }; - - require('jsdoc/src/handlers').attachTo(parser); - parser.addNodeVisitor(visitor); - parser.parse(sourceCode); - - doclet = parser.results()[0]; - - expect(doclet).toBeDefined(); - expect(typeof doclet).toBe('object'); - expect(doclet.name).toBeDefined(); - expect(doclet.name).toBe('bar'); - }); - - it('should not call a second Rhino node visitor if the first visitor stopped ' + - 'propagation', function() { - var doclet; - - var visitor1 = { - visitNode: function(rhinoNode, e, visitParser, sourceName) { - e.stopPropagation = true; - } - }; - var visitor2 = { - visitNode: function(rhinoNode, e, visitParser, sourceName) { - e.propertyThatWillNeverBeSet = ':('; - } - }; - - require('jsdoc/src/handlers').attachTo(parser); - parser.addNodeVisitor(visitor1); - parser.addNodeVisitor(visitor2); - parser.parse(sourceCode); - - doclet = parser.results()[0]; - - expect(doclet.propertyThatWillNeverBeSet).not.toBeDefined(); - }); - }); - }); -}); diff --git a/test/specs/rhino/src/visitor.js b/test/specs/rhino/src/visitor.js deleted file mode 100644 index 88e765f5..00000000 --- a/test/specs/rhino/src/visitor.js +++ /dev/null @@ -1,89 +0,0 @@ -'use strict'; - -describe('rhino/jsdoc/src/visitor', function() { - var runtime = require('jsdoc/util/runtime'); - var jsdoc = { - src: { - visitor: require( runtime.getModulePath('jsdoc/src/visitor') ) - } - }; - - it('should exist', function() { - expect(jsdoc.src.visitor).toBeDefined(); - expect(typeof jsdoc.src.visitor).toBe('object'); - }); - - it('should export a "Visitor" constructor', function() { - expect(jsdoc.src.visitor.Visitor).toBeDefined(); - expect(typeof jsdoc.src.visitor.Visitor).toBe('function'); - }); - - describe('Visitor', function() { - var parser; - var visitor; - - function newVisitor() { - parser = require('jsdoc/src/parser').createParser('rhino'); - visitor = new jsdoc.src.visitor.Visitor(parser); - } - - newVisitor(); - - it('should inherit from jsdoc/src/visitor', function() { - var parent = require('jsdoc/src/visitor').Visitor; - expect(visitor instanceof parent).toBe(true); - }); - - it('should have an "addRhinoNodeVisitor" method', function() { - expect(visitor.addRhinoNodeVisitor).toBeDefined(); - expect(typeof visitor.addRhinoNodeVisitor).toBe('function'); - }); - - it('should have a "getRhinoNodeVisitors" method', function() { - expect(visitor.getRhinoNodeVisitors).toBeDefined(); - expect(typeof visitor.getRhinoNodeVisitors).toBe('function'); - }); - - describe('addRhinoNodeVisitor', function() { - function visitorA() {} - function visitorB() {} - - var visitors; - - beforeEach(newVisitor); - - it('should work with a single Rhino node visitor', function() { - visitor.addRhinoNodeVisitor(visitorA); - - visitors = visitor.getRhinoNodeVisitors(); - - expect(visitors.length).toBe(1); - expect(visitors[0]).toBe(visitorA); - }); - - it('should work with multiple Rhino node visitors', function() { - visitor.addRhinoNodeVisitor(visitorA); - visitor.addRhinoNodeVisitor(visitorB); - - visitors = visitor.getRhinoNodeVisitors(); - - expect(visitors.length).toBe(2); - expect(visitors[0]).toBe(visitorA); - expect(visitors[1]).toBe(visitorB); - }); - }); - - describe('getRhinoNodeVisitors', function() { - beforeEach(newVisitor); - - it('should return an empty array by default', function() { - var visitors = visitor.getRhinoNodeVisitors(); - - expect( Array.isArray(visitors) ).toBe(true); - expect(visitors.length).toBe(0); - }); - - // other functionality is covered by the addNodeVisitors tests - }); - }); -});